mullet 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mullet/container.rb +8 -4
- data/lib/mullet/default_model.rb +9 -9
- data/lib/mullet/default_nested_model.rb +7 -6
- data/lib/mullet/html/attribute_command.rb +8 -4
- data/lib/mullet/html/attributes.rb +22 -0
- data/lib/mullet/html/command.rb +4 -3
- data/lib/mullet/html/command_element_renderer.rb +19 -0
- data/lib/mullet/html/element.rb +41 -0
- data/lib/mullet/html/element_renderer.rb +261 -0
- data/lib/mullet/html/filtered_element_handler.rb +87 -0
- data/lib/mullet/html/for_element_renderer.rb +47 -0
- data/lib/mullet/html/if_element_renderer.rb +46 -0
- data/lib/mullet/html/layout.rb +48 -0
- data/lib/mullet/html/message.rb +55 -0
- data/lib/mullet/html/message_attribute_command.rb +30 -0
- data/lib/mullet/html/model_attribute_command.rb +30 -0
- data/lib/mullet/html/page_builder.rb +152 -0
- data/lib/mullet/html/parser/attribute.rb +8 -0
- data/lib/mullet/html/parser/constants.rb +1061 -0
- data/lib/mullet/html/parser/default_handler.rb +27 -0
- data/lib/mullet/html/parser/input_stream.rb +711 -0
- data/lib/mullet/html/parser/open_element.rb +77 -0
- data/lib/mullet/html/parser/simple_parser.rb +128 -0
- data/lib/mullet/html/parser/tokenizer.rb +1085 -0
- data/lib/mullet/html/remove_mode.rb +30 -0
- data/lib/mullet/html/static_text_renderer.rb +20 -0
- data/lib/mullet/html/template.rb +44 -0
- data/lib/mullet/html/template_builder.rb +208 -63
- data/lib/mullet/html/template_loader.rb +77 -39
- data/lib/mullet/html/template_parser.rb +48 -0
- data/lib/mullet/html/unless_element_renderer.rb +24 -0
- data/lib/mullet/model.rb +2 -5
- data/lib/mullet/render_context.rb +24 -18
- data/lib/mullet/tilt.rb +37 -0
- data/lib/mullet/version.rb +2 -1
- data/lib/mullet.rb +1 -0
- metadata +58 -11
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'mullet/template_error'
|
2
|
+
|
3
|
+
module Mullet; module HTML
|
4
|
+
|
5
|
+
# Specifies what to remove.
|
6
|
+
class RemoveMode
|
7
|
+
# remove tag, and preserve children of element
|
8
|
+
TAG = RemoveMode.new()
|
9
|
+
|
10
|
+
# preserve tag, and remove children of element
|
11
|
+
CONTENT = RemoveMode.new()
|
12
|
+
|
13
|
+
# remove tag and children of element
|
14
|
+
ELEMENT = RemoveMode.new()
|
15
|
+
|
16
|
+
def self.value_of(argument)
|
17
|
+
string = argument.downcase()
|
18
|
+
if string == 'element'
|
19
|
+
return ELEMENT
|
20
|
+
elsif string == 'tag'
|
21
|
+
return TAG
|
22
|
+
elsif string == 'content'
|
23
|
+
return CONTENT
|
24
|
+
else
|
25
|
+
raise TemplateError.new("invalid remove argument '%{argument}'")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end; end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mullet; module HTML
|
2
|
+
|
3
|
+
# Renders static markup and text. May end with an unclosed start tag under
|
4
|
+
# the assumption a subsequent static text fragment closes the tag.
|
5
|
+
class StaticTextRenderer
|
6
|
+
|
7
|
+
# Constructor
|
8
|
+
#
|
9
|
+
# @param [String] text
|
10
|
+
# rendered tags and text
|
11
|
+
def initialize(text)
|
12
|
+
@text = text
|
13
|
+
end
|
14
|
+
|
15
|
+
def render(render_context)
|
16
|
+
render_context << @text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end; end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'mullet/container'
|
2
|
+
require 'mullet/render_context'
|
3
|
+
|
4
|
+
module Mullet; module HTML
|
5
|
+
|
6
|
+
# Template containing static text and dynamically generated content.
|
7
|
+
class Template
|
8
|
+
include Container
|
9
|
+
|
10
|
+
RETURN_EMPTY_STRING = Proc.new { '' }
|
11
|
+
|
12
|
+
def initialize()
|
13
|
+
super
|
14
|
+
@on_missing = RETURN_EMPTY_STRING
|
15
|
+
@on_nil = RETURN_EMPTY_STRING
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_missing(strategy)
|
19
|
+
@on_missing = strategy
|
20
|
+
return self
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_nil(strategy)
|
24
|
+
@on_nil = strategy
|
25
|
+
return self
|
26
|
+
end
|
27
|
+
|
28
|
+
def render(render_context)
|
29
|
+
render_children(render_context)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Renders the template.
|
33
|
+
#
|
34
|
+
# @param [Object] data
|
35
|
+
# provides data to render
|
36
|
+
# @param [#<<] output
|
37
|
+
# where to write rendered output
|
38
|
+
def execute(data, output)
|
39
|
+
render_context = RenderContext.new(data, @on_missing, @on_nil, output)
|
40
|
+
render(render_context)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end; end
|
@@ -1,46 +1,65 @@
|
|
1
|
-
require '
|
1
|
+
require 'mullet/html/attributes'
|
2
2
|
require 'mullet/html/command'
|
3
|
+
require 'mullet/html/element'
|
4
|
+
require 'mullet/html/element_renderer'
|
5
|
+
require 'mullet/html/for_element_renderer'
|
6
|
+
require 'mullet/html/if_element_renderer'
|
7
|
+
require 'mullet/html/parser/default_handler'
|
8
|
+
require 'mullet/html/parser/simple_parser'
|
9
|
+
require 'mullet/html/remove_mode'
|
10
|
+
require 'mullet/html/static_text_renderer'
|
11
|
+
require 'mullet/html/template'
|
12
|
+
require 'mullet/html/unless_element_renderer'
|
13
|
+
require 'mullet/template_error'
|
3
14
|
require 'set'
|
4
15
|
|
5
16
|
module Mullet; module HTML
|
6
17
|
|
7
18
|
# Handles SAX events to build a template.
|
8
|
-
class TemplateBuilder <
|
19
|
+
class TemplateBuilder < Parser::DefaultHandler
|
9
20
|
include Command
|
10
21
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
22
|
+
COMMANDS = Set[
|
23
|
+
ACTION,
|
24
|
+
ALT,
|
25
|
+
ALT_MESSAGE,
|
26
|
+
ATTR,
|
27
|
+
ATTR_MESSAGE,
|
16
28
|
ESCAPE_XML,
|
17
29
|
FOR,
|
30
|
+
HREF,
|
18
31
|
IF,
|
19
32
|
INCLUDE,
|
33
|
+
REMOVE,
|
34
|
+
SRC,
|
20
35
|
TEXT,
|
21
36
|
TEXT_MESSAGE,
|
22
|
-
|
23
|
-
|
24
|
-
|
37
|
+
TITLE,
|
38
|
+
TITLE_MESSAGE,
|
39
|
+
UNLESS,
|
40
|
+
VALUE,
|
41
|
+
VALUE_MESSAGE]
|
42
|
+
START_CDATA = '<![CDATA['
|
43
|
+
END_CDATA = ']]>'
|
25
44
|
|
26
|
-
|
45
|
+
attr_reader :template
|
27
46
|
|
28
|
-
# This is a stack of elements where this handler has seen the start tag and
|
29
|
-
# not yet seen the end tag.
|
30
|
-
@openElements = []
|
31
|
-
|
32
|
-
# stack of current containers to add renderers to
|
33
|
-
@containers = []
|
34
|
-
|
35
|
-
@staticText = ""
|
36
|
-
@template = nil
|
37
|
-
|
38
47
|
# Constructor
|
39
48
|
#
|
40
49
|
# @param [TemplateLoader] loader
|
41
50
|
# template loader to use to load included template files
|
42
51
|
def initialize(loader)
|
43
52
|
@loader = loader
|
53
|
+
|
54
|
+
# Stack of elements where this handler has seen the start tag and not yet
|
55
|
+
# seen the end tag.
|
56
|
+
@open_elements = []
|
57
|
+
|
58
|
+
# stack of current containers to add renderers to
|
59
|
+
@containers = []
|
60
|
+
|
61
|
+
@static_text = ''
|
62
|
+
@template = nil
|
44
63
|
end
|
45
64
|
|
46
65
|
# Adds renderer to current container.
|
@@ -48,7 +67,7 @@ module Mullet; module HTML
|
|
48
67
|
# @param [#render] renderer
|
49
68
|
# renderer to add
|
50
69
|
def add_child(renderer)
|
51
|
-
@containers.last.add_child(renderer)
|
70
|
+
@containers.last().add_child(renderer)
|
52
71
|
end
|
53
72
|
|
54
73
|
# Deletes renderer from current container.
|
@@ -56,7 +75,7 @@ module Mullet; module HTML
|
|
56
75
|
# @param [#render] renderer
|
57
76
|
# renderer to delete
|
58
77
|
def delete_child(renderer)
|
59
|
-
@containers.last.delete_child(renderer)
|
78
|
+
@containers.last().delete_child(renderer)
|
60
79
|
end
|
61
80
|
|
62
81
|
# Partitions the attributes into ordinary and command attributes.
|
@@ -65,77 +84,203 @@ module Mullet; module HTML
|
|
65
84
|
# input attributes
|
66
85
|
# @param [Hash] ns
|
67
86
|
# hash of namespace prefix to uri mappings
|
68
|
-
# @param [#store]
|
87
|
+
# @param [#store] ordinary_attributes
|
69
88
|
# hash will receive name to value mappings for ordinary attributes
|
70
|
-
# @param [#store]
|
89
|
+
# @param [#store] command_attributes
|
71
90
|
# hash will receive name to value mappings for command attributes
|
72
91
|
# @return [Boolean] true if any command attribute found
|
73
|
-
def find_commands(attributes, ns,
|
74
|
-
|
92
|
+
def find_commands(attributes, ns, ordinary_attributes, command_attributes)
|
93
|
+
found_command = false
|
75
94
|
attributes.each do |attr|
|
76
|
-
if attr.
|
77
|
-
|
78
|
-
if
|
79
|
-
|
95
|
+
if attr.localname.start_with?(DATA_PREFIX)
|
96
|
+
command_name = attr.localname.slice(DATA_PREFIX.length()..-1)
|
97
|
+
if COMMANDS.include?(command_name)
|
98
|
+
command_attributes.store(command_name, attr.value)
|
99
|
+
found_command = true
|
100
|
+
end
|
101
|
+
elsif attr.uri == NAMESPACE_URI || attr.prefix == NAMESPACE_PREFIX
|
102
|
+
command_name = attr.localname
|
103
|
+
if !COMMANDS.include?(command_name)
|
104
|
+
raise TemplateError("invalid command '#{command_name}'")
|
80
105
|
end
|
81
|
-
|
82
|
-
|
106
|
+
command_attributes.store(command_name, attr.value)
|
107
|
+
found_command = true
|
83
108
|
else
|
84
|
-
|
85
|
-
|
109
|
+
attribute_name = [attr.prefix, attr.localname].compact().join(':')
|
110
|
+
ordinary_attributes.store(attribute_name, attr.value)
|
86
111
|
end
|
87
112
|
end
|
88
113
|
|
89
114
|
ns.each do |prefix, uri|
|
90
115
|
if uri != NAMESPACE_URI
|
91
|
-
|
92
|
-
|
116
|
+
attribute_name = ['xmlns', prefix].compact().join(':')
|
117
|
+
ordinary_attributes.store(attribute_name, uri)
|
93
118
|
end
|
94
119
|
end
|
95
120
|
|
96
|
-
return
|
121
|
+
return found_command
|
97
122
|
end
|
98
123
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
124
|
+
def append_static_text(data)
|
125
|
+
@static_text << data
|
126
|
+
end
|
127
|
+
|
128
|
+
def end_static_text()
|
129
|
+
if !@static_text.empty?()
|
130
|
+
add_child(StaticTextRenderer.new(@static_text))
|
131
|
+
@static_text = ''
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Marks the most deeply nested open element as having content.
|
136
|
+
def set_has_content()
|
137
|
+
if !@open_elements.empty?()
|
138
|
+
@open_elements.last().has_content = true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def start_document()
|
143
|
+
@template = Template.new()
|
144
|
+
@containers.push(@template)
|
145
|
+
end
|
146
|
+
|
147
|
+
def end_document()
|
148
|
+
end_static_text()
|
149
|
+
end
|
150
|
+
|
151
|
+
def doctype(name, public_id, system_id)
|
152
|
+
text = "<!DOCTYPE #{name}"
|
153
|
+
|
154
|
+
if public_id
|
155
|
+
text << %( PUBLIC "#{public_id}")
|
156
|
+
end
|
157
|
+
|
158
|
+
if system_id
|
159
|
+
text << %( "#{system_id}")
|
160
|
+
end
|
161
|
+
|
162
|
+
text << '>'
|
163
|
+
append_static_text(text)
|
164
|
+
end
|
165
|
+
|
166
|
+
def create_element_renderer(element, command_attributes)
|
167
|
+
renderer = nil
|
168
|
+
|
169
|
+
variable_name = command_attributes.fetch(IF, nil)
|
170
|
+
if variable_name != nil
|
171
|
+
renderer = IfElementRenderer.new(element, variable_name)
|
103
172
|
end
|
104
|
-
tag << name
|
105
173
|
|
106
|
-
|
107
|
-
|
108
|
-
if
|
109
|
-
|
174
|
+
if renderer == nil
|
175
|
+
variable_name = command_attributes.fetch(UNLESS, nil)
|
176
|
+
if variable_name != nil
|
177
|
+
renderer = UnlessElementRenderer.new(element, variable_name)
|
110
178
|
end
|
111
|
-
tag = attribute.localname << '="' << attribute.value << '"'
|
112
179
|
end
|
113
180
|
|
114
|
-
|
115
|
-
|
116
|
-
if
|
117
|
-
|
181
|
+
if renderer == nil
|
182
|
+
variable_name = command_attributes.fetch(FOR, nil)
|
183
|
+
if variable_name != nil
|
184
|
+
renderer = ForElementRenderer.new(element, variable_name)
|
118
185
|
end
|
119
186
|
end
|
120
187
|
|
121
|
-
|
122
|
-
|
188
|
+
if renderer == nil
|
189
|
+
renderer = ElementRenderer.new(element)
|
190
|
+
end
|
191
|
+
|
192
|
+
renderer.configure_commands(command_attributes, @loader)
|
193
|
+
return renderer
|
123
194
|
end
|
124
195
|
|
125
196
|
def start_element_namespace(name, attributes, prefix, uri, ns)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
197
|
+
set_has_content()
|
198
|
+
|
199
|
+
ordinary_attributes = Attributes.new()
|
200
|
+
command_attributes = Attributes.new()
|
201
|
+
found_command = find_commands(
|
202
|
+
attributes, ns, ordinary_attributes, command_attributes)
|
203
|
+
|
204
|
+
qualified_name = [prefix, name].compact().join(':')
|
205
|
+
element = Element.new(qualified_name, ordinary_attributes)
|
206
|
+
@open_elements.push(element)
|
207
|
+
|
208
|
+
if found_command
|
209
|
+
end_static_text()
|
210
|
+
|
211
|
+
element.has_command = true
|
212
|
+
renderer = create_element_renderer(element, command_attributes)
|
213
|
+
add_child(renderer)
|
214
|
+
|
215
|
+
@containers.push(renderer)
|
132
216
|
else
|
133
|
-
|
217
|
+
append_static_text(element.render_start_tag(element.attributes))
|
134
218
|
end
|
135
219
|
end
|
136
220
|
|
137
|
-
def
|
138
|
-
|
221
|
+
def configure_remove_command(element, renderer)
|
222
|
+
case renderer.remove_mode
|
223
|
+
when RemoveMode::TAG
|
224
|
+
if !renderer.has_command && !renderer.has_dynamic_content
|
225
|
+
# Discard tag, but preserve the children.
|
226
|
+
delete_child(renderer)
|
227
|
+
renderer.children.each do |child|
|
228
|
+
add_child(child)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
when RemoveMode::CONTENT
|
232
|
+
if !renderer.has_command
|
233
|
+
# Discard children. Statically render the tag.
|
234
|
+
delete_child(renderer)
|
235
|
+
|
236
|
+
append_static_text(element.render_start_tag(element.attributes))
|
237
|
+
append_static_text(element.render_end_tag())
|
238
|
+
end
|
239
|
+
when RemoveMode::ELEMENT
|
240
|
+
# Discard element and all its content.
|
241
|
+
delete_child(renderer)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def end_element_namespace(name, prefix, uri)
|
246
|
+
element = @open_elements.pop()
|
247
|
+
if element.has_command
|
248
|
+
end_static_text()
|
249
|
+
|
250
|
+
renderer = @containers.pop()
|
251
|
+
if renderer.has_dynamic_content
|
252
|
+
# Discard children because the content will be replaced at render
|
253
|
+
# time.
|
254
|
+
renderer.clear_children()
|
255
|
+
end
|
256
|
+
|
257
|
+
configure_remove_command(element, renderer)
|
258
|
+
elsif uri != Parser::SimpleParser::IMPLICIT_END_TAG_NS_URI
|
259
|
+
append_static_text(element.render_end_tag())
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def characters(data)
|
264
|
+
set_has_content()
|
265
|
+
append_static_text(data)
|
266
|
+
end
|
267
|
+
|
268
|
+
def cdata_block(data)
|
269
|
+
append_static_text(START_CDATA)
|
270
|
+
characters(data)
|
271
|
+
append_static_text(END_CDATA)
|
272
|
+
end
|
273
|
+
|
274
|
+
def comment(data)
|
275
|
+
append_static_text('<!--')
|
276
|
+
characters(data)
|
277
|
+
append_static_text('-->')
|
278
|
+
end
|
279
|
+
|
280
|
+
def processing_instruction(data)
|
281
|
+
append_static_text('<?')
|
282
|
+
characters(data)
|
283
|
+
append_static_text('?>')
|
139
284
|
end
|
140
285
|
end
|
141
286
|
|
@@ -1,55 +1,93 @@
|
|
1
|
-
require '
|
1
|
+
require 'mullet/html/template'
|
2
|
+
require 'mullet/html/template_parser'
|
2
3
|
|
3
|
-
module Mullet
|
4
|
+
module Mullet; module HTML
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
# Loads templates from files, and caches them for fast retrieval of already
|
7
|
+
# loaded templates.
|
8
|
+
#
|
9
|
+
# By default, templates render an empty string when a variable is not found
|
10
|
+
# or its value is null. Call the `on_missing` and `on_nil` methods to
|
11
|
+
# configure how templates loaded by this loader should handle missing and nil
|
12
|
+
# values respectively.
|
13
|
+
class TemplateLoader
|
14
|
+
|
15
|
+
attr_accessor :template_path
|
7
16
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
17
|
+
# Constructor
|
18
|
+
#
|
19
|
+
# @param [String] template_path
|
20
|
+
# name of directory to load templates from
|
21
|
+
def initialize(template_path)
|
22
|
+
@template_path = template_path
|
23
|
+
@template_cache = Hash.new()
|
24
|
+
@parser = TemplateParser.new(self)
|
25
|
+
@on_missing = Template::RETURN_EMPTY_STRING
|
26
|
+
@on_nil = Template::RETURN_EMPTY_STRING
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets block to execute on attempt to render a variable that was not found.
|
30
|
+
#
|
31
|
+
# @param [Proc] strategy
|
32
|
+
# The value returned from block will be rendered.
|
33
|
+
# @return [TemplateLoader] this object to allow method call chaining
|
34
|
+
def on_missing(strategy)
|
35
|
+
@on_missing = strategy
|
36
|
+
return self
|
12
37
|
end
|
13
|
-
tag << name
|
14
38
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
39
|
+
# Sets block to execute on attempt to render a nil value.
|
40
|
+
#
|
41
|
+
# @param [Proc] strategy
|
42
|
+
# The value returned from block will be rendered.
|
43
|
+
# @return [TemplateLoader] this object to allow method call chaining
|
44
|
+
def on_nil(strategy)
|
45
|
+
@on_nil = strategy
|
46
|
+
return self
|
21
47
|
end
|
22
48
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
49
|
+
# Loads named template.
|
50
|
+
#
|
51
|
+
# @param [String] uri
|
52
|
+
# file name optionally followed by `#`_id_
|
53
|
+
def load(uri)
|
54
|
+
id = nil
|
55
|
+
hash_index = uri.index('#')
|
56
|
+
if hash_index
|
57
|
+
id = uri[(hash_index + 1)..-1]
|
58
|
+
uri = uri[0...hash_index]
|
27
59
|
end
|
60
|
+
|
61
|
+
return load_file(uri, id)
|
28
62
|
end
|
29
63
|
|
30
|
-
|
31
|
-
return tag
|
32
|
-
end
|
64
|
+
private
|
33
65
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
66
|
+
def get_cache_key(file_name, id)
|
67
|
+
cache_key = File.join(@template_path, file_name)
|
68
|
+
if id != nil
|
69
|
+
cache_key << '#' << id
|
70
|
+
end
|
71
|
+
return cache_key
|
38
72
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
73
|
+
|
74
|
+
def parse_file(file_name, id)
|
75
|
+
template_file = File.join(@template_path, file_name)
|
76
|
+
template = @parser.parse_file(template_file, id)
|
77
|
+
|
78
|
+
template.on_missing(@on_missing).on_nil(@on_nil)
|
79
|
+
return template
|
43
80
|
end
|
44
|
-
end
|
45
81
|
|
46
|
-
|
47
|
-
|
82
|
+
def load_file(file_name, id)
|
83
|
+
cache_key = get_cache_key(file_name, id)
|
84
|
+
template = @template_cache.fetch(cache_key, nil)
|
85
|
+
if template == nil
|
86
|
+
template = parse_file(file_name, id)
|
87
|
+
@template_cache.store(cache_key, template)
|
88
|
+
end
|
89
|
+
return template
|
90
|
+
end
|
48
91
|
end
|
49
|
-
end
|
50
92
|
|
51
|
-
|
52
|
-
f = File.open("login.html")
|
53
|
-
parser.parse(f)
|
54
|
-
f.close
|
55
|
-
end
|
93
|
+
end; end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'mullet/html/filtered_element_handler'
|
2
|
+
require 'mullet/html/parser/simple_parser'
|
3
|
+
require 'mullet/html/template_builder'
|
4
|
+
|
5
|
+
module Mullet; module HTML
|
6
|
+
|
7
|
+
class TemplateParser
|
8
|
+
|
9
|
+
def initialize(loader)
|
10
|
+
@loader = loader
|
11
|
+
end
|
12
|
+
|
13
|
+
# Parses template from string.
|
14
|
+
#
|
15
|
+
# @param [String] source
|
16
|
+
# string to parse
|
17
|
+
# @return [Template] template
|
18
|
+
def parse(source)
|
19
|
+
template_builder = TemplateBuilder.new(@loader)
|
20
|
+
parser = Parser::SimpleParser.new(template_builder)
|
21
|
+
parser.parse(source)
|
22
|
+
return template_builder.template
|
23
|
+
end
|
24
|
+
|
25
|
+
# Parses template from file.
|
26
|
+
#
|
27
|
+
# @param [String] file_name
|
28
|
+
# name of file containing template
|
29
|
+
# @param [String] id
|
30
|
+
# If `nil`, then the template is the entire file, otherwise the
|
31
|
+
# template is the content of the element having an `id` attribute
|
32
|
+
# value equal to this argument.
|
33
|
+
# @return [Template] template
|
34
|
+
def parse_file(file_name, id)
|
35
|
+
template_builder = TemplateBuilder.new(@loader)
|
36
|
+
handler = (id == nil) ?
|
37
|
+
template_builder : FilteredElementHandler.new(template_builder, id)
|
38
|
+
|
39
|
+
parser = Parser::SimpleParser.new(handler)
|
40
|
+
File.open(file_name) do |file|
|
41
|
+
parser.parse(file)
|
42
|
+
end
|
43
|
+
|
44
|
+
return template_builder.template
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end; end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'mullet/html/if_element_renderer'
|
2
|
+
|
3
|
+
module Mullet; module HTML
|
4
|
+
|
5
|
+
# Renders an element if variable is false.
|
6
|
+
class UnlessElementRenderer < IfElementRenderer
|
7
|
+
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# @param [Element] element
|
11
|
+
# element to render
|
12
|
+
# @param [String] variable_name
|
13
|
+
# name of variable containing condition
|
14
|
+
def initialize(element, variable_name)
|
15
|
+
super(element, variable_name)
|
16
|
+
@variable_name = variable_name.to_sym()
|
17
|
+
end
|
18
|
+
|
19
|
+
def should_render_element(render_context)
|
20
|
+
return !super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end; end
|
data/lib/mullet/model.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
module Mullet
|
2
2
|
|
3
|
-
# A model responds to the method `
|
4
|
-
# returning the variable value.
|
5
|
-
# returns the value `NOT_FOUND` instead of raising an exception. A model
|
6
|
-
# class must include this module because the implementation calls
|
7
|
-
# `is_a?(Model)` to determine if an object satisfies the concept of a model.
|
3
|
+
# A model responds to the method `get_variable_value` taking a variable name
|
4
|
+
# argument and returning the variable value.
|
8
5
|
module Model
|
9
6
|
|
10
7
|
# special value indicating variable name was not found
|