volt 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/Readme.md +47 -40
  3. data/VERSION +1 -1
  4. data/app/volt/controllers/notices_controller.rb +3 -3
  5. data/app/volt/tasks/live_query/data_store.rb +2 -2
  6. data/app/volt/tasks/live_query/live_query.rb +20 -20
  7. data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
  8. data/app/volt/tasks/live_query/query_tracker.rb +15 -15
  9. data/app/volt/tasks/query_tasks.rb +13 -13
  10. data/app/volt/tasks/store_tasks.rb +7 -7
  11. data/app/volt/views/notices/index.html +17 -18
  12. data/lib/volt/assets/test.rb +2 -2
  13. data/lib/volt/benchmark/benchmark.rb +25 -23
  14. data/lib/volt/cli/asset_compile.rb +11 -0
  15. data/lib/volt/cli/new_gem.rb +16 -16
  16. data/lib/volt/cli.rb +14 -12
  17. data/lib/volt/console.rb +5 -6
  18. data/lib/volt/controllers/model_controller.rb +18 -18
  19. data/lib/volt/extra_core/array.rb +4 -4
  20. data/lib/volt/extra_core/hash.rb +3 -3
  21. data/lib/volt/extra_core/object.rb +6 -6
  22. data/lib/volt/extra_core/string.rb +6 -6
  23. data/lib/volt/extra_core/symbol.rb +5 -5
  24. data/lib/volt/extra_core/time.rb +4 -4
  25. data/lib/volt/extra_core/true_false.rb +6 -6
  26. data/lib/volt/extra_core/try.rb +9 -9
  27. data/lib/volt/models/array_model.rb +26 -26
  28. data/lib/volt/models/model.rb +35 -35
  29. data/lib/volt/models/model_hash_behaviour.rb +15 -15
  30. data/lib/volt/models/model_helpers.rb +8 -8
  31. data/lib/volt/models/model_wrapper.rb +6 -6
  32. data/lib/volt/models/persistors/array_store.rb +36 -36
  33. data/lib/volt/models/persistors/base.rb +6 -6
  34. data/lib/volt/models/persistors/flash.rb +5 -5
  35. data/lib/volt/models/persistors/model_identity_map.rb +2 -2
  36. data/lib/volt/models/persistors/model_store.rb +22 -22
  37. data/lib/volt/models/persistors/params.rb +3 -3
  38. data/lib/volt/models/persistors/query/query_listener.rb +14 -14
  39. data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
  40. data/lib/volt/models/persistors/store.rb +8 -8
  41. data/lib/volt/models/persistors/store_factory.rb +2 -2
  42. data/lib/volt/models/url.rb +37 -37
  43. data/lib/volt/page/bindings/attribute_binding.rb +14 -14
  44. data/lib/volt/page/bindings/base_binding.rb +9 -9
  45. data/lib/volt/page/bindings/component_binding.rb +7 -7
  46. data/lib/volt/page/bindings/content_binding.rb +3 -3
  47. data/lib/volt/page/bindings/each_binding.rb +13 -13
  48. data/lib/volt/page/bindings/event_binding.rb +4 -4
  49. data/lib/volt/page/bindings/if_binding.rb +12 -12
  50. data/lib/volt/page/bindings/template_binding.rb +30 -30
  51. data/lib/volt/page/channel.rb +19 -19
  52. data/lib/volt/page/channel_stub.rb +6 -6
  53. data/lib/volt/page/document.rb +2 -2
  54. data/lib/volt/page/document_events.rb +4 -4
  55. data/lib/volt/page/draw_cycle.rb +3 -3
  56. data/lib/volt/page/memory_test.rb +6 -6
  57. data/lib/volt/page/page.rb +19 -19
  58. data/lib/volt/page/reactive_template.rb +9 -9
  59. data/lib/volt/page/sub_context.rb +5 -5
  60. data/lib/volt/page/targets/attribute_section.rb +9 -9
  61. data/lib/volt/page/targets/attribute_target.rb +3 -3
  62. data/lib/volt/page/targets/base_section.rb +2 -2
  63. data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
  64. data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
  65. data/lib/volt/page/targets/dom_section.rb +40 -38
  66. data/lib/volt/page/targets/dom_target.rb +2 -2
  67. data/lib/volt/page/tasks.rb +12 -12
  68. data/lib/volt/page/template_renderer.rb +4 -4
  69. data/lib/volt/page/url_tracker.rb +6 -6
  70. data/lib/volt/reactive/array_extensions.rb +2 -2
  71. data/lib/volt/reactive/destructive_methods.rb +5 -5
  72. data/lib/volt/reactive/event_chain.rb +25 -25
  73. data/lib/volt/reactive/events.rb +33 -33
  74. data/lib/volt/reactive/object_tracker.rb +21 -21
  75. data/lib/volt/reactive/object_tracking.rb +2 -2
  76. data/lib/volt/reactive/reactive_array.rb +57 -57
  77. data/lib/volt/reactive/reactive_tags.rb +16 -16
  78. data/lib/volt/reactive/reactive_value.rb +72 -72
  79. data/lib/volt/reactive/string_extensions.rb +3 -3
  80. data/lib/volt/router/routes.rb +22 -23
  81. data/lib/volt/server/component_handler.rb +5 -5
  82. data/lib/volt/server/component_templates.rb +14 -11
  83. data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
  84. data/lib/volt/server/html_parser/each_scope.rb +18 -0
  85. data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
  86. data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
  87. data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
  88. data/lib/volt/server/html_parser/view_handler.rb +82 -0
  89. data/lib/volt/server/html_parser/view_parser.rb +23 -0
  90. data/lib/volt/server/html_parser/view_scope.rb +145 -0
  91. data/lib/volt/server/rack/asset_files.rb +17 -17
  92. data/lib/volt/server/rack/component_paths.rb +18 -18
  93. data/lib/volt/server/rack/index_files.rb +8 -8
  94. data/lib/volt/server/rack/opal_files.rb +11 -11
  95. data/lib/volt/server/socket_connection_handler.rb +13 -13
  96. data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
  97. data/lib/volt/server.rb +18 -18
  98. data/lib/volt/tasks/dispatcher.rb +5 -5
  99. data/lib/volt/utils/ejson.rb +2 -2
  100. data/lib/volt/utils/generic_counting_pool.rb +8 -8
  101. data/lib/volt/utils/generic_pool.rb +16 -16
  102. data/lib/volt/volt/environment.rb +4 -4
  103. data/lib/volt.rb +6 -6
  104. data/spec/integration/test_integration_spec.rb +2 -2
  105. data/spec/models/event_chain_spec.rb +38 -38
  106. data/spec/models/model_spec.rb +128 -128
  107. data/spec/models/old_model_spec.rb +17 -17
  108. data/spec/models/persistors/params_spec.rb +3 -3
  109. data/spec/models/persistors/store_spec.rb +7 -7
  110. data/spec/models/reactive_array_spec.rb +82 -82
  111. data/spec/models/reactive_generator_spec.rb +11 -11
  112. data/spec/models/reactive_tags_spec.rb +6 -6
  113. data/spec/models/reactive_value_spec.rb +70 -70
  114. data/spec/models/store_spec.rb +4 -4
  115. data/spec/models/string_extensions_spec.rb +13 -13
  116. data/spec/page/bindings/content_binding_spec.rb +6 -6
  117. data/spec/page/sub_context_spec.rb +1 -1
  118. data/spec/router/routes_spec.rb +3 -3
  119. data/spec/server/html_parser/sample_page.html +595 -0
  120. data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
  121. data/spec/server/html_parser/view_parser_spec.rb +286 -0
  122. data/spec/server/rack/asset_files_spec.rb +6 -6
  123. data/spec/server/rack/component_paths_spec.rb +5 -5
  124. data/spec/spec_helper.rb +4 -5
  125. data/spec/store/mongo_spec.rb +3 -3
  126. data/spec/tasks/live_query_spec.rb +6 -6
  127. data/spec/tasks/query_tasks.rb +4 -4
  128. data/spec/tasks/query_tracker_spec.rb +20 -20
  129. data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
  130. data/spec/templates/template_binding_spec.rb +28 -28
  131. data/spec/utils/generic_counting_pool_spec.rb +5 -5
  132. data/spec/utils/generic_pool_spec.rb +14 -14
  133. data/templates/newgem/app/newgem/views/index/index.html +1 -2
  134. data/templates/project/app/home/config/dependencies.rb +1 -1
  135. data/templates/project/app/home/controllers/index_controller.rb +1 -1
  136. data/templates/project/app/home/views/index/about.html +4 -6
  137. data/templates/project/app/home/views/index/home.html +4 -5
  138. data/templates/project/app/home/views/index/index.html +8 -9
  139. data/templates/project/spec/spec_helper.rb +1 -1
  140. metadata +17 -8
  141. data/lib/volt/server/binding_setup.rb +0 -2
  142. data/lib/volt/server/if_binding_setup.rb +0 -31
  143. data/lib/volt/server/scope.rb +0 -43
  144. data/lib/volt/server/template_parser.rb +0 -453
  145. data/spec/server/template_parser_spec.rb +0 -50
