hobo 0.6.4 → 0.7.0

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 (71) hide show
  1. data/bin/hobo +4 -6
  2. data/hobo_files/plugin/CHANGES.txt +170 -0
  3. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +9 -9
  4. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +9 -9
  5. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +7 -2
  6. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +4 -4
  7. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_rapid.css → hobo-rapid.css} +0 -0
  8. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_rapid.js → hobo-rapid.js} +66 -47
  9. data/hobo_files/plugin/generators/hobo_rapid/templates/lowpro.js +130 -44
  10. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_base.css → reset.css} +0 -5
  11. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/pencil.png +0 -0
  12. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/small_close.png +0 -0
  13. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +45 -0
  14. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid_ui.css +167 -0
  15. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/views/application.dryml +10 -0
  16. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_bodytop.gif → bkg-bodytop.gif} +0 -0
  17. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_01.gif → bkg-corner-01.gif} +0 -0
  18. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_02.gif → bkg-corner-02.gif} +0 -0
  19. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_03.gif → bkg-corner-03.gif} +0 -0
  20. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_04.gif → bkg-corner-04.gif} +0 -0
  21. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_bottom.gif → bkg-shadow-bottom.gif} +0 -0
  22. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_left.gif → bkg-shadow-left.gif} +0 -0
  23. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_right.gif → bkg-shadow-right.gif} +0 -0
  24. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_top.gif → bkg-shadow-top.gif} +0 -0
  25. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_blue.gif → header-blue.gif} +0 -0
  26. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_dblue.gif → header-dblue.gif} +0 -0
  27. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_green.gif → header-green.gif} +0 -0
  28. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_purple.gif → header-purple.gif} +0 -0
  29. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_red.gif → header-red.gif} +0 -0
  30. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_dblue.gif → txt-list-img-dblue.gif} +0 -0
  31. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_green.gif → txt-list-img-green.gif} +0 -0
  32. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_purple.gif → txt-list-img-purple.gif} +0 -0
  33. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_red.gif → txt-list-img-red.gif} +0 -0
  34. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_01.gif → window-corner-01.gif} +0 -0
  35. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_02.gif → window-corner-02.gif} +0 -0
  36. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_03.gif → window-corner-03.gif} +0 -0
  37. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_04.gif → window-corner-04.gif} +0 -0
  38. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_bottom.gif → window-shadow-bottom.gif} +0 -0
  39. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_left.gif → window-shadow-left.gif} +0 -0
  40. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_right.gif → window-shadow-right.gif} +0 -0
  41. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_top.gif → window-shadow-top.gif} +0 -0
  42. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +69 -69
  43. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +39 -53
  44. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +1 -1
  45. data/hobo_files/plugin/lib/extensions.rb +0 -16
  46. data/hobo_files/plugin/lib/hobo/dryml/part_context.rb +1 -1
  47. data/hobo_files/plugin/lib/hobo/dryml/tag_parameters.rb +35 -0
  48. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +2 -2
  49. data/hobo_files/plugin/lib/hobo/dryml/template.rb +165 -236
  50. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +158 -123
  51. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +15 -4
  52. data/hobo_files/plugin/lib/hobo/model.rb +30 -11
  53. data/hobo_files/plugin/lib/hobo/model_controller.rb +13 -9
  54. data/hobo_files/plugin/lib/hobo/model_router.rb +27 -7
  55. data/hobo_files/plugin/lib/hobo/static_tags +0 -2
  56. data/hobo_files/plugin/lib/hobo/user.rb +3 -3
  57. data/hobo_files/plugin/lib/rexml.rb +10 -3
  58. data/hobo_files/plugin/tags/core.dryml +11 -16
  59. data/hobo_files/plugin/tags/rapid.dryml +147 -110
  60. data/hobo_files/plugin/tags/rapid_document_tags.dryml +22 -20
  61. data/hobo_files/plugin/tags/rapid_editing.dryml +41 -41
  62. data/hobo_files/plugin/tags/rapid_forms.dryml +51 -49
  63. data/hobo_files/plugin/tags/rapid_navigation.dryml +34 -34
  64. data/hobo_files/plugin/tags/rapid_pages.dryml +174 -174
  65. data/hobo_files/plugin/tags/rapid_plus.dryml +19 -19
  66. data/hobo_files/plugin/tags/rapid_support.dryml +5 -5
  67. data/hobo_files/plugin/tasks/dump_fixtures.rake +62 -53
  68. data/hobo_files/plugin/tasks/fix_dryml.rake +144 -0
  69. data/hobo_files/plugin/tasks/hobo_tasks.rake +0 -4
  70. metadata +43 -32
  71. data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +0 -9
@@ -20,7 +20,7 @@ class <%= class_name %> < ActiveRecord::Base
20
20
  end
21
21
 
22
22
  def creatable_by?(creator)
23
- false
23
+ true
24
24
  end
25
25
 
