express_templates 0.5.0 → 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 (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