cml 1.4.2

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.
Files changed (61) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +56 -0
  6. data/VERSION +1 -0
  7. data/cml.gemspec +129 -0
  8. data/lib/cml/converters/jsawesome.rb +103 -0
  9. data/lib/cml/gold.rb +33 -0
  10. data/lib/cml/liquid_filters.rb +13 -0
  11. data/lib/cml/parser.rb +160 -0
  12. data/lib/cml/tag.rb +308 -0
  13. data/lib/cml/tags/checkbox.rb +77 -0
  14. data/lib/cml/tags/checkboxes.rb +38 -0
  15. data/lib/cml/tags/group.rb +25 -0
  16. data/lib/cml/tags/hidden.rb +17 -0
  17. data/lib/cml/tags/iterate.rb +86 -0
  18. data/lib/cml/tags/meta.rb +12 -0
  19. data/lib/cml/tags/multiple_text.rb +11 -0
  20. data/lib/cml/tags/option.rb +29 -0
  21. data/lib/cml/tags/radio.rb +48 -0
  22. data/lib/cml/tags/radios.rb +36 -0
  23. data/lib/cml/tags/ratings.rb +61 -0
  24. data/lib/cml/tags/search.rb +97 -0
  25. data/lib/cml/tags/select.rb +50 -0
  26. data/lib/cml/tags/text.rb +45 -0
  27. data/lib/cml/tags/textarea.rb +45 -0
  28. data/lib/cml/tags/thumb.rb +25 -0
  29. data/lib/cml/tags/unknown.rb +21 -0
  30. data/lib/cml.rb +15 -0
  31. data/spec/complex_spec.rb +127 -0
  32. data/spec/converters/jsawesome_spec.rb +75 -0
  33. data/spec/fixtures/complex.cml +23 -0
  34. data/spec/fixtures/html.cml +34 -0
  35. data/spec/fixtures/invalid.cml +10 -0
  36. data/spec/fixtures/script-style.cml +12 -0
  37. data/spec/fixtures/segfault.cml +1 -0
  38. data/spec/gold_spec.rb +29 -0
  39. data/spec/meta_spec.rb +47 -0
  40. data/spec/normalize_spec.rb +214 -0
  41. data/spec/show_data_spec.rb +308 -0
  42. data/spec/sorta_match.rb +41 -0
  43. data/spec/spec_helper.rb +26 -0
  44. data/spec/tags/checkbox_spec.rb +155 -0
  45. data/spec/tags/checkboxes_spec.rb +171 -0
  46. data/spec/tags/group_spec.rb +108 -0
  47. data/spec/tags/hidden_spec.rb +17 -0
  48. data/spec/tags/iterate_spec.rb +259 -0
  49. data/spec/tags/meta_spec.rb +14 -0
  50. data/spec/tags/multiple_text_spec.rb +40 -0
  51. data/spec/tags/radios_spec.rb +81 -0
  52. data/spec/tags/ratings_spec.rb +79 -0
  53. data/spec/tags/search_spec.rb +132 -0
  54. data/spec/tags/select_spec.rb +76 -0
  55. data/spec/tags/tag_spec.rb +93 -0
  56. data/spec/tags/text_spec.rb +66 -0
  57. data/spec/tags/textarea_spec.rb +58 -0
  58. data/spec/tags/thumb_spec.rb +20 -0
  59. data/spec/tags/unknown_spec.rb +19 -0
  60. data/spec/validation_spec.rb +62 -0
  61. metadata +182 -0