26
26
  def updatable_by?(updater, new)
@@ -31,22 +31,6 @@ class Module
31
31
  end
32
32
 
33
33
 
34
- def alias_tag_chain(tag, feature)
35
- if tag.to_s =~ /^[A-Z]/
36
- without = "#{tag}Without#{feature.to_s.camelize}"
37
- with = "#{tag}With#{feature.to_s.camelize}"
38
- else
39
- without = "#{tag}_without_#{feature}"
40
- with = "#{tag}_with_#{feature}"
41
- end
42
-
43
- unless instance_methods.include?(without)
44
- alias_method without, tag
45
- alias_method tag, with
46
- end
47
- end
48
-
49
-
50
34
  # Fix delegate so it doesn't go bang if 'to' is nil
51
35
  def delegate(*methods)
52
36
  options = methods.pop
@@ -20,7 +20,7 @@ module Hobo
20
20
 
21
21
  contexts.map do |dom_id, context|
22
22
  code = context.marshal(session).split("\n").map{|line| "'#{line}\\n'"}.join(" +\n ")
23
- "hoboParts.#{dom_id} = (#{code});\n"
23
+ "hoboParts['#{dom_id}'] = (#{code});\n"
24
24
  end.join
25
25
  end
26
26
 
@@ -0,0 +1,35 @@
1
+ module Hobo
2
+
3
+ module Dryml
4
+
5
+ class NoParameterError < RuntimeError; end
6
+
7
+ class TagParameters < Hash
8
+
9
+ def initialize(parameters, exclude_names=nil)
10
+ if exclude_names.blank?
11
+ update(parameters)
12
+ else
13
+ parameters.each_pair { |k, v| self[k] = v unless k.in?(exclude_names) }
14
+ end
15
+ end
16
+
17
+ def method_missing(name, default_content="")
18
+ if name.to_s =~ /\?$/
19
+ has_key?(name.to_s[0..-2].to_sym)
20
+ else
21
+ self[name]._?.call(default_content) || ""
22
+ end
23
+ end
24
+
25
+ undef_method :default
26
+
27
+ def [](param_name)
28
+ fetch(param_name, nil)
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -45,7 +45,7 @@ module Hobo::Dryml
45
45
 
46
46
  def included(base)
47
47
  @tag_aliases.each do |tag, feature|
48
- base.send(:alias_tag_chain, tag, feature)
48
+ base.send(:alias_method_chain, tag, feature)
49
49
  end
50
50
  end
51
51
 
@@ -54,7 +54,7 @@ module Hobo::Dryml
54
54
  end
55
55
  attr_reader :tag_attrs
56
56
 
57
- def _alias_tag_chain(tag, feature)
57
+ def delayed_alias_method_chain(tag, feature)
58
58
  @tag_aliases[tag] = feature
59
59
  end
60
60
 
@@ -4,15 +4,18 @@ module Hobo::Dryml
4
4
 
5
5
  class Template
6
6
 
7
- DRYML_NAME = "[a-zA-Z_][a-zA-Z0-9_]*"
7
+ DRYML_NAME = "[a-zA-Z\-][a-zA-Z0-9\-]*"
8
8
  DRYML_NAME_RX = /^#{DRYML_NAME}$/
9
+
10
+ RUBY_NAME = "[a-zA-Z_][a-zA-Z0-9_]*"
11
+ RUBY_NAME_RX = /^#{RUBY_NAME}$/
9
12
 
10
13
  CODE_ATTRIBUTE_CHAR = "&"
11
14
 
