dryml 1.3.3 → 1.4.0.pre2

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 (44) hide show
  1. data/Gemfile +6 -0
  2. data/README +2 -0
  3. data/Rakefile +2 -1
  4. data/VERSION +1 -1
  5. data/cucumber.yml +9 -0
  6. data/dryml.gemspec +4 -2
  7. data/features/cookbook/01_simple_page_templates.feature +44 -0
  8. data/features/cookbook/02_defining_simple_tags.feature +375 -0
  9. data/features/cookbook/03_implicit_context.feature +229 -0
  10. data/features/cookbook/04_tag_attributes.feature +120 -0
  11. data/features/cookbook/05_repeated_and_optional_content.feature +241 -0
  12. data/features/cookbook/06_pseudo_parameters.feature +191 -0
  13. data/features/cookbook/07_nested_parameters.feature +147 -0
  14. data/features/cookbook/08_customizing_tags.feature +307 -0
  15. data/features/cookbook/09_aliasing_tags.feature +50 -0
  16. data/features/cookbook/10_polymorphic_tags.feature +168 -0
  17. data/features/cookbook/11_wrapping_content.feature +57 -0
  18. data/features/cookbook/12_local_and_scoped_variables.feature +102 -0
  19. data/features/doctest_examples.feature +187 -0
  20. data/features/merge_params.feature +36 -0
  21. data/features/replace_parameters.feature +21 -0
  22. data/features/static_tags.feature +91 -0
  23. data/features/step_definitions/contexts.rb +25 -0
  24. data/features/step_definitions/dom_comparison.rb +10 -0
  25. data/features/step_definitions/rendering.rb +21 -0
  26. data/features/support/env.rb +32 -0
  27. data/features/support/models/author.rb +18 -0
  28. data/features/support/models/blog_post.rb +37 -0
  29. data/features/support/models/discussion.rb +15 -0
  30. data/features/support/models/post.rb +12 -0
  31. data/features/support/strip_formatter.rb +14 -0
  32. data/lib/dryml/dryml_builder.rb +4 -14
  33. data/lib/dryml/dryml_doc.rb +6 -1
  34. data/lib/dryml/helper.rb +17 -1
  35. data/lib/dryml/part_context.rb +12 -15
  36. data/lib/dryml/railtie/template_handler.rb +1 -3
  37. data/lib/dryml/railtie.rb +1 -0
  38. data/lib/dryml/taglib.rb +24 -30
  39. data/lib/dryml/template.rb +32 -86
  40. data/lib/dryml/template_environment.rb +40 -17
  41. data/lib/dryml.rb +22 -11
  42. data/taglibs/core.dryml +18 -12
  43. data/taglibs/dryml.dryml +3 -0
  44. metadata +97 -56
