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.
- checksums.yaml +4 -4
- data/README.md +22 -41
- data/lib/arbre/patches.rb +50 -0
- data/lib/core_extensions/proc.rb +1 -0
- data/lib/express_templates/compiler.rb +2 -7
- data/lib/express_templates/components/base.rb +33 -37
- data/lib/express_templates/components/capabilities/resourceful.rb +30 -18
- data/lib/express_templates/components/configurable.rb +41 -0
- data/lib/express_templates/components/form_rails_support.rb +5 -6
- data/lib/express_templates/components/forms/basic_fields.rb +3 -6
- data/lib/express_templates/components/forms/checkbox.rb +1 -1
- data/lib/express_templates/components/forms/express_form.rb +15 -25
- data/lib/express_templates/components/forms/form_component.rb +20 -11
- data/lib/express_templates/components/forms/option_support.rb +2 -2
- data/lib/express_templates/components/forms/radio.rb +7 -8
- data/lib/express_templates/components/forms/select.rb +61 -37
- data/lib/express_templates/components/forms/select_collection.rb +2 -8
- data/lib/express_templates/components/forms/submit.rb +7 -6
- data/lib/express_templates/components/forms.rb +0 -1
- data/lib/express_templates/components/tree_for.rb +26 -42
- data/lib/express_templates/components.rb +1 -9
- data/lib/express_templates/version.rb +1 -1
- data/lib/express_templates.rb +2 -3
- data/test/components/base_test.rb +17 -15
- data/test/components/capabilities/resourceful_test.rb +3 -3
- data/test/components/configurable_test.rb +27 -21
- data/test/components/forms/basic_fields_test.rb +57 -17
- data/test/components/forms/checkbox_test.rb +16 -22
- data/test/components/forms/express_form_test.rb +23 -76
- data/test/components/forms/radio_test.rb +31 -27
- data/test/components/forms/select_test.rb +46 -71
- data/test/components/forms/submit_test.rb +10 -5
- data/test/components/tree_for_test.rb +24 -52
- data/test/dummy/app/views/hello/show.html.et +4 -3
- data/test/dummy/app/views/layouts/application.html.et +1 -1
- data/test/dummy/log/test.log +4794 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-cDLO4NJHMndDHchOLz8KLD7QBc68WtaAbYxK2r6GsU.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/0t68EIwZ96sAqQSxFka9MQyIk4viw8ZIoREMCGiJRx0.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/2zt1IbQCnmzGyeZS_I4sYQzrgneSCKIJBRxcffVHlWY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/EDVlXrcn_wEfaZ5nc_4QJBT7lPiIBcX96jBo7PBz-vc.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Eso3tkb79hXQ1XdQgjbV03KyQwSeZFAHxVHImsjQ-HQ.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/I8LhheC1OlOyvp_qY8kWpqKcZFiqv_BO-l5bExvDEi0.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Kf4VrP5sW-qzziYSN-m7p4nETjLiEwwwRfwUOm7rOr0.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/QJ0Z8hROMfWpY6f5Chb7GSuDHE4gpabKVQTr9BCZe9s.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/T1pSAx767vY7X1UDN0vdF7YGEkI5wMSVUKopsdvp7kI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VlSPFPDK05c7ImadRiRVKzsaa6e15RwX77QR3NYabME.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Y7_BbgB9jgJIWYjDCsASySd26DTfPADAu_3DDnLlFog.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/g2xQygPqA5kMmp5L3wVGWaUIhdVsxFmOel9FF6M0Fuw.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/kaif59owjUr3HBharCH5GUxU6KoW_zXD9a9JiTjIYPY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/p1cwnBd8RQBm9x5HzDmiiU7RhvnxhPX8VTfi0tTElJY.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/qT6_0ti_v6fAjS3wETXqvTkr6W0LP4PB942uLYQzWK8.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/y8T65xpx0s3RgT_YiqWEEXIaBsgK4woCNSuZ1zjQZBk.cache +2 -0
- data/test/express_templates_test.rb +5 -1
- data/test/handler_test.rb +19 -17
- data/test/performance_test.rb +11 -7
- data/test/test_helper.rb +162 -1
- metadata +50 -53
- data/lib/express_templates/components/capabilities/adoptable.rb +0 -20
- data/lib/express_templates/components/capabilities/building.rb +0 -14
- data/lib/express_templates/components/capabilities/conditionality.rb +0 -54
- data/lib/express_templates/components/capabilities/configurable.rb +0 -90
- data/lib/express_templates/components/capabilities/iterating.rb +0 -75
- data/lib/express_templates/components/capabilities/parenting.rb +0 -72
- data/lib/express_templates/components/capabilities/rendering.rb +0 -30
- data/lib/express_templates/components/capabilities/templating.rb +0 -198
- data/lib/express_templates/components/capabilities/wrapping.rb +0 -84
- data/lib/express_templates/components/column.rb +0 -13
- data/lib/express_templates/components/container.rb +0 -7
- data/lib/express_templates/components/content_for.rb +0 -42
- data/lib/express_templates/components/for_each.rb +0 -30
- data/lib/express_templates/components/forms/form_support.rb +0 -13
- data/lib/express_templates/components/null_wrap.rb +0 -41
- data/lib/express_templates/components/row.rb +0 -28
- data/lib/express_templates/components/table_for.rb +0 -163
- data/lib/express_templates/components/unless_block.rb +0 -40
- data/lib/express_templates/expander.rb +0 -140
- data/lib/express_templates/macro.rb +0 -45
- data/lib/express_templates/markup/html_tag.rb +0 -62
- data/lib/express_templates/markup/tag.rb +0 -150
- data/lib/express_templates/markup/wrapper.rb +0 -94
- data/lib/express_templates/markup/yielder.rb +0 -21
- data/lib/express_templates/markup.rb +0 -9
- data/test/components/column_test.rb +0 -11
- data/test/components/conditionality_test.rb +0 -37
- data/test/components/container_test.rb +0 -66
- data/test/components/content_for_test.rb +0 -60
- data/test/components/iterating_test.rb +0 -127
- data/test/components/null_wrap_test.rb +0 -28
- data/test/components/row_test.rb +0 -16
- data/test/components/table_for_test.rb +0 -211
- data/test/expander_stack_test.rb +0 -41
- data/test/expander_test.rb +0 -99
- data/test/markup/tag_test.rb +0 -149
- data/test/markup/wrapper_test.rb +0 -42
- data/test/markup/yielder_test.rb +0 -9
@@ -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
|