dolores-cfml 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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