formdown 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ script: bundle exec rspec spec
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in formdown.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Brad Gessler
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ [![Build Status](https://travis-ci.org/bradgessler/formdown.svg?branch=master)](https://travis-ci.org/bradgessler/formdown)
2
+
3
+ # Formdown
4
+
5
+ Build HTML forms with the simplicity of [Markdown](http://daringfireball.net/projects/markdown/). In other words, markdown like:
6
+
7
+ ```markdown
8
+ Hi _________(Name)
9
+
10
+ How are you doing today? () Good () Ok () Bad
11
+
12
+ Could I have your email address? __________@(Email)
13
+
14
+ Write a few lines that describe your mood: ____________///(Mood)
15
+
16
+ [ Submit your feelings ]
17
+ ```
18
+
19
+ Generates the following HTML:
20
+
21
+ ```html
22
+ <p>Hi <input type="text" placeholder="Name" name="Name" size="9"></input>
23
+ </p>
24
+
25
+ <p>How are you doing today? <input type="radio"></input>
26
+ Good <input type="radio"></input>
27
+ Ok <input type="radio"></input>
28
+ Bad</p>
29
+
30
+ <p>Could I have your email address? <input type="email" placeholder="Email" name="Email" size="10"></input>
31
+ </p>
32
+
33
+ <p>Write a few lines that describe your mood: <textarea placeholder="Mood" name="Mood" cols="12" rows="3"></textarea>
34
+ </p>
35
+
36
+ <p> <input type="submit" value="Submit your feelings"></input>
37
+ </p>
38
+ ```
39
+
40
+ A more extensive reference of Formdown in action may be found in the [kitchen sink](./spec/fixtures/kitchen_sink.fmd) fmd file. As this gem matures more extensive syntax documentation will be created for version 1.0.
41
+
42
+ ## Installation
43
+
44
+ Add this line to your application's Gemfile:
45
+
46
+ ```ruby
47
+ gem 'formdown'
48
+ ```
49
+
50
+ or for Rails:
51
+
52
+ ```ruby
53
+ gem 'formdown', require: 'formdown/rails'
54
+ ```
55
+
56
+ And then execute:
57
+
58
+ $ bundle
59
+
60
+ Or install it yourself as:
61
+
62
+ $ gem install formdown
63
+
64
+ ## Usage
65
+
66
+ ### CLI
67
+
68
+ The quickest way to render Formdown is via the command line. Just cat your file into the render and you'll get HTML:
69
+
70
+ ```sh
71
+ $ cat my_form.fmd | formdown render > my_form.html
72
+ ```
73
+
74
+ Now open `my_form.html` and enjoy all of that HTML goodness.
75
+
76
+ ### Ruby
77
+
78
+ ```ruby
79
+ text = "What is your email address? _________@(Email)"
80
+ formdown = Formdown::Renderer.new(text)
81
+ formdown.to_html # => "<p>What is your email address? <input type=\"email\" placeholder=\"Email\" name=\"Email\" size=\"9\"></input>\n</p>\n"
82
+ ```
83
+
84
+ ### Rails
85
+
86
+ In the rails Gemfile, include the formdown gem via:
87
+
88
+ ```ruby
89
+ gem "formdown", require: "formdown/rails"
90
+ ```
91
+
92
+ Rails will pick up files with the extension `.fmd` and render them as HTML. For example, `app/views/user/my_form.fmd.html` would render the formdown document.
93
+
94
+ Its recommended to use a layout around the Formdown file to handle the form submission action and surrounding HTML content.
95
+
96
+ **Note**: There's currently no simple way of mapping Formdown fields to ActiveRecord model attributes.
97
+
98
+ ## Contributing
99
+
100
+ 1. Fork it ( https://github.com/[my-github-username]/formdown/fork )
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/formdown ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'formdown/cli'
4
+
5
+ Formdown::CLI.start
data/formdown.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'formdown/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "formdown"
8
+ spec.version = Formdown::VERSION
9
+ spec.authors = ["Brad Gessler"]
10
+ spec.email = ["bradgessler@gmail.com"]
11
+ spec.summary = %q{A Markdown-like syntax for web forms.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "kramdown", "~> 1.4"
21
+ spec.add_dependency "thor"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'formdown'
2
+ require 'thor'
3
+
4
+ class Formdown::CLI < Thor
5
+ desc "render", "Render formdown file to html"
6
+ def render
7
+ if $stdin.tty?
8
+ error "Pipe Formdown into this command. Example: `$ echo 'Email: ____@(Email)' | formdown render`"
9
+ else
10
+ puts Formdown::Renderer.new($stdin.read).to_html
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'formdown'
2
+
3
+ # TODO - Implement rails auto-detection code so that we dont have to
4
+ # `gem 'formdown', require: 'formdown/rails'` from the rails app Gemfile.
5
+ module ActionView
6
+ module Template::Handlers
7
+ class Formdown
8
+ class_attribute :default_format
9
+ self.default_format = Mime::HTML
10
+
11
+ def call(template)
12
+ ::Formdown::Renderer.new(template.source).to_html.inspect
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ # Register in the rails stack.
19
+ ActionView::Template.register_template_handler(:fmd, ActionView::Template::Handlers::Formdown.new)
@@ -0,0 +1,3 @@
1
+ module Formdown
2
+ VERSION = "0.0.1"
3
+ end
data/lib/formdown.rb ADDED
@@ -0,0 +1,95 @@
1
+ require "formdown/version"
2
+
3
+ # Formdown extends the Markdown language with practical HTML form builder syntax.
4
+ #
5
+ # TODO
6
+ # - name: parameters should be applied at a different layer, NOT within this file. This will
7
+ # make sure that we don't clobber the users form submissions.
8
+ # - DRY up the methods below into more of a macro language. The constants, extractions, etc.
9
+ # are a common pattern.
10
+
11
+ require 'kramdown'
12
+ require 'kramdown/parser/kramdown'
13
+ require 'kramdown/document'
14
+
15
+ module Formdown
16
+ class Parser < Kramdown::Parser::Kramdown
17
+ def initialize(source, options)
18
+ super
19
+ @span_parsers.unshift :text_fields, :text_areas, :checkboxes, :buttons, :radio_buttons
20
+ end
21
+
22
+ TEXT_FIELD_START = /(_+)([@\#]?)\((.+?)\)/
23
+
24
+ def parse_text_fields
25
+ @src.pos += @src.matched_size
26
+ line, type, placeholder = TEXT_FIELD_START.match(@src.matched).captures
27
+ # Optionally pull out email or number types.
28
+ type = case type
29
+ when '@' then :email
30
+ when '#' then :number
31
+ else :text
32
+ end
33
+ @tree.children << Element.new(:html_element, :input, type: type, placeholder: placeholder, name: placeholder, size: line.size)
34
+ end
35
+ define_parser(:text_fields, TEXT_FIELD_START, '_{')
36
+
37
+
38
+ TEXT_AREA_START = /(_+)(\/+)\((.+?)\)/
39
+
40
+ def parse_text_areas
41
+ @src.pos += @src.matched_size
42
+ col, rows, placeholder = TEXT_AREA_START.match(@src.matched).captures
43
+ @tree.children << Element.new(:html_element, :textarea, placeholder: placeholder, name: placeholder, cols: col.size, rows: rows.size)
44
+ end
45
+ define_parser(:text_areas, TEXT_AREA_START, '_/')
46
+
47
+
48
+ CHECKBOX_FIELD_START = /\[([\sxX])?\]/
49
+
50
+ def parse_checkboxes
51
+ @src.pos += @src.matched_size
52
+ @tree.children << Element.new(:html_element, :input, type: :checkbox)
53
+ end
54
+ define_parser(:checkboxes, CHECKBOX_FIELD_START, '\[')
55
+
56
+ RADIO_BUTTON_FIELD_START = /\(([\sxX])?\)/
57
+
58
+ def parse_radio_buttons
59
+ @src.pos += @src.matched_size
60
+ @tree.children << Element.new(:html_element, :input, type: :radio)
61
+ end
62
+ define_parser(:radio_buttons, RADIO_BUTTON_FIELD_START, '\(')
63
+
64
+ BUTTON_START = /\[\s(.+)\s\]([\!])?/
65
+
66
+ def parse_buttons
67
+ @src.pos += @src.matched_size
68
+ value, type = BUTTON_START.match(@src.matched).captures
69
+ type = case type
70
+ when '!' then :submit
71
+ # else :button
72
+ else :submit # TODO - Should we even support other types of buttons? Probably not... just make it a submit.
73
+ end
74
+ @tree.children << Element.new(:html_element, :input, type: type, value: value)
75
+ end
76
+ define_parser(:buttons, BUTTON_START, '\[')
77
+ end
78
+ end
79
+
80
+ # Work around to get this build passing for Ruby 1.9 since the kramdown Parser.const_get()
81
+ # TODO - Patch kramdown to work with nested namespaces in Ruby 1.9.
82
+ # Details about the issue noted at https://github.com/gettalong/kramdown/commit/cd5423f23eb783a2c435e8545a98625cb280f286#diff-1f46a84d29e6ac9751ae5d75bafc25aeR88
83
+ FormdownParser = Formdown::Parser
84
+
85
+ module Formdown
86
+ class Renderer
87
+ def initialize(content)
88
+ @document = ::Kramdown::Document.new(content, input: 'FormdownParser')
89
+ end
90
+
91
+ def to_html
92
+ @document.to_html
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,18 @@
1
+ Hi there __________(Name)
2
+
3
+ How are you doing today? () Good () OK () Bad
4
+
5
+ Please elaborate on those feelings: __________///(Description)
6
+
7
+ Why do you think you feel that way?
8
+
9
+ [] Because I accidentally swallowed a bug
10
+ [] Its sunny outside
11
+ [] I'm stuck under a cloud of fog
12
+ [] I just ate a Twinkie and they're delicious!
13
+
14
+ How many times did you sneeze today? __#(Sneezes)
15
+
16
+ Please enter your email address: ____________@(Email)
17
+
18
+ [ Submit response ]
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formdown::Renderer do
4
+ subject { Formdown::Renderer.new(File.read('spec/fixtures/kitchen_sink.fmd')).to_html }
5
+ it "renders text input" do
6
+ expect(subject).to include(%(<input type="text" placeholder="Name" name="Name" size="10"></input>))
7
+ end
8
+
9
+ it "renders email input" do
10
+ expect(subject).to include(%(<input type="email" placeholder="Email" name="Email" size="12"></input>))
11
+ end
12
+
13
+ it "renders number input" do
14
+ expect(subject).to include(%(<input type="number" placeholder="Sneezes" name="Sneezes" size="2"></input>))
15
+ end
16
+
17
+ it "renders submit button" do
18
+ expect(subject).to include(%(<input type="submit" value="Submit response"></input>))
19
+ end
20
+
21
+ # TODO - Multiline text area inputs for readability.
22
+ it "renders textarea" do
23
+ expect(subject).to include(%(<textarea placeholder="Description" name="Description" cols="10" rows="3"></textarea>))
24
+ end
25
+
26
+ # TODO - Make text to left, right of this be a lable.
27
+ # - Support multi-line inputs that act like MD bullets
28
+ it "renders checkbox input"
29
+ it "renders radio buttons"
30
+ end
@@ -0,0 +1,64 @@
1
+ require 'formdown'
2
+
3
+ RSpec.configure do |config|
4
+ # The settings below are suggested to provide a good initial experience
5
+ # with RSpec, but feel free to customize to your heart's content.
6
+ =begin
7
+ # These two settings work together to allow you to limit a spec run
8
+ # to individual examples or groups you care about by tagging them with
9
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
10
+ # get run.
11
+ config.filter_run :focus
12
+ config.run_all_when_everything_filtered = true
13
+
14
+ # Many RSpec users commonly either run the entire suite or an individual
15
+ # file, and it's useful to allow more verbose output when running an
16
+ # individual spec file.
17
+ if config.files_to_run.one?
18
+ # Use the documentation formatter for detailed output,
19
+ # unless a formatter has already been configured
20
+ # (e.g. via a command-line flag).
21
+ config.default_formatter = 'doc'
22
+ end
23
+
24
+ # Print the 10 slowest examples and example groups at the
25
+ # end of the spec run, to help surface which specs are running
26
+ # particularly slow.
27
+ config.profile_examples = 10
28
+
29
+ # Run specs in random order to surface order dependencies. If you find an
30
+ # order dependency and want to debug it, you can fix the order by providing
31
+ # the seed, which is printed after each run.
32
+ # --seed 1234
33
+ config.order = :random
34
+
35
+ # Seed global randomization in this process using the `--seed` CLI option.
36
+ # Setting this allows you to use `--seed` to deterministically reproduce
37
+ # test failures related to randomization by passing the same `--seed` value
38
+ # as the one that triggered the failure.
39
+ Kernel.srand config.seed
40
+
41
+ # rspec-expectations config goes here. You can use an alternate
42
+ # assertion/expectation library such as wrong or the stdlib/minitest
43
+ # assertions if you prefer.
44
+ config.expect_with :rspec do |expectations|
45
+ # Enable only the newer, non-monkey-patching expect syntax.
46
+ # For more details, see:
47
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
48
+ expectations.syntax = :expect
49
+ end
50
+
51
+ # rspec-mocks config goes here. You can use an alternate test double
52
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
53
+ config.mock_with :rspec do |mocks|
54
+ # Enable only the newer, non-monkey-patching expect syntax.
55
+ # For more details, see:
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ mocks.syntax = :expect
58
+
59
+ # Prevents you from mocking or stubbing a method that does not exist on
60
+ # a real object. This is generally recommended.
61
+ mocks.verify_partial_doubles = true
62
+ end
63
+ =end
64
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: formdown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brad Gessler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-08-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: kramdown
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.4'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '10.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '3.0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '3.0'
94
+ description:
95
+ email:
96
+ - bradgessler@gmail.com
97
+ executables:
98
+ - formdown
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .rspec
104
+ - .travis.yml
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - bin/formdown
110
+ - formdown.gemspec
111
+ - lib/formdown.rb
112
+ - lib/formdown/cli.rb
113
+ - lib/formdown/rails.rb
114
+ - lib/formdown/version.rb
115
+ - spec/fixtures/kitchen_sink.fmd
116
+ - spec/formdown_spec.rb
117
+ - spec/spec_helper.rb
118
+ homepage: ''
119
+ licenses:
120
+ - MIT
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 1.8.23
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: A Markdown-like syntax for web forms.
143
+ test_files:
144
+ - spec/fixtures/kitchen_sink.fmd
145
+ - spec/formdown_spec.rb
146
+ - spec/spec_helper.rb
147
+ has_rdoc: