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,229 @@
1
+ Feature: The implicit context
2
+ Background:
3
+ Given a file named "example_taglib.dryml" with:
4
+ """
5
+ <def tag="view"><%= h this.to_s %></def>
6
+
7
+ <def tag="l"><a href="#{this.url}" param="default"/></def>
8
+
9
+ <def tag="page">
10
+ <html>
11
+ <head>
12
+ <title>My Blog</title>
13
+ </head>
14
+ <body param="content"/>
15
+ </html>
16
+ </def>
17
+ """
18
+
19
+ Scenario: Rendering a blog post
20
+ Given a file named "show.dryml" with:
21
+ """
22
+ <page>
23
+ <content:>
24
+ <h2><view:title/></h2>
25
+ <div class="details">
26
+ Published by <l:author><view:name/></l> on <view:published-at/>.
27
+ </div>
28
+ <div class="post-body">
29
+ <view:body/>
30
+ </div>
31
+ </content:>
32
+ </page>
33
+ """
34
+ When I include the taglib "example_taglib"
35
+ And the current context is a blog post
36
+ And I render "show.dryml"
37
+ Then the output DOM should be:
38
+ """
39
+ <html>
40
+ <head>
41
+ <title>My Blog</title>
42
+ </head>
43
+ <body class="content">
44
+ <h2>A Blog Post</h2>
45
+ <div class="details">
46
+ Published by <a href="/authors/1">Nobody</a> on 2011-12-30 10:25:00 UTC.
47
+ </div>
48
+ <div class="post-body">
49
+ Some body content
50
+ </div>
51
+ </body>
52
+ </html>
53
+ """
54
+
55
+ Scenario: Rendering a blog post using only with
56
+ Given a file named "show.dryml" with:
57
+ """
58
+ <page>
59
+ <content:>
60
+ <h2><view with="&this.title"/></h2>
61
+ <div class="details">
62
+ Published by <l with="&this.author"><view with="&this.name"/></l>
63
+ on <view with="&this.published_at"/>.
64
+ </div>
65
+ <div class="post-body">
66
+ <view with="&this.body"/>
67
+ </div>
68
+ </content:>
69
+ </page>
70
+ """
71
+ When I include the taglib "example_taglib"
72
+ And the current context is a blog post
73
+ And I render "show.dryml"
74
+ Then the output DOM should be:
75
+ """
76
+ <html>
77
+ <head>
78
+ <title>My Blog</title>
79
+ </head>
80
+ <body class="content">
81
+ <h2>A Blog Post</h2>
82
+ <div class="details">
83
+ Published by <a href="/authors/1">Nobody</a> on 2011-12-30 10:25:00 UTC.
84
+ </div>
85
+ <div class="post-body">
86
+ Some body content
87
+ </div>
88
+ </body>
89
+ </html>
90
+ """
91
+
92
+ Scenario: Rendering a blog post using only field
93
+ Given a file named "show.dryml" with:
94
+ """
95
+ <page>
96
+ <content:>
97
+ <h2><view field="title"/></h2>
98
+ <div class="details">
99
+ Published by <l field="author"><view field="name"/></l>
100
+ on <view field="published_at"/>.
101
+ </div>
102
+ <div class="post-body">
103
+ <view field="body"/>
104
+ </div>
105
+ </content:>
106
+ </page>
107
+ """
108
+ When I include the taglib "example_taglib"
109
+ And the current context is a blog post
110
+ And I render "show.dryml"
111
+ Then the output DOM should be:
112
+ """
113
+ <html>
114
+ <head>
115
+ <title>My Blog</title>
116
+ </head>
117
+ <body class="content">
118
+ <h2>A Blog Post</h2>
119
+ <div class="details">
120
+ Published by <a href="/authors/1">Nobody</a> on 2011-12-30 10:25:00 UTC.
121
+ </div>
122
+ <div class="post-body">
123
+ Some body content
124
+ </div>
125
+ </body>
126
+ </html>
127
+ """
128
+
129
+ Scenario: field chains
130
+ Given a file named "show.dryml" with:
131
+ """
132
+ <div><do:author.name><view /></do></div>
133
+ <div><do field="author.name"><view /></do></div>
134
+ """
135
+ When I include the taglib "example_taglib"
136
+ And the current context is a blog post
137
+ And I render "show.dryml"
138
+ Then the output DOM should be:
139
+ """
140
+ <div>Nobody</div>
141
+ <div>Nobody</div>
142
+ """
143
+
144
+ Scenario: this_field and this_parent
145
+ Given a file named "show.dryml" with:
146
+ """
147
+ <div>
148
+ <do with="&this.author.name">
149
+ <div><view /></div>
150
+ <div><%= this_parent.class.name %></div>
151
+ <div><%= this_field %></div>
152
+ </do>
153
+ </div>
154
+ <div>
155
+ <do with="&this.author" field="name">
156
+ <div><view /></div>
157
+ <div><%= this_parent.class.name %></div>
158
+ <div><%= this_field %></div>
159
+ </do>
160
+ </div>
161
+ """
162
+ When I include the taglib "example_taglib"
163
+ And the current context is a blog post
164
+ And I render "show.dryml"
165
+ Then the output DOM should be:
166
+ """
167
+ <div>
168
+ <div>Nobody</div>
169
+ <div>NilClass</div>
170
+ <div></div>
171
+ </div>
172
+ <div>
173
+ <div>Nobody</div>
174
+ <div>Author</div>
175
+ <div>name</div>
176
+ </div>
177
+ """
178
+
179
+ Scenario: indexing into a collection
180
+ Given a file named "show.dryml" with:
181
+ """
182
+ <div><do field="1"><view /></do></div>
183
+ <div><do field="3"><view /></do></div>
184
+ """
185
+ When I include the taglib "example_taglib"
186
+ And the current context is an array
187
+ And I render "show.dryml"
188
+ Then the output DOM should be:
189
+ """
190
+ <div>bar</div>
191
+ <div>blam</div>
192
+ """
193
+
194
+ Scenario: repeating on a collection stores the index in this_field
195
+ Given a file named "show.dryml" with:
196
+ """
197
+ <repeat>
198
+ <div>
199
+ <span><%= this_field %></span>
200
+ <span><view /></span>
201
+ </div>
202
+ </repeat>
203
+ """
204
+ When I include the taglib "example_taglib"
205
+ And the current context is an array
206
+ And I render "show.dryml"
207
+ Then the output DOM should be:
208
+ """
209
+ <div>
210
+ <span>0</span>
211
+ <span>foo</span>
212
+ </div>
213
+ <div>
214
+ <span>1</span>
215
+ <span>bar</span>
216
+ </div>
217
+ <div>
218
+ <span>2</span>
219
+ <span>baz</span>
220
+ </div>
221
+ <div>
222
+ <span>3</span>
223
+ <span>blam</span>
224
+ </div>
225
+ <div>
226
+ <span>4</span>
227
+ <span>mumble</span>
228
+ </div>
229
+ """
@@ -0,0 +1,120 @@
1
+ Feature: Tag attributes
2
+
3
+ Scenario: A tag with one attribute
4
+ Given a file named "example_taglib.dryml" with:
5
+ """
6
+ <def tag="help-link" attrs="file">
7
+ <a class="help" href="/help/#{file}.html" param="default"/>
8
+ </def>
9
+ """
10
+ And a file named "example.dryml" with:
11
+ """
12
+ <help-link file="intro">Introductory Help</help-link>
13
+ """
14
+ When I include the taglib "example_taglib"
15
+ And I render "example.dryml"
16
+ Then the output DOM should be:
17
+ """
18
+ <a class="help" href="/help/intro.html">Introductory Help</a>
19
+ """
20
+
21
+ Scenario: A tag with a boolean attribute
22
+ Given a file named "example_taglib.dryml" with:
23
+ """
24
+ <def tag="help-link" attrs="file, new-window">
25
+ <a class="help" href="/help/#{file}.html" target="#{new_window ? '_blank' : '_self' }" param="default"/>
26
+ </def>
27
+ """
28
+ And a file named "example.dryml" with:
29
+ """
30
+ <help-link file="intro" new-window="&true">Introductory Help In A New Window</help-link>
31
+ <help-link file="intro" new-window="&false">Introductory Help</help-link>
32
+ """
33
+ When I include the taglib "example_taglib"
34
+ And I render "example.dryml"
35
+ Then the output DOM should be:
36
+ """
37
+ <a class="help" href="/help/intro.html" target="_blank">Introductory Help In A New Window</a>
38
+ <a class="help" href="/help/intro.html" target="_self">Introductory Help</a>
39
+ """
40
+
41
+ Scenario: A tag with a flag attribute
42
+ Given a file named "example_taglib.dryml" with:
43
+ """
44
+ <def tag="help-link" attrs="file, new-window">
45
+ <a class="help" href="/help/#{file}.html" target="#{new_window ? '_blank' : '_self' }" param="default"/>
46
+ </def>
47
+ """
48
+ And a file named "example.dryml" with:
49
+ """
50
+ <help-link file="intro" new-window>Introductory Help In A New Window</help-link>
51
+ <help-link file="intro">Introductory Help</help-link>
52
+ """
53
+ When I include the taglib "example_taglib"
54
+ And I render "example.dryml"
55
+ Then the output DOM should be:
56
+ """
57
+ <a class="help" href="/help/intro.html" target="_blank">Introductory Help In A New Window</a>
58
+ <a class="help" href="/help/intro.html" target="_self">Introductory Help</a>
59
+ """
60
+
61
+ Scenario: Using merge-attrs
62
+ Given a file named "example_taglib.dryml" with:
63
+ """
64
+ <def tag="markdown-help">
65
+ <a href="http://daringfireball.net/..." merge-attrs param="default"/>
66
+ </def>
67
+ """
68
+ And a file named "example.dryml" with:
69
+ """
70
+ Add formatting using <markdown-help target="_blank">markdown</markdown-help>
71
+ """
72
+ When I include the taglib "example_taglib"
73
+ And I render "example.dryml"
74
+ Then the output DOM should be:
75
+ """
76
+ Add formatting using <a href="http://daringfireball.net/..." target="_blank">markdown</a>
77
+ """
78
+
79
+ Scenario: Using merge-attrs and attributes_for
80
+ Given a file named "example_taglib.dryml" with:
81
+ """
82
+ <def tag="help-link" attrs="file, new-window">
83
+ <a class="help" href="/help/#{file}.html" target="#{new_window ? '_blank' : '_self' }" param="default"/>
84
+ </def>
85
+
86
+ <def tag="decorated-help" attrs="image, alt">
87
+ <help-link merge-attrs="&attributes - attrs_for(:help_link)">
88
+ <img src="/images/#{image}.png" alt="#{alt || image}" /><do param="default"/>
89
+ </help-link>
90
+ </def>
91
+ """
92
+ And a file named "example.dryml" with:
93
+ """
94
+ <decorated-help image="intro" file="intro" new-window>Introductory Help In A New Window</decorated-help>
95
+ """
96
+ When I include the taglib "example_taglib"
97
+ And I render "example.dryml"
98
+ Then the output DOM should be:
99
+ """
100
+ <a class="help" href="/help/.html" target="_self"><img alt="intro" src="/images/intro.png"/>Introductory Help In A New Window</a>
101
+ """
102
+
103
+ Scenario: Merging the class attribute
104
+ Given a file named "example_taglib.dryml" with:
105
+ """
106
+ <def tag="help-link" attrs="file">
107
+ <a class="help" href="/help/#{file}.html" param="default" merge-attrs/>
108
+ </def>
109
+ """
110
+ And a file named "example.dryml" with:
111
+ """
112
+ <help-link file="intro" class="important">Introductory Help</help-link>
113
+ """
114
+ When I include the taglib "example_taglib"
115
+ And I render "example.dryml"
116
+ Then the output DOM should be:
117
+ """
118
+ <a class="help important" href="/help/intro.html">Introductory Help</a>
119
+ """
120
+
@@ -0,0 +1,241 @@
1
+ Feature: Repeated and optional content
2
+
3
+ Scenario: The if tag
4
+ Given a file named "example.dryml" with:
5
+ """
6
+ <% some_var = 'foo' %>
7
+ <if test="&some_var"><p>some_var is true</p></if>
8
+ <% some_other_var = '' %>
9
+ <if test="&some_other_var"><p>some_other_var is true</p></if>
10
+ """
11
+ When I render "example.dryml"
12
+ Then the output DOM should be:
13
+ """
14
+ <p>some_var is true</p>
15
+ """
16
+
17
+ Scenario: The else tag
18
+ Given a file named "example.dryml" with:
19
+ """
20
+ <% some_var = 'foo' %>
21
+ <if test="&some_var"><p>some_var is true</p></if>
22
+ <else><p>some_var is false</p></else>
23
+ <% some_other_var = '' %>
24
+ <if test="&some_other_var"><p>some_other_var is true</p></if>
25
+ <else><p>some_other_var is false</p></else>
26
+ """
27
+ When I render "example.dryml"
28
+ Then the output DOM should be:
29
+ """
30
+ <p>some_var is true</p>
31
+ <p>some_other_var is false</p>
32
+ """
33
+
34
+ Scenario: The unless tag
35
+ Given a file named "example.dryml" with:
36
+ """
37
+ <% some_var = 'foo' %>
38
+ <unless test="&some_var"><p>some_var is false</p></unless>
39
+ <% some_other_var = '' %>
40
+ <unless test="&some_other_var"><p>some_other_var is false</p></unless>
41
+ """
42
+ When I render "example.dryml"
43
+ Then the output DOM should be:
44
+ """
45
+ <p>some_other_var is false</p>
46
+ """
47
+
48
+ Scenario: The if tag with a field
49
+ Given a file named "example.dryml" with:
50
+ """
51
+ <if:author.name><p>author name is not blank</p></if>
52
+ <% this.author.name = '' %>
53
+ <if:author.name><p>author name is still not blank</p></if>
54
+ <else><p>now it is</p></else>
55
+ """
56
+ When the current context is a blog post
57
+ And I render "example.dryml"
58
+ Then the output DOM should be:
59
+ """
60
+ <p>author name is not blank</p>
61
+ <p>now it is</p>
62
+ """
63
+
64
+ Scenario: The if parameter
65
+ Given a file named "example.dryml" with:
66
+ """
67
+ <% some_var = 'foo' %>
68
+ <p if="&some_var">some_var is true</p>
69
+ <% some_other_var = '' %>
70
+ <p if="&some_other_var">some_other_var is true</p>
71
+ """
72
+ When I render "example.dryml"
73
+ Then the output DOM should be:
74
+ """
75
+ <p>some_var is true</p>
76
+ """
77
+
78
+ Scenario: The unless parameter
79
+ Given a file named "example.dryml" with:
80
+ """
81
+ <% some_var = 'foo' %>
82
+ <p unless="&some_var">some_var is false</p>
83
+ <% some_other_var = '' %>
84
+ <p unless="&some_other_var">some_other_var is false</p>
85
+ """
86
+ When I render "example.dryml"
87
+ Then the output DOM should be:
88
+ """
89
+ <p>some_other_var is false</p>
90
+ """
91
+
92
+ Scenario: The if parameter with a field - NOTE NO &
93
+ Given a file named "example.dryml" with:
94
+ """
95
+ <p if="author.name">author name is not blank</p>
96
+ <% this.author.name = '' %>
97
+ <p if="author.name">author name is still not blank</p>
98
+ <else><p>now it is</p></else>
99
+ """
100
+ When the current context is a blog post
101
+ And I render "example.dryml"
102
+ Then the output DOM should be:
103
+ """
104
+ <p>author name is not blank</p>
105
+ <p>now it is</p>
106
+ """
107
+
108
+ Scenario: The if parameter without an argument
109
+ Given a file named "example.dryml" with:
110
+ """
111
+ <do:author.name><p if>author name is not blank</p></do>
112
+ <% this.author.name = '' %>
113
+ <do:author.name><p if>author name is still not blank</p></do>
114
+ <else><p>now it is</p></else>
115
+ """
116
+ When the current context is a blog post
117
+ And I render "example.dryml"
118
+ Then the output DOM should be:
119
+ """
120
+ <p>author name is not blank</p>
121
+ <p>now it is</p>
122
+ """
123
+
124
+ Scenario: The if parameter without an argument applies to the surrounding context
125
+ Given a file named "example.dryml" with:
126
+ """
127
+ <% this.author = '' %>
128
+ <do:author if><p>first if is true</p></do>
129
+ <do:author><do if><p>second if is true</p></do></do>
130
+ """
131
+ When the current context is a blog post
132
+ And I render "example.dryml"
133
+ Then the output DOM should be:
134
+ """
135
+ <p>first if is true</p>
136
+ """
137
+
138
+ Scenario: repeat tag
139
+ Given a file named "example.dryml" with:
140
+ """
141
+ <repeat with="&[1,2,3,4]">
142
+ <p><%= this %></p>
143
+ </repeat>
144
+ """
145
+ When I render "example.dryml"
146
+ Then the output DOM should be:
147
+ """
148
+ <p>1</p>
149
+ <p>2</p>
150
+ <p>3</p>
151
+ <p>4</p>
152
+ """
153
+
154
+ Scenario: repeat attribute
155
+ Given a file named "example.dryml" with:
156
+ """
157
+ <p repeat="&[1,2,3,4]"><%= this %></p>
158
+ """
159
+ When I render "example.dryml"
160
+ Then the output DOM should be:
161
+ """
162
+ <p>1</p>
163
+ <p>2</p>
164
+ <p>3</p>
165
+ <p>4</p>
166
+ """
167
+
168
+ Scenario: attributes on a repeated tag are re-evaluated at each iteration
169
+ Given a file named "example.dryml" with:
170
+ """
171
+ <p repeat="&[1,2,3,4]" id="#{this}"><%= this %></p>
172
+ """
173
+ When I render "example.dryml"
174
+ Then the output DOM should be:
175
+ """
176
+ <p id="1">1</p>
177
+ <p id="2">2</p>
178
+ <p id="3">3</p>
179
+ <p id="4">4</p>
180
+ """
181
+
182
+ Scenario: even-odd scoped variable
183
+ Given a file named "example.dryml" with:
184
+ """
185
+ <p repeat="&[1,2,3,4]" class="#{scope.even_odd}"><%= this %></p>
186
+ """
187
+ When I render "example.dryml"
188
+ Then the output DOM should be:
189
+ """
190
+ <p class="odd">1</p>
191
+ <p class="even">2</p>
192
+ <p class="odd">3</p>
193
+ <p class="even">4</p>
194
+ """
195
+
196
+ Scenario: repeating the implicit context with if
197
+ Given a file named "example.dryml" with:
198
+ """
199
+ <do with="&[1,2,nil,4]">
200
+ <repeat if><p id="#{this}"><%= this %></p></repeat>
201
+ </do>
202
+ <do with="&[]">
203
+ <repeat if><p id="#{this}"><%= this %></p></repeat>
204
+ </do>
205
+ """
206
+ When I render "example.dryml"
207
+ Then the output DOM should be:
208
+ """
209
+ <p id="1">1</p>
210
+ <p id="2">2</p>
211
+ <p id=""></p>
212
+ <p id="4">4</p>
213
+ """
214
+
215
+ Scenario: first_item? helper
216
+ Given a file named "example.dryml" with:
217
+ """
218
+ <p repeat="&[1,2,3,4]" id="#{this}"><%= first_item? ? this*10 : this %></p>
219
+ """
220
+ When I render "example.dryml"
221
+ Then the output DOM should be:
222
+ """
223
+ <p id="1">10</p>
224
+ <p id="2">2</p>
225
+ <p id="3">3</p>
226
+ <p id="4">4</p>
227
+ """
228
+
229
+ Scenario: repeating over a hash sets this_key (not reliable on Ruby < 1.9)
230
+ Given a file named "example.dryml" with:
231
+ """
232
+ <p repeat="&{:foo => 1, :bar => 2, :baz => 3}" id="#{this_key}"><%= this %></p>
233
+ """
234
+ When I render "example.dryml"
235
+ Then the output DOM should be:
236
+ """
237
+ <p id="foo">1</p>
238
+ <p id="bar">2</p>
239
+ <p id="baz">3</p>
240
+ """
241
+