@@ -0,0 +1,168 @@
1
+ Feature: Polymorphic tags
2
+
3
+ Scenario: Using a polymorphic tag
4
+ Given a file named "example_taglib.dryml" with:
5
+ """
6
+ <def tag="card" polymorphic>
7
+ <div class="card" merge-attrs>
8
+ <h3 param="heading"><%= h this.to_s %></h3>
9
+ <div param="body"></div>
10
+ </div>
11
+ </def>
12
+
13
+ <def tag="card" for="BlogPost">
14
+ <card merge>
15
+ <heading: param><a href="#{this.url}"><%= this.title %></a></heading:>
16
+ <body: param><do:author><%= this.name %></do></body:>
17
+ </card>
18
+ </def>
19
+ """
20
+ And a file named "example.dryml" with:
21
+ """
22
+ <card />
23
+ """
24
+ When I include the taglib "example_taglib"
25
+ And the current context is a blog post
26
+ And I render "example.dryml"
27
+ Then the output DOM should be:
28
+ """
29
+ <div class="card">
30
+ <h3 class="heading"><a href="/blog_posts/1">A Blog Post</a></h3>
31
+ <div class="body">Nobody</div>
32
+ </div>
33
+ """
34
+
35
+ Scenario: Using a polymorphic tag for a subclass
36
+ Given a file named "example_taglib.dryml" with:
37
+ """
38
+ <def tag="card" polymorphic>
39
+ <div class="card" merge-attrs>
40
+ <h3 param="heading"><%= h this.to_s %></h3>
41
+ <div param="body"></div>
42
+ </div>
43
+ </def>
44
+
45
+ <def tag="card" for="BlogPost">
46
+ <card merge>
47
+ <heading: param><a href="#{this.url}"><%= this.title %></a></heading:>
48
+ <body: param><do:author><%= this.name %></do></body:>
49
+ </card>
50
+ </def>
51
+ """
52
+ And a file named "example.dryml" with:
53
+ """
54
+ <card />
55
+ """
56
+ When I include the taglib "example_taglib"
57
+ And the current context is a special blog post
58
+ And I render "example.dryml"
59
+ Then the output DOM should be:
60
+ """
61
+ <div class="card">
62
+ <h3 class="heading"><a href="/special_blog_posts/1">A Blog Post</a></h3>
63
+ <div class="body">Nobody</div>
64
+ </div>
65
+ """
66
+
67
+
68
+ Scenario: Using a polymorphic tag for a subclass with a customized tag (fails)
69
+ issue 779 / https://github.com/tablatom/hobo/commit/aceb7afc384287b19e59ebb94020a2c509143c76
70
+ Given a file named "example_taglib.dryml" with:
71
+ """
72
+ <def tag="card" polymorphic>
73
+ <div class="card" merge-attrs>
74
+ <h3 param="heading"><%= h this.to_s %></h3>
75
+ <div param="body"></div>
76
+ </div>
77
+ </def>
78
+
79
+ <def tag="card" for="BlogPost">
80
+ <card merge>
81
+ <heading: param><a href="#{this.url}"><%= this.title %></a></heading:>
82
+ <body: param><do:author><%= this.name %></do></body:>
83
+ </card>
84
+ </def>
85
+
86
+ <def tag="card" for="SpecialBlogPost">
87
+ <card class="special" for-type="BlogPost" merge/>
88
+ </def>
89
+ """
90
+ And a file named "example.dryml" with:
91
+ """
92
+ <card class="more_special" />
93
+ """
94
+ When I include the taglib "example_taglib"
95
+ And the current context is a special blog post
96
+ And I render "example.dryml"
97
+ Then the output DOM should be:
98
+ """
99
+ <div class="card special more_special">
100
+ <h3 class="heading"><a href="/special_blog_posts/1">A Blog Post</a></h3>
101
+ <div class="body">Nobody</div>
102
+ </div>
103
+ """
104
+
105
+ Scenario: using call-tag to call a polymorphic tag
106
+ Given a file named "example_taglib.dryml" with:
107
+ """
108
+ <def tag="card" polymorphic>
109
+ <div class="card" merge-attrs>
110
+ <h3 param="heading"><%= h this.to_s %></h3>
111
+ <div param="body"></div>
112
+ </div>
113
+ </def>
114
+
115
+ <def tag="card" for="BlogPost">
116
+ <card merge>
117
+ <heading: param><a href="#{this.url}"><%= this.title %></a></heading:>
118
+ <body: param><do:author><%= this.name %></do></body:>
119
+ </card>
120
+ </def>
121
+ """
122
+ And a file named "example.dryml" with:
123
+ """
124
+ <call-tag tag="card" />
125
+ """
126
+ When I include the taglib "example_taglib"
127
+ And the current context is a blog post
128
+ And I render "example.dryml"
129
+ Then the output DOM should be:
130
+ """
131
+ <div class="card">
132
+ <h3 class="heading"><a href="/blog_posts/1">A Blog Post</a></h3>
133
+ <div class="body">Nobody</div>
134
+ </div>
135
+ """
136
+
137
+ Scenario: using call-tag to call a polymorphic tag with an explicit type (fails)
138
+ Given a file named "example_taglib.dryml" with:
139
+ """
140
+ <def tag="card" polymorphic>
141
+ <div class="card" merge-attrs>
142
+ <h3 param="heading"><%= h this.to_s %></h3>
143
+ <div param="body"></div>
144
+ </div>
145
+ </def>
146
+
147
+ <def tag="card" for="BlogPost">
148
+ <card merge>
149
+ <heading: param><a href="#{this.url}"><%= this.title %></a></heading:>
150
+ <body: param><do:author><%= this.name %></do></body:>
151
+ </card>
152
+ </def>
153
+ """
154
+ And a file named "example.dryml" with:
155
+ """
156
+ <call-tag tag="card" for-type="BlogPost" />
157
+ """
158
+ When I include the taglib "example_taglib"
159
+ And the current context is a special blog post
160
+ And I render "example.dryml"
161
+ Then the output DOM should be:
162
+ """
163
+ <div class="card">
164
+ <h3 class="heading"><a href="/special_blog_posts/1">A Blog Post</a></h3>
165
+ <div class="body">Nobody</div>
166
+ </div>
167
+ """
168
+
@@ -0,0 +1,57 @@
1
+ Feature: Wrapping content
2
+
3
+ Background:
4
+ Given a file named "example_taglib.dryml" with:
5
+ """
6
+ <def tag="card">
7
+ <div class="card" merge-attrs>
8
+ <h3 param="heading"><%= this.name %></h3>
9
+ <div param="body"></div>
10
+ </div>
11
+ </def>
12
+ """
13
+
14
+ Scenario: wrapping content inside a parameter
15
+ Given a file named "example.dryml" with:
16
+ """
17
+ <card>
18
+ <heading:><a href="#{this.url}"><param-content for="heading"/></a></heading:>
19
+ </card>
20
+ """
21
+ When I include the taglib "example_taglib"
22
+ And the current context is a blog post
23
+ And I render "example.dryml"
24
+ Then the output DOM should be:
25
+ """
26
+ <div class="card">
27
+ <h3 class="heading"><a href="/blog_posts/1">A Blog Post</a></h3>
28
+ <div class="body"></div>
29
+ </div>
30
+ """
31
+
32
+ Scenario: wrapping content outside a parameter
33
+ Given a file named "example.dryml" with:
34
+ """
35
+ <card>
36
+ <heading: replace>
37
+ <div class="header">
38
+ <heading: restore/>
39
+ <p>ID: <%= this.id %></p>
40
+ </div>
41
+ </heading:>
42
+ </card>
43
+ """
44
+ When I include the taglib "example_taglib"
45
+ And the current context is a blog post
46
+ And I render "example.dryml"
47
+ Then the output DOM should be:
48
+ """
49
+ <div class="card">
50
+ <div class="header">
51
+ <h3 class="heading">A Blog Post</h3>
52
+ <p>ID: 1</p>
53
+ </div>
54
+ <div class="body"></div>
55
+ </div>
56
+ """
57
+
@@ -0,0 +1,102 @@
1
+ Feature: Local and scoped variables
2
+
3
+ Scenario: local variables
4
+ Given a file named "example.dryml" with:
5
+ """
6
+ <% erb_local = 'Hello World' %>
7
+ <set dryml-local="Hello World" />
8
+ <p><%= erb_local %></p>
9
+ <p><%= dryml_local %></p>
10
+ """
11
+ When I render "example.dryml"
12
+ Then the output DOM should be:
13
+ """
14
+ <p>Hello World</p>
15
+ <p>Hello World</p>
16
+ """
17
+
18
+ Scenario: scoped variables
19
+ Given a file named "example_taglib.dryml" with:
20
+ """
21
+ <def tag="show-the-var">
22
+ <p><%= scope.the_var %></p>
23
+ </def>
24
+ """
25
+ And a file named "example.dryml" with:
26
+ """
27
+ <show-the-var />
28
+ <set-scoped the-var="foo">
29
+ <show-the-var />
30
+ <set-scoped the-var="bar">
31
+ <show-the-var />
32
+ </set-scoped>
33
+ <show-the-var />
34
+ </set-scoped>
35
+ <show-the-var />
36
+ """
37
+ When I include the taglib "example_taglib"
38
+ And I render "example.dryml"
39
+ Then the output DOM should be:
40
+ """
41
+ <p></p>
42
+ <p>foo</p>
43
+ <p>bar</p>
44
+ <p>foo</p>
45
+ <p></p>
46
+ """
47
+
48
+ Scenario: collecting content in a scoped var
49
+ Given a file named "example_taglib.dryml" with:
50
+ """
51
+ <def tag="tab-item" attrs="id, name">
52
+ <% scope.tabs_content << [id, parameters.default] %>
53
+ <li><a href="##{id}"><%= name %></a></li>
54
+ </def>
55
+
56
+ <def tag="tabs">
57
+ <set-scoped tabs-content="&[]">
58
+ <ul class="tabs">
59
+ <do param="default" />
60
+ </ul>
61
+ <repeat with="&scope.tabs_content">
62
+ <div id="#{this[0]}">
63
+ <%= this[1] %>
64
+ </div>
65
+ </repeat>
66
+ </set-scoped>
67
+ </def>
68
+ """
69
+ And a file named "example.dryml" with:
70
+ """
71
+ <tabs>
72
+ <tab-item id="foo" name="First Item">
73
+ <p>Foo Foo Foo</p>
74
+ </tab-item>
75
+ <tab-item id="bar" name="Second Item">
76
+ <p>Bar Bar Bar</p>
77
+ </tab-item>
78
+ <tab-item id="baz" name="Third Item">
79
+ <p>Baz Baz Baz</p>
80
+ </tab-item>
81
+ </tabs>
82
+ """
83
+ When I include the taglib "example_taglib"
84
+ And I render "example.dryml"
85
+ Then the output DOM should be:
86
+ """
87
+ <ul class="tabs">
88
+ <li><a href="#foo">First Item</a></li>
89
+ <li><a href="#bar">Second Item</a></li>
90
+ <li><a href="#baz">Third Item</a></li>
91
+ </ul>
92
+ <div id="foo">
93
+ <p>Foo Foo Foo</p>
94
+ </div>
95
+ <div id="bar">
96
+ <p>Bar Bar Bar</p>
97
+ </div>
98
+ <div id="baz">
99
+ <p>Baz Baz Baz</p>
100
+ </div>
101
+ """
102
+
@@ -0,0 +1,187 @@
1
+ Feature: Doctest examples
2
+
3
+ Scenario: plain text
4
+ Given a file named "doctest.dryml" with:
5
+ """
6
+ hi
7
+ """
8
+ When I render "doctest.dryml"
9
+ Then the output DOM should be:
10
+ """
11
+ hi
12
+ """
13
+
14
+ Scenario: single ERB output tag
15
+ Given a file named "doctest.dryml" with:
16
+ """
17
+ <%= this %>
18
+ """
19
+ And the local variable "this" has the value "hello"
20
+ When I render "doctest.dryml"
21
+ Then the output DOM should be:
22
+ """
23
+ hello
24
+ """
25
+
26
+ Scenario: if-else
27
+ Given a file named "doctest.dryml" with:
28
+ """
29
+ <if test="&true">
30
+ Hi
31
+ </if>
32
+ <else>
33
+ Bye
34
+ </else>
35
+ """
36
+ When I render "doctest.dryml"
37
+ Then the output DOM should be:
38
+ """
39
+ Hi
40
+ """
41
+
42
+ Scenario: repeating tags
43
+ Given a file named "doctest.dryml" with:
44
+ """
45
+ <repeat with="&[1,2,3]">
46
+ <span><%= this %></span>
47
+ </repeat>
48
+ """
49
+ When I render "doctest.dryml"
50
+ Then the output DOM should be:
51
+ """
52
+ <span>1</span>
53
+ <span>2</span>
54
+ <span>3</span>
55
+ """
56
+
57
+ Scenario: defining a tag with a default parameter
58
+ Given a file named "doctest.dryml" with:
59
+ """
60
+ <def tag="myp">
61
+ <p param="default"/>
62
+ </def>
63
+ <myp>Hi</myp>
64
+ """
65
+ When I render "doctest.dryml"
66
+ Then the output DOM should be:
67
+ """
68
+ <p>
69
+ Hi
70
+ </p>
71
+ """
72
+
73
+ Scenario: calling a tag using call-tag
74
+ Given a file named "doctest.dryml" with:
75
+ """
76
+ <def tag="myp">
77
+ <p param="default" />
78
+ </def>
79
+ <call-tag tag="myp">
80
+ Hi
81
+ </call-tag>
82
+ """
83
+ When I render "doctest.dryml"
84
+ Then the output DOM should be:
85
+ """
86
+ <p>
87
+ Hi
88
+ </p>
89
+ """
90
+
91
+ Scenario: wrapping content with a custom tag
92
+ Given a file named "doctest.dryml" with:
93
+ """
94
+ <def tag="myp">
95
+ <p param="default" />
96
+ </def>
97
+ <wrap tag="myp" when="&true">
98
+ img
99
+ </wrap>
100
+ """
101
+ When I render "doctest.dryml"
102
+ Then the output DOM should be:
103
+ """
104
+ <p>
105
+ img
106
+ </p>
107
+ """
108
+
109
+ Scenario: extending a tag (fails)
110
+ Given a file named "doctest_taglib.dryml" with:
111
+ """
112
+ <def tag="myp">
113
+ <p param="default" />
114
+ </def>
115
+ """
116
+ And a file named "doctest_extend.dryml" with:
117
+ """
118
+ <extend tag="myp">
119
+ <old-myp merge>
120
+ <default: replace>Hello <default restore /></default:>
121
+ </old-myp>
122
+ </extend>
123
+ """
124
+ And a file named "doctest.dryml" with:
125
+ """
126
+ <myp>New World</myp>
127
+ """
128
+ When I include the taglib "doctest_taglib"
129
+ And I include the taglib "doctest_extend"
130
+ When I render "doctest.dryml"
131
+ Then the output DOM should be:
132
+ """
133
+ <p>Hello New World</p>
134
+ """
135
+
136
+ Scenario: extending a tag with a non-default param (fails)
137
+ Given a file named "doctest_taglib.dryml" with:
138
+ """
139
+ <def tag="myp">
140
+ <p param="foo" />
141
+ </def>
142
+ """
143
+ And a file named "doctest_extend.dryml" with:
144
+ """
145
+ <extend tag="myp">
146
+ <old-myp merge>
147
+ <foo:>
148
+ Hello <param-content for="foo" />
149
+ </foo:>
150
+ </old-myp>
151
+ </extend>
152
+ """
153
+ And a file named "doctest.dryml" with:
154
+ """
155
+ <myp><foo:>New World</foo:></myp>
156
+ """
157
+ When I include the taglib "doctest_taglib"
158
+ And I include the taglib "doctest_extend"
159
+ When I render "doctest.dryml"
160
+ Then the output DOM should be:
161
+ """
162
+ <p class="foo">Hello New World</p>
163
+ """
164
+
165
+ Scenario: param-content-restore from an output context
166
+ Given a file named "doctest_taglib.dryml" with:
167
+ """
168
+ <def tag="myp">
169
+ <p param="foo">World</p>
170
+ </def>
171
+ """
172
+ And a file named "doctest.dryml" with:
173
+ """
174
+ <myp>
175
+ <foo:>
176
+ Hello <param-content for="foo" />
177
+ </foo:>
178
+ </myp>
179
+ """
180
+ When I include the taglib "doctest_taglib"
181
+ When I render "doctest.dryml"
182
+ Then the output DOM should be:
183
+ """
184
+ <p class="foo">Hello World</p>
185
+ """
186
+
187
+
@@ -0,0 +1,36 @@
1
+ Feature: merge-params
2
+
3
+ Scenario: merge-params with a param name
4
+ Given a file named "doctest_taglib.dryml" with:
5
+ """
6
+ <def tag="myp">
7
+ <p param="foo">This is foo</p>
8
+ <p param="bar">This is bar</p>
9
+ </def>
10
+ """
11
+ And a file named "doctest_extend.dryml" with:
12
+ """
13
+ <extend tag="myp">
14
+ <old-myp merge-params="bar" />
15
+ </extend>
16
+ """
17
+ And a file named "doctest.dryml" with:
18
+ """
19
+ <myp>
20
+ <foo:>
21
+ New stuff
22
+ </foo:>
23
+ <bar:>
24
+ Brand-new bar
25
+ </bar:>
26
+ </myp>
27
+ """
28
+ When I include the taglib "doctest_taglib"
29
+ And I include the taglib "doctest_extend"
30
+ When I render "doctest.dryml"
31
+ Then the output DOM should be:
32
+ """
33
+ <p class="foo">This is foo</p>
34
+ <p class="bar">Brand-new bar</p>
35
+ """
36
+
@@ -0,0 +1,21 @@
1
+ Feature: replace parameters
2
+
3
+ Scenario: simple replace parameter
4
+ Given a file named "doctest_taglib.dryml" with:
5
+ """
6
+ <def tag="myp">
7
+ <p param="foo" />
8
+ </def>
9
+ """
10
+ And a file named "doctest.dryml" with:
11
+ """
12
+ <myp><foo: replace>Hello World</foo:></myp>
13
+ """
14
+ When I include the taglib "doctest_taglib"
15
+ When I render "doctest.dryml"
16
+ Then the output DOM should be:
17
+ """
18
+ Hello World
19
+ """
20
+
21
+
@@ -0,0 +1,91 @@
1
+ Feature: Static tags render correctly
2
+
3
+ Scenario: Static tag with static attributes
4
+
5
+ Given a file named "static_tag.dryml" with:
6
+ """
7
+ <div class="foo">
8
+ FOO
9
+ </div>
10
+ """
11
+ When I render "static_tag.dryml"
12
+ Then the output DOM should be:
13
+ """
14
+ <div class="foo">
15
+ FOO
16
+ </div>
17
+ """
18
+
19
+ Scenario: Static tag with an interpolated attribute
20
+
21
+ Given a file named "static_tag.dryml" with:
22
+ """
23
+ <% some_var = 'foo' %>
24
+ <div class="#{some_var}">
25
+ FOO
26
+ </div>
27
+ """
28
+ When I render "static_tag.dryml"
29
+ Then the output DOM should be:
30
+ """
31
+ <div class="foo">
32
+ FOO
33
+ </div>
34
+ """
35
+
36
+ Scenario: define tags that are used in Rapid
37
+ Given a file named "static_tag.dryml" with:
38
+ """
39
+ <html lang="en">
40
+ <head>
41
+ <link rel="stylesheet" href="foo" />
42
+ </head>
43
+ <body>
44
+ <header>
45
+ <a href="something" target="_blank">Link text</a>
46
+ </header>
47
+ <section class="content">
48
+ <table width="100%">
49
+ <tr>
50
+ <td>FOO</td>
51
+ <td>BAR</td>
52
+ </tr>
53
+ </table>
54
+ </section>
55
+ <footer>
56
+ <form action="wut">
57
+ <input type="text" name="some_field" />
58
+ <submit value="Submit" />
59
+ </form>
60
+ </footer>
61
+ </body>
62
+ </html>
63
+ """
64
+ When I render "static_tag.dryml"
65
+ Then the output DOM should be:
66
+ """
67
+ <html lang="en">
68
+ <head>
69
+ <link rel="stylesheet" href="foo" />
70
+ </head>
71
+ <body>
72
+ <header>
73
+ <a href="something" target="_blank">Link text</a>
74
+ </header>
75
+ <section class="content">
76
+ <table width="100%">
77
+ <tr>
78
+ <td>FOO</td>
79
+ <td>BAR</td>
80
+ </tr>
81
+ </table>
82
+ </section>
83
+ <footer>
84
+ <form action="wut">
85
+ <input type="text" name="some_field" />
86
+ <submit value="Submit" />
87
+ </form>
88
+ </footer>
89
+ </body>
90
+ </html>
91
+ """
@@ -0,0 +1,25 @@
1
+ When /^the current context is a blog post$/ do
2
+ @locals ||= {}
3
+ @locals[:this] = BlogPost.new
4
+ end
5
+
6
+ When /^the current context is a special blog post$/ do
7
+ @locals ||= {}
8
+ @locals[:this] = SpecialBlogPost.new
9
+ end
10
+
11
+ When /^the current context is an array$/ do
12
+ @locals ||= {}
13
+ @locals[:this] = %w(foo bar baz blam mumble)
14
+ end
15
+
16
+ When /^the current context is a list of discussions$/ do
17
+ @locals ||= {}
18
+ discussions = []
19
+ (1..3).each do |i|
20
+ posts = (1..i).to_a.map { |x| Post.new(:title => "Post #{x+3*i}") }
21
+ discussions << Discussion.new(:name => "Discussion #{i}", :posts => posts)
22
+ end
23
+ @locals[:this] = discussions
24
+ end
25
+