express_templates 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -41
  3. data/lib/arbre/patches.rb +50 -0
  4. data/lib/core_extensions/proc.rb +1 -0
  5. data/lib/express_templates/compiler.rb +2 -7
  6. data/lib/express_templates/components/base.rb +33 -37
  7. data/lib/express_templates/components/capabilities/resourceful.rb +30 -18
  8. data/lib/express_templates/components/configurable.rb +41 -0
  9. data/lib/express_templates/components/form_rails_support.rb +5 -6
  10. data/lib/express_templates/components/forms/basic_fields.rb +3 -6
  11. data/lib/express_templates/components/forms/checkbox.rb +1 -1
  12. data/lib/express_templates/components/forms/express_form.rb +15 -25
  13. data/lib/express_templates/components/forms/form_component.rb +20 -11
  14. data/lib/express_templates/components/forms/option_support.rb +2 -2
  15. data/lib/express_templates/components/forms/radio.rb +7 -8
  16. data/lib/express_templates/components/forms/select.rb +61 -37
  17. data/lib/express_templates/components/forms/select_collection.rb +2 -8
  18. data/lib/express_templates/components/forms/submit.rb +7 -6
  19. data/lib/express_templates/components/forms.rb +0 -1
  20. data/lib/express_templates/components/tree_for.rb +26 -42
  21. data/lib/express_templates/components.rb +1 -9
  22. data/lib/express_templates/version.rb +1 -1
  23. data/lib/express_templates.rb +2 -3
  24. data/test/components/base_test.rb +17 -15
  25. data/test/components/capabilities/resourceful_test.rb +3 -3
  26. data/test/components/configurable_test.rb +27 -21
  27. data/test/components/forms/basic_fields_test.rb +57 -17
  28. data/test/components/forms/checkbox_test.rb +16 -22
  29. data/test/components/forms/express_form_test.rb +23 -76
  30. data/test/components/forms/radio_test.rb +31 -27
  31. data/test/components/forms/select_test.rb +46 -71
  32. data/test/components/forms/submit_test.rb +10 -5
  33. data/test/components/tree_for_test.rb +24 -52
  34. data/test/dummy/app/views/hello/show.html.et +4 -3
  35. data/test/dummy/app/views/layouts/application.html.et +1 -1
  36. data/test/dummy/log/test.log +4794 -0
  37. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-cDLO4NJHMndDHchOLz8KLD7QBc68WtaAbYxK2r6GsU.cache +0 -0
  38. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/0t68EIwZ96sAqQSxFka9MQyIk4viw8ZIoREMCGiJRx0.cache +0 -0
  39. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/2zt1IbQCnmzGyeZS_I4sYQzrgneSCKIJBRxcffVHlWY.cache +1 -0
  40. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/EDVlXrcn_wEfaZ5nc_4QJBT7lPiIBcX96jBo7PBz-vc.cache +1 -0
  41. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Eso3tkb79hXQ1XdQgjbV03KyQwSeZFAHxVHImsjQ-HQ.cache +2 -0
  42. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/I8LhheC1OlOyvp_qY8kWpqKcZFiqv_BO-l5bExvDEi0.cache +1 -0
  43. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Kf4VrP5sW-qzziYSN-m7p4nETjLiEwwwRfwUOm7rOr0.cache +0 -0
  44. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/QJ0Z8hROMfWpY6f5Chb7GSuDHE4gpabKVQTr9BCZe9s.cache +1 -0
  45. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/T1pSAx767vY7X1UDN0vdF7YGEkI5wMSVUKopsdvp7kI.cache +1 -0
  46. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VlSPFPDK05c7ImadRiRVKzsaa6e15RwX77QR3NYabME.cache +0 -0
  47. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Y7_BbgB9jgJIWYjDCsASySd26DTfPADAu_3DDnLlFog.cache +0 -0
  48. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/g2xQygPqA5kMmp5L3wVGWaUIhdVsxFmOel9FF6M0Fuw.cache +0 -0
  49. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/kaif59owjUr3HBharCH5GUxU6KoW_zXD9a9JiTjIYPY.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/p1cwnBd8RQBm9x5HzDmiiU7RhvnxhPX8VTfi0tTElJY.cache +3 -0
  51. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/qT6_0ti_v6fAjS3wETXqvTkr6W0LP4PB942uLYQzWK8.cache +3 -0
  52. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/y8T65xpx0s3RgT_YiqWEEXIaBsgK4woCNSuZ1zjQZBk.cache +2 -0
  53. data/test/express_templates_test.rb +5 -1
  54. data/test/handler_test.rb +19 -17
  55. data/test/performance_test.rb +11 -7
  56. data/test/test_helper.rb +162 -1
  57. metadata +50 -53
  58. data/lib/express_templates/components/capabilities/adoptable.rb +0 -20
  59. data/lib/express_templates/components/capabilities/building.rb +0 -14
  60. data/lib/express_templates/components/capabilities/conditionality.rb +0 -54
  61. data/lib/express_templates/components/capabilities/configurable.rb +0 -90
  62. data/lib/express_templates/components/capabilities/iterating.rb +0 -75
  63. data/lib/express_templates/components/capabilities/parenting.rb +0 -72
  64. data/lib/express_templates/components/capabilities/rendering.rb +0 -30
  65. data/lib/express_templates/components/capabilities/templating.rb +0 -198
  66. data/lib/express_templates/components/capabilities/wrapping.rb +0 -84
  67. data/lib/express_templates/components/column.rb +0 -13
  68. data/lib/express_templates/components/container.rb +0 -7
  69. data/lib/express_templates/components/content_for.rb +0 -42
  70. data/lib/express_templates/components/for_each.rb +0 -30
  71. data/lib/express_templates/components/forms/form_support.rb +0 -13
  72. data/lib/express_templates/components/null_wrap.rb +0 -41
  73. data/lib/express_templates/components/row.rb +0 -28
  74. data/lib/express_templates/components/table_for.rb +0 -163
  75. data/lib/express_templates/components/unless_block.rb +0 -40
  76. data/lib/express_templates/expander.rb +0 -140
  77. data/lib/express_templates/macro.rb +0 -45
  78. data/lib/express_templates/markup/html_tag.rb +0 -62
  79. data/lib/express_templates/markup/tag.rb +0 -150
  80. data/lib/express_templates/markup/wrapper.rb +0 -94
  81. data/lib/express_templates/markup/yielder.rb +0 -21
  82. data/lib/express_templates/markup.rb +0 -9
  83. data/test/components/column_test.rb +0 -11
  84. data/test/components/conditionality_test.rb +0 -37
  85. data/test/components/container_test.rb +0 -66
  86. data/test/components/content_for_test.rb +0 -60
  87. data/test/components/iterating_test.rb +0 -127
  88. data/test/components/null_wrap_test.rb +0 -28
  89. data/test/components/row_test.rb +0 -16
  90. data/test/components/table_for_test.rb +0 -211
  91. data/test/expander_stack_test.rb +0 -41
  92. data/test/expander_test.rb +0 -99
  93. data/test/markup/tag_test.rb +0 -149
  94. data/test/markup/wrapper_test.rb +0 -42
  95. data/test/markup/yielder_test.rb +0 -9