@@ -0,0 +1,61 @@
1
+ module CML
2
+ module Tags
3
+ class Ratings < Tag
4
+ Template = <<-HTML.freeze
5
+ {{legend}}
6
+ <div class="cml_row">
7
+ <table>
8
+ <thead>
9
+ <tr>
10
+ <th></th>
11
+ {% for rating in ratings limit:10 %}
12
+ <th class="{{gold_classes[forloop.index0]}}">{{rating.raw_label}}</th>
13
+ {% endfor %}
14
+ <th></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <tr>
19
+ <td>{{from}}</td>
20
+ {% for rating in ratings limit:10 %}
21
+ <td class="{{gold_classes[forloop.index0]}}">{{rating}}</td>
22
+ {% endfor %}
23
+ <td>{{to}}</td>
24
+ </tr>
25
+ </tbody>
26
+ </table>
27
+ </div>
28
+ HTML
29
+
30
+ def data
31
+ super.merge({
32
+ "ratings" => ratings,
33
+ "from" => @attrs["from"].to_s,
34
+ "to" => @attrs["to"].to_s,
35
+ "gold_classes" => gold_classes
36
+ })
37
+ end
38
+
39
+ def gold_classes
40
+ ratings.map {|rating| rating.gold_class }
41
+ end
42
+
43
+ def ratings
44
+ if @cml.xpath(".//cml:rating").empty?
45
+ max = @attrs["points"] ? @attrs["points"].to_s.to_i : 4
46
+ tags = Parser.parse((1..max).map do |r|
47
+ "<cml:rating label='#{r}' />"
48
+ end.join("\n")).xpath("root/cml:rating")
49
+ else
50
+ tags = @cml.xpath(".//cml:rating")
51
+ end
52
+ tags.map do |c|
53
+ c["validates"] ||= @attrs["validates"].to_s
54
+ c["name"] ||= name
55
+ (@opts[:normalize] ? Checkbox : Radio).new(c, @opts.merge(:bare => true))
56
+ end
57
+ end
58
+ memoize :ratings
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,97 @@
1
+ module CML
2
+ module Tags
3
+ class Search < Tag
4
+ DEFAULT_CSE = "002077591359011991755:yygrm1glnxq"
5
+ BareTemplate = <<-HTML.freeze
6
+ <div class="cml_row search" data-engine="{{engine}}" data-cse="{{custom_search_engine}}" >
7
+ <input name="{{prefixed_search_terms_name}}" type="text" value="{{search_terms_value}}" class="{{search_terms_classes}}"/> <input type="button" value="Search" class="no_validate" />
8
+ </div>
9
+ <div class="cml_row results"></div>
10
+ {{inputs}}
11
+ HTML
12
+
13
+ Template = <<-HTML.freeze
14
+ {{label}}
15
+ #{BareTemplate}
16
+ HTML
17
+
18
+ InputTemplate = <<-HTML.freeze
19
+ <div class="cml_row selected_result">
20
+ <input name="{{name}}" type="text" class="{{classes}}" value="{{search_result_value}}" />
21
+ </div>
22
+ HTML
23
+
24
+ def is_field?
25
+ !(@attrs["field"] && @attrs["field"].to_s == "false")
26
+ end
27
+
28
+ def search_terms_classes
29
+ (@attrs["default"] ? "default " : "") + engine + " no_validate"
30
+ end
31
+
32
+ def engine
33
+ (@attrs["engine"] ? @attrs["engine"].to_s : nil) || "googlecse"
34
+ end
35
+
36
+ def custom_search_engine
37
+ engine.to_s == "googlecse" ? (@attrs["cse"] || DEFAULT_CSE).to_s : ""
38
+ end
39
+
40
+ def search_terms_name
41
+ name(true, "search_terms")
42
+ end
43
+
44
+ def prefixed_search_terms_name
45
+ prefix(search_terms_name)
46
+ end
47
+
48
+ def search_terms_value
49
+ ((@opts[:data] || {})[search_terms_name] || @attrs["default"]).to_s
50
+ end
51
+
52
+ def search_result_value
53
+ (@attrs["value"] || (@opts[:data] || {})[name] || "").to_s
54
+ end
55
+
56
+ def data
57
+ super.merge({
58
+ "search_terms_classes" => search_terms_classes,
59
+ "engine" => engine,
60
+ "search_terms_name" => search_terms_name,
61
+ "prefixed_search_terms_name" => prefixed_search_terms_name,
62
+ "search_terms_value" => search_terms_value,
63
+ "search_result_value" => search_result_value,
64
+ "custom_search_engine" => custom_search_engine
65
+ })
66
+ end
67
+
68
+ def to_html
69
+ if is_field?
70
+ if @opts[:normalize]
71
+ seeds = Array((@opts[:data] || {})[name])
72
+ seeds << nil if seeds.length == 0
73
+
74
+ inputs = seeds.map do |input|
75
+ Liquid::Template.parse(InputTemplate).render(data.merge({
76
+ "search_result_value" => input.to_s,
77
+ "classes" => classes+(input ? " cml_gold_loaded" : "")
78
+ }))
79
+ end.join("\n")
80
+ else
81
+ inputs = Liquid::Template.parse(InputTemplate).render(data)
82
+ end
83
+ else
84
+ inputs = ""
85
+ end
86
+
87
+ wrapper(Liquid::Template.parse(Template).render(data.merge({
88
+ "inputs" => inputs
89
+ }), [LiquidFilters]))
90
+ end
91
+
92
+ def wrapper_classes
93
+ super + " text"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,50 @@
1
+ module CML
2
+ module Tags
3
+ class Select < Tag
4
+ Template = <<-HTML.freeze
5
+ {{label}}
6
+ <div class="cml_row"><select name="{{name}}" class="{{classes}}">
7
+ {{content}}
8
+ </select></div>
9
+ HTML
10
+
11
+ #Auto magically prepend a default option if required
12
+ def default
13
+ default = [Option.new("<cml:option value=\"\">#{@cml["default"]}</cml:option>", @opts)] if @cml["default"]
14
+ default ||= [Option.new("<cml:option value=\"\">Select one</cml:option>", @opts)] if validations.include?('validates-required')
15
+ default || []
16
+ end
17
+
18
+ def children
19
+ default + @cml.xpath(".//cml:option").map do |c|
20
+ Option.new(c, @opts)
21
+ end
22
+ end
23
+ memoize :children
24
+
25
+ def data
26
+ super.merge({"content" => content})
27
+ end
28
+
29
+ def content
30
+ cloned= @cml.dup
31
+ c = children
32
+ # Add the default...
33
+ d = default
34
+ # Preloaded data
35
+ preload = preloaded_data
36
+
37
+ cloned.add_child(d[0].cml) if d.length > 0
38
+ cloned.xpath(".//cml:*[not(self::cml:option)]").remove
39
+ cloned.xpath(".//cml:option").each_with_index do |r,i|
40
+ r.namespace = nil
41
+ c[i].selected = true if preload && preload == c[i].value
42
+ r.replace(c[i].convert)
43
+ end
44
+ #Remove the surrounding tag
45
+ cloned.to_xhtml.gsub(/<\/?cml:select[^>]*?>|<\/?>/,'')
46
+ end
47
+ memoize :content
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ module CML
2
+ module Tags
3
+ class Text < Tag
4
+ BareTemplate = <<-HTML.freeze
5
+ <div class="cml_row"><input name="{{name}}" type="text" value="{{value}}" class="{{classes}}"/></div>
6
+ HTML
7
+
8
+ Template = <<-HTML.freeze
9
+ {{label}}
10
+ #{BareTemplate}
11
+ HTML
12
+
13
+ def classes
14
+ super + (@attrs["default"] ? " default" : "")
15
+ end
16
+
17
+ def value
18
+ (@attrs["value"] || @attrs["default"]).to_s
19
+ end
20
+
21
+ def to_html
22
+ if @opts[:normalize]
23
+ #Making some text boxes
24
+ seeds = Array(@opts[:data][@opts[:parser].golds[name(false)]] || @opts[:data][name(false)])
25
+ seeds = @opts[:iteration] ? [seeds[@opts[:iteration]]].flatten : seeds
26
+ seeds << nil if seeds.length == 0
27
+ inputs = seeds.map do |input|
28
+ Liquid::Template.parse(BareTemplate).render(data.merge({
29
+ "value" => CGI.escapeHTML(input.to_s),
30
+ "classes" => classes+(input ? " cml_gold_loaded" : "")
31
+ }))
32
+ end.join("\n")
33
+ wrapper("#{label}\n#{inputs}")
34
+ elsif preload = preloaded_data
35
+ wrapper(Liquid::Template.parse(Template).render(data.merge({
36
+ "value" => CGI.escapeHTML(preload.to_s),
37
+ "classes" => classes
38
+ })))
39
+ else
40
+ wrapper(Liquid::Template.parse(Template).render(data, [LiquidFilters]))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ module CML
2
+ module Tags
3
+ class Textarea < Tag
4
+ BareTemplate = <<-HTML.freeze
5
+ <div class="cml_row"><textarea name="{{name}}" class="{{classes}}">{{value}}</textarea></div>
6
+ HTML
7
+
8
+ Template = <<-HTML.freeze
9
+ {{label}}
10
+ #{BareTemplate}
11
+ HTML
12
+
13
+ def classes
14
+ super + (@attrs["default"] ? " default" : "")
15
+ end
16
+
17
+ def value
18
+ (@attrs["value"] || @attrs["default"]).to_s
19
+ end
20
+
21
+ def to_html
22
+ if @opts[:normalize]
23
+ #Making some text boxes
24
+ seeds = Array(@opts[:data][@opts[:parser].golds[name(false)]] || @opts[:data][name(false)])
25
+ seeds = @opts[:iteration] ? [seeds[@opts[:iteration]]].flatten : seeds
26
+ seeds << nil if seeds.length == 0
27
+ inputs = seeds.map do |input|
28
+ Liquid::Template.parse(BareTemplate).render(data.merge({
29
+ "value" => input.to_s,
30
+ "classes" => classes+(input ? " cml_gold_loaded" : "")
31
+ }))
32
+ end.join("\n")
33
+ wrapper("#{label}\n#{inputs}")
34
+ elsif preload = preloaded_data
35
+ wrapper(Liquid::Template.parse(Template).render(data.merge({
36
+ "value" => preload.to_s,
37
+ "classes" => classes
38
+ })))
39
+ else
40
+ wrapper(Liquid::Template.parse(Template).render(data, [LiquidFilters]))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ module CML
2
+ module Tags
3
+ class Thumb < Tag
4
+ Template = <<-HTML.freeze
5
+ <img src="http://nodenailer.crowdflower.com/?{{query_string}}" />
6
+ HTML
7
+
8
+ def validate?
9
+ false
10
+ end
11
+
12
+ def query_string
13
+ params = {}
14
+ [["w","width"], ["h", "height"], ["method", "method"], ["url", "src"]].each do |param, atr|
15
+ params[param] = CGI.escape(@attrs[atr].to_s) if @attrs[atr]
16
+ end
17
+ params.map {|v| v.join("=") }.join("&")
18
+ end
19
+
20
+ def data
21
+ super.merge("query_string" => query_string)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module CML
2
+ module Tags
3
+ class Unknown < Tag
4
+ Template = <<-HTML.freeze
5
+ {{content}}
6
+ HTML
7
+
8
+ def validate?
9
+ false
10
+ end
11
+
12
+ def wrapper_classes
13
+ super + " unknown"
14
+ end
15
+
16
+ def data
17
+ super.merge({"content" => @cml.inner_html})
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/cml.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+ require 'json'
4
+ require 'liquid'
5
+
6
+ require 'cml/parser'
7
+ require 'cml/liquid_filters'
8
+ require 'cml/tag'
9
+ require 'cml/gold'
10
+ CML::TagClasses = {}
11
+ Dir[File.dirname(__FILE__) + '/cml/tags/*.rb'].each do |dir|
12
+ require dir
13
+ camelcase = dir.split(/\//).last.sub(/\.rb/,"")
14
+ CML::TagClasses[camelcase] = CML::Tags.const_get(camelcase.gsub(/(^|_)(.)/) { $2.upcase }.intern)
15
+ end
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "CML Complex" do
4
+ it "parses" do
5
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/complex.cml"), {:prefix => "u12345"})
6
+ #puts Parser.escape(@p.to_html).gsub(/\n/,"<br/>")
7
+ @p.to_html.should sorta_match(<<-HTML)
8
+ <div class="cml" id="u12345">
9
+ <h1>This is my name</h1>
10
+ <p>This is a description about me</p>
11
+ <div class="select cml_field">
12
+ <label class="legend">Awesome</label>
13
+ <div class="cml_row"><select name="u12345[awesome]" class="awesome validates-required">
14
+ <option value="">Choose an option</option>
15
+ <option>Awesome</option>
16
+ <option>Cool</option>
17
+ <option>Rad</option>
18
+ <option>Neat</option>
19
+ </select></div>
20
+ <p class="instructions">Just be cool about it</p>
21
+ </div>
22
+ <div class="text cml_field large">
23
+ <label class="legend">Opinion</label>
24
+ <div class="cml_row"><input name="u12345[opinion]" class="opinion validates-minLength:30 large" type="text" value=""></div>
25
+ </div>
26
+ <div class="text cml_field">
27
+ <label class="legend">Email</label>
28
+ <div class="cml_row"><input name="u12345[email]" class="email validates-required validates-email" type="text" value=""></div>
29
+ </div>
30
+ <div class="rad">
31
+ <div class="checkbox cml_field">
32
+ <div class="cml_row"><label class="">
33
+ <input name="u12345[you_sure]" class="you_sure" type="checkbox" value="yes"> You sure?</label></div>
34
+ </div>
35
+ </div>
36
+ <div class="group logic-only-if:awesome" style="color:red">
37
+
38
+ <div class="checkboxes cml_field">
39
+ <h2 class="legend">Cool checkboxes</h2>
40
+
41
+ <div class="cml_row"><label class="">
42
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Wanna do it?">
43
+ Wanna do it?</label></div>
44
+
45
+ <div class="cml_row"><label class="">
46
+ <input name="u12345[rad][]" class="rad" type="checkbox" value="Sure?">
47
+ Sure?</label></div>
48
+ <p class=\"instructions\">This <i>is</i> cool</p>
49
+ </div>
50
+ <div class="text cml_field">
51
+ <label class="legend">nice</label>
52
+ <div class="cml_row"><input name="u12345[nice]" class="nice" type="text" value=""></div>
53
+ </div>
54
+ <div class="hidden cml_field">
55
+ <input type="hidden" name="u12345[secret]" value="cool" class="secret" />
56
+ </div>
57
+ </div>
58
+ </div>
59
+ HTML
60
+ end
61
+
62
+ it "doesn't segfault" do
63
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/segfault.cml"), {:prefix => "u12345"})
64
+ @p.to_html
65
+ end
66
+
67
+ it "script / styles" do
68
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/script-style.cml"), {:prefix => "u12345"})
69
+ @p.to_html.should sorta_match(<<-HTML)
70
+ <div class="cml" id="u12345"><script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.8&amp;appid=Knx84fDV34H2VnhVU1DoD7chT1wjJ2r36uf4dZW7Vc5si9sqQRAYU_g8fo7zV.wF"> </script>
71
+ <script src="/javascripts/upload.js" type="text/javascript" charset="utf-8"> </script>
72
+
73
+ <script type="text/javascript">
74
+ var cool ='cool\'s';
75
+ </script>
76
+ <style type="text/css">
77
+ a { font: awesome;}
78
+ </style>
79
+ </div>
80
+ HTML
81
+ end
82
+
83
+ it "parses scripts and styles" do
84
+ @p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/html.cml"), {:prefix => "u12345"})
85
+ @p.to_html.length.should > 900
86
+ #puts Parser.escape(@p.to_html).gsub(/\n/,"<br/>")
87
+
88
+ @p.to_html.should sorta_match(<<-HTML)
89
+ <div class="cml" id="u12345"><hr />
90
+ <a target="_blank" class="toggle" href="#">toggle series description</a>
91
+ <div style="display:none">
92
+ {{seriesdescription | textilize}}
93
+ </div>
94
+ <br style="clear:both" />
95
+ {% for image in image_name %}
96
+ <div class="wrap">
97
+ <img src="{{url}}/{{image}}" style="width:110px" /></div>
98
+ {% endfor %}
99
+ <br style="clear:both" />
100
+ <div class="text cml_field"><label class="legend">Cool dude</label>
101
+ <div class="cml_row"><input name="u12345[cool_dude]" class="cool_dude" value="" type="text" /></div>
102
+ </div>
103
+ <style media="screen" type="text/css">
104
+ div.wrap {
105
+ position:relative;
106
+ float:left;
107
+ margin:5px 5px 0 0;
108
+ }
109
+ </style>
110
+ <script type="text/javascript" charset="utf-8">
111
+ // query1 = 'compare'
112
+ // query2 = 'base'
113
+ if (1 < 1) {
114
+ var x = 0;
115
+ }
116
+ var ranking = [null]
117
+ //Some really long comment that doesn't get borked by libxml... don't you dare insert a new line.
118
+ //Why are my && disapearing?
119
+ if(ranking && !false) {
120
+ //Preserve my curlies
121
+ var unit_id = {{_unit_id}};
122
+ var rad = "even inside strings {{awesome}}"
123
+ }
124
+ </script></div>
125
+ HTML
126
+ end
127
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/cml/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|moo\", \"~yah\"]],
10
+ [\"^check\", [\"One|totally_rad\", [\"two\",true], \"three\"]],
11
+ [\"*radio\", [\"a\", \"b|D\", [\"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
+ \"rando\": \"so_cool\",
26
+ \"check\": \"check_gold\",
27
+ \"_awesome_gold_strict\": true,
28
+ \"text_field\": \"awesome_gold\",
29
+ \"_awesome_gold_regex\": [\"\\\\.asdf\\\\.\", \"i\"]
30
+ }}]"
31
+ @c = Converters::JSAwesome.new(json)
32
+ @c.convert.should sorta_match(<<-HTML)
33
+ <cml:text name="text_field" label="JSAwesome" default="default value">
34
+ <gold src="awesome_gold" flags="i" regex="\\.asdf\\." strict="true" />
35
+ </cml:text>
36
+ <cml:textarea name="text_area" validates="required" label="Input some text with atleast one digit" />
37
+ <cml:select label="Single select" validates="required">
38
+ <cml:option label="Boo" value="moo" />
39
+ <cml:option label="Yah" />
40
+ </cml:select>
41
+ <cml:checkboxes label="Check" gold="true">
42
+ <cml:checkbox label="One" value="totally_rad" />
43
+ <cml:checkbox label="Two" checked="true" />
44
+ <cml:checkbox label="Three" />
45
+ </cml:checkboxes>
46
+ <cml:radios label="Radio">
47
+ <cml:radio label="A" />
48
+ <cml:radio label="B" value="D" />
49
+ <cml:radio label="C" checked="true" />
50
+ </cml:radios>
51
+ <cml:hidden label="Hidden" value="hot" />
52
+ <cml:checkbox label="Single check" />
53
+ <cml:checkbox label="Edge" name="edge_case" default="false" />
54
+ <cml:meta name="rando" gold="so_cool"/>
55
+ HTML
56
+ end
57
+
58
+ it "Gets all complex" do
59
+ json = '[[["#w_forth_st",""],[["city",""],["stateprovince",""]],[["zippostal_code",""],["country",""]],["#extra_address_information",""],["^any_issues",["No address could be found even after checking the url or searching the web|searching_the_web"]]],{"w_forth_st":{"label":"Street address (eg. 35 W Forth St.)","required":true},"city":{"required":true},"stateprovince":{"label":"State\/Province"},"any_issues":{"label":"Any issues?"},"country":{"required":true},"zippostal_code":{"validation":["^[\\d-]*$","Postal code must only be numbers and dashes"],"label":"Zip\/Postal Code"},"extra_address_information":{"label":"Any extra company or address information?"}}]'
60
+ @c = Converters::JSAwesome.new(json)
61
+ @c.convert.should sorta_match(<<-HTML)
62
+ <cml:textarea label="Street address (eg. 35 W Forth St.)" name="w_forth_st" validates="required" />
63
+ <cml:text label="City" validates="required" />
64
+ <cml:text label="State/Province" name="stateprovince" />
65
+ HTML
66
+
67
+ #For some reason can't get this spec to pass... not worth my time right now.
68
+ #<cml:text label="Zip/Postal Code" name="zippostal_code" />
69
+ #<cml:text label="Country" validates="required" />
70
+ #<cml:textarea label="Any extra company or address information?" name="extra_address_information"/>
71
+ #<cml:checkboxes label="Any issues?" name="any_issues">
72
+ # <cml:checkbox label="No address could be found even after checking the url or searching the web" name="searching_the_web" />
73
+ #</cml:checkboxes>
74
+ end
75
+ end
@@ -0,0 +1,23 @@
1
+ <h1>This is my name</h1>
2
+ <p>This is a description about me</p>
3
+ <cml:select label="Awesome" validates="required" default="Choose an option" instructions="Just be cool about it">
4
+ <cml:gold src="awesome_gold" regex="\\.asdf\\." flags="i" no_escape="true" strict="true" />
5
+ <cml:option label="Awesome" />
6
+ <cml:option label="Cool" />
7
+ <cml:option label="Rad" />
8
+ <cml:option label="Neat" />
9
+ </cml:select>
10
+ <cml:text label="Opinion" validates="minLength:30" class="large" />
11
+ <cml:text label="Email" validates="required email" />
12
+ <div class="rad">
13
+ <cml:checkbox label="You sure?" value="yes" gold="true" />
14
+ </div>
15
+ <cml:group only-if="awesome" style="color:red">
16
+ <cml:checkboxes label="Cool checkboxes" name="rad">
17
+ <cml:instructions>This <i>is</i> great</cml:instructions>
18
+ <cml:checkbox label="Wanna do it?"/>
19
+ <cml:checkbox label="Sure?"/>
20
+ </cml:checkboxes>
21
+ <cml:text label="nice"/>
22
+ <cml:hidden name="secret" value="cool"/>
23
+ </cml:group>
@@ -0,0 +1,34 @@
1
+ <hr>
2
+ <a target="_blank" class="toggle" href="#">toggle series description</a>
3
+ <div style="display:none">
4
+ {{seriesdescription | textilize}}
5
+ </div>
6
+ <br style="clear:both">
7
+ {% for image in image_name %}
8
+ <div class="wrap">
9
+ <img src="{{url}}/{{image}}" style="width:110px"></div>
10
+ {% endfor %}
11
+ <br style="clear:both">
12
+ <cml:text label="Cool dude"/>
13
+ <style media="screen" type="text/css">
14
+ div.wrap {
15
+ position:relative;
16
+ float:left;
17
+ margin:5px 5px 0 0;
18
+ }
19
+ </style>
20
+ <script type="text/javascript" charset="utf-8">
21
+ // query1 = 'compare'
22
+ // query2 = 'base'
23
+ if (1 < 1) {
24
+ var x = 0;
25
+ }
26
+ var ranking = [null]
27
+ //Some really long comment that doesn't get borked by libxml... don't you dare insert a new line.
28
+ //Why are my && disapearing?
29
+ if(ranking && !false) {
30
+ //Preserve my curlies
31
+ var unit_id = {{_unit_id}};
32
+ var rad = "even inside strings {{awesome}}"
33
+ }
34
+ </script>
@@ -0,0 +1,10 @@
1
+ <cml:select label="Awesome">
2
+ <cml:gold src="awesome_gold" regex="\\.asdf\\." flags="i" no_escape="true" strict="true" />
3
+ <cml:option label="Awesome" />
4
+ <cml:option label="Rad" />
5
+ <cml:option label="Rad" />
6
+ <cml:option label="Neat" />
7
+ </cml:select>
8
+ <cml:text label="Opinion" validates="minLength:30" class="large" />
9
+ <cml:text label="Awesome" validates="required email" />
10
+ <cml:checkbox label="" value="yes" gold="true" />
@@ -0,0 +1,12 @@
1
+ <script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.8&amp;appid=Knx84fDV34H2VnhVU1DoD7chT1wjJ2r36uf4dZW7Vc5si9sqQRAYU_g8fo7zV.wF"></script>
2
+ <script src="/javascripts/upload.js" type="text/javascript" charset="utf-8"></script>
3
+
4
+
5
+ <script type="text/javascript">
6
+ var cool = 'cool\'s'
7
+ </script>
8
+ <style type="text/css">
9
+ .invisible{
10
+ a { font: awesome;}
11
+ }
12
+ </style>