dolores-cfml 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Van Pelt
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = cfml
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Chris Van Pelt. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "cfml"
8
+ gem.summary = "CFML is Crowd Flower Marup Language"
9
+ gem.description = "CFML let's you easily create form elements and custom interfaces for the CrowdFlower Croudsourcing platform"
10
+ gem.email = "vanpelt@doloreslabs.com"
11
+ gem.homepage = "http://github.com/dolores/cfml"
12
+ gem.authors = ["Chris Van Pelt"]
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'spec/rake/spectask'
21
+ Spec::Rake::SpecTask.new(:spec) do |spec|
22
+ spec.libs << 'lib' << 'spec'
23
+ spec.spec_files = FileList['spec/**/*_spec.rb']
24
+ end
25
+
26
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.rcov = true
30
+ end
31
+
32
+
33
+
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ if File.exist?('VERSION.yml')
40
+ config = YAML.load(File.read('VERSION.yml'))
41
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
42
+ else
43
+ version = ""
44
+ end
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "cfml #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
51
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/cfml.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+ require 'liquid'
4
+
5
+ require 'cfml/parser'
6
+ require 'cfml/liquid_filters'
7
+ require 'cfml/tag'
8
+ Dir[File.dirname(__FILE__) + '/cfml/tags/*.rb'].each {|dir| require dir }
@@ -0,0 +1,16 @@
1
+ module CFML
2
+ module LiquidFilters
3
+ def marukurized(input)
4
+ if input.blank?
5
+ ""
6
+ else
7
+ marukurized = ::Maruku.new(input)
8
+ marukurized.to_html
9
+ end
10
+ end
11
+
12
+ def to_json(input)
13
+ input.to_json
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,60 @@
1
+ module CFML
2
+ class Parser
3
+ def initialize(content, opts = {})
4
+ @opts = opts
5
+ @doc = Nokogiri::XML("<root xmlns:cf='http://crowdflower.com'>#{content}</root>")
6
+ @cftags = @doc.xpath("//cf:*[not(ancestor::cf:*)]")
7
+ end
8
+
9
+ def convert
10
+ @cftags.each do |t|
11
+ t.replace(tag_class(t.name).new(t, @opts).convert)
12
+ end
13
+ @doc
14
+ end
15
+
16
+ def golds
17
+ return @golds if @golds
18
+ @golds = {}
19
+ @doc.xpath("//cf:gold|//cf:*[@gold]").map do |g|
20
+ p = g.name == "gold" ? g.parent : g
21
+ next unless p
22
+ ref = tag_class(p.name).new(p, @opts).name
23
+ gold = (g.attributes["gold"] || g.attributes["src"]).to_s
24
+ gold = "#{ref}_gold" if gold =~ /^(true|\s*)$/
25
+ @golds[ref] = gold
26
+ ["strict","regex"].each do |attrs|
27
+ if a = g.attributes[attrs]
28
+ @golds["_#{gold}_#{attrs}"] = attrs == "regex" ? [a.to_s,g.attributes["flags"].to_s] : a.to_s
29
+ end
30
+ end
31
+ end
32
+ @golds
33
+ end
34
+
35
+ def wrap(content)
36
+ @opts[:no_wrap] ? content : "<div class=\"cfml #{@opts[:prefix]}\">#{content}</div>"
37
+ end
38
+
39
+ def to_html
40
+ convert
41
+ wrap(@doc.at("root").inner_html)
42
+ end
43
+
44
+ def self.escape( string )
45
+ string.to_s.gsub( /&/, "&amp;" ).
46
+ gsub( /</, "&lt;" ).
47
+ gsub( />/, "&gt;" ).
48
+ gsub( /"/, "&quot;" )
49
+ end
50
+
51
+ private
52
+
53
+ #This takes the name of the tag and converts it to the appropriate task
54
+ def tag_class(name)
55
+ CFML::Tags.module_eval(name.gsub(/(^|_)(.)/) { $2.upcase })
56
+ rescue
57
+ CFML::Tags::Unknown
58
+ end
59
+ end
60
+ end
data/lib/cfml/tag.rb ADDED
@@ -0,0 +1,75 @@
1
+ module CFML
2
+ class Tag
3
+ def initialize(cfml, opts = {})
4
+ @cfml = cfml
5
+ @attrs = @cfml.attributes#Hash[*cfml.attributes.map {|k,v| [k.intern,v]}.flatten]
6
+ @tag = @cfml.name
7
+ @opts = opts
8
+ end
9
+
10
+ def prefix(name)
11
+ @opts[:prefix] ? "#{@opts[:prefix]}[#{name}]" : "#{name}"
12
+ end
13
+
14
+ def name
15
+ (@attrs["name"] || @attrs["label"]).to_s.downcase.gsub(/\s/,"_").gsub(/\W/,"")
16
+ end
17
+
18
+ def wrapper_classes
19
+ extras = @attrs["only-if"] ? "only-if:#{@attrs["only-if"]}" : ""
20
+ "#{@tag} #{extras}".strip
21
+ end
22
+
23
+ def classes
24
+ @classes ||= [name] << validations << @attrs["class"].to_s.split(/ /)
25
+ @classes.uniq.reject {|c| c.length == 0 }.join(" ").strip
26
+ end
27
+
28
+ def convert
29
+ Nokogiri::HTML.fragment(to_html).children.first
30
+ end
31
+
32
+ def to_html
33
+ @parsed ||= Liquid::Template.parse(self.class::Template).render(data, [LiquidFilters])
34
+ wrapper(@parsed)
35
+ end
36
+
37
+ def label(label, tag = "label")
38
+ required = " <span class=\"required\">(required)</span>" if validations.include?("required")
39
+ "<#{tag}>#{label}#{required}</#{tag}>" if label
40
+ end
41
+
42
+ def legend(label)
43
+ label(label, "legend") if label
44
+ end
45
+
46
+ def validations
47
+ @validations ||= @attrs["validations"].to_s.split(/ /).map {|v| "validates-#{v}"}
48
+ end
49
+
50
+ def instructions
51
+ @instructions ||= @attrs["instructions"] || (@cfml.at("instructions") ? @cfml.at("instructions").inner_html : nil)
52
+ @instructions ? "<p class=\"instructions\">#{@instructions}</p>" : nil
53
+ end
54
+
55
+ def wrapper(parsed, tag = "div")
56
+ #Deal with a label only wrapper... kinda jank
57
+ if tag == "label" && instructions
58
+ tag = "div"
59
+ parsed = "<label>#{parsed}</label>"
60
+ end
61
+ #Inserting instructions here makes it a non-variable input maybe...
62
+ "<#{tag} class=\"#{wrapper_classes}\">#{parsed}#{instructions}</#{tag}>"
63
+ end
64
+
65
+ def data
66
+ (@opts[:data] || {}).merge({
67
+ "name" => prefix(name),
68
+ "label" => label(@attrs["label"]),
69
+ "legend" => legend(@attrs["label"]),
70
+ "classes" => classes,
71
+ "value" => @attrs["value"].to_s
72
+ })
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,31 @@
1
+ module CFML
2
+ module Tags
3
+ class Checkbox < Tag
4
+ Template = <<-HTML.freeze
5
+ {{default}}
6
+ <input name="{{name}}" type="checkbox" value="{{value}}" class="{{classes}}"/>
7
+ HTML
8
+
9
+ def wrapper(parsed)
10
+ super("#{parsed} #{@attrs["label"]}", "label")
11
+ end
12
+
13
+ def prefix(name)
14
+ super(name) + (grouped? ? "[]" : "")
15
+ end
16
+
17
+ def grouped?
18
+ @cfml.parent && @cfml.parent.name == "checkboxes"
19
+ end
20
+
21
+ def data
22
+ default = ""
23
+ if @attrs["default"]
24
+ default = Parser.new("<cf:hidden name=\"#{name}\" value=\"#{@attrs["default"]}\"/>", @opts.merge(:no_wrap => true)).to_html
25
+ end
26
+ value = @attrs["value"] || (grouped? ? @attrs["label"] : "true")
27
+ super.merge({"value" => value.to_s, "default" => default})
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ module CFML
2
+ module Tags
3
+ class Checkboxes < Tag
4
+ Template = <<-HTML.freeze
5
+ {{legend}}
6
+ {% for checkbox in checkboxes %}
7
+ {{checkbox}}
8
+ {% endfor %}
9
+ HTML
10
+
11
+ def data
12
+ super.merge({"checkboxes" => checkboxes})
13
+ end
14
+
15
+ def checkboxes
16
+ @cfml.xpath("cf:checkbox").map do |c|
17
+ c["name"] ||= name
18
+ c["validations"] ||= @attrs["validations"].to_s
19
+ Checkbox.new(c, @opts).to_html
20
+ end
21
+ end
22
+
23
+ def wrapper(parsed)
24
+ super(parsed,"fieldset")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ module CFML
2
+ module Tags
3
+ class Group < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ {{content}}
7
+ HTML
8
+
9
+ def data
10
+ super.merge({"content" => Parser.new(@cfml.inner_html, @opts.merge(:no_wrap => true)).to_html})
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module CFML
2
+ module Tags
3
+ class Hidden < Tag
4
+ Template = <<-HTML.freeze
5
+ <input name="{{name}}" type="hidden" value="{{value}}" class="{{classes}}"/>
6
+ HTML
7
+
8
+ def wrapper(parsed)
9
+ parsed
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module CFML
2
+ module Tags
3
+ class Radio < Tag
4
+ Template = <<-HTML.freeze
5
+ <input name="{{name}}" type="radio" value="{{value}}" class="{{classes}}"/>
6
+ HTML
7
+
8
+ def wrapper(parsed)
9
+ super("#{parsed} #{@attrs["label"]}", "label")
10
+ end
11
+
12
+ def data
13
+ value = @attrs["value"] || @attrs["label"]
14
+ super.merge({"value" => value.to_s})
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ module CFML
2
+ module Tags
3
+ class Radios < Tag
4
+ Template = <<-HTML.freeze
5
+ {{legend}}
6
+ {% for radio in radios %}
7
+ {{radio}}
8
+ {% endfor %}
9
+ HTML
10
+
11
+ def data
12
+ super.merge({"radios" => radios})
13
+ end
14
+
15
+ def radios
16
+ @cfml.xpath("cf:radio").map do |c|
17
+ c["name"] ||= name
18
+ c["validations"] ||= @attrs["validations"].to_s
19
+ Radio.new(c, @opts).to_html
20
+ end
21
+ end
22
+
23
+ def wrapper(parsed)
24
+ super(parsed, "fieldset")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ module CFML
2
+ module Tags
3
+ class Ratings < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th></th>
10
+ {% for rating in ratings limit:10 %}
11
+ <th>{{forloop.index}}</th>
12
+ {% endfor %}
13
+ <th></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr>
18
+ <td>{{from}}</td>
19
+ {% for rating in ratings limit:10 %}
20
+ <td>{{rating}}</td>
21
+ {% endfor %}
22
+ <td>{{to}}</td>
23
+ </tr>
24
+ </tbody>
25
+ </table>
26
+ HTML
27
+
28
+ def data
29
+ super.merge({"ratings" => ratings, "from" => @attrs["from"].to_s, "to" => @attrs["to"].to_s})
30
+ end
31
+
32
+ def ratings
33
+ @cfml.xpath("cf:rating").map do |c|
34
+ c["name"] ||= prefix
35
+ c["validations"] ||= @attrs["validations"]
36
+ c["value"] ||= @attrs["label"]
37
+ Radio.new(c).convert
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,16 @@
1
+ module CFML
2
+ module Tags
3
+ class Select < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ <select name="{{name}}" class="{{classes}}">{% for option in options %}
7
+ {{option}}{% endfor %}
8
+ </select>
9
+ HTML
10
+
11
+ def data
12
+ super.merge({"options" => @cfml.xpath("option").map {|c| c.to_xhtml}})
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module CFML
2
+ module Tags
3
+ class Text < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ <input name="{{name}}" type="text" value="{{value}}" class="{{classes}}"/>
7
+ HTML
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module CFML
2
+ module Tags
3
+ class Textarea < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ <textarea name="{{name}}" class="{{classes}}">{{value}}</textarea>
7
+ HTML
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module CFML
2
+ module Tags
3
+ class Unknown < Tag
4
+ Template = <<-HTML.freeze
5
+ {{content}}
6
+ HTML
7
+
8
+ def wrapper_classes
9
+ super + " unknown"
10
+ end
11
+
12
+ def data
13
+ super.merge({"content" => @cfml.inner_html})
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "CFML Complex" do
4
+ it "parses" do
5
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/complex.cfml"), {:prefix => "u12345"})
6
+ @p.to_html.should sorta_match(<<-HTML)
7
+ <div class="cfml u12345">
8
+ <h1>This is my name</h1>
9
+ <p>This is a description about me</p>
10
+ <div class="select">
11
+ <label>Awesome</label>
12
+ <select name="u12345[awesome]" class="awesome validates-required">
13
+ <option value="">Choose an option</option>
14
+ <option>Awesome</option>
15
+ <option>Cool</option>
16
+ <option>Rad</option>
17
+ <option>Neat</option>
18
+ </select>
19
+ <p class="instructions">Just be cool about it</p>
20
+ </div>
21
+ <div class="text">
22
+ <label>Opinion</label>
23
+ <input name="u12345[opinion]" class="opinion validates-minLength:30 large" type="text" value="">
24
+ </div>
25
+ <div class="text">
26
+ <label>Email</label>
27
+ <input name="u12345[email]" class="email validates-required validates-email" type="text" value="">
28
+ </div>
29
+ <div class="rad">
30
+ <label class="checkbox">
31
+ <input name="u12345[you_sure]" class="you_sure" type="checkbox" value="yes"> You sure?
32
+ </label>
33
+ </div>
34
+ <div class="group only-if:awesome">
35
+
36
+ <fieldset class="checkboxes">
37
+ <legend>Cool checkboxes</legend>
38
+
39
+ <label class="checkbox">
40
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Wanna do it?">
41
+ Wanna do it?</label>
42
+
43
+ <label class="checkbox">
44
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Sure?">
45
+ Sure?</label>
46
+
47
+ </fieldset>
48
+ <input type="hidden" name="u12345[secret]" value="cool" class="secret" />
49
+ </div>
50
+ </div>
51
+ HTML
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ <h1>This is my name</h1>
2
+ <p>This is a description about me</p>
3
+ <cf:select label="Awesome" validations="required" instructions="Just be cool about it">
4
+ <cf:gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
5
+ <option value="">Choose an option</option>
6
+ <option>Awesome</option>
7
+ <option>Cool</option>
8
+ <option>Rad</option>
9
+ <option>Neat</option>
10
+ </cf:select>
11
+ <cf:text label="Opinion" validations="minLength:30" class="large" />
12
+ <cf:text label="Email" validations="required email" />
13
+ <div class="rad">
14
+ <cf:checkbox label="You sure?" value="yes" gold="true" />
15
+ </div>
16
+ <cf:group only-if="awesome">
17
+ <cf:checkboxes label="Cool checkboxes" name="rad">
18
+ <cf:instructions>This <i>is</i> great</cf:instructions>
19
+ <cf:checkbox label="Wanna do it?"/>
20
+ <cf:checkbox label="Sure?"/>
21
+ </cf:checkboxes>
22
+ <cf:hidden name="secret" value="cool"/>
23
+ </cf:group>
data/spec/gold_spec.rb ADDED
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "CFML Gold" do
4
+ it "should give me da gold" do
5
+ cfml = <<-HTML
6
+ <cf:checkboxes label="Checkboxes">
7
+ <cf:gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
8
+ <cf:checkbox label="Wanna do it?" />
9
+ <cf:checkbox label="Sure?" />
10
+ </cf:checkboxes>
11
+ <cf:text name="cool" gold="true" />
12
+ <cf:textarea name="sweet" gold="sweetness" />
13
+ HTML
14
+ @p = Parser.new(cfml, :prefix => "u12345")
15
+ @p.golds.should == {
16
+ "_awesome_gold_strict" => "true",
17
+ "sweet" => "sweetness",
18
+ "checkboxes" => "awesome_gold",
19
+ "_awesome_gold_regex" => ["\\.asdf\\.", "i"],
20
+ "cool" => "cool_gold"
21
+ }
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ class SortaMatch
2
+ def initialize(dom1,dom2)
3
+ @nodes1 = Nokogiri::HTML(dom1).xpath("//*").to_a
4
+ @nodes2 = Nokogiri::HTML(dom2).xpath("//*").to_a
5
+ @children = []
6
+ @nodes1.each_with_index { |d,i| @children << [d,@nodes2[i]] }
7
+ end
8
+
9
+ def missed
10
+ [present(@nodes1[@i]), present(@nodes2[@i])]
11
+ end
12
+
13
+ def present(node)
14
+ node ? "<#{node.name}#{node.attributes.map {|k,v| " #{k}=\"#{v}\""}}>#{node.children.first if first_text?(node)}" : @why
15
+ end
16
+
17
+ def first_text?(node)
18
+ node.children.first && node.children.first.text?
19
+ end
20
+
21
+ def matches?
22
+ @i = 0
23
+ @children.detect do |a,b|
24
+ if a.nil? || b.nil?
25
+ @why = "missing"
26
+ elsif !a.text?
27
+ if a.name != b.name
28
+ @why = "tag"
29
+ elsif a.attributes.map {|k,v| [k.to_s,v.to_s]} != b.attributes.map {|k,v| [k.to_s,v.to_s]}
30
+ @why = "attributes"
31
+ elsif first_text?(b) && a.children.first.to_s.strip != b.children.first.to_s.strip
32
+ @why = "text"
33
+ end
34
+ else
35
+ @why = nil
36
+ end
37
+ @i += 1 unless @why
38
+ @why
39
+ end.nil?
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'cfml'
4
+ require 'spec'
5
+ require 'sorta_match'
6
+ #require 'spec/autorun'
7
+ include CFML
8
+
9
+ Spec::Runner.configure do |config|
10
+
11
+ end
12
+
13
+ Spec::Matchers.define :sorta_match do |expected|
14
+ match do |actual|
15
+ @sm = SortaMatch.new(expected, actual)
16
+ @sm.matches?
17
+ end
18
+
19
+ failure_message_for_should do |actual|
20
+ "Expected DOM's to sorta match but they had these differences:\n #{@sm.missed.inspect}"
21
+ end
22
+ end
23
+
24
+ def convert(html)
25
+ Nokogiri::HTML.fragment(html)
26
+ end
@@ -0,0 +1,81 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Radio" do
4
+ it "should render basic checkbox" do
5
+ cfml = <<-HTML
6
+ <cf:checkbox label="Check"/>
7
+ HTML
8
+ @p = Parser.new(cfml, :prefix => "u12345")
9
+ @p.to_html.should sorta_match(<<-HTML)
10
+ <div class="cfml u12345">
11
+ <label class="checkbox">
12
+ <input type="checkbox" value="true" name="u12345[check]" class="check"/> Check
13
+ </label>
14
+ </div>
15
+ HTML
16
+ end
17
+
18
+ it "should render checkbox custom value" do
19
+ cfml = <<-HTML
20
+ <cf:checkbox label="Check" value="yes"/>
21
+ HTML
22
+ @p = Parser.new(cfml, :prefix => "u12345")
23
+ @p.to_html.should sorta_match(<<-HTML)
24
+ <div class="cfml u12345">
25
+ <label class="checkbox">
26
+ <input type="checkbox" value="yes" name="u12345[check]" class="check"/> Check
27
+ </label>
28
+ </div>
29
+ HTML
30
+ end
31
+
32
+ it "should render default checkbox" do
33
+ cfml = <<-HTML
34
+ <cf:checkbox label="Check" default="false"/>
35
+ HTML
36
+ @p = Parser.new(cfml, :prefix => "u12345")
37
+ @p.to_html.should sorta_match(<<-HTML)
38
+ <div class="cfml u12345">
39
+ <label class="checkbox">
40
+ <input type="hidden" value="false" name="u12345[check]" class="check"/>
41
+ <input type="checkbox" value="true" name="u12345[check]" class="check"/> Check
42
+ </label>
43
+ </div>
44
+ HTML
45
+ end
46
+
47
+ it "should render checkbox with instructions attribute" do
48
+ cfml = <<-HTML
49
+ <cf:checkbox label="Rad" instructions="Please be careful when you are selecting these."/>
50
+ HTML
51
+ @p = Parser.new(cfml, :prefix => "u12345")
52
+ @p.to_html.should sorta_match(<<-HTML)
53
+ <div class="cfml u12345">
54
+ <div class="checkbox">
55
+ <label>
56
+ <input type="checkbox" value="true" name="u12345[rad]" class="rad"/> Rad
57
+ </label>
58
+ <p class="instructions">Please be careful when you are selecting these.</p>
59
+ </div>
60
+ </div>
61
+ HTML
62
+ end
63
+
64
+ it "should render checkbox nested" do
65
+ cfml = <<-HTML
66
+ <div class="rando">
67
+ <cf:checkbox label="Rad"/>
68
+ </div>
69
+ HTML
70
+ @p = Parser.new(cfml, :prefix => "u12345")
71
+ @p.to_html.should sorta_match(<<-HTML)
72
+ <div class="cfml u12345">
73
+ <div class="rando">
74
+ <label class="checkbox">
75
+ <input type="checkbox" value="true" name="u12345[rad]" class="rad"/> Rad
76
+ </label>
77
+ </div>
78
+ </div>
79
+ HTML
80
+ end
81
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Checkboxes" do
4
+ it "should render basic checkboxes" do
5
+ cfml = <<-HTML
6
+ <cf:checkboxes label="Cool checkboxes">
7
+ <cf:checkbox label="Wanna do it?"/>
8
+ <cf:checkbox label="Sure?">
9
+ </cf:checkboxes>
10
+ HTML
11
+ @p = Parser.new(cfml, :prefix => "u12345")
12
+ @p.to_html.should sorta_match(<<-HTML)
13
+ <div class="cfml u12345">
14
+ <fieldset class="checkboxes">
15
+ <legend>Cool checkboxes</legend>
16
+ <label class="checkbox">
17
+ <input type="checkbox" value="Wanna do it?" name="u12345[cool_checkboxes][]" class="cool_checkboxes"/> Wanna do it?
18
+ </label>
19
+ <label class="checkbox">
20
+ <input type="checkbox" value="Sure?" name="u12345[cool_checkboxes][]" class="cool_checkboxes"/> Sure?
21
+ </label>
22
+ </fieldset>
23
+ </div>
24
+ HTML
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Select" do
4
+ it "should render group" do
5
+ cfml = <<-HTML
6
+ <cf:group only-if="awesome">
7
+ <cf:checkboxes label="Cool checkboxes" name="rad">
8
+ <cf:checkbox label="Wanna do it?"/>
9
+ <cf:checkbox label="Sure?"/>
10
+ </cf:checkboxes>
11
+ <cf:text label="Something"/>
12
+ </cf:group>
13
+ HTML
14
+ @p = Parser.new(cfml, :prefix => "u12345")
15
+ @p.to_html.should sorta_match(<<-HTML)
16
+ <div class="cfml u12345">
17
+ <div class="group only-if:awesome">
18
+ <fieldset class="checkboxes">
19
+ <legend>Cool checkboxes</legend>
20
+ <label class="checkbox">
21
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Wanna do it?" /> Wanna do it?
22
+ </label>
23
+ <label class="checkbox">
24
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Sure?" /> Sure?
25
+ </label>
26
+ </fieldset>
27
+ <div class="text">
28
+ <label>Something</label>
29
+ <input name="u12345[something]" class="something" type="text" value="" />
30
+ </div>
31
+ </div>
32
+ </div>
33
+ HTML
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Hidden" do
4
+ it "should render basic hidden field" do
5
+ cfml = <<-HTML
6
+ <cf:hidden name="secret" value="shit"/>
7
+ HTML
8
+ @p = Parser.new(cfml, :prefix => "u12345")
9
+ @p.to_html.should sorta_match(<<-HTML)
10
+ <div class="cfml u12345">
11
+ <input type="hidden" value="shit" name="u12345[secret]" class="secret"/>
12
+ </div>
13
+ HTML
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Radio" do
4
+ it "should render basic radio" do
5
+ cfml = <<-HTML
6
+ <cf:radio label="Rad"/>
7
+ HTML
8
+ @p = Parser.new(cfml, :prefix => "u12345")
9
+ @p.to_html.should sorta_match(<<-HTML)
10
+ <div class="cfml u12345">
11
+ <label class="radio">
12
+ <input type="radio" value="Rad" name="u12345[rad]" class="rad"/> Rad
13
+ </label>
14
+ </div>
15
+ HTML
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Radios" do
4
+ it "should render basic radios" do
5
+ cfml = <<-HTML
6
+ <cf:radios label="Cool radios">
7
+ <cf:radio label="Wanna do it?"/>
8
+ <cf:radio label="Sure!">
9
+ </cf:radios>
10
+ HTML
11
+ @p = Parser.new(cfml, :prefix => "u12345")
12
+ @p.to_html.should sorta_match(<<-HTML)
13
+ <div class="cfml u12345">
14
+ <fieldset class="radios">
15
+ <legend>Cool radios</legend>
16
+ <label class="radio">
17
+ <input type="radio" value="Wanna do it?" name="u12345[cool_radios]" class="cool_radios"/> Wanna do it?
18
+ </label>
19
+ <label class="radio">
20
+ <input type="radio" value="Sure!" name="u12345[cool_radios]" class="cool_radios"/> Sure!
21
+ </label>
22
+ </fieldset>
23
+ </div>
24
+ HTML
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Select" do
4
+ it "should render basic select" do
5
+ cfml = <<-HTML
6
+ <cf:select label="Basic">
7
+ <option>One</option>
8
+ <option>Two</option>
9
+ <option>Three</option>
10
+ </cf:select>
11
+ HTML
12
+ @p = Parser.new(cfml, :prefix => "u12345")
13
+ @p.to_html.should sorta_match(<<-HTML)
14
+ <div class="cfml u12345">
15
+ <div class="select">
16
+ <label>Basic</label>
17
+ <select name="u12345[basic]" class="basic">
18
+ <option>One</option>
19
+ <option>Two</option>
20
+ <option>Three</option>
21
+ </select>
22
+ </div>
23
+ </div>
24
+ HTML
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Text" do
4
+ it "should render basic text" do
5
+ cfml = <<-HTML
6
+ <cf:text label="Coolio"/>
7
+ HTML
8
+ @p = Parser.new(cfml, :prefix => "u12345")
9
+ @p.to_html.should sorta_match(<<-HTML)
10
+ <div class="cfml u12345">
11
+ <div class="text">
12
+ <label>Coolio</label>
13
+ <input type="text" value="" name="u12345[coolio]" class="coolio"/>
14
+ </div>
15
+ </div>
16
+ HTML
17
+ end
18
+
19
+ it "should render text with classes and instructions tag" do
20
+ cfml = <<-HTML
21
+ <cf:text label="Coolio" class="small">
22
+ <instructions>Just be <b>cool</b> bro!</instructions>
23
+ </cf:text>
24
+ HTML
25
+ @p = Parser.new(cfml, :prefix => "u12345")
26
+ @p.to_html.should sorta_match(<<-HTML)
27
+ <div class="cfml u12345">
28
+ <div class="text">
29
+ <label>Coolio</label>
30
+ <input type="text" class="coolio small" value="" name="u12345[coolio]" class="coolio"/>
31
+ <p class="instructions">Just be <b>cool</b> bro!</p>
32
+ </div>
33
+ </div>
34
+ HTML
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Textarea" do
4
+ it "should render basic text" do
5
+ cfml = <<-HTML
6
+ <cf:textarea label="Sweet dude man!" value="4 sure"/>
7
+ HTML
8
+ @p = Parser.new(cfml, :prefix => "u12345")
9
+ @p.to_html.should sorta_match(<<-HTML)
10
+ <div class="cfml u12345">
11
+ <div class="textarea">
12
+ <label>Sweet dude man!</label>
13
+ <textarea name="u12345[sweet_dude_man]" class="sweet_dude_man">4 sure</textarea>
14
+ </div>
15
+ </div>
16
+ HTML
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CFML Unknown" do
4
+ it "should render unknown field" do
5
+ cfml = <<-HTML
6
+ <cf:crazy name="secret">
7
+ Something
8
+ </cf:crazy>
9
+ HTML
10
+ @p = Parser.new(cfml, :prefix => "u12345")
11
+ @p.to_html.should sorta_match(<<-HTML)
12
+ <div class="cfml u12345">
13
+ <div class="crazy unknown">
14
+ Something
15
+ </div>
16
+ </div>
17
+ HTML
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dolores-cfml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Van Pelt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: CFML let's you easily create form elements and custom interfaces for the CrowdFlower Croudsourcing platform
17
+ email: vanpelt@doloreslabs.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - lib/cfml.rb
33
+ - lib/cfml/liquid_filters.rb
34
+ - lib/cfml/parser.rb
35
+ - lib/cfml/tag.rb
36
+ - lib/cfml/tags/checkbox.rb
37
+ - lib/cfml/tags/checkboxes.rb
38
+ - lib/cfml/tags/group.rb
39
+ - lib/cfml/tags/hidden.rb
40
+ - lib/cfml/tags/radio.rb
41
+ - lib/cfml/tags/radios.rb
42
+ - lib/cfml/tags/ratings.rb
43
+ - lib/cfml/tags/select.rb
44
+ - lib/cfml/tags/text.rb
45
+ - lib/cfml/tags/textarea.rb
46
+ - lib/cfml/tags/unknown.rb
47
+ - spec/complex_spec.rb
48
+ - spec/fixtures/complex.cfml
49
+ - spec/gold_spec.rb
50
+ - spec/sorta_match.rb
51
+ - spec/spec_helper.rb
52
+ - spec/tags/checkbox_spec.rb
53
+ - spec/tags/checkboxes_spec.rb
54
+ - spec/tags/group_spec.rb
55
+ - spec/tags/hidden_spec.rb
56
+ - spec/tags/radio_spec.rb
57
+ - spec/tags/radios_spec.rb
58
+ - spec/tags/select_spec.rb
59
+ - spec/tags/text_spec.rb
60
+ - spec/tags/textarea_spec.rb
61
+ - spec/tags/unknown_spec.rb
62
+ has_rdoc: false
63
+ homepage: http://github.com/dolores/cfml
64
+ licenses:
65
+ post_install_message:
66
+ rdoc_options:
67
+ - --charset=UTF-8
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.5
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: CFML is Crowd Flower Marup Language
89
+ test_files:
90
+ - spec/complex_spec.rb
91
+ - spec/gold_spec.rb
92
+ - spec/sorta_match.rb
93
+ - spec/spec_helper.rb
94
+ - spec/tags/checkbox_spec.rb
95
+ - spec/tags/checkboxes_spec.rb
96
+ - spec/tags/group_spec.rb
97
+ - spec/tags/hidden_spec.rb
98
+ - spec/tags/radio_spec.rb
99
+ - spec/tags/radios_spec.rb
100
+ - spec/tags/select_spec.rb
101
+ - spec/tags/text_spec.rb
102
+ - spec/tags/textarea_spec.rb
103
+ - spec/tags/unknown_spec.rb