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.
- 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
|