hobo 0.8.5 → 0.8.6

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 (68) hide show
  1. data/CHANGES.txt +41 -0
  2. data/Manifest +1 -5
  3. data/Rakefile +10 -3
  4. data/bin/hobo +38 -15
  5. data/dryml_generators/rapid/cards.dryml.erb +7 -7
  6. data/dryml_generators/rapid/pages.dryml.erb +52 -24
  7. data/hobo.gemspec +42 -322
  8. data/init.rb +0 -7
  9. data/lib/active_record/association_collection.rb +9 -0
  10. data/lib/hobo.rb +13 -14
  11. data/lib/hobo/accessible_associations.rb +32 -7
  12. data/lib/hobo/authentication_support.rb +1 -1
  13. data/lib/hobo/controller.rb +5 -7
  14. data/lib/hobo/dryml.rb +9 -2
  15. data/lib/hobo/dryml/dryml_builder.rb +11 -12
  16. data/lib/hobo/dryml/dryml_doc.rb +22 -24
  17. data/lib/hobo/dryml/dryml_generator.rb +41 -4
  18. data/lib/hobo/dryml/part_context.rb +5 -3
  19. data/lib/hobo/dryml/template.rb +7 -7
  20. data/lib/hobo/dryml/template_environment.rb +11 -22
  21. data/lib/hobo/dryml/template_handler.rb +94 -25
  22. data/lib/hobo/find_for.rb +2 -2
  23. data/lib/hobo/hobo_helper.rb +21 -21
  24. data/lib/hobo/include_in_save.rb +9 -5
  25. data/lib/hobo/lifecycles/transition.rb +2 -2
  26. data/lib/hobo/model.rb +11 -61
  27. data/lib/hobo/model_controller.rb +28 -29
  28. data/lib/hobo/model_router.rb +12 -13
  29. data/lib/hobo/permissions.rb +47 -37
  30. data/lib/hobo/permissions/associations.rb +1 -1
  31. data/lib/hobo/scopes/association_proxy_extensions.rb +5 -6
  32. data/lib/hobo/scopes/automatic_scopes.rb +7 -4
  33. data/lib/hobo/tasks/rails.rb +4 -0
  34. data/lib/hobo/user.rb +0 -1
  35. data/lib/hobo/user_controller.rb +3 -1
  36. data/lib/hobo/view_hints.rb +17 -3
  37. data/rails_generators/hobo/hobo_generator.rb +1 -0
  38. data/rails_generators/hobo_front_controller/templates/functional_test.rb +1 -11
  39. data/rails_generators/hobo_front_controller/templates/index.dryml +1 -6
  40. data/rails_generators/hobo_rapid/hobo_rapid_generator.rb +1 -0
  41. data/rails_generators/hobo_rapid/templates/hobo-rapid.css +3 -2
  42. data/rails_generators/hobo_rapid/templates/hobo-rapid.js +24 -15
  43. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +17 -12
  44. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +6 -2
  45. data/rails_generators/hobo_rapid/templates/themes/clean/views/clean.dryml +2 -2
  46. data/rails_generators/hobo_user_model/templates/forgot_password.erb +2 -2
  47. data/rails_generators/hobo_user_model/templates/model.rb +2 -2
  48. data/taglibs/rapid.dryml +3 -2
  49. data/taglibs/rapid_core.dryml +21 -16
  50. data/taglibs/rapid_document_tags.dryml +1 -1
  51. data/taglibs/rapid_editing.dryml +7 -10
  52. data/taglibs/rapid_forms.dryml +115 -26
  53. data/taglibs/rapid_generics.dryml +13 -3
  54. data/taglibs/rapid_lifecycles.dryml +18 -1
  55. data/taglibs/rapid_navigation.dryml +50 -61
  56. data/taglibs/rapid_pages.dryml +103 -19
  57. data/taglibs/rapid_plus.dryml +54 -6
  58. data/taglibs/rapid_support.dryml +38 -1
  59. data/taglibs/rapid_user_pages.dryml +17 -5
  60. data/test/permissions/models/models.rb +24 -12
  61. data/test/permissions/models/test.sqlite3 +0 -0
  62. metadata +6 -15
  63. data/lib/extensions/test_case.rb +0 -129
  64. data/lib/hobo/composite_model.rb +0 -73
  65. data/lib/hobo/model_support.rb +0 -44
  66. data/tasks/fix_dryml.rake +0 -143
  67. data/tasks/generate_tag_reference.rake +0 -192
  68. data/test/dryml/complilation_test.rb +0 -261