12
- SPECIAL_ATTRIBUTES = %w(param merge merge_params merge_attrs
13
- for_type
15
+ SPECIAL_ATTRIBUTES = %w(param merge merge-params merge-attrs
16
+ for-type
14
17
  if unless repeat
15
- part part_locals
18
+ part part-locals
16
19
  restore)
17
20
 
18
21
  @build_cache = {}
@@ -134,8 +137,7 @@ module Hobo::Dryml
134
137
 
135
138
 
136
139
  def element_to_erb(el)
137
- dryml_exception("parameter tags (<#{el.name}>) are no more, wake up and smell the coffee", el) if
138
- el.name.starts_with?(":")
140
+ dryml_exception("old-style parameter tag (<#{el.name}>)", el) if el.name.starts_with?(":")
139
141
 
140
142
  @last_element = el
141
143
  case el.dryml_name
@@ -145,7 +147,7 @@ module Hobo::Dryml
145
147
  # return nothing - the include has no presence in the erb source
146
148
  tag_newlines(el)
147
149
 
148
- when "set_theme"
150
+ when "set-theme"
149
151
  require_attribute(el, "name", /^#{DRYML_NAME}$/)
150
152
  @builder.add_build_instruction(:set_theme, :name => el.attributes['name'])
151
153
 
@@ -155,25 +157,18 @@ module Hobo::Dryml
155
157
  when "def"
156
158
  def_element(el)
157
159
 
158
- when "tagbody"
159
- tagbody_element(el)
160
-
161
160
  when "set"
162
161
  set_element(el)
163
162
 
164
- when "set_scoped"
163
+ when "set-scoped"
165
164
  set_scoped_element(el)
166
165
 
167
- when "default_tagbody"
168
- default_tagbody_element(el)
166
+ when "param-content"
167
+ param_content_element(el)
169
168
 
170
169
  else
171
170
  if el.dryml_name.not_in?(Hobo.static_tags) || el.attributes['param'] || el.attributes['restore']
172
- if el.dryml_name =~ /^[A-Z]/
173
- template_call(el)
174
- else
175
- tag_call(el)
176
- end
171
+ tag_call(el)
177
172
  else
178
173
  static_element_to_erb(el)
179
174
  end
@@ -204,7 +199,7 @@ module Hobo::Dryml
204
199
  def set_element(el)
205
200
  assigns = el.attributes.map do |name, value|
206
201
  dryml_exception(el, "invalid name in set") unless name =~ /^#{DRYML_NAME}(\.#{DRYML_NAME})*$/
207
- "#{name} = #{attribute_to_ruby(value)}; "
202
+ "#{ruby_name name} = #{attribute_to_ruby(value)}; "
208
203
  end.join
209
204
  code = apply_control_attributes("begin; #{assigns}; end", el)
210
205
  "<% #{assigns}#{tag_newlines(el)} %>"
@@ -213,8 +208,8 @@ module Hobo::Dryml
213
208
 
214
209
  def set_scoped_element(el)
215
210
  assigns = el.attributes.map do |name, value|
216
- dryml_exception(el, "invalid name in set_scoped") unless name =~ DRYML_NAME_RX
217
- "scope[:#{name}] = #{attribute_to_ruby(value)}; "
211
+ dryml_exception(el, "invalid name in set-scoped") unless name =~ DRYML_NAME_RX
212
+ "scope[:#{ruby_name name}] = #{attribute_to_ruby(value)}; "
218
213
  end.join
219
214
  "<% scope.new_scope { #{assigns}#{tag_newlines(el)} %>#{children_to_erb(el)}<% } %>"
220
215
  end
@@ -222,19 +217,32 @@ module Hobo::Dryml
222
217
 
223
218
  def declared_attributes(def_element)
224
219
  attrspec = def_element.attributes["attrs"]
225
- attr_names = attrspec ? attrspec.split(/\s*,\s*/).every(:to_sym) : []
220
+ attr_names = attrspec ? attrspec.split(/\s*,\s*/).map{ |n| n.underscore.to_sym } : []
226
221
  invalids = attr_names & ([:with, :field, :this] + SPECIAL_ATTRIBUTES.every(:to_sym))
227
222
  dryml_exception("invalid attrs in def: #{invalids * ', '}", def_element) unless invalids.empty?
228
223
  attr_names
229
224
  end
225
+
226
+
227
+ def ruby_name(dryml_name)
228
+ dryml_name.gsub('-', '_')
229
+ end
230
+
231
+
232
+ def with_containing_tag_name(el)
233
+ old = @containing_tag_name
234
+ @containing_tag_name = el.dryml_name
235
+ yield
236
+ @containing_tag_name = old
237
+ end
230
238
 
231
239
 
232
240
  def def_element(el)
233
241
  require_toplevel(el)
234
242
  require_attribute(el, "tag", DRYML_NAME_RX)
235
243
  require_attribute(el, "attrs", /^\s*#{DRYML_NAME}(\s*,\s*#{DRYML_NAME})*\s*$/, true)
236
- require_attribute(el, "alias_of", DRYML_NAME_RX, true)
237
- require_attribute(el, "extend_with", DRYML_NAME_RX, true)
244
+ require_attribute(el, "alias-of", DRYML_NAME_RX, true)
245
+ require_attribute(el, "extend-with", DRYML_NAME_RX, true)
238
246
 
239
247
  unsafe_name = el.attributes["tag"]
240
248
  name = Hobo::Dryml.unreserve(unsafe_name)
@@ -257,32 +265,28 @@ module Hobo::Dryml
257
265
  old_def_name = @def_name
258
266
  @def_name = @def_name ? "#{@def_name}_#{unsafe_name}" : unsafe_name
259
267
 
260
- alias_of = el.attributes['alias_of']
261
- extend_with = el.attributes['extend_with']
268
+ alias_of = el.attributes['alias-of']
269
+ extend_with = el.attributes['extend-with']
262
270
 
263
- dryml_exception("def cannot have both alias_of and extend_with", el) if alias_of && extend_with
264
- dryml_exception("def with alias_of must be empty", el) if alias_of and el.size > 0
271
+ dryml_exception("def cannot have both alias-of and extend-with", el) if alias_of && extend_with
272
+ dryml_exception("def with alias-of must be empty", el) if alias_of and el.size > 0
265
273
 
266
274
 
267
275
  @builder.add_build_instruction(:alias_method,
268
- :new => name.to_sym, :old => alias_of.to_sym) if alias_of
276
+ :new => ruby_name(name).to_sym, :old => ruby_name(alias_of).to_sym) if alias_of
269
277
 
270
278
  res = if alias_of
271
279
  "<% #{tag_newlines(el)} %>"
272
280
  else
273
281
  src = ""
274
282
  if extend_with
275
- src << "<% _alias_tag_chain :#{name}, :#{extend_with} %>"
276
- name = extended_name(name, extend_with)
283
+ src << "<% delayed_alias_method_chain :#{ruby_name name}, :#{ruby_name extend_with} %>"
284
+ name = "#{name}-with-#{extend_with}"
277
285
  end
278
- src << if template_name?(name)
279
- template_method(name, el)
280
- else
281
- tag_method(name, el)
282
- end
283
- src << "<% _register_tag_attrs(:#{name}, #{declared_attributes(el).inspect}) %>"
286
+ src << tag_method(name, el) +
287
+ "<% _register_tag_attrs(:#{ruby_name name}, #{declared_attributes(el).inspect.underscore}) %>"
284
288
 
285
- logger.debug(restore_erb_scriptlets(src)) if el.attributes["debug_source"]
289
+ logger.debug(restore_erb_scriptlets(src)) if el.attributes["debug-source"]
286
290
 
287
291
  @builder.add_build_instruction(:def,
288
292
  :src => restore_erb_scriptlets(src),
@@ -295,62 +299,36 @@ module Hobo::Dryml
295
299
  end
296
300
 
297
301
 
298
- def extended_name(name, feature)
299
- if template_name?(name)
300
- "#{name}With#{feature.camelize}"
301
- else
302
- "#{name}_with_#{feature}"
303
- end
304
- end
305
-
306
-
307
- def template_call?(el)
308
- template_name?(el.dryml_name)
309
- end
310
-
311
-
312
- def template_name?(name)
313
- name =~ /^[A-Z]/
314
- end
315
-
316
-
317
- def param_names_in_template(el)
302
+ def param_names_in_definition(el)
318
303
  REXML::XPath.match(el, ".//*[@param]").map do |e|
319
304
  name = get_param_name(e)
320
305
  dryml_exception("invalid param name: #{name.inspect}", e) unless
321
- is_code_attribute?(name) || name =~ DRYML_NAME_RX || name =~ /#\{/
306
+ is_code_attribute?(name) || name =~ RUBY_NAME_RX || name =~ /#\{/
322
307
  name.to_sym unless is_code_attribute?(name)
323
308
  end.compact
324
309
  end
325
310
 
326
311
 
327
- def template_method(name, el)
328
- param_names = param_names_in_template(el)
312
+ def tag_method(name, el)
313
+ param_names = param_names_in_definition(el)
329
314
 
330
- "<% def #{name}(all_attributes={}, all_parameters={}, &__block__); " +
331
- "parameters = all_parameters - #{param_names.inspect}; " +
315
+ "<% def #{ruby_name name}(all_attributes={}, all_parameters={}); " +
316
+ "parameters = Hobo::Dryml::TagParameters.new(all_parameters, #{param_names.inspect.underscore}); " +
317
+ "all_parameters = Hobo::Dryml::TagParameters.new(all_parameters); " +
332
318
  tag_method_body(el) +
333
319
  "; end %>"
334
320
  end
335
321
 
336
-
337
- def tag_method(name, el)
338
- "<% def #{name}(all_attributes={}, &__block__); " +
339
- "parameters = nil; " +
340
- tag_method_body(el) +
341
- "; end %>"
342
- end
343
-
344
-
345
- def tag_method_body(el, attributes_var="all_attributes", block_var="__block__")
322
+
323
+ def tag_method_body(el)
346
324
  attrs = declared_attributes(el)
347
325
 
348
326
  # A statement to assign values to local variables named after the tag's attrs
349
327
  # The trailing comma on `attributes` is supposed to be there!
350
- setup_locals = attrs.map{|a| "#{Hobo::Dryml.unreserve(a)}, "}.join + "attributes, = " +
351
- "_tag_locals(#{attributes_var}, #{attrs.inspect})"
328
+ setup_locals = attrs.map{|a| "#{Hobo::Dryml.unreserve(a).underscore}, "}.join + "attributes, = " +
329
+ "_tag_locals(all_attributes, #{attrs.inspect})"
352
330
 
353
- start = "_tag_context(#{attributes_var}, #{block_var}) do |tagbody| #{setup_locals}"
331
+ start = "_tag_context(all_attributes) do #{setup_locals}"
354
332
 
355
333
  "#{start} " +
356
334
  # reproduce any line breaks in the start-tag so that line numbers are preserved
@@ -359,38 +337,11 @@ module Hobo::Dryml
359
337
  "<% _erbout; end"
360
338
  end
361
339
 
362
-
363
- def tagbody_element(el)
364
- dryml_exception("tagbody can only appear inside a <def>", el) unless
365
- find_ancestor(el) {|e| e.name == 'def'}
366
- dryml_exception("tagbody cannot appear inside a part", el) if
367
- find_ancestor(el) {|e| e.attributes['part']}
368
- tagbody_call(el)
369
- end
370
-
371
-
372
- def tagbody_call(el)
373
- attributes = []
374
- with = el.attributes['with']
375
- field = el.attributes['field']
376
- attributes << ":with => #{attribute_to_ruby(with)}" if with
377
- attributes << ":field => #{attribute_to_ruby(field)}" if field
378
-
379
- default_body = if el.children.empty?
380
- "nil"
381
- else
382
- "proc { %>#{children_to_erb(el)}<% }"
383
- end
384
-
385
- call = apply_control_attributes("do_tagbody(tagbody, {#{attributes * ', '}}, #{default_body})", el)
386
- "<% _output(#{call}) %>"
387
- end
388
-
389
-
390
- def default_tagbody_element(el)
340
+
341
+ def param_content_element(el)
391
342
  name = el.attributes['for'] || @containing_tag_name
392
- local_name = default_tagbody_name(name)
393
- "<% #{local_name} && #{local_name}.call %>"
343
+ local_name = param_content_local_name(name)
344
+ "<%= #{local_name} && #{local_name}.call %>"
394
345
  end
395
346
 
396
347
 
@@ -398,8 +349,9 @@ module Hobo::Dryml
398
349
  require_attribute(el, "part", DRYML_NAME_RX)
399
350
  part_name = el.attributes['part']
400
351
  dom_id = el.attributes['id'] || part_name
352
+ part_name = ruby_name(part_name)
401
353
 
402
- part_locals = el.attributes["part_locals"]
354
+ part_locals = el.attributes["part-locals"]
403
355
 
404
356
  part_src = "<% def #{part_name}_part(#{part_locals._?.gsub('@', '')}) #{tag_newlines(el)}; new_context do %>" +
405
357
  content +
@@ -417,28 +369,23 @@ module Hobo::Dryml
417
369
 
418
370
  if param_name
419
371
  def_tag = find_ancestor(el) {|e| e.name == "def"}
420
- dryml_exception("param is not allowed outside of template definitions", el) if
421
- def_tag.nil? || !template_name?(def_tag.attributes["tag"])
372
+ dryml_exception("param is not allowed outside of tag definitions", el) if def_tag.nil?
373
+
374
+ ruby_name(param_name == "&true" ? el.dryml_name : param_name)
375
+ else
376
+ nil
422
377
  end
423
-
424
- res = param_name == "&true" ? el.dryml_name : param_name
425
-
426
- dryml_exception("param '#{res}' is for a template call must be capitalised", el) if
427
- res && template_call?(el) && !template_name?(res)
428
- dryml_exception("param '#{res}' is for a block-tag call and must not be capitalised", el) if
429
- res && !template_call?(el) && template_name?(res)
430
-
431
- res
432
378
  end
433
379
 
434
380
 
435
381
  def call_name(el)
436
- Hobo::Dryml.unreserve(el.dryml_name)
382
+ dryml_exception("invalid tag name", el) unless el.dryml_name =~ /^#{DRYML_NAME}(\.#{DRYML_NAME})*$/
383
+ Hobo::Dryml.unreserve(ruby_name(el.dryml_name))
437
384
  end
438
385
 
439
386
 
440
387
  def polymorphic_call_type(el)
441
- t = el.attributes['for_type']
388
+ t = el.attributes['for-type']
442
389
  if t.nil?
443
390
  nil
444
391
  elsif t == "&true"
@@ -450,42 +397,42 @@ module Hobo::Dryml
450
397
  elsif is_code_attribute?(t)
451
398
  t[1..-1]
452
399
  else
453
- dryml_exception("invalid for_type attribute", el)
400
+ dryml_exception("invalid for-type attribute", el)
454
401
  end
455
402
  end
456
403
 
457
404
 
458
- def template_call(el)
405
+ def tag_call(el)
459
406
  name = call_name(el)
460
407
  param_name = get_param_name(el)
461
408
  attributes = tag_attributes(el)
462
409
  newlines = tag_newlines(el)
463
410
 
464
- parameters = tag_newlines(el) + tag_parameters(el)
411
+ parameters = tag_newlines(el) + parameter_tags_hash(el)
465
412
 
466
- is_param_default_call = el.attributes['restore']
413
+ is_param_restore = el.attributes['restore']
467
414
 
468
415
  call = if param_name
469
416
  param_name = attribute_to_ruby(param_name, :symbolize => true)
470
- args = "#{attributes}, #{parameters}, all_parameters[#{param_name}]"
471
- to_call = if is_param_default_call
417
+ args = "#{attributes}, #{parameters}, all_parameters, #{param_name}"
418
+ to_call = if is_param_restore
472
419
  # The tag is available in a local variable
473
420
  # holding a proc
474
- name
421
+ param_restore_local_name(name)
475
422
  elsif (call_type = polymorphic_call_type(el))
476
- "find_polymorphic_template(:#{name}, #{call_type})"
423
+ "find_polymorphic_tag(:#{name.underscore}, #{call_type})"
477
424
  else
478
- ":#{name}"
425
+ ":#{name.underscore}"
479
426
  end
480
- "call_template_parameter(#{to_call}, #{args})"
427
+ "call_tag_parameter(#{to_call}, #{args})"
481
428
  else
482
- if is_param_default_call
429
+ if is_param_restore
483
430
  # The tag is a proc available in a local variable
484
- "#{default_parameter_name(name)}.call(#{attributes}, #{parameters})"
431
+ "#{param_restore_local_name(name)}.call(#{attributes}, #{parameters})"
485
432
  elsif (call_type = polymorphic_call_type(el))
486
- "send(find_polymorphic_template(:#{name}, #{call_type}), #{attributes}, #{parameters})"
433
+ "send(find_polymorphic_tag(:#{name.underscore}, #{call_type}), #{attributes}, #{parameters})"
487
434
  else
488
- "#{name}(#{attributes}, #{parameters})"
435
+ "#{name.underscore}(#{attributes}, #{parameters})"
489
436
  end
490
437
  end
491
438
 
@@ -501,41 +448,69 @@ module Hobo::Dryml
501
448
  end
502
449
 
503
450
 
504
- # Tag parameters are parameters to templates.
505
- def tag_parameters(el)
506
- dryml_exception("content is not allowed directly inside template calls", el) if
507
- el.children.find { |e| e.is_a?(REXML::Text) && !e.to_s.blank? }
508
-
451
+ def parameter_tags_hash(el)
452
+ call_type = nil
453
+
509
454
  param_items = el.map do |node|
510
455
  case node
511
456
  when REXML::Text
512
- # Just whitespace
457
+ text = node.to_s
458
+ if text.blank?
459
+ # include whitespace in hash literal to keep line numbers
460
+ # matching
461
+ text
462
+ else
463
+ case call_type
464
+ when nil
465
+ call_type = :default_param_only
466
+ text
467
+ when :default_param_only
468
+ text
469
+ when :named_params
470
+ dryml_exception("mixed content and parameter tags", el)
471
+ end
472
+ end
513
473
  node.to_s
514
474
  when REXML::Element
515
475
  e = node
516
- param_name = get_param_name(e)
517
- if param_name
518
- if template_call?(e)
519
- ":#{e.name} => merge_template_parameter(#{template_proc(e)}, all_parameters[:#{param_name}]), "
476
+ is_parameter_tag = e.parameter_tag?
477
+
478
+ # Make sure there isn't a mix of parameter tags and normal content
479
+ case call_type
480
+ when nil
481
+ call_type = is_parameter_tag ? :named_params : :default_param_only
482
+ when :named_params
483
+ dryml_exception("mixed parameter tags and non-parameter tags", el) unless is_parameter_tag
484
+ when :default_param_only
485
+ dryml_exception("mixed parameter tags and non-parameter tags", el) if is_parameter_tag
486
+ end
487
+
488
+ if is_parameter_tag
489
+ param_name = get_param_name(e)
490
+ if param_name
491
+ ":#{ruby_name e.name} => merge_tag_parameter(#{param_proc(e)}, all_parameters[:#{param_name}]), "
520
492
  else
521
- ":#{e.name} => merge_block_tag_parameter(#{template_proc(e)}, all_parameters[:#{param_name}]), "
493
+ ":#{ruby_name e.name} => #{param_proc(e)}, "
522
494
  end
523
- else
524
- ":#{e.name} => #{template_proc(e)}, "
525
495
  end
526
496
  end
527
497
  end.join
528
498
 
499
+ if call_type == :default_param_only
500
+ with_containing_tag_name(el) do
501
+ param_items = " :default => #{default_param_proc(el)}, "
502
+ end
503
+ end
529
504
 
530
- merge_params = el.attributes['merge_params'] || merge_attribute(el)
505
+ merge_params = el.attributes['merge-params'] || merge_attribute(el)
531
506
  if merge_params
532
507
  extra_params = if merge_params == "&true"
533
508
  "parameters"
534
- elsif is_code_attribute?(merge_params)
535
- merge_params[1..-1]
536
- else
537
- dryml_exception("invalid merge_params", el)
538
- end
509
+ elsif is_code_attribute?(merge_params)
510
+ merge_params[1..-1]
511
+ else
512
+ dryml_exception("invalid merge_params", el)
513
+ end
539
514
  "{#{param_items}}.merge((#{extra_params}) || {})"
540
515
  else
541
516
  "{#{param_items}}"
@@ -543,96 +518,46 @@ module Hobo::Dryml
543
518
  end
544
519
 
545
520
 
546
- def template_proc(el)
521
+ def default_param_proc(el)
522
+ "proc { |#{param_content_local_name(el.dryml_name)}| new_context { %>#{children_to_erb(el)}<% } #{tag_newlines(el)}}"
523
+ end
524
+
525
+
526
+ def param_restore_local_name(name)
527
+ "_#{name.underscore}_restore"
528
+ end
529
+
530
+
531
+ def param_proc(el)
532
+ param_name = el.dryml_name
547
533
  nl = tag_newlines(el)
534
+
548
535
  if (repl = el.attribute("replace"))
549
536
  dryml_exception("replace attribute must not have a value", el) if repl.has_rhs?
550
537
  dryml_exception("replace parameters must not have attributes", el) if el.attributes.length > 1
551
538
 
552
- "proc {|#{default_parameter_name(el.dryml_name)}| new_context { %>#{children_to_erb(el)}<% } #{nl}}"
539
+ "proc { |#{param_restore_local_name(param_name)}| new_context { %>#{children_to_erb(el)}<% } #{nl}}"
553
540
  else
554
541
  attributes = el.attributes.map do
555
- |name, value| ":#{name} => #{attribute_to_ruby(value, el)}" unless name.in?(SPECIAL_ATTRIBUTES)
542
+ |name, value| ":#{ruby_name name} => #{attribute_to_ruby(value, el)}" unless name.in?(SPECIAL_ATTRIBUTES)
556
543
  end.compact
557
-
558
- if template_call?(el || modifiers.first)
559
- parameters = el ? tag_parameters(el) : "{}"
560
- "proc { [{#{attributes * ', '}}, #{parameters}] #{nl}}"
561
- else
562
- if el && el.has_end_tag?
563
- old = @containing_tag_name
564
- @containing_tag_name = el.dryml_name
565
- body = children_to_erb(el)
566
- @containing_tag_name = old
567
-
568
- attributes << ":tagbody => proc {|#{default_tagbody_name(el.dryml_name)}| new_context { %>#{body}<% } } "
569
- end
570
- "proc { {#{attributes * ', '}} #{nl}}"
571
- end
544
+
545
+ nested_parameters_hash = parameter_tags_hash(el)
546
+ "proc { [{#{attributes * ', '}}, #{nested_parameters_hash}] #{nl}}"
572
547
  end
573
548
  end
574
549
 
575
550
 
576
- def default_parameter_name(name)
577
- "_#{name}__default"
551
+ def param_content_local_name(name)
552
+ "_#{name.underscore}__default_content"
578
553
  end
579
554
 
580
-
581
- def default_tagbody_name(name)
582
- "_#{name}_default_tagbody"
583
- end
584
-
585
-
586
- def tag_call(el)
587
- name = call_name(el)
588
- param_name = get_param_name(el)
589
- attributes = tag_attributes(el)
590
- newlines = tag_newlines(el)
591
-
592
- is_param_default_call = el.attributes['restore']
593
-
594
- call = if param_name
595
- to_call = if is_param_default_call
596
- # The tag is available in a local variable
597
- # holding a proc
598
- name
599
- elsif (call_type = polymorphic_call_type(el))
600
- "find_polymorphic_tag(:#{name}, #{call_type})"
601
- else
602
- ":#{name}"
603
- end
604
- param_name = attribute_to_ruby(param_name, :symbolize => true)
605
- "call_block_tag_parameter(#{to_call}, #{attributes}, all_parameters[#{param_name}])"
606
- else
607
- if is_param_default_call
608
- "#{default_parameter_name(name)}.call_with_block(#{attributes})"
609
- elsif (call_type = polymorphic_call_type(el))
610
- "send(find_polymorphic_tag(:#{name}, #{call_type}), #{attributes})"
611
- else
612
- "#{name}(#{attributes unless attributes == '{}'})"
613
- end
614
- end
615
-
616
- if el.children.empty?
617
- call = apply_control_attributes(call, el)
618
- maybe_make_part_call(el, "<%= #{call} #{newlines}%>")
619
- else
620
- old = @containing_tag_name
621
- @containing_tag_name = el.dryml_name
622
- children = children_to_erb(el)
623
- @containing_tag_name = old
624
555
 
625
- call_statement = "#{call} do |#{default_tagbody_name(el.dryml_name)}| #{newlines}%>#{children}<% end"
626
- call = "<% _output(" + apply_control_attributes(call_statement, el) + ") %>"
627
- maybe_make_part_call(el, call)
628
- end
629
- end
630
-
631
556
  def maybe_make_part_call(el, call)
632
557
  part_name = el.attributes['part']
633
558
  if part_name
634
559
  part_id = part_name && "<%= #{attribute_to_ruby(el.attributes['id'] || part_name)} %>"
635
- "<span class='part_wrapper' id='#{part_id}'>" + part_element(el, call) + "</span>"
560
+ "<span class='part-wrapper' id='#{part_id}'>" + part_element(el, call) + "</span>"
636
561
  else
637
562
  call
638
563
  end
@@ -642,22 +567,26 @@ module Hobo::Dryml
642
567
  def tag_attributes(el)
643
568
  attributes = el.attributes
644
569
  items = attributes.map do |n,v|
645
- ":#{n} => #{attribute_to_ruby(v)}" unless n.in?(SPECIAL_ATTRIBUTES)
570
+ dryml_exception("invalid attribute name '#{n}'", el) unless n =~ DRYML_NAME_RX
571
+
572
+ unless n.in?(SPECIAL_ATTRIBUTES)
573
+ ":#{ruby_name n} => #{attribute_to_ruby(v)}"
574
+ end
646
575
  end.compact
647
576
 
648
577
  # if there's a ':' el.name is just the part after the ':'
649
- items << ":field => \"#{el.name}\"" if el.name != el.expanded_name
578
+ items << ":field => \"#{el.name}\"" if el.name != el.dryml_name
650
579
 
651
580
  items = items.join(", ")
652
581
 
653
- merge_attrs = attributes['merge_attrs'] || merge_attribute(el)
582
+ merge_attrs = attributes['merge-attrs'] || merge_attribute(el)
654
583
  if merge_attrs
655
584
  extra_attributes = if merge_attrs == "&true"
656
585
  "attributes"
657
586
  elsif is_code_attribute?(merge_attrs)
658
587
  merge_attrs[1..-1]
659
588
  else
660
- dryml_exception("invalid merge_attrs", el)
589
+ dryml_exception("invalid merge-attrs", el)
661
590
  end
662
591
  "merge_attrs({#{items}},(#{extra_attributes}) || {})"
663
592
  else
@@ -670,7 +599,7 @@ module Hobo::Dryml
670
599
  attrs = el.attributes.map do |n, v|
671
600
  next if n.in? SPECIAL_ATTRIBUTES
672
601
  val = restore_erb_scriptlets(v).gsub('"', '\"').gsub(/<%=(.*?)%>/, '#{\1}')
673
- %(:#{n} => "#{val}")
602
+ %('#{n}' => "#{val}")
674
603
  end.compact
675
604
 
676
605
  # If there's a part but no id, the id defaults to the part name
@@ -679,9 +608,9 @@ module Hobo::Dryml
679
608
  end
680
609
 
681
610
  # Convert the attributes hash to a call to merge_attrs if
682
- # there's a merge_attrs attribute
683
- attrs = if (merge_attrs = el.attributes['merge_attrs'])
684
- dryml_exception("merge_attrs was given a string", el) unless is_code_attribute?(merge_attrs)
611
+ # there's a merge-attrs attribute
612
+ attrs = if (merge_attrs = el.attributes['merge-attrs'])
613
+ dryml_exception("merge-attrs was given a string", el) unless is_code_attribute?(merge_attrs)
685
614
 
686
615
  "merge_attrs({#{attrs * ', '}}, " +
687
616
  "((__merge_attrs__ = (#{merge_attrs[1..-1]})) == true ? attributes : __merge_attrs__))"
@@ -692,7 +621,7 @@ module Hobo::Dryml
692
621
  if el.children.empty?
693
622
  dryml_exception("part attribute on empty static tag", el) if part
694
623
 
695
- "<%= " + apply_control_attributes("tag(:#{el.name}, #{attrs} #{tag_newlines(el)})", el) + " %>"
624
+ "<%= " + apply_control_attributes("element(:#{el.name}, #{attrs} #{tag_newlines(el)})", el) + " %>"
696
625
  else
697
626
  if part
698
627
  body = part_element(el, children_to_erb(el))
@@ -700,14 +629,14 @@ module Hobo::Dryml
700
629
  body = children_to_erb(el)
701
630
  end
702
631
 
703
- output_tag = "tag(:#{el.name}, #{attrs}, true) + new_context { %>#{body}</#{el.name}><% }"
632
+ output_tag = "element(:#{el.name}, #{attrs}, new_context { %>#{body}<% })"
704
633
  "<% _output(" + apply_control_attributes(output_tag, el) + ") %>"
705
634
  end
706
635
  end
707
636
 
708
637
 
709
638
  def static_element_to_erb(el)
710
- if %w(part merge_attrs if unless repeat).any? {|x| el.attributes[x]}
639
+ if %w(part merge-attrs if unless repeat).any? {|x| el.attributes[x]}
711
640
  static_tag_to_method_call(el)
712
641
  else
713
642
  start_tag_src = el.start_tag_source.gsub(REXML::CData::START, "").gsub(REXML::CData::STOP, "")