dolores-cfml 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ begin
12
12
  gem.authors = ["Chris Van Pelt"]
13
13
  gem.add_dependency 'liquid', '>= 2.0.0'
14
14
  gem.add_dependency 'nokogiri', '>= 1.3.3'
15
- gem.add_dependency 'httparty', '>= 1.1.3'
15
+ gem.add_dependency 'json_pure', '>= 1.1.3'
16
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
17
  end
18
18
 
@@ -32,8 +32,11 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
32
  spec.rcov = true
33
33
  end
34
34
 
35
-
36
-
35
+ task :refresh_builder => [:build] do
36
+ cp "pkg/cfml-#{File.read("VERSION").strip}.gem", "../builder/gems/cache/"
37
+ rm_rf "../builder/gems/gems/cfml-#{File.read("VERSION").strip}/"
38
+ `cd ../builder && bin/thor merb:gem:redeploy`
39
+ end
37
40
 
38
41
  task :default => :spec
39
42
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/cfml.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{cfml}
5
- s.version = "0.1.1"
5
+ s.version = "0.2.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Chris Van Pelt"]
9
- s.date = %q{2009-08-16}
9
+ s.date = %q{2009-08-19}
10
10
  s.description = %q{CFML let's you easily create form elements and custom interfaces for the CrowdFlower CroudSourcing platform}
11
11
  s.email = %q{vanpelt@doloreslabs.com}
12
12
  s.extra_rdoc_files = [
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  "VERSION",
23
23
  "cfml.gemspec",
24
24
  "lib/cfml.rb",
25
+ "lib/cfml/converters/jsawesome.rb",
25
26
  "lib/cfml/liquid_filters.rb",
26
27
  "lib/cfml/parser.rb",
27
28
  "lib/cfml/tag.rb",
@@ -29,6 +30,7 @@ Gem::Specification.new do |s|
29
30
  "lib/cfml/tags/checkboxes.rb",
30
31
  "lib/cfml/tags/group.rb",
31
32
  "lib/cfml/tags/hidden.rb",
33
+ "lib/cfml/tags/option.rb",
32
34
  "lib/cfml/tags/radio.rb",
33
35
  "lib/cfml/tags/radios.rb",
34
36
  "lib/cfml/tags/ratings.rb",
@@ -37,20 +39,21 @@ Gem::Specification.new do |s|
37
39
  "lib/cfml/tags/textarea.rb",
38
40
  "lib/cfml/tags/unknown.rb",
39
41
  "spec/complex_spec.rb",
42
+ "spec/converters/jsawesome_spec.rb",
40
43
  "spec/fixtures/complex.cfml",
41
- "spec/gold_spec.rb",
44
+ "spec/fixtures/invalid.cfml",
45
+ "spec/meta_spec.rb",
42
46
  "spec/sorta_match.rb",
43
47
  "spec/spec_helper.rb",
44
48
  "spec/tags/checkbox_spec.rb",
45
49
  "spec/tags/checkboxes_spec.rb",
46
50
  "spec/tags/group_spec.rb",
47
51
  "spec/tags/hidden_spec.rb",
48
- "spec/tags/radio_spec.rb",
49
- "spec/tags/radios_spec.rb",
50
52
  "spec/tags/select_spec.rb",
51
53
  "spec/tags/text_spec.rb",
52
54
  "spec/tags/textarea_spec.rb",
53
- "spec/tags/unknown_spec.rb"
55
+ "spec/tags/unknown_spec.rb",
56
+ "spec/validation_spec.rb"
54
57
  ]
55
58
  s.homepage = %q{http://github.com/dolores/cfml}
56
59
  s.rdoc_options = ["--charset=UTF-8"]
@@ -59,19 +62,19 @@ Gem::Specification.new do |s|
59
62
  s.summary = %q{CFML is Crowd Flower Markup Language}
60
63
  s.test_files = [
61
64
  "spec/complex_spec.rb",
62
- "spec/gold_spec.rb",
65
+ "spec/converters/jsawesome_spec.rb",
66
+ "spec/meta_spec.rb",
63
67
  "spec/sorta_match.rb",
64
68
  "spec/spec_helper.rb",
65
69
  "spec/tags/checkbox_spec.rb",
66
70
  "spec/tags/checkboxes_spec.rb",
67
71
  "spec/tags/group_spec.rb",
68
72
  "spec/tags/hidden_spec.rb",
69
- "spec/tags/radio_spec.rb",
70
- "spec/tags/radios_spec.rb",
71
73
  "spec/tags/select_spec.rb",
72
74
  "spec/tags/text_spec.rb",
73
75
  "spec/tags/textarea_spec.rb",
74
- "spec/tags/unknown_spec.rb"
76
+ "spec/tags/unknown_spec.rb",
77
+ "spec/validation_spec.rb"
75
78
  ]
76
79
 
77
80
  if s.respond_to? :specification_version then
@@ -81,15 +84,15 @@ Gem::Specification.new do |s|
81
84
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
82
85
  s.add_runtime_dependency(%q<liquid>, [">= 2.0.0"])
83
86
  s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.3"])
84
- s.add_runtime_dependency(%q<httparty>, [">= 1.1.3"])
87
+ s.add_runtime_dependency(%q<json_pure>, [">= 1.1.3"])
85
88
  else
86
89
  s.add_dependency(%q<liquid>, [">= 2.0.0"])
87
90
  s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
88
- s.add_dependency(%q<httparty>, [">= 1.1.3"])
91
+ s.add_dependency(%q<json_pure>, [">= 1.1.3"])
89
92
  end
90
93
  else
91
94
  s.add_dependency(%q<liquid>, [">= 2.0.0"])
92
95
  s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
93
- s.add_dependency(%q<httparty>, [">= 1.1.3"])
96
+ s.add_dependency(%q<json_pure>, [">= 1.1.3"])
94
97
  end
95
98
  end
@@ -0,0 +1,92 @@
1
+ module CFML
2
+ module Converters
3
+ class JSAwesome
4
+ def initialize(json)
5
+ parsed = JSON.parse(json)
6
+ @json = parsed[0] || []
7
+ @labels = parsed[1] || {}
8
+ end
9
+
10
+ def convert
11
+ @json.map do |k,v|
12
+ if k.is_a?(Array)
13
+ (k << v).map {|k,v| process(k,v)}
14
+ else
15
+ process(k,v)
16
+ end
17
+ end.join("\n")
18
+ end
19
+
20
+ def label(k)
21
+ k = k.sub(/^[_#*^~]?\+?/,'')
22
+ l = @labels[k]
23
+ label = l.is_a?(Hash) ? l["label"] : l if l
24
+ label ||= k.capitalize.gsub(/_/,' ')
25
+ end
26
+
27
+ def tag(tag, val, opts = {})
28
+ val = Array(val)
29
+ parts = val[0].split("|")
30
+ key = parts[0].sub(/^[_#*^~]?\+?/,'')
31
+ attrs = ["label=\"#{label(parts[0])}\""]
32
+ attrs << "name=\"#{parts[1]}\"" if parts[1]
33
+ attrs << "checked=\"true\"" if val[1]
34
+ attrs << "required=\"true\"" if @labels[key] && @labels[key]["required"]
35
+ opts.reject {|k,v| v.to_s.strip.length == 0}.each do |k,v|
36
+ attrs << "#{k}=\"#{v}\""
37
+ end
38
+ if @labels["gold"] && @labels["gold"][key]
39
+ src = @labels["gold"][key]
40
+ gattrs = ["src=\"#{src}\""]
41
+ regex = Array(@labels["gold"]["_"+src+"_regex"])
42
+ gattrs << "regex=\"#{regex[0]}\"" if regex[0]
43
+ gattrs << "flags=\"#{regex[1]}\"" if regex[1]
44
+ gattrs << "strict=\"true\"" if @labels["gold"]["_"+src+"_strict"]
45
+ gold = "><cf:gold #{gattrs.join(" ")} /></cf:#{tag}>"
46
+ else
47
+ gold = "/>"
48
+ end
49
+
50
+ "<cf:#{tag} #{attrs.join(" ")} #{gold}"
51
+ end
52
+
53
+ def process(k,v)
54
+ select_default = @labels['{}'] || "Choose Category"
55
+ cfml = case v
56
+ #a select tag or group of radios/checkboxes
57
+ when Array:
58
+ if(k =~ /^[^_]/)
59
+ if $~[0] == "*"
60
+ parent = "radios"
61
+ child = "radio"
62
+ elsif $~[0] == "^"
63
+ parent = "checkboxes"
64
+ child = "checkbox"
65
+ else
66
+ parent = "select"
67
+ child = "option"
68
+ end
69
+ <<-HTML
70
+ <cf:#{parent} label="#{label(k)}">
71
+ #{v.map { |c| tag(child, c)}.join("\n")}
72
+ </cf:#{parent}>
73
+ HTML
74
+ #Multiple hidden fields...
75
+ elsif(k =~ /^_/)
76
+ v.map { |c| tag("hidden", c)}.join("\n")
77
+ end
78
+ else
79
+ if(k =~ /^#/)
80
+ tag("textarea", k, {:default => v})
81
+ elsif(k =~ /^_/)
82
+ tag("hidden", k, {:value => v})
83
+ elsif(k =~ /^\^/)
84
+ tag("checkbox", k, {:default => v})
85
+ else
86
+ tag("text", k, {:default => v})
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
data/lib/cfml/parser.rb CHANGED
@@ -1,37 +1,77 @@
1
1
  module CFML
2
2
  class Parser
3
+ attr_reader :doc, :cftags, :tags, :errors
4
+
3
5
  def initialize(content, opts = {})
4
6
  @opts = opts
5
- @doc = Nokogiri::XML("<root xmlns:cf='http://crowdflower.com'>#{content}</root>")
7
+ @doc = Parser.parse(content)
6
8
  @cftags = @doc.xpath("//cf:*[not(ancestor::cf:*)]")
9
+ @tags = @cftags.map do |t|
10
+ tag_class(t.name).new(t, @opts)
11
+ end
12
+ end
13
+
14
+ def self.parse(content)
15
+ Nokogiri::XML("<root xmlns:cf='http://crowdflower.com'>#{content}</root>")
7
16
  end
8
17
 
9
18
  def convert
10
- @cftags.each do |t|
11
- t.replace(tag_class(t.name).new(t, @opts).convert)
19
+ @cftags.each_with_index do |t,i|
20
+ t.replace(@tags[i].convert)
12
21
  end
13
22
  @doc
14
23
  end
15
24
 
25
+ def fields
26
+ @fields = {}
27
+ @tags.each do |g|
28
+ agg = g.attrs["aggregation"]
29
+ @fields[g.name] = agg.to_s if agg
30
+ end
31
+ @fields
32
+ end
33
+
16
34
  def golds
17
35
  return @golds if @golds
18
36
  @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
37
+ @tags.each do |g|
38
+ gold = g.gold?
39
+ next unless gold
40
+ val = (gold.attributes["gold"] || gold.attributes["src"]).to_s
41
+ val = "#{g.name}_gold" if val =~ /^(true|\s*)$/
42
+ @golds[g.name] = val
26
43
  ["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
44
+ if a = gold.attributes[attrs]
45
+ @golds["_#{val}_#{attrs}"] = attrs == "regex" ? [a.to_s, gold.attributes["flags"].to_s] : a.to_s
29
46
  end
30
47
  end
31
48
  end
32
49
  @golds
33
50
  end
34
51
 
52
+ def valid?
53
+ @errors = []
54
+ @tags.select {|t| t.validate? && t.name =~ /^\s*$/ }.each do |t|
55
+ @errors << [t.to_s.split("\n")[0], "does not have a label or name specified."]
56
+ end
57
+ dupes = @tags.select do |tag|
58
+ tag.validate? && @tags.select {|t| t.name == tag.name}.length > 1
59
+ end
60
+ (dupes[1..-1] || []).each do |t|
61
+ @errors << [t.to_s.split("\n")[0], "has a duplicated name, please specify a unique name attribute."]
62
+ end
63
+ @tags.each do |t|
64
+ next unless t.children
65
+ dupes = t.children.select do |child|
66
+ t.children.select {|c| c.value == child.value}.length > 1
67
+ end
68
+ (dupes[1..-1] || []).each do |c|
69
+ @errors << [c.to_s, "a child of #{t.to_s.split("\n")[0]} has a duplicated value, please specify a unique value attribute."]
70
+ end
71
+ end
72
+ @errors.length == 0
73
+ end
74
+
35
75
  def wrap(content)
36
76
  @opts[:no_wrap] ? content : "<div class=\"cfml #{@opts[:prefix]}\">#{content}</div>"
37
77
  end
data/lib/cfml/tag.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  module CFML
2
2
  class Tag
3
+ attr_reader :attrs, :tag, :data
4
+
3
5
  def initialize(cfml, opts = {})
4
- @cfml = cfml
6
+ @cfml = cfml.is_a?(String) ? Parser.parse(cfml).root.children.first : cfml
5
7
  @attrs = @cfml.attributes#Hash[*cfml.attributes.map {|k,v| [k.intern,v]}.flatten]
6
8
  @tag = @cfml.name
7
9
  @opts = opts
@@ -11,6 +13,10 @@ module CFML
11
13
  @opts[:prefix] ? "#{@opts[:prefix]}[#{name}]" : "#{name}"
12
14
  end
13
15
 
16
+ def gold?
17
+ @attrs["gold"] ? @cfml : @cfml.at("./cf:gold")
18
+ end
19
+
14
20
  def name
15
21
  (@attrs["name"] || @attrs["label"]).to_s.downcase.gsub(/\s/,"_").gsub(/\W/,"")
16
22
  end
@@ -20,6 +26,10 @@ module CFML
20
26
  "#{@tag} #{extras}".strip
21
27
  end
22
28
 
29
+ def children
30
+ false
31
+ end
32
+
23
33
  def classes
24
34
  @classes ||= [name] << validations << @attrs["class"].to_s.split(/ /)
25
35
  @classes.uniq.reject {|c| c.length == 0 }.join(" ").strip
@@ -34,24 +44,37 @@ module CFML
34
44
  wrapper(@parsed)
35
45
  end
36
46
 
47
+ def to_s
48
+ @cfml.to_s
49
+ end
50
+
37
51
  def label(label, tag = "label")
52
+ label ||= @attrs["name"].to_s.capitalize
38
53
  required = " <span class=\"required\">(required)</span>" if validations.include?("required")
39
- "<#{tag}>#{label}#{required}</#{tag}>" if label
54
+ "<#{tag}>#{label}#{required}</#{tag}>" if label.to_s != ""
40
55
  end
41
56
 
42
57
  def legend(label)
43
58
  label(label, "legend") if label
44
59
  end
45
60
 
61
+ def to_liquid
62
+ to_html
63
+ end
64
+
46
65
  def validations
47
66
  @validations ||= @attrs["validations"].to_s.split(/ /).map {|v| "validates-#{v}"}
48
67
  end
49
68
 
50
69
  def instructions
51
- @instructions ||= @attrs["instructions"] || (@cfml.at("instructions") ? @cfml.at("instructions").inner_html : nil)
70
+ @instructions ||= @attrs["instructions"] || (@cfml.at("./cf:instructions") ? @cfml.at("./cf:instructions").inner_html : nil)
52
71
  @instructions ? "<p class=\"instructions\">#{@instructions}</p>" : nil
53
72
  end
54
73
 
74
+ def validate?
75
+ true
76
+ end
77
+
55
78
  def wrapper(parsed, tag = "div")
56
79
  #Deal with a label only wrapper... kinda jank
57
80
  if tag == "label" && instructions
@@ -62,13 +85,17 @@ module CFML
62
85
  "<#{tag} class=\"#{wrapper_classes}\">#{parsed}#{instructions}</#{tag}>"
63
86
  end
64
87
 
88
+ def value
89
+ @attrs["value"].to_s
90
+ end
91
+
65
92
  def data
66
93
  (@opts[:data] || {}).merge({
67
94
  "name" => prefix(name),
68
95
  "label" => label(@attrs["label"]),
69
96
  "legend" => legend(@attrs["label"]),
70
97
  "classes" => classes,
71
- "value" => @attrs["value"].to_s
98
+ "value" => value
72
99
  })
73
100
  end
74
101
  end
@@ -3,7 +3,7 @@ module CFML
3
3
  class Checkbox < Tag
4
4
  Template = <<-HTML.freeze
5
5
  {{default}}
6
- <label><input name="{{name}}" type="checkbox" value="{{value}}" class="{{classes}}"/> {{label}}</label>
6
+ <label><input name="{{name}}" type="checkbox" value="{{value}}" class="{{classes}}" {{checked}}/> {{label}}</label>
7
7
  HTML
8
8
 
9
9
  def prefix(name)
@@ -21,10 +21,13 @@ module CFML
21
21
  def data
22
22
  default = ""
23
23
  if @attrs["default"]
24
- default = Parser.new("<cf:hidden name=\"#{name}\" value=\"#{@attrs["default"]}\"/>", @opts.merge(:no_wrap => true)).to_html
24
+ default = Hidden.new("<cf:hidden name=\"#{name}\" value=\"#{@attrs["default"]}\"/>", @opts).to_html
25
25
  end
26
- value = @attrs["value"] || (grouped? ? @attrs["label"] : "true")
27
- super.merge({"value" => value.to_s, "default" => default, "label" => @attrs["label"].to_s})
26
+ super.merge({
27
+ "value" => (@attrs["value"] || (grouped? ? @attrs["label"] : "true")).to_s,
28
+ "default" => default,
29
+ "checked" => @attrs["checked"] ? "checked=\"checked\"" : "",
30
+ "label" => @attrs["label"].to_s})
28
31
  end
29
32
  end
30
33
  end
@@ -9,14 +9,14 @@ module CFML
9
9
  HTML
10
10
 
11
11
  def data
12
- super.merge({"checkboxes" => checkboxes})
12
+ super.merge({"checkboxes" => children})
13
13
  end
14
14
 
15
- def checkboxes
15
+ def children
16
16
  @cfml.xpath("cf:checkbox").map do |c|
17
17
  c["name"] ||= name
18
18
  c["validations"] ||= @attrs["validations"].to_s
19
- Checkbox.new(c, @opts).to_html
19
+ Checkbox.new(c, @opts)
20
20
  end
21
21
  end
22
22
 
@@ -6,6 +6,10 @@ module CFML
6
6
  {{content}}
7
7
  HTML
8
8
 
9
+ def validate?
10
+ false
11
+ end
12
+
9
13
  def data
10
14
  super.merge({"content" => Parser.new(@cfml.inner_html, @opts.merge(:no_wrap => true)).to_html})
11
15
  end
@@ -0,0 +1,25 @@
1
+ module CFML
2
+ module Tags
3
+ class Option < Tag
4
+ Template = <<-HTML.freeze
5
+ <option {{value}} {{selected}}>{{label}}</option>
6
+ HTML
7
+
8
+ def wrapper(parsed)
9
+ parsed
10
+ end
11
+
12
+ def value
13
+ (@attrs["value"] || @attrs["label"]).to_s
14
+ end
15
+
16
+ def data
17
+ super.merge({
18
+ "value" => @attrs["value"] ? "value=\"#{@attrs["value"]}\"" : "",
19
+ "selected" => @attrs["selected"] ? "selected=\"selected\"" : "",
20
+ "label" => (@attrs["label"] || @cfml.inner_html).to_s
21
+ })
22
+ end
23
+ end
24
+ end
25
+ end
@@ -2,7 +2,7 @@ module CFML
2
2
  module Tags
3
3
  class Radio < Tag
4
4
  Template = <<-HTML.freeze
5
- <label><input name="{{name}}" type="radio" value="{{value}}" class="{{classes}}"/> {{label}}</label>
5
+ <label><input name="{{name}}" type="radio" value="{{value}}" class="{{classes}}" {{checked}}/> {{label}}</label>
6
6
  HTML
7
7
 
8
8
  #Radios should always be grouped, but for consistency with checkboxes, we check
@@ -15,8 +15,11 @@ module CFML
15
15
  end
16
16
 
17
17
  def data
18
- value = @attrs["value"] || @attrs["label"]
19
- super.merge({"value" => value.to_s, "label" => @attrs["label"].to_s})
18
+ super.merge({
19
+ "value" => (@attrs["value"] || @attrs["label"]).to_s,
20
+ "checked" => @attrs["checked"] ? "checked=\"checked\"" : "",
21
+ "label" => @attrs["label"].to_s
22
+ })
20
23
  end
21
24
  end
22
25
  end
@@ -9,14 +9,14 @@ module CFML
9
9
  HTML
10
10
 
11
11
  def data
12
- super.merge({"radios" => radios})
12
+ super.merge({"radios" => children})
13
13
  end
14
14
 
15
- def radios
15
+ def children
16
16
  @cfml.xpath("cf:radio").map do |c|
17
17
  c["name"] ||= name
18
18
  c["validations"] ||= @attrs["validations"].to_s
19
- Radio.new(c, @opts).to_html
19
+ Radio.new(c, @opts)
20
20
  end
21
21
  end
22
22
 
@@ -8,8 +8,15 @@ module CFML
8
8
  </select>
9
9
  HTML
10
10
 
11
+ def children
12
+ default = @cfml["default"] ? [Option.new("<cf:option value=\"\">#{@cfml["default"]}</cf:option>", @opts)] : []
13
+ default + @cfml.xpath("cf:option").map do |c|
14
+ Option.new(c, @opts)
15
+ end
16
+ end
17
+
11
18
  def data
12
- super.merge({"options" => @cfml.xpath("option").map {|c| c.to_xhtml}})
19
+ super.merge({"options" => children})
13
20
  end
14
21
  end
15
22
  end
@@ -5,6 +5,10 @@ module CFML
5
5
  {{content}}
6
6
  HTML
7
7
 
8
+ def validate?
9
+ false
10
+ end
11
+
8
12
  def wrapper_classes
9
13
  super + " unknown"
10
14
  end
data/spec/complex_spec.rb CHANGED
@@ -43,7 +43,7 @@ describe "CFML Complex" do
43
43
  <label>
44
44
  <input name="u12345[rad][]" class="rad" type="checkbox" value="Sure?">
45
45
  Sure?</label>
46
-
46
+ <p class=\"instructions\">This <i>is</i> cool</p>
47
47
  </fieldset>
48
48
  <input type="hidden" name="u12345[secret]" value="cool" class="secret" />
49
49
  </div>
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/cfml/converters/jsawesome")
3
+
4
+ describe "JSAwesome Converter" do
5
+ it "converts" do
6
+ json = "[[
7
+ [\"text_field\", \"default value\"],
8
+ [\"#text_area\", \"\"],
9
+ [\"single_select\", [\"boo\", \"~yah\"]],
10
+ [\"^check\", [\"One|totally_rad\", [\"two\",true], \"three\"]],
11
+ [\"*radio\", [\"a\", \"b\", [\"c\", true]]],
12
+ [\"_hidden\",\"hot\"],
13
+ [[\"^single_check\"],[\"^Edge|edge_case\", false]]
14
+ ],
15
+ {\"text_field\": \"JSAwesome\",
16
+ \"text_area\": {
17
+ \"required\":true,
18
+ \"validation\": [\"\\d+\", \"Field must contain atleast one digit\"],
19
+ \"label\": \"Input some text with atleast one digit\"
20
+ },
21
+ \"single_select\": {
22
+ \"required\":true
23
+ },
24
+ \"gold\": {
25
+ \"_awesome_gold_strict\": true,
26
+ \"text_field\": \"awesome_gold\",
27
+ \"_awesome_gold_regex\": [\"\\\\.asdf\\\\.\", \"i\"]
28
+ }}]"
29
+ @c = Converters::JSAwesome.new(json)
30
+ #puts Parser.escape(@c.convert)
31
+ @c.convert.should sorta_match(<<-HTML)
32
+ <cf:text label="JSAwesome" default="default value">
33
+ <gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
34
+ </cf:text>
35
+ <cf:textarea label="Input some text with atleast one digit" required="true" />
36
+ <cf:select label="Single select">
37
+ <cf:option label="Boo" />
38
+ <cf:option label="Yah" />
39
+ </cf:select>
40
+ <cf:checkboxes label="Check">
41
+ <cf:checkbox label="One" name="totally_rad" />
42
+ <cf:checkbox label="Two" checked="true" />
43
+ <cf:checkbox label="Three" />
44
+ </cf:checkboxes>
45
+ <cf:radios label="Radio">
46
+ <cf:radio label="A" />
47
+ <cf:radio label="B" />
48
+ <cf:radio label="C" checked="true" />
49
+ </cf:radios>
50
+ <cf:hidden label="Hidden" value="hot" />
51
+ <cf:checkbox label="Single check" />
52
+ <cf:checkbox label="Edge" name="edge_case" default="false" />
53
+ HTML
54
+ end
55
+ end
@@ -1,12 +1,11 @@
1
1
  <h1>This is my name</h1>
2
2
  <p>This is a description about me</p>
3
- <cf:select label="Awesome" validations="required" instructions="Just be cool about it">
3
+ <cf:select label="Awesome" validations="required" default="Choose an option" instructions="Just be cool about it">
4
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>
5
+ <cf:option label="Awesome" />
6
+ <cf:option label="Cool" />
7
+ <cf:option label="Rad" />
8
+ <cf:option label="Neat" />
10
9
  </cf:select>
11
10
  <cf:text label="Opinion" validations="minLength:30" class="large" />
12
11
  <cf:text label="Email" validations="required email" />
@@ -0,0 +1,10 @@
1
+ <cf:select label="Awesome">
2
+ <cf:gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
3
+ <cf:option label="Awesome" />
4
+ <cf:option label="Rad" />
5
+ <cf:option label="Rad" />
6
+ <cf:option label="Neat" />
7
+ </cf:select>
8
+ <cf:text label="Opinion" validations="minLength:30" class="large" />
9
+ <cf:text label="Awesome" validations="required email" />
10
+ <cf:checkbox label="" value="yes" gold="true" />
@@ -1,23 +1,31 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "CFML Gold" do
4
- it "should give me da gold" do
4
+ it "should give me da gold & fields" do
5
5
  cfml = <<-HTML
6
- <cf:checkboxes label="Checkboxes">
6
+ <cf:checkboxes label="Checkboxes" aggregation="all">
7
7
  <cf:gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
8
8
  <cf:checkbox label="Wanna do it?" />
9
9
  <cf:checkbox label="Sure?" />
10
10
  </cf:checkboxes>
11
- <cf:text name="cool" gold="true" />
11
+ <cf:checkbox label="No way">
12
+ <cf:gold />
13
+ </cf:checkbox>
14
+ <cf:text name="cool" gold="true" aggregation="agg" />
12
15
  <cf:textarea name="sweet" gold="sweetness" />
13
16
  HTML
14
17
  @p = Parser.new(cfml, :prefix => "u12345")
15
18
  @p.golds.should == {
16
19
  "_awesome_gold_strict" => "true",
17
- "sweet" => "sweetness",
20
+ "sweet" => "sweetness",
21
+ "no_way" => "no_way_gold",
18
22
  "checkboxes" => "awesome_gold",
19
23
  "_awesome_gold_regex" => ["\\.asdf\\.", "i"],
20
24
  "cool" => "cool_gold"
21
25
  }
26
+ @p.fields.should == {
27
+ "checkboxes"=>"all",
28
+ "cool"=>"agg"
29
+ }
22
30
  end
23
31
  end
@@ -61,6 +61,23 @@ describe "CFML Radio" do
61
61
  HTML
62
62
  end
63
63
 
64
+ it "should render gold" do
65
+ cfml = <<-HTML
66
+ <cf:checkbox label="Rad">
67
+ <cf:gold src="rad_gold"/>
68
+ </cf:checkbox>
69
+ HTML
70
+ @p = Parser.new(cfml, :prefix => "u12345")
71
+ @p.tags[0].should be_gold
72
+ @p.to_html.should sorta_match(<<-HTML)
73
+ <div class="cfml u12345">
74
+ <div class="checkbox">
75
+ <label><input type="checkbox" value="true" name="u12345[rad]" class="rad"/> Rad</label>
76
+ </div>
77
+ </div>
78
+ HTML
79
+ end
80
+
64
81
  it "should render checkbox nested" do
65
82
  cfml = <<-HTML
66
83
  <div class="rando">
@@ -5,7 +5,8 @@ describe "CFML Checkboxes" do
5
5
  cfml = <<-HTML
6
6
  <cf:checkboxes label="Cool checkboxes">
7
7
  <cf:checkbox label="Wanna do it?"/>
8
- <cf:checkbox label="Sure?">
8
+ <cf:checkbox label="Sure?"/>
9
+ <cf:checkbox label="Not really..." value="nope" checked="true"/>
9
10
  </cf:checkboxes>
10
11
  HTML
11
12
  @p = Parser.new(cfml, :prefix => "u12345")
@@ -19,6 +20,9 @@ describe "CFML Checkboxes" do
19
20
  <label>
20
21
  <input type="checkbox" value="Sure?" name="u12345[cool_checkboxes][]" class="cool_checkboxes"/> Sure?
21
22
  </label>
23
+ <label>
24
+ <input type="checkbox" value="nope" checked="checked" name="u12345[cool_checkboxes][]" class="cool_checkboxes"/> Sure?
25
+ </label>
22
26
  </fieldset>
23
27
  </div>
24
28
  HTML
@@ -4,9 +4,9 @@ describe "CFML Select" do
4
4
  it "should render basic select" do
5
5
  cfml = <<-HTML
6
6
  <cf:select label="Basic">
7
- <option>One</option>
8
- <option>Two</option>
9
- <option>Three</option>
7
+ <cf:option>One</option>
8
+ <cf:option>Two</option>
9
+ <cf:option>Three</option>
10
10
  </cf:select>
11
11
  HTML
12
12
  @p = Parser.new(cfml, :prefix => "u12345")
@@ -23,4 +23,28 @@ describe "CFML Select" do
23
23
  </div>
24
24
  HTML
25
25
  end
26
+
27
+ it "should render complex select" do
28
+ cfml = <<-HTML
29
+ <cf:select label="Basic" default="Choose an option">
30
+ <cf:option value="oney">One</option>
31
+ <cf:option selected="true">Two</option>
32
+ <cf:option label="Awesome"/>
33
+ </cf:select>
34
+ HTML
35
+ @p = Parser.new(cfml, :prefix => "u12345")
36
+ @p.to_html.should sorta_match(<<-HTML)
37
+ <div class="cfml u12345">
38
+ <div class="select">
39
+ <label>Basic</label>
40
+ <select name="u12345[basic]" class="basic">
41
+ <option value="">Choose an option</option>
42
+ <option value="oney">One</option>
43
+ <option selected="selected">Two</option>
44
+ <option>Awesome</option>
45
+ </select>
46
+ </div>
47
+ </div>
48
+ HTML
49
+ end
26
50
  end
@@ -19,7 +19,7 @@ describe "CFML Text" do
19
19
  it "should render text with classes and instructions tag" do
20
20
  cfml = <<-HTML
21
21
  <cf:text label="Coolio" class="small">
22
- <instructions>Just be <b>cool</b> bro!</instructions>
22
+ <cf:instructions>Just be <b>cool</b> bro!</cf:instructions>
23
23
  </cf:text>
24
24
  HTML
25
25
  @p = Parser.new(cfml, :prefix => "u12345")
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "CFML Validation" do
4
+ it "adds errors if invalid" do
5
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/invalid.cfml"), {:prefix => "u12345"})
6
+ @p.should_not be_valid
7
+ @p.errors.should == [
8
+ ["<cf:checkbox label=\"\" value=\"yes\" gold=\"true\"/>", "does not have a label or name specified."],
9
+ ["<cf:text label=\"Awesome\" validations=\"required email\"/>", "has a duplicated name, please specify a unique name attribute."],
10
+ ["<cf:option label=\"Rad\"/>", "a child of <cf:select label=\"Awesome\"> has a duplicated value, please specify a unique value attribute."]
11
+ ]
12
+ end
13
+
14
+ it "oks valid cfml" do
15
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/complex.cfml"), {:prefix => "u12345"})
16
+ @p.valid?
17
+ @p.should be_valid
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dolores-cfml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Van Pelt
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-16 00:00:00 -07:00
12
+ date: 2009-08-19 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: 1.3.3
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
- name: httparty
36
+ name: json_pure
37
37
  type: :runtime
38
38
  version_requirement:
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -60,6 +60,7 @@ files:
60
60
  - VERSION
61
61
  - cfml.gemspec
62
62
  - lib/cfml.rb
63
+ - lib/cfml/converters/jsawesome.rb
63
64
  - lib/cfml/liquid_filters.rb
64
65
  - lib/cfml/parser.rb
65
66
  - lib/cfml/tag.rb
@@ -67,6 +68,7 @@ files:
67
68
  - lib/cfml/tags/checkboxes.rb
68
69
  - lib/cfml/tags/group.rb
69
70
  - lib/cfml/tags/hidden.rb
71
+ - lib/cfml/tags/option.rb
70
72
  - lib/cfml/tags/radio.rb
71
73
  - lib/cfml/tags/radios.rb
72
74
  - lib/cfml/tags/ratings.rb
@@ -75,20 +77,21 @@ files:
75
77
  - lib/cfml/tags/textarea.rb
76
78
  - lib/cfml/tags/unknown.rb
77
79
  - spec/complex_spec.rb
80
+ - spec/converters/jsawesome_spec.rb
78
81
  - spec/fixtures/complex.cfml
79
- - spec/gold_spec.rb
82
+ - spec/fixtures/invalid.cfml
83
+ - spec/meta_spec.rb
80
84
  - spec/sorta_match.rb
81
85
  - spec/spec_helper.rb
82
86
  - spec/tags/checkbox_spec.rb
83
87
  - spec/tags/checkboxes_spec.rb
84
88
  - spec/tags/group_spec.rb
85
89
  - spec/tags/hidden_spec.rb
86
- - spec/tags/radio_spec.rb
87
- - spec/tags/radios_spec.rb
88
90
  - spec/tags/select_spec.rb
89
91
  - spec/tags/text_spec.rb
90
92
  - spec/tags/textarea_spec.rb
91
93
  - spec/tags/unknown_spec.rb
94
+ - spec/validation_spec.rb
92
95
  has_rdoc: false
93
96
  homepage: http://github.com/dolores/cfml
94
97
  licenses:
@@ -118,16 +121,16 @@ specification_version: 3
118
121
  summary: CFML is Crowd Flower Markup Language
119
122
  test_files:
120
123
  - spec/complex_spec.rb
121
- - spec/gold_spec.rb
124
+ - spec/converters/jsawesome_spec.rb
125
+ - spec/meta_spec.rb
122
126
  - spec/sorta_match.rb
123
127
  - spec/spec_helper.rb
124
128
  - spec/tags/checkbox_spec.rb
125
129
  - spec/tags/checkboxes_spec.rb
126
130
  - spec/tags/group_spec.rb
127
131
  - spec/tags/hidden_spec.rb
128
- - spec/tags/radio_spec.rb
129
- - spec/tags/radios_spec.rb
130
132
  - spec/tags/select_spec.rb
131
133
  - spec/tags/text_spec.rb
132
134
  - spec/tags/textarea_spec.rb
133
135
  - spec/tags/unknown_spec.rb
136
+ - spec/validation_spec.rb
@@ -1,18 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe "CFML Radio" do
4
- #Doesn't make sense on its own but tested here anyway...
5
- it "should render basic radio" do
6
- cfml = <<-HTML
7
- <cf:radio label="Rad"/>
8
- HTML
9
- @p = Parser.new(cfml, :prefix => "u12345")
10
- @p.to_html.should sorta_match(<<-HTML)
11
- <div class="cfml u12345">
12
- <div class="radio">
13
- <label><input type="radio" value="Rad" name="u12345[rad]" class="rad"/> Rad</label>
14
- </div>
15
- </div>
16
- HTML
17
- end
18
- end
@@ -1,26 +0,0 @@
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>
17
- <input type="radio" value="Wanna do it?" name="u12345[cool_radios]" class="cool_radios"/> Wanna do it?
18
- </label>
19
- <label>
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