@@ -1,13 +0,0 @@
1
- module ExpressTemplates
2
- module Components
3
- module Forms
4
- module FormSupport
5
-
6
- def form_action
7
- @config[:action] || "{{@#{resource_name}.try(:persisted?) ? #{resource_path(ivar: true)} : #{collection_path}}}"
8
- end
9
-
10
- end
11
- end
12
- end
13
- end
@@ -1,41 +0,0 @@
1
- module ExpressTemplates
2
- module Components
3
- # NullWrap is useful for creating a node in the component tree that does
4
- # not produce any markup. It can be used in a template fragment to
5
- # wrap bare text or string content where such would not normally be possible.
6
- #
7
- # Example:
8
- #
9
- # ```ruby
10
- # div {
11
- # some_component
12
- # null_wrap {
13
- # "Some text"
14
- # }
15
- # other_component
16
- # }
17
- # ```
18
- #
19
- # Otherwise you can use it to hold already-complied code meant for
20
- # evaluation in the view that needs to be protected from being compiled
21
- # again. This use is largely internal to express_templates. It is not
22
- # expected that users of this library would need this.
23
- #
24
- # Example:
25
- #
26
- # ```ruby
27
- # null_wrap("(@collection.map do |member| \"<li>#{member.name}</li>\").join")
28
- # ```
29
- #
30
- class NullWrap < Components::Container
31
- def initialize(*args)
32
- @already_compiled_stuff = args.shift if args.first.is_a?(String)
33
- super(*args)
34
- end
35
-
36
- def compile
37
- @already_compiled_stuff || compile_children
38
- end
39
- end
40
- end
41
- end
@@ -1,28 +0,0 @@
1
- module ExpressTemplates
2
- module Components
3
- # A Row is a Container implemented as a div with
4
- # a CSS class "row"
5
- #
6
- # An optional dom ID may be specified as a symbol.
7
- #
8
- # Example:
9
- #
10
- # row(:main) {
11
- # p "Some content"
12
- # }
13
- #
14
- # This will render as:
15
- #
16
- # <div id="main" class="row"><p>Some content</p></div>
17
- #
18
- class Row < Container
19
- include Capabilities::Configurable
20
-
21
- emits -> {
22
- div.row(my[:id]) {
23
- _yield
24
- }
25
- }
26
- end
27
- end
28
- end
@@ -1,163 +0,0 @@
1
- module ExpressTemplates
2
- module Components
3
- # Create an html table from a collection of data.
4
- #
5
- # Typically this will be a collection of models
6
- # of the same type. Each member of the collection must
7
- # respond to the column names provided.
8
- #
9
- # Example:
10
- #
11
- # ````ruby
12
- # table_for(:people) do |t|
13
- # t.column :name
14
- # t.column :email
15
- # t.column :phone
16
- # t.column :hourly_rate, header: "Rate",
17
- # formatter: -> (amount) {'$%0.2f' % amount rescue 'N/A'}
18
- # end
19
- # ````
20
- #
21
- # This assumes that a @people variable will exist in the
22
- # view and that it will be a collection whose members respond to
23
- # :name, :email, :phone, :hourly_rate
24
- #
25
- # This will result in markup like the following:
26
- #
27
- # <table id="people">
28
- # <thead>
29
- # <tr>
30
- # <th class="name">Name</th>
31
- # <th class="email">Email</th>
32
- # <th class="phone">Phone</th>
33
- # <th class="hourly_rate">Rate</th>
34
- # </tr>
35
- # </thead>
36
- # <tbody>
37
- # <tr id="person-1">
38
- # <td class="name">Steven Talcott Smith</td>
39
- # <td class="email">steve@aelogica.com</td>
40
- # <td class="phone">415-555-1212</td>
41
- # <td class="hourly_rate">$250.00</td>
42
- # </tr>
43
- # </tbody>
44
- # </table>
45
- #
46
- # Note that column options include :formatter and :header.
47
- #
48
- # :formatter may be a stabby lambda which is passed the value to be formatted.
49
- #
50
- # :header may be either a string
51
- #
52
- class TableFor < Base
53
- include Capabilities::Configurable
54
- include Capabilities::Building
55
-
56
- def initialize(*args)
57
- super(*args)
58
- _process_args!(args) # from Configurable
59
- yield(self) if block_given?
60
- end
61
-
62
- attr :columns
63
-
64
- def column(name, options = {})
65
- @columns ||= []
66
- @columns << Column.new(name, options)
67
- end
68
-
69
- emits -> {
70
- table(my[:id]) {
71
- thead {
72
- tr {
73
- columns.each do |column|
74
- th.send(column.name) {
75
- column.title
76
- }
77
- end
78
- }
79
- }
80
- tbody {
81
- for_each("@#{my[:id]}".to_sym) {
82
-
83
- tr(id: "#{my[:id].to_s.singularize}-{{#{my[:id].to_s.singularize}.id}}",
84
- class: my[:id].to_s.singularize) {
85
-
86
- columns.each do |column|
87
- if(column.has_actions?)
88
- td(class: column.name) {
89
- column.show_actions(my[:id].to_s)
90
- }
91
- else
92
- td(class: column.name) {
93
- column.format(my[:id].to_s.singularize)
94
- }
95
- end
96
- end
97
- }
98
- }
99
- }
100
- }
101
- }
102
-
103
- def wrap_for_stack_trace(body)
104
- "ExpressTemplates::Components::TableFor.render_in(self) {\n#{body}\n}"
105
- end
106
-
107
- def compile
108
- wrap_for_stack_trace(lookup(:markup))
109
- end
110
-
111
- class Column
112
- attr :name, :options
113
- def initialize(name, options = {})
114
- @name = name
115
- @options = options
116
- @formatter = options[:formatter]
117
- @header = options[:header]
118
- @actions = options[:actions] || []
119
- end
120
-
121
- def has_actions?
122
- @actions.any?
123
- end
124
-
125
- def format(item_name)
126
- if @formatter.nil?
127
- "\#\{#{item_name}.#{name}\}"
128
- elsif @formatter.kind_of?(Proc)
129
- "\#\{(#{@formatter.source}).call(#{item_name}.#{name})\}"
130
- end
131
- end
132
-
133
- def show_actions(item_name)
134
- action_links = StringIO.new
135
- @actions.each do |action|
136
- action_name = action.to_s
137
- if action_name.eql?('edit')
138
- action_links.puts "<a href='/#{item_name}/{{#{item_name.singularize}.id}}/edit'>Edit</a>"
139
- elsif action_name.eql?('delete')
140
- action_links.puts "<a href='/#{item_name}/{{#{item_name.singularize}.id}}' data-method='delete' data-confirm='Are you sure?'>Delete</a>"
141
- elsif action_name.eql?('show')
142
- action_links.puts "<a href='/#{item_name}/{{#{item_name.singularize}.id}}'>Show</a>"
143
- end
144
- end
145
- action_links.string
146
- end
147
-
148
- def title
149
- case
150
- when @header.nil?
151
- @name.to_s.try(:titleize)
152
- when @header.kind_of?(String)
153
- @header
154
- when @header.kind_of?(Proc)
155
- "{{(#{@header.source}).call(#{@name})}}"
156
- end
157
- end
158
- end
159
-
160
- end
161
-
162
- end
163
- end
@@ -1,40 +0,0 @@
1
- module ExpressTemplates
2
- module Components
3
- class UnlessBlock < Components::Container
4
-
5
- attr :conditional
6
-
7
- def initialize(*args)
8
- @conditional = args.shift
9
- @alt = args.shift[:alt] if args.first.kind_of?(Hash)
10
- parent = args.shift
11
- if @conditional.kind_of?(Symbol)
12
- @conditional = @conditional.to_s
13
- elsif @conditional.kind_of?(Proc)
14
- @conditional = "(#{@conditional.source}.call)"
15
- elsif iterator.kind_of?(String)
16
- @conditional = "(#{@conditional}.call)"
17
- else
18
- raise "UnlessBlock unknown conditional: #{@conditional.inspect}"
19
- end
20
-
21
- if @alt.kind_of?(Proc)
22
- @alt = _compile_fragment @alt
23
- elsif @alt.nil?
24
- @alt = "''"
25
- end
26
- end
27
-
28
- def compile
29
- s = unless @alt
30
- %Q((unless #{@conditional}#{compile_children}\nend))
31
- else
32
- %Q((unless #{@conditional}#{compile_children}\nelse #{@alt}\nend))
33
- end
34
- puts s if ENV['DEBUG'].eql?('true')
35
- s
36
- end
37
-
38
- end
39
- end
40
- end
@@ -1,140 +0,0 @@
1
- require 'express_templates/components'
2
- module ExpressTemplates
3
- class Expander
4
-
5
- cattr_accessor :module_search_space
6
-
7
- attr_accessor :stack, :handlers, :locals, :template
8
-
9
- def initialize(*args)
10
- initialize_expander(*args)
11
- end
12
-
13
- def initialize_expander(template, handlers = {}, locals = {})
14
- @template = template
15
- @stack = Stack.new
16
- @handlers = handlers
17
- @locals = locals
18
- self
19
- end
20
-
21
- def expand(source=nil, &block)
22
- case
23
- when block.nil? && source
24
- modified = _replace_yield_with_yielder(source)
25
- instance_eval(modified, @template.inspect)
26
- when block
27
- instance_exec &block
28
- else
29
- raise ArgumentError
30
- end
31
- stack.current
32
- end
33
-
34
- def process_children!(parent, &block)
35
- begin
36
- stack.descend!
37
- result = instance_exec &block
38
- if stack.current.empty? && result.is_a?(String)
39
- stack << result
40
- end
41
- parent.children += stack.current
42
- stack.ascend!
43
- end
44
- stack.current
45
- end
46
-
47
- # define a "macro" method for a component
48
- # these methods accept args which are passed to the
49
- # initializer for the component
50
- # blocks supplied are evaluated and children added to the "stack"
51
- # are added as children to the component
52
- def self.register_macros_for(*components)
53
- components.each do |component|
54
- define_method(component.macro_name.to_sym) do |*args, &block|
55
- new_component = nil
56
- # this is a code smell here.
57
- if component.ancestors.include?(Components::Capabilities::Building)
58
- new_component = component.new(*(args.push(self)), &block)
59
- else
60
- new_component = component.new(*(args.push(self)))
61
- process_children!(new_component, &block) unless block.nil?
62
- end
63
- stack << new_component
64
- end
65
- end
66
- end
67
-
68
-
69
- @module_search_space = [ExpressTemplates::Markup, ExpressTemplates::Components]
70
-
71
- @module_search_space.each do |mod|
72
- register_macros_for(*
73
- mod.constants.map { |const| [mod.to_s, const.to_s].join("::").constantize }.
74
- select { |klass| klass.ancestors.include? (ExpressTemplates::Markup::Tag) }
75
- )
76
- end
77
-
78
- def method_missing(name, *args, &block)
79
- raise "#{self.class} unexpected macro: \"#{name}\"." if locals.nil?
80
- return locals[name] if locals.keys.include?(name)
81
-
82
- if handlers.keys.include?(name)
83
- stack << handlers[name].send(name, *args, &block)
84
- else
85
- stack << ExpressTemplates::Markup::Wrapper.new(name.to_s, *args, &block)
86
- end
87
- nil
88
- end
89
-
90
- private
91
-
92
- def _replace_yield_with_yielder(source)
93
- source.gsub(/(\W)(yield)(\([^\)]*\))?/, '\1 (stack << ExpressTemplates::Markup::Yielder.new\3)')
94
- end
95
-
96
- class Stack
97
- def initialize
98
- @stack = [[]]
99
- @frame = 0
100
- end
101
-
102
- def all
103
- @stack
104
- end
105
-
106
- def dump
107
- puts "Current frame: #{@frame}"
108
- require 'pp'
109
- pp all
110
- end
111
-
112
- def <<(child)
113
- current << child
114
- child
115
- end
116
-
117
- def current
118
- @stack[@frame]
119
- end
120
-
121
- def next
122
- @stack[@frame+1] ||= []
123
- end
124
-
125
- def descend!
126
- @frame += 1
127
- @stack[@frame] ||= []
128
- @stack[@frame].clear
129
- @frame
130
- end
131
-
132
- def ascend!
133
- raise "Cannot ascend" if @frame <= 0
134
- current.clear ;
135
- self.next.clear
136
- @frame -= 1
137
- end
138
- end
139
- end
140
- end
@@ -1,45 +0,0 @@
1
- module ExpressTemplates
2
- module Macro
3
-
4
- def self.included(base)
5
- base.class_eval do
6
- extend ClassMethods
7
- include InstanceMethods
8
- end
9
- end
10
-
11
- module ClassMethods
12
- def macro_name
13
- to_s.split('::').last.underscore
14
- end
15
- end
16
- module InstanceMethods
17
- def macro_name ; self.class.macro_name end
18
-
19
- def initialize(*children_or_options)
20
- @children = []
21
- @options = {}.with_indifferent_access
22
- # expander passes itself as last arg
23
- @expander = children_or_options.pop if children_or_options.last.kind_of?(ExpressTemplates::Expander)
24
- _process(*children_or_options)
25
- end
26
-
27
- private
28
-
29
- def _process(*children_or_options)
30
- children_or_options.each do |child_or_option|
31
- case
32
- when child_or_option.kind_of?(Hash)
33
- @options.merge!(child_or_option)
34
- when child_or_option.kind_of?(Symbol)
35
- @options.merge!(id: child_or_option.to_s)
36
- when child_or_option.nil?
37
- else
38
- @children << child_or_option
39
- end
40
- end
41
- end
42
-
43
- end
44
- end
45
- end
@@ -1,62 +0,0 @@
1
- module ExpressTemplates
2
- module Markup
3
- class HtmlTag < Tag
4
- NON_VOID_TAGS = [:a, :abbr, :address, :article, :aside, :audio,
5
- :b, :bdi, :bdo, :blockquote, :body, :button,
6
- :canvas, :caption, :cite, :code, :colgroup,
7
- :data, :datalist, :dd, :del, :details, :dfn, :div, :dl, :dt,
8
- :em,
9
- :fieldset, :figcaption, :figure, :footer, :form,
10
- :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :html,
11
- :i, :iframe, :ins,
12
- :kbd,
13
- :label, :legend, :li,
14
- :main, :map, :mark, :math, :menu, :menuitem, :meter,
15
- :nav, :noscript,
16
- :object, :ol, :optgroup, :option, :output,
17
- :p, :pre, :progress,
18
- :q,
19
- :rp, :rt, :ruby,
20
- :s, :samp, :script, :section, :select, :small,
21
- :span, :strong, :style, :sub, :sup, :summary, :svg,
22
- :table, :tbody, :td, :textarea, :tfoot, :th, :thead, :time, :title, :tr,
23
- :u, :ul,
24
- :var, :video]
25
-
26
- VOID_TAGS = [:area, :base, :br, :col, :command, :doctype, :embed, :hr, :img, :input,
27
- :keygen, :link, :meta, :param, :source, :track, :wbr]
28
-
29
- ALL_TAGS = NON_VOID_TAGS + VOID_TAGS
30
- end
31
-
32
- HtmlTag::ALL_TAGS.each do |tag|
33
- klass = tag.to_s.titleize
34
- ExpressTemplates::Markup.module_eval "class #{klass} < ExpressTemplates::Markup::HtmlTag ; end"
35
- end
36
-
37
- HtmlTag::VOID_TAGS.each do |tag|
38
- klass = "ExpressTemplates::Markup::#{tag.to_s.titleize}"
39
- klass.constantize.class_eval do
40
- def close_tag
41
- ''
42
- end
43
-
44
- def transform_close_tag?
45
- false
46
- end
47
- end
48
- end
49
-
50
- Doctype.class_eval do
51
- def start_tag
52
- "<!DOCTYPE html>"
53
- end
54
- end
55
-
56
- I.class_eval do
57
- def should_not_abbreviate?
58
- true
59
- end
60
- end
61
- end
62
- end
@@ -1,150 +0,0 @@
1
- module ExpressTemplates
2
- module Markup
3
- class Tag
4
- include ExpressTemplates::Macro
5
-
6
- attr_accessor :children
7
-
8
- INDENT = ' '
9
-
10
- # These come from Macro but must remain overridden here for performance reasons.
11
- # To verify, comment these two methods and
12
- # run rake test and observe the performance hit. Why?
13
- def self.macro_name
14
- @macro_name ||= to_s.split('::').last.underscore
15
- end
16
-
17
- def macro_name ; self.class.macro_name end
18
-
19
-
20
- def html_options
21
- @options.each_pair.map do |name, value|
22
- case
23
- when name.to_sym.eql?(:data) && value.kind_of?(Hash)
24
- value.each_pair.map {|k,v| %Q(data-#{k}=\\"#{v}\\") }.join(" ")
25
- when value.kind_of?(Proc)
26
- %Q(#{name}=\\"\#{(#{value.source}).call}\\")
27
- else
28
- %Q(#{name}=\\"#{value}\\")
29
- end
30
- end.join(" ")
31
- end
32
-
33
- def start_tag
34
- "<#{macro_name}#{html_options.empty? ? '' : ' '+html_options}>"
35
- end
36
-
37
- def close_tag
38
- "</#{macro_name}>"
39
- end
40
-
41
- def add_css_class(css_class)
42
- @options['class'] ||= ''
43
- css_class = css_class.to_s.gsub('_', '-').gsub(/^-/,'') if css_class.to_s.match /^_.*_/
44
- @options['class'] = (@options['class'].split + [css_class]).uniq.join(" ")
45
- end
46
-
47
- def method_missing(name, *args, &children)
48
- add_css_class(name)
49
- _process(*args) unless args.empty?
50
- if children # in the case where CSS classes are specified via method
51
- unless @expander.nil?
52
- @expander.process_children! self, &children
53
- else
54
- raise "block passed without expander"
55
- end
56
- end
57
- return self
58
- end
59
-
60
- def should_not_abbreviate?
61
- false
62
- end
63
-
64
- def transform_close_tag?
65
- true
66
- end
67
-
68
- def compile
69
- ExpressTemplates::Indenter.for(:markup) do |whitespace|
70
- ruby_fragments = @children.map do |child|
71
- if child.respond_to?(:compile)
72
- child.compile
73
- else
74
- %Q("#{child}")
75
- end
76
- end
77
- unless ruby_fragments.empty?
78
- _wrap_with_tags(ruby_fragments, whitespace)
79
- else
80
- if should_not_abbreviate?
81
- _wrap_with_tags(ruby_fragments, whitespace)
82
- elsif transform_close_tag?
83
- %Q("#{start_tag.gsub(/>$/, ' />')}")
84
- else
85
- %Q("#{start_tag}")
86
- end
87
- end
88
- end
89
- end
90
-
91
- def to_template
92
- # ExpressTemplates::Indenter.for(:template) do
93
- template_fragments = @children.map do |child|
94
- if child.respond_to?(:to_template)
95
- child.to_template
96
- else
97
- child
98
- end
99
- end
100
- macro_name + _blockify(template_fragments.join("\n"))
101
- # end
102
- end
103
-
104
- def self.formatted
105
- old_setting = Thread.current[:formatted]
106
- begin
107
- Thread.current[:formatted] = true
108
- yield if block_given?
109
- ensure
110
- Thread.current[:formatted] = old_setting
111
- end
112
- end
113
-
114
- private
115
-
116
- def _wrap_with_tags(ruby_fragments, whitespace)
117
- opening, closing = nil, nil
118
- if !ENV['ET_NO_INDENT_MARKUP'].eql?('true') || #TODO: change to setting
119
- Thread.current[:formatted]
120
- child_code = ruby_fragments.join
121
- should_format = ruby_fragments.size > 1 ||
122
- (child_code.size > 40 && !child_code.match(/^"\#\{.*\}"$/)) ||
123
- child_code.match(/\n/)
124
-
125
- nl = should_format ? "\n" : nil
126
- nl_after_start = !ruby_fragments.first.try(:match, /^"\n/) ? nl : nil
127
- # binding.pry
128
- nl_before_end = !ruby_fragments.last.try(:match, /\n"$/) ? nl : nil
129
- opening = %Q("\n#{whitespace}#{start_tag}#{nl_after_start}")
130
- closing = %Q("#{nl_before_end}#{should_format && whitespace}#{close_tag}#{nl}")
131
- else
132
- opening = %Q("#{start_tag}")
133
- closing = %Q("#{close_tag}")
134
- end
135
- ruby_fragments.unshift opening
136
- ruby_fragments.push closing
137
- ruby_fragments.reject {|frag| frag.empty? }.join("+")
138
- end
139
-
140
- def _indent(code)
141
- code.split("\n").map {|line| ExpressTemplates::Indenter::WHITESPACE + line }.join("\n")
142
- end
143
-
144
- def _blockify(code)
145
- code.empty? ? code : " {\n#{_indent(code)}\n}\n"
146
- end
147
-
148
- end
149
- end
150
- end