@@ -1,453 +0,0 @@
1
- require 'volt/server/scope'
2
- require 'volt/server/if_binding_setup'
3
- require 'nokogiri'
4
-
5
- # TODO: The section_name that we're passing in should probably be
6
- # abstracted out. Possibly this whole thing needs a rewrite.
7
-
8
- class Template
9
- attr_accessor :current_scope, :section_name
10
-
11
- def initialize(template_parser, section_name, template, scope=Scope.new)
12
- @binding_number = 0
13
-
14
- @template_parser = template_parser
15
- @section_name = section_name
16
- @template = template
17
- @scopes = [scope]
18
- @current_scope = @scopes.first
19
- end
20
-
21
- def html
22
- if @template.respond_to?(:name) && @template.name[0] == ':'
23
- # Don't return the <:section> tags
24
- return @template.children.to_html
25
- else
26
- # if @template.class == Nokogiri::XML::NodeSet
27
- # result = ''
28
- # @template.each do |node|
29
- # result << node.to_html
30
- # end
31
- # else
32
- result = @template.to_html
33
- # end
34
- result
35
- end
36
- end
37
-
38
-
39
- def add_binding(node, content)
40
- if content[0] == '/'
41
- add_close_mustache(node)
42
- elsif content[0] == '#'
43
- command, *content = content.split(/ /)
44
- content = content.join(' ')
45
-
46
- case command
47
- when '#template'
48
- return add_template(node, content)
49
- when '#each'
50
- return add_each_binding(node, content)
51
- when '#if'
52
- return add_if_binding(node, content)
53
- when '#elsif'
54
- return add_else_binding(node, content)
55
- when '#else'
56
- if content.present?
57
- # TODO: improve error, include line/file
58
- raise "#else should not include a condition, use #elsif instead. #{content} was passed as a condition."
59
- end
60
-
61
- return add_else_binding(node, nil)
62
- else
63
- # TODO: Handle invalid command
64
- raise "Invalid Command"
65
- end
66
- else
67
- # text binding
68
- return add_text_binding(content)
69
- end
70
- end
71
-
72
- def add_template(node, content, name='Template')
73
- html = "<!-- $#{@binding_number} --><!-- $/#{@binding_number} -->"
74
-
75
- @current_scope.add_binding(@binding_number, "lambda { |__p, __t, __c, __id| #{name}Binding.new(__p, __t, __c, __id, #{@template_parser.template_path.inspect}, Proc.new { [#{content}] }) }")
76
-
77
- @binding_number += 1
78
- return html
79
- end
80
-
81
- def add_each_binding(node, content)
82
- html = "<!-- $#{@binding_number} -->"
83
-
84
- content, variable_name = content.strip.split(/ as /)
85
-
86
- template_name = "#{@template_parser.template_path}/#{section_name}/__template/#{@binding_number}"
87
- @current_scope.add_binding(@binding_number, "lambda { |__p, __t, __c, __id| EachBinding.new(__p, __t, __c, __id, Proc.new { #{content} }, #{variable_name.inspect}, #{template_name.inspect}) }")
88
-
89
- # Add the node, the binding number, then store the location where the
90
- # bindings for this block starts.
91
- @current_scope = Scope.new(@binding_number)
92
- @scopes << @current_scope
93
-
94
- @binding_number += 1
95
- return html
96
- end
97
-
98
- def add_if_binding(node, content)
99
- html = "<!-- $#{@binding_number} -->"
100
-
101
- template_name = "#{@template_parser.template_path}/#{section_name}/__template/#{@binding_number}"
102
- if_binding_setup = IfBindingSetup.new
103
- if_binding_setup.add_branch(content, template_name)
104
-
105
- @current_scope.start_if_binding(@binding_number, if_binding_setup)
106
-
107
- # Add the node, the binding number, then store the location where the
108
- # bindings for this block starts.
109
- @current_scope = Scope.new(@binding_number)
110
- @scopes << @current_scope
111
-
112
- @binding_number += 1
113
- return html
114
- end
115
-
116
- def add_else_binding(node, content)
117
- html = add_close_mustache(node, false)
118
-
119
- html += "<!-- $#{@binding_number} -->"
120
- template_name = "#{@template_parser.template_path}/#{section_name}/__template/#{@binding_number}"
121
-
122
- @current_scope.current_if_binding[1].add_branch(content, template_name)
123
-
124
- # Add the node, the binding number, then store the location where the
125
- # bindings for this block starts.
126
- @current_scope = Scope.new(@binding_number)
127
- @scopes << @current_scope
128
-
129
- @binding_number += 1
130
-
131
- return html
132
- end
133
-
134
- def add_close_mustache(node, close_if=true)
135
- scope = @scopes.pop
136
- @current_scope = @scopes.last
137
-
138
- # Close an outstanding if binding (if it exists)
139
- @current_scope.close_if_binding! if close_if
140
-
141
- # Track that this scope was closed out
142
- @current_scope.add_closed_child_scope(scope)
143
-
144
- html = "<!-- $/#{scope.outer_binding_number} -->"
145
-
146
- return html
147
- end
148
-
149
- # When we find a binding, we pass it's content in here and replace it with
150
- # the return value
151
- def add_text_binding(content)
152
- html = "<!-- $#{@binding_number} --><!-- $/#{@binding_number} -->"
153
-
154
- @current_scope.add_binding(@binding_number, "lambda { |__p, __t, __c, __id| ContentBinding.new(__p, __t, __c, __id, Proc.new { #{content} }) }")
155
-
156
- @binding_number += 1
157
- return html
158
- end
159
-
160
- def setup_node_id(node)
161
- id = node['id']
162
- # First assign this node an id if it doesn't have one
163
- unless id
164
- id = node['id'] = "id#{@binding_number}"
165
- @binding_number += 1
166
- end
167
- end
168
-
169
- # Attribute bindings support multiple handlebar listeners
170
- # Exvoltle:
171
- # <button click="{_primary} {_important}">...
172
- #
173
- # To accomplish this, we create a new listener from the existing ones in the Proc
174
- # that we pass to the binding when it is created.
175
- def add_attribute_binding(node, attribute, content)
176
- setup_node_id(node)
177
-
178
- if content =~ /^\{[^\{]+\}$/
179
- # Getter is the content inside of { ... }
180
- add_single_getter(node, attribute, content)
181
- else
182
- add_multiple_getters(node, attribute, content)
183
- end
184
-
185
- end
186
-
187
- def add_single_getter(node, attribute, content)
188
- if attribute == 'checked' || true
189
- # For a checkbox, we don't want to add
190
- getter = content[1..-2]
191
- else
192
- # Otherwise we should combine them
193
- # TODO: We should make .or handle assignment
194
- getter = "_tmp = #{content[1..-2]}.or('') ; _tmp.reactive_manager.setter! { |val| self.#{content[1..-2]} = val } ; _tmp"
195
- end
196
-
197
- @current_scope.add_binding(node['id'], "lambda { |__p, __t, __c, __id| AttributeBinding.new(__p, __t, __c, __id, #{attribute.inspect}, Proc.new { #{getter} }) }")
198
- end
199
-
200
- def add_multiple_getters(node, attribute, content)
201
- case attribute
202
- when 'checked', 'value'
203
- if parts.size > 1
204
- # Multiple ReactiveValue's can not be passed to value or checked attributes.
205
- raise "Multiple bindings can not be passed to a #{attribute} binding."
206
- end
207
- end
208
-
209
- reactive_template_path = add_reactive_template(content)
210
-
211
- @current_scope.add_binding(node['id'], "lambda { |__p, __t, __c, __id| AttributeBinding.new(__p, __t, __c, __id, #{attribute.inspect}, Proc.new { ReactiveTemplate.new(__p, __c, #{reactive_template_path.inspect}) }) }")
212
- end
213
-
214
- # Returns a path to a template for the content. This can be passed
215
- # into ReactiveTemplate.new, along with the current context.
216
- def add_reactive_template(content)
217
- # Return a template path instead
218
- template_name = "__attribute/#{@binding_number}"
219
- full_template_path = "#{@template_parser.template_path}/#{section_name}/#{template_name}"
220
- @binding_number += 1
221
-
222
- attribute_template = Template.new(@template_parser, "#{section_name}/#{template_name}", Nokogiri::HTML::DocumentFragment.parse(content))
223
- @template_parser.add_template("#{section_name}/#{template_name}", attribute_template)
224
- attribute_template.start_walk
225
- attribute_template.pull_closed_block_scopes
226
-
227
- return full_template_path
228
- end
229
-
230
- def add_event_binding(node, attribute_name, content)
231
- setup_node_id(node)
232
-
233
- event = attribute_name[2..-1]
234
-
235
- if node.name == 'a'
236
- # For links, we need to add blank href to make it clickable.
237
- node['href'] ||= ''
238
- end
239
-
240
- @current_scope.add_binding(node['id'], "lambda { |__p, __t, __c, __id| EventBinding.new(__p, __t, __c, __id, #{event.inspect}, Proc.new {|event| #{content} })}")
241
- end
242
-
243
- def pull_closed_block_scopes(scope=@current_scope)
244
- if scope.closed_block_scopes
245
- scope.closed_block_scopes.each do |sub_scope|
246
- # Loop through any subscopes first, pull them in.
247
- pull_closed_block_scopes(sub_scope)
248
-
249
- # Grab everything between the start/end html comments
250
- start_node = find_by_comment("$#{sub_scope.outer_binding_number}")
251
- end_node = find_by_comment("$/#{sub_scope.outer_binding_number}")
252
-
253
- move_nodes_to_new_template(start_node, end_node, sub_scope)
254
- end
255
- end
256
- end
257
-
258
-
259
- def move_nodes_to_new_template(start_node, end_node, scope)
260
- # TODO: currently this doesn't handle spanning nodes within seperate containers.
261
- # so doing tr's doesn't work for some reason.
262
-
263
- start_parent = start_node.parent
264
- start_parent = start_parent.children if start_parent.is_a?(Nokogiri::HTML::DocumentFragment) || start_parent.is_a?(Nokogiri::XML::Element)
265
- start_index = start_parent.index(start_node) + 1
266
-
267
- end_parent = end_node.parent
268
- end_parent = end_parent.children if end_parent.is_a?(Nokogiri::HTML::DocumentFragment) || end_parent.is_a?(Nokogiri::XML::Element)
269
- end_index = end_parent.index(end_node) - 1
270
-
271
- move_nodes = start_parent[start_index..end_index]
272
- move_nodes.remove
273
-
274
- new_template = Template.new(@template_parser, section_name, move_nodes, scope)
275
-
276
- @template_parser.add_template("#{section_name}/__template/#{scope.outer_binding_number}", new_template)
277
- end
278
-
279
-
280
- def find_by_comment(name)
281
- return @template.xpath("descendant::comment()[. = ' #{name} ']").first
282
- end
283
-
284
- def start_walk
285
- walk(@template)
286
- end
287
-
288
- # We implement a dom walker that can walk down the dom and spit out output
289
- # html as we go
290
- def walk(node)
291
- case node.type
292
- when 1
293
- # html node
294
- walk_html_node(node)
295
- when 3
296
- # text node
297
- walk_text_node(node)
298
- end
299
-
300
- node.children.each do |child|
301
- walk(child)
302
- end
303
- end
304
-
305
- def walk_html_node(node)
306
- if node.name[0] == ':' && node.path.count('/') > 1
307
- parse_component(node)
308
- elsif node.name == 'textarea'
309
- parse_textarea(node)
310
- else
311
- parse_html_node(node)
312
- end
313
- end
314
-
315
- # We provide a quick way to render components with tags starting
316
- # with a :
317
- # Count the number of /'s in the path, if we are at the root node
318
- # we can ignore it, since this is the template its self.
319
- # TODO: Root node might not be the template if we parsed directly
320
- # without a subtemplate specifier. We need to find a good way to
321
- # parse only within the subtemplate.
322
- def parse_component(node)
323
- template_path = node.name[1..-1].gsub(':', '/')
324
-
325
- # Take the attributes and turn them into a hash
326
- attribute_hash = {}
327
- node.attribute_nodes.each do |attribute_node|
328
- content = attribute_node.value
329
-
330
- if !content.index('{')
331
- # passing in a string
332
- value = content.inspect
333
- elsif content =~ /^\{[^\}]+\}$/
334
- # Has one binding, just get it
335
- value = "Proc.new { #{content[1..-2]} }"
336
- else
337
- # Has multiple bindings, we need to render a template here
338
- attr_template_path = add_reactive_template(content)
339
-
340
- value = "Proc.new { ReactiveTemplate.new(__p, __c, #{attr_template_path.inspect}) }"
341
- end
342
-
343
- attribute_hash[attribute_node.name] = value
344
- end
345
-
346
- attributes_string = attribute_hash.to_a.map do |key, value|
347
- "#{key.inspect} => #{value}"
348
- end.join(', ')
349
-
350
- # Setup the arguments string, which goes to the TemplateBinding
351
- args_str = "#{template_path.inspect}"
352
- args_str << ", {#{attributes_string}}" if attribute_hash.size > 0
353
-
354
- new_html = add_template(node, args_str, 'Component')
355
-
356
- node.swap(new_html)#Nokogiri::HTML::DocumentFragment.parse(new_html))
357
- end
358
-
359
- def parse_textarea(node)
360
- # The contents of textareas should really be treated like a
361
- # value= attribute. So here we pull the content into a value attribute
362
- # if the textarea has bindings in the content.
363
- if node.inner_html =~ /\{[^\}]+\}/
364
- node[:value] = node.inner_html
365
- node.children.remove
366
- end
367
-
368
- parse_html_node(node)
369
- end
370
-
371
- def parse_html_node(node)
372
-
373
- node.attribute_nodes.each do |attribute_node|
374
- if attribute_node.name =~ /^e\-/
375
- # We have an e- binding
376
- add_event_binding(node, attribute_node.name, attribute_node.value)
377
-
378
- # remove the attribute
379
- attribute_node.remove
380
- elsif attribute_node.value.match(/\{[^\}]+\}/)
381
- # Has bindings
382
- add_attribute_binding(node, attribute_node.name, attribute_node.value)
383
-
384
- # remove the attribute
385
- attribute_node.remove
386
- end
387
- end
388
- end
389
-
390
- def walk_text_node(node)
391
- new_html = node.to_html.gsub(/\{([^\}]+)\}/) do |template_binding|
392
- add_binding(node, $1)
393
- end
394
-
395
- # puts "------! #{new_html.inspect} - #{node.class.inspect} - #{node.inspect}"
396
-
397
- # TODO: Broke here in jruby
398
- node.swap(new_html)# if new_html.blank?
399
-
400
- #Nokogiri::HTML::DocumentFragment.parse(new_html))
401
- end
402
- end
403
-
404
- class TemplateParser
405
- attr_accessor :dom, :bindings, :template_path
406
-
407
- def initialize(template, template_path)
408
- @templates = {}
409
- @template_path = template_path
410
-
411
- template_fragment = Nokogiri::HTML::DocumentFragment.parse(template)
412
- # Add templates for each section
413
-
414
- # Check for sections
415
- sections = []
416
- if (first_child = template_fragment.children[0]) && first_child.name[0] == ':'
417
- template_fragment.children.each do |child|
418
- if child.is_a?(Nokogiri::XML::Element)
419
- sections << [child, child.name[1..-1]]
420
- end
421
- end
422
- else
423
- sections << [template_fragment, 'body']
424
- end
425
-
426
- sections.each do |section, name|
427
- template = Template.new(self, name, section)
428
- add_template(name, template)
429
- template.start_walk
430
- template.pull_closed_block_scopes
431
- end
432
-
433
- end
434
-
435
- def add_template(name, template)
436
- raise "Already defined at #{@template_path + '/' + name}" if @templates[@template_path + '/' + name]
437
- @templates[@template_path + '/' + name] = template
438
- end
439
-
440
- # Return the templates, but map the html from nokogiri to html
441
- def templates
442
- mapped = {}
443
- @templates.each_pair do |name, template|
444
- mapped[name] = {
445
- 'html' => template.html,
446
- 'bindings' => template.current_scope.bindings
447
- }
448
- end
449
-
450
- return mapped
451
- end
452
-
453
- end
@@ -1,50 +0,0 @@
1
- # require 'volt/server/template_parser'
2
- #
3
- # describe TemplateParser do
4
- # it 'should parse a doc' do
5
- # template = <<-END
6
- # <h1>Header {name}</h1>
7
- #
8
- # <p class="{paragraph_class}">{content}</p>
9
- #
10
- # <!-- Original Comment -->
11
- # {#each some_array}
12
- # <p>Line {some_name}</p>
13
- # {/}
14
- #
15
- # END
16
- # parser = TemplateParser.new(template, 'main')
17
- # end
18
- #
19
- # it 'should parse nested' do
20
- # template = <<-END
21
- # <div class="test">
22
- # <div class="test2">
23
- # <h1>Header</h1>
24
- # </div>
25
- # </div>
26
- # END
27
- # parser = TemplateParser.new(template, 'main')
28
- # end
29
- #
30
- # it "should parse nested bindings" do
31
- # template = <<-END
32
- # 1{#if _a}2
33
- # 3{#if _b}4
34
- # _a and _b
35
- # {/}
36
- # {/}
37
- # END
38
- # parser = TemplateParser.new(template, 'main')
39
- #
40
- # expect(parser.templates.keys).to eq(["main/body", "main/body/__template/1", "main/body/__template/0"])
41
- # expect(parser.templates['main/body/__template/1']).to eq({"html"=>"4\n _a and _b\n ", "bindings"=>{}})
42
- # end
43
- #
44
- # it "should parse templates in attributes" do
45
- # template = <<-END
46
- # <div class="{#if _model._is_cool}cool{/}">yes</div>
47
- # END
48
- # parser = TemplateParser.new(template, 'main')
49
- # end
50
- # end