@@ -1,44 +0,0 @@
1
- module Hobo
2
-
3
- module ModelSupport
4
-
5
- # This module provides methods common to both Hobo::Model and Hobo::CompositeModel
6
-
7
- def self.included(base)
8
- base.extend(ClassMethods) if base.is_a? Class
9
- end
10
-
11
- module ClassMethods
12
-
13
- def delegate_and_compose(*methods)
14
- options = methods.pop
15
- unless options.is_a?(Hash) && to = options[:to]
16
- raise ArgumentError, ("Delegation needs a target. Supply an options hash " +
17
- "with a :to key as the last argument (e.g. delegate :hello, :to => :greeter).")
18
- end
19
- use = options[:use]
20
-
21
- methods.each do |method|
22
- module_eval(<<-EOS, "(__COMPOSED_DELEGATION__)", 1)
23
- def #{method}
24
- @__#{method}_result__ ||= begin
25
- obj = #{to}.__send__(#{method.inspect})
26
- return nil if obj.nil?
27
-
28
- if obj.nil?
29
- nil
30
- elsif obj.is_a?(Array)
31
- obj.map {|o| self.compose_with(o, #{use.inspect})}
32
- else
33
- self.compose_with(obj, #{use.inspect})
34
- end
35
- end
36
- end
37
- EOS
38
- end
39
- end
40
-
41
- end
42
-
43
- end
44
- end
@@ -1,143 +0,0 @@
1
- require 'fileutils'
2
-
3
- def restore_erb_scriptlets(scriptlets, src)
4
- src.gsub(/\[!\[HOBO-ERB(\d+)\s*\]!\]/m) {|s| "<%#{scriptlets[$1.to_i]}%>" }
5
- end
6
-
7
-
8
- def fix_nodes(nodes)
9
- nodes.map{|x| fix_element(x) if x.is_a?(REXML::Element) }
10
- end
11
-
12
-
13
- def start_tag_replace(el, repl)
14
- i, len = el.source_offset, el.start_tag_source.length
15
- @src[i..i+len-1] = repl
16
- end
17
-
18
-
19
- def classes?
20
- ENV['CLASS']
21
- end
22
-
23
- def ids?
24
- ENV['ID']
25
- end
26
-
27
-
28
- def string_interpolate_safe_dasherize(s)
29
- token = "[[MAKE_ME_A_DASH!]]"
30
- s.gsub("_", token).
31
- gsub(/\#\{.*?\}/) {|s2| s2.gsub(token, "_") }.
32
- gsub(token, "-")
33
- end
34
-
35
-
36
- def fix_children(element, template_params)
37
- element.elements.to_a.reverse.each do |e|
38
- # recurse first - we're going backwards
39
- is_template_call = e.dryml_name =~ /^[A-Z]/ && !e.attribute("replace")
40
- fix_children(e, is_template_call)
41
-
42
- fixed = fix_element(e, template_params)
43
- start_tag_replace(e, fixed)
44
- end
45
- end
46
-
47
-
48
- def fix_element(e, template_param)
49
- tag = e.start_tag_source.dup
50
-
51
- if e.dryml_name == "tagbody"
52
- tag.sub!("<tagbody", '<do param="default"')
53
- elsif e.dryml_name == "default_tagbody"
54
- tag.sub!("<default_tagbody", '<param-content')
55
- else
56
- tag.sub!("<#{e.dryml_name}", "<#{e.dryml_name.underscore.dasherize}#{':' if template_param}")
57
- end
58
-
59
- start = e.expanded_name.length+1
60
- tag[start..-1] = tag[start..-1].gsub(/([A-Za-z_]+)(\s*=\s*("(.*?)"|'(.*?)'))?/) do |s|
61
- _, name, _, value = *Regexp.last_match
62
-
63
- s.sub!(/^#{name}/, name.dasherize)
64
-
65
- if value
66
- # underscore / dasherize the values of various attributes
67
-
68
- if e.name == "def" && name.in?(%w(tag attrs alias_of extend_with))
69
- s.sub!(/#{Regexp.escape(value)}$/) {|v| v.underscore.dasherize}
70
-
71
- elsif name.in?(%w(part update)) || (classes? && name == 'class') || (ids? && name == 'id')
72
- s.sub!(/#{Regexp.escape(value)}$/) {|v| string_interpolate_safe_dasherize(v) }
73
-
74
- elsif name == "param"
75
- s.sub!(/#{Regexp.escape(value)}$/) {|v| string_interpolate_safe_dasherize(v.underscore) }
76
- end
77
-
78
- end
79
- s
80
- end
81
- tag
82
- end
83
-
84
-
85
- def fix_file(filename)
86
- puts "Fixing #{filename}"
87
- src = File.read(filename)
88
-
89
- # Ripped from Hobo::Dryml::Template - hide erb scriptlets and parse with REXML
90
- scriptlets = {}
91
- src = src.gsub(/<%(.*?)%>/m) do
92
- _, scriptlet = *Regexp.last_match
93
- id = scriptlets.size + 1
94
- scriptlets[id] = scriptlet
95
- newlines = "\n" * scriptlet.count("\n")
96
- "[![HOBO-ERB#{id}#{newlines}]!]"
97
- end
98
-
99
- # DRYML doesn't have to have a single root - add one to keep REXML
100
- # happy
101
- @src = "<root>" + src + "</root>"
102
- begin
103
- doc = Hobo::Dryml::Parser::Document.new(Hobo::Dryml::Parser::Source.new(@src))
104
- rescue REXML::ParseException => e
105
- raise Exception, "File: #{@template_path}\n#{e}"
106
- end
107
-
108
- fix_children(doc[0], false)
109
-
110
- #Fix close tags
111
- @src.gsub!(/<\/[^:>]*/) { |s| s.underscore.dasherize }
112
- @src.gsub!(/<\/tagbody\s*>/, "</do>")
113
-
114
- # Strip the root tag we added
115
- @src.sub!(/^<root>/, "")
116
- @src.sub!(/<\/root>$/, "")
117
-
118
- fixed = restore_erb_scriptlets(scriptlets, @src)
119
- File.open(filename, 'w') { |f| f.write(fixed) }
120
- end
121
-
122
-
123
- namespace :hobo do
124
-
125
- desc "Replace old-style DRYML source code with CamelCaseTags and underscores with new DRYML syntax"
126
- task :fixdryml => :environment do
127
-
128
- dir = ENV['DIR']._?.sub(/\/$/, '') || "app/views"
129
-
130
- # Make a backup
131
- backup_dir = "#{dir.gsub('../', '').gsub('/', '_')}_before_fixdryml"
132
- if File.exist?(backup_dir)
133
- puts "Backup (#{backup_dir}) already exists - be careful! (nothing changed)"
134
- exit
135
- end
136
- FileUtils.cp_r(dir, backup_dir)
137
-
138
- Dir["#{dir}/**/*.dryml"].each do |f|
139
- fix_file(f)
140
- end
141
- end
142
-
143
- end
@@ -1,192 +0,0 @@
1
- require 'fileutils'
2
-
3
- ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) + "/../lib"
4
-
5
- require 'rexml/xpath'
6
- XPath = REXML::XPath
7
-
8
- def tag_title(tag, link=false)
9
- if tag.is_a? String
10
- name = tag
11
- anchor = tag
12
- else
13
- for_attr = tag.attributes['for'] and for_decl = %( for=`"#{for_attr}"`)
14
- name = tag.attributes['tag']
15
- anchor = tag_anchor(tag)
16
- end
17
-
18
- title = "&lt;#{name}#{for_decl}&gt;"
19
-
20
- if link
21
- "[#{title}](##{anchor})"
22
- else
23
- title
24
- end
25
- end
26
-
27
-
28
- def link_to_tag(tag)
29
- tag_title(tag, true)
30
- end
31
-
32
-
33
- def tag_anchor(element)
34
- for_attr = element.attributes['for']
35
- name = element.attributes['tag']
36
-
37
- if for_attr
38
- "#{name}--for-#{for_attr}"
39
- else
40
- name
41
- end
42
- end
43
-
44
-
45
- def comment_for_tag(element)
46
- space = element.previous_sibling and
47
- space.to_s.blank? && space.to_s.count("\n") == 1 and
48
- comment = space.previous_sibling
49
-
50
- comment.to_s.strip if comment.is_a?(REXML::Comment)
51
- end
52
-
53
-
54
- def doc_for_tag(tagdef)
55
- comment = comment_for_tag(tagdef)
56
-
57
- params_merged_with = XPath.first(tagdef, ".//*[@merge|@merge-params]")._?.name
58
- params_merged_with &&= "(merged with #{link_to_tag params_merged_with})"
59
-
60
- attrs_merged_with = XPath.first(tagdef, ".//*[@merge|@merge-attrs]")._?.name
61
- attrs_merged_with &&= "(merged with #{link_to_tag attrs_merged_with})"
62
-
63
- attrs = tagdef.attributes['attrs'] || []
64
- attrs = attrs.split(/,\s*/).where_not.blank?.map { |a| " * #{a}\n" }.join
65
-
66
- parameters = params_to_list(get_parameters(tagdef))
67
- <<-END
68
- ---
69
-
70
- <a name="#{tag_anchor tagdef}">&nbsp;</a>
71
- ## #{tag_title tagdef}
72
-
73
- #{comment}
74
-
75
- ### Attributes #{attrs_merged_with}
76
-
77
- #{attrs.blank? ? 'None' : attrs}
78
-
79
- ### Parameters #{params_merged_with}
80
-
81
- #{parameters.blank? ? 'None' : parameters}
82
- END
83
- end
84
-
85
-
86
- def get_parameters(elem)
87
- result = []
88
- elem.elements.each do |e|
89
- if e.attributes['param']
90
- result << [e, get_parameters(e)]
91
- else
92
- result.concat(get_parameters(e))
93
- end
94
- end
95
- result
96
- end
97
-
98
-
99
- def params_to_list(params, indent=" ")
100
- items = params.map do |elem, sub_params|
101
- p_attr = elem.attributes['param']
102
- entry = if p_attr == "&true"
103
- "&lt;#{elem.name}:&gt;"
104
- elsif p_attr =~ /#\{/
105
- "(dynamic parameter) (&lt;#{elem.name}&gt;)"
106
- else
107
- "&lt;#{p_attr}:&gt; (&lt;#{elem.name}&gt;)"
108
- end
109
- sub_list = params_to_list(sub_params, indent + ' ') unless sub_params.empty?
110
- "<li>#{entry}\n#{sub_list}</li>\n"
111
- end.join
112
-
113
- items.any? ? "<ul>#{items}</ul>" : ""
114
- end
115
-
116
-
117
- def contents(root)
118
- tags = XPath.match(root, '/*/*[@tag]')
119
- tags.map { |tag| " * #{link_to_tag tag}\n" }.join
120
- end
121
-
122
-
123
- def doc_for_taglib(title, root)
124
- tags = XPath.match(root, '/*/*[@tag]').map { |e| doc_for_tag(e) }.join("\n\n")
125
-
126
- "# #{title}\n\n" + contents(root) + "\n\n" + tags
127
- end
128
-
129
- def index_page(output_files, output_dir)
130
- markdown = "# Tag Documentation\n\n" + output_files.map do |f|
131
- link = f.gsub(output_dir+'/', '')
132
- link_text = link.gsub('_', '\_').gsub(/\.html$/, '')
133
- "* [#{link_text}](#{link})"
134
- end.join("\n")
135
-
136
- html = Maruku.new(markdown).to_html
137
-
138
- File.open("#{output_dir}/index.html", 'w') { |f| f.write(html) }
139
- end
140
-
141
- def process_directory(src, output_dir, output_format)
142
- raise RuntimeError, "#{output_dir} is not a directory" if File.exists?(output_dir) && !File.directory?(output_dir)
143
-
144
- FileUtils.mkdir output_dir unless File.exists? output_dir
145
-
146
- dryml_files = File.directory?(src) ? Dir["#{src}/*"] : [src]
147
-
148
- output_files = []
149
-
150
- dryml_files.each do |f|
151
- if File.directory?(f)
152
- output_files += process_directory(f, "#{output_dir}/#{File.basename(f)}", output_format)
153
- elsif f =~ /\.dryml$/
154
- basename = File.basename(f).sub(/\.dryml$/, '')
155
- title = basename.titleize
156
-
157
- doc = Hobo::Dryml::Parser::Document.new(File.read(f), f)
158
-
159
- output = doc.restore_erb_scriptlets(doc_for_taglib(title, doc))
160
- output = Maruku.new(output).to_html.gsub('&amp;', '&') if output_format == 'html'
161
-
162
- output_file = "#{output_dir}/#{basename}.#{output_format}"
163
- puts output_file
164
- File.open(output_file, 'w') { |f| f.write(output) }
165
- output_files << output_file
166
- end
167
- end
168
- output_files
169
- end
170
-
171
-
172
-
173
- namespace :hobo do
174
-
175
- desc "Generate markdown formatted reference docs automatically from DRYML taglibs"
176
- task :generate_tag_reference => :environment do
177
- gem 'maruku'
178
- require 'maruku'
179
-
180
- src = ENV['src']
181
-
182
- output_dir = ENV['output'] || "taglib-docs"
183
-
184
- output_format = ENV['format'] || "markdown"
185
-
186
- output_files = process_directory(src, output_dir, output_format)
187
-
188
- index_page(output_files, output_dir)
189
- end
190
-
191
- end
192
-
@@ -1,261 +0,0 @@
1
- require "#{File.dirname __FILE__}/dryml_test_case"
2
-
3
- class CompilationTest < DrymlTestCase
4
-
5
- should "compile tag calls as method calls" do
6
- assert_compiles_to "<% _output(foo.to_s) %>", "<foo/>"
7
- end
8
-
9
- should "convert dashes in tag names to underscores in compiled method calls" do
10
- assert_compiles_to "<% _output(foo_baa.to_s) %>", "<foo-baa/>"
11
- end
12
-
13
- should "compile attributes as keyword parameters" do
14
- assert_compiles_to '<% _output(foo({:a => "1", :b => "2"}, {})) %>', "<foo a='1' b='2'/>"
15
- end
16
-
17
- should "convert attribute names with dashes in tag calls to symbols with underscores" do
18
- assert_compiles_to "<% _output(foo({:my_attribute => \"1\"}, {})) %>", "<foo my-attribute='1'/>"
19
- end
20
-
21
- should "compile code attributes as ruby code" do
22
- assert_compiles_to '<% _output(foo({:a => (1 + 2)}, {})) %>', "<foo a='&1 + 2'/>"
23
- end
24
-
25
- should "compile attributes with no RHS as passing `true`" do
26
- assert_compiles_to '<% _output(foo({:a => (true)}, {})) %>', "<foo a/>"
27
- end
28
-
29
- should "compile content of a tag call as the default parameter" do
30
- assert_compiles_to "<% _output(foo({}, { :default => proc { |_foo__default_content| new_context { %>the body<% } }, })) %>",
31
- "<foo>the body</foo>"
32
- end
33
-
34
- should "support <param_content/> inside the content of a tag" do
35
- src = "<foo>!!<param-content/>??</foo>"
36
- assert_compiles_to "<% _output(foo({}, { :default => proc { |_foo__default_content| new_context { %>!!<%= _foo__default_content && _foo__default_content.call %>??<% } }, })) %>", src
37
- end
38
-
39
- should "support the 'for' attribute on <param-content/>" do
40
- src = "<x><y>123<param-content for='x'/>456</y></x>"
41
- assert_compiles_to(
42
- "<% _output(x({}, { :default => proc { |_x__default_content| new_context { %><% _output(y({}, { :default => proc { |_y__default_content| new_context { %>" +
43
- "123<%= _x__default_content && _x__default_content.call %>456" +
44
- "<% } }, })) %><% } }, })) %>", src)
45
- end
46
-
47
- should "allow :foo as a shorthand for field='foo' on tags" do
48
- assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
49
- end
50
-
51
- should "allow static tag names like :title as a shorthand for field='title'" do
52
- assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
53
- end
54
-
55
- should "allow close tags to ommit the :field_name part" do
56
- assert_compiles_to '<% _output(foo({:field => "name"}, { :default => proc { |_foo__default_content| new_context { %><% } }, })) %>', "<foo:name></foo>"
57
-
58
- end
59
-
60
- should "compile tag calls with merge-attrs" do
61
- assert_compiles_to "<% _output(foo(merge_attrs({},(attributes) || {}), {})) %>", "<foo merge-attrs/>"
62
- assert_compiles_to '<% _output(foo(merge_attrs({:a => "1"},(attributes) || {}), {})) %>', "<foo a='1' merge-attrs/>"
63
- end
64
-
65
-
66
- # --- Compilation: Defining Tags --- #
67
-
68
- should "compile defs" do
69
- assert_compiles_to(
70
- "<% def foo(all_attributes={}, all_parameters={}); " +
71
- "parameters = Hobo::Dryml::TagParameters.new(all_parameters, []); " +
72
- "all_parameters = Hobo::Dryml::TagParameters.new(all_parameters); " +
73
- "_tag_context(all_attributes) do attributes, = _tag_locals(all_attributes, []) %>" +
74
- "<% _erbout; end; end %>",
75
-
76
- "<def tag='foo'></def>")
77
-
78
- end
79
-
80
- should "compile attrs in defs as local variables" do
81
- assert_compiles_to(
82
- "<% def foo(all_attributes={}, all_parameters={}); " +
83
- "parameters = Hobo::Dryml::TagParameters.new(all_parameters, []); " +
84
- "all_parameters = Hobo::Dryml::TagParameters.new(all_parameters); " +
85
- "_tag_context(all_attributes) do " +
86
- "a, my_attr, attributes, = _tag_locals(all_attributes, [:a, :my_attr]) %>" +
87
- "<% _erbout; end; end %>",
88
-
89
- "<def tag='foo' attrs='a, my-attr'></def>")
90
- end
91
-
92
- should "dissallow `param` outside of tag definitions" do
93
- assert_raise(DrymlException) { compile_dryml("<foo param/>") }
94
- end
95
-
96
- should "compile param-tag calls as calls to `call_tag_parameter`" do
97
- assert_compiles_to '<% _output(call_tag_parameter(:foo, {:a => "1"}, {}, all_parameters, :foo)) %>',
98
- "<foo param a='1'/>",
99
- :in_def
100
- end
101
-
102
- should "compile with support for named params" do
103
- assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, {}, all_parameters, :zap)) %>", "<foo param='zap'/>", :in_def
104
- end
105
-
106
- should "compile a param tag-call with a body" do
107
- assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, { :default => proc { |_foo__default_content| new_context { %>abc<% } }, }, all_parameters, :foo)) %>",
108
- "<foo param>abc</foo>",
109
- :in_def
110
- end
111
-
112
- should "compile a param tag-call with a body and a call to <param_content/>" do
113
- assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, { :default => proc { |_foo__default_content| new_context { %>!!<%= _foo__default_content && _foo__default_content.call %>!!<% } }, }, all_parameters, :foo)) %>",
114
- "<foo param>!!<param-content/>!!</foo>",
115
- :in_def
116
-
117
- end
118
-
119
- should "compile param template-calls as calls to `call_tag_parameter`" do
120
- assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, {}, all_parameters, :foo)) %>",
121
- "<foo param/>",
122
- :in_def
123
- end
124
-
125
- should "compile param tag calls with parameters as calls to `call_tag_parameter`" do
126
- assert_compiles_to '<% _output(call_tag_parameter(:foo, {}, {:a => proc { [{:x => "1"}, {}] }, }, all_parameters, :foo)) %>',
127
- "<foo param><a: x='1'/></foo>",
128
- :in_def
129
- end
130
-
131
- should "compile parameters with param" do
132
- assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{}, {}] }, all_parameters[:abc]), })) %>',
133
- "<foo><abc: param/></foo>",
134
- :in_def
135
- end
136
-
137
- should "compile tag parameters with named params" do
138
- assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{}, {}] }, all_parameters[:x]), })) %>',
139
- "<foo><abc: param='x'/></foo>",
140
- :in_def
141
- end
142
-
143
- should "compile tag parameters with param and attributes" do
144
- assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{:a => "b"}, {}] }, all_parameters[:x]), })) %>',
145
- "<foo><abc: param='x' a='b'/></foo>",
146
- :in_def
147
- end
148
-
149
- should "compile tag parameters with param and a tag body" do
150
- assert_compiles_to(
151
- '<% _output(foo({}, {:abc => merge_tag_parameter(' +
152
- 'proc { [{}, { :default => proc { |_abc__default_content| new_context { %>ha!<% } }, }] }, all_parameters[:abc]), })) %>',
153
- "<foo><abc: param>ha!</abc></foo>",
154
- :in_def)
155
-
156
- end
157
-
158
- should "compile tag parameters with param and nested parameters" do
159
- assert_compiles_to(
160
- '<% _output(foo({}, {:baa => merge_tag_parameter(' +
161
- 'proc { [{}, {:x => proc { [{}, { :default => proc { |_x__default_content| new_context { %>hello<% } }, }] }, }] }, all_parameters[:baa]), })) %>',
162
- "<foo><baa: param><x:>hello</x:></baa:></foo>",
163
- :in_def)
164
- end
165
-
166
- # --- Compilation: Calling tags with parameters --- #
167
-
168
- should "compile tag parameters as procs" do
169
- assert_compiles_to(
170
- '<% _output(foo({}, {' +
171
- ':x => proc { [{}, { :default => proc { |_x__default_content| new_context { %>hello<% } }, }] }, ' +
172
- ':y => proc { [{}, { :default => proc { |_y__default_content| new_context { %>world<% } }, }] }, })) %>',
173
- "<foo><x:>hello</x><y:>world</y:></foo>"
174
- )
175
- end
176
-
177
- should "compile tag parameters with attributes" do
178
- assert_compiles_to(
179
- '<% _output(foo({}, {:abc => proc { [{:x => "1"}, { :default => proc { |_abc__default_content| new_context { %>hello<% } }, }] }, })) %>',
180
- "<foo><abc: x='1'>hello</abc></foo>"
181
- )
182
- end
183
-
184
- should "allow :foo as a shorthand for field='foo' on template tags" do
185
- assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
186
- end
187
-
188
- should "compile template parameters which are themselves templates" do
189
- # Tag parameters with nested tag parameters are procs that return
190
- # a pair of hashes, the first is the attributes, the second is the
191
- # sub-template procs
192
- assert_compiles_to(
193
- '<% _output(foo({}, ' +
194
- '{:baa => proc { [{:x => "1"}, {:a => proc { [{}, { :default => proc { |_a__default_content| new_context { %>hello<% } }, }] }, }] }, })) %>',
195
- "<foo><baa: x='1'><a:>hello</a></baa></foo>")
196
- end
197
-
198
- should "compile 'replace' parameters" do
199
- # A replace parameter is detected at runtime by the arity of the
200
- # block == 1 (for a normal parameter it would be 0). See
201
- # TemplateEnvironment#call_tag_parameter
202
- assert_compiles_to(
203
- '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc<% } }, })) %>',
204
- "<page><head: replace>abc</head></page>"
205
- )
206
- end
207
-
208
- should "compile 'replace' parameters where the restore contains a default parameter call" do
209
- assert_compiles_to(
210
- '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc ' +
211
- '<% _output(_head_restore.call({}, { :default => proc { |_head__default_content| new_context { %>blah<% } }, })) %>' +
212
- '<% } }, })) %>',
213
-
214
- "<page><head: replace>abc <head restore>blah</head></head></page>"
215
- )
216
- end
217
-
218
- should "compile 'replace' tag parameters with a default parameter call" do
219
- assert_compiles_to(
220
- '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc ' +
221
- '<% _output(_head_restore.call({}, {})) %>' +
222
- '<% } }, })) %>',
223
- "<page><head: replace>abc <head restore/></head></page>")
224
- end
225
-
226
-
227
- # --- Compilation: Syntax sugar for before, after, append, prepend --- #
228
-
229
- should "compile 'before' parameters" do
230
- assert_compiles_to(
231
- '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc' +
232
- '<% _output(_head_restore.call({}, {})) %>' +
233
- '<% } }, })) %>',
234
- "<page><before-head:>abc</before-head></page>")
235
- end
236
-
237
- should "compile 'after' parameters" do
238
- assert_compiles_to(
239
- '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>' +
240
- '<% _output(_head_restore.call({}, {})) %>' +
241
- 'abc<% } }, })) %>',
242
- "<page><after-head:>abc</after-head></page>")
243
- end
244
-
245
- should "compile 'apppend' parameters" do
246
- assert_compiles_to(
247
- '<% _output(page({}, {:head => proc { [{}, { :default => proc { |_head__default_content| new_context { %>' +
248
- '<%= _head__default_content && _head__default_content.call %>:o)' +
249
- '<% } } } ] }, })) %>',
250
- "<page><append-head:>:o)</append-head></page>")
251
- end
252
-
253
- should "compile 'prepend' parameters" do
254
- assert_compiles_to(
255
- '<% _output(page({}, {:head => proc { [{}, { :default => proc { |_head__default_content| new_context { %>' +
256
- ':o)<%= _head__default_content && _head__default_content.call %>' +
257
- '<% } } } ] }, })) %>',
258
- "<page><prepend-head:>:o)</prepend-head></page>")
259
- end
260
-
261
- end