phlex 2.3.1 → 2.4.0.beta1
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/lib/phlex/compiler/class_compiler.rb +35 -0
- data/lib/phlex/compiler/compilation.rb +45 -0
- data/lib/phlex/compiler/file_compiler.rb +46 -0
- data/lib/phlex/compiler/method_compiler.rb +591 -0
- data/lib/phlex/compiler.rb +18 -0
- data/lib/phlex/html.rb +3 -3
- data/lib/phlex/sgml/attributes.rb +280 -0
- data/lib/phlex/sgml/elements.rb +8 -8
- data/lib/phlex/sgml.rb +11 -260
- data/lib/phlex/svg.rb +2 -2
- data/lib/phlex/version.rb +1 -1
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66da2693f1133dc2ee688f43e91cca9ce2fb3537a3df44b364d89c653a4c85a0
|
4
|
+
data.tar.gz: 4148a9f44e78765e788758c61e38a681d47833a30d5e4a6e6cae1d99dbf61cb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 642bbd9e026528f5e5a8c505b6b8ff557e40ad90a9ac7ec8b83af85c32825f5963d31ce5c420b29658db8ffc0dbe337daae1f99cd42437db9d45500582be4a06
|
7
|
+
data.tar.gz: c4eb6e00e6424f381cbbdc0a68c4923f6d14b6296673d669a0fa4a3a7a3b411d247108590863f949e5801414d0bf0d2880a85c9d9931e03959188867a9a7737f
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Phlex::Compiler::ClassCompiler < Refract::Visitor
|
4
|
+
def initialize(compiler)
|
5
|
+
super()
|
6
|
+
@compiler = compiler
|
7
|
+
@compiled_snippets = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def compile(node)
|
11
|
+
visit(node.body)
|
12
|
+
@compiled_snippets.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
visit Refract::DefNode do |node|
|
16
|
+
return if node.name == :initialize
|
17
|
+
return if node.receiver
|
18
|
+
|
19
|
+
@compiled_snippets << Phlex::Compiler::MethodCompiler.new(
|
20
|
+
@compiler.component
|
21
|
+
).compile(node)
|
22
|
+
end
|
23
|
+
|
24
|
+
visit Refract::ClassNode do |node|
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
visit Refract::ModuleNode do |node|
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
visit Refract::BlockNode do |node|
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Phlex::Compiler
|
4
|
+
class Compilation
|
5
|
+
def initialize(component, path, line, source, tree)
|
6
|
+
@component = component
|
7
|
+
@path = path
|
8
|
+
@line = line
|
9
|
+
@source = source
|
10
|
+
@tree = tree
|
11
|
+
freeze
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :component, :line, :source, :path
|
15
|
+
|
16
|
+
def compile
|
17
|
+
result = FileCompiler.new(self).compile(@tree)
|
18
|
+
|
19
|
+
result.compiled_snippets.each do |snippet|
|
20
|
+
start_line = snippet.start_line
|
21
|
+
|
22
|
+
namespaced = result.namespace.reverse_each.reduce(snippet) do |body, scope|
|
23
|
+
start_line -= 1
|
24
|
+
|
25
|
+
scope.copy(
|
26
|
+
body: Refract::StatementsNode.new(
|
27
|
+
body: [body]
|
28
|
+
)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
source = Refract::Formatter.new.format_node(namespaced)
|
33
|
+
|
34
|
+
redefine_method(
|
35
|
+
source,
|
36
|
+
start_line
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def redefine_method(source, line)
|
42
|
+
eval("# frozen_string_literal: true\n#{source}", TOPLEVEL_BINDING, @path, line - 1)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Phlex::Compiler::FileCompiler < Refract::Visitor
|
4
|
+
Result = Data.define(:namespace, :compiled_snippets)
|
5
|
+
|
6
|
+
def initialize(compiler)
|
7
|
+
super()
|
8
|
+
@compiler = compiler
|
9
|
+
@current_namespace = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def compile(node)
|
13
|
+
catch(:phlex_compiler_result) do
|
14
|
+
visit(node)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
visit Refract::ModuleNode do |node|
|
19
|
+
@current_namespace.push(node)
|
20
|
+
super(node)
|
21
|
+
@current_namespace.pop
|
22
|
+
end
|
23
|
+
|
24
|
+
visit Refract::ClassNode do |node|
|
25
|
+
@current_namespace.push(node)
|
26
|
+
|
27
|
+
if @compiler.line == node.start_line
|
28
|
+
throw :phlex_compiler_result, Result.new(
|
29
|
+
namespace: @current_namespace.dup.freeze,
|
30
|
+
compiled_snippets: Phlex::Compiler::ClassCompiler.new(@compiler).compile(node)
|
31
|
+
)
|
32
|
+
else
|
33
|
+
super(node)
|
34
|
+
end
|
35
|
+
|
36
|
+
@current_namespace.pop
|
37
|
+
end
|
38
|
+
|
39
|
+
visit Refract::DefNode do |node|
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
visit Refract::BlockNode do |node|
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,591 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "prism"
|
4
|
+
|
5
|
+
module Phlex::Compiler
|
6
|
+
class MethodCompiler < Refract::MutationVisitor
|
7
|
+
def initialize(component)
|
8
|
+
super()
|
9
|
+
@component = component
|
10
|
+
@current_buffer = nil
|
11
|
+
@preamble = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def compile(node)
|
15
|
+
visit(node)
|
16
|
+
end
|
17
|
+
|
18
|
+
def around_visit(node)
|
19
|
+
result = super
|
20
|
+
|
21
|
+
# We want to clear the buffer when there’s a node that isn’t a statements node,
|
22
|
+
# but we should ignore nils, which are usually other buffers.
|
23
|
+
clear_buffer unless result in Refract::StatementsNode | nil
|
24
|
+
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
visit Refract::ClassNode do |node|
|
29
|
+
node
|
30
|
+
end
|
31
|
+
|
32
|
+
visit Refract::ModuleNode do |node|
|
33
|
+
node
|
34
|
+
end
|
35
|
+
|
36
|
+
visit Refract::DefNode do |node|
|
37
|
+
if @stack.size == 1
|
38
|
+
node.copy(
|
39
|
+
body: Refract::StatementsNode.new(
|
40
|
+
body: [
|
41
|
+
Refract::StatementsNode.new(
|
42
|
+
body: @preamble
|
43
|
+
),
|
44
|
+
Refract::NilNode.new,
|
45
|
+
visit(node.body),
|
46
|
+
]
|
47
|
+
)
|
48
|
+
)
|
49
|
+
else
|
50
|
+
node
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
visit Refract::CallNode do |node|
|
55
|
+
if nil == node.receiver
|
56
|
+
if (tag = standard_element?(node))
|
57
|
+
return compile_standard_element(node, tag)
|
58
|
+
elsif (tag = void_element?(node))
|
59
|
+
return compile_void_element(node, tag)
|
60
|
+
elsif whitespace_helper?(node)
|
61
|
+
return compile_whitespace_helper(node)
|
62
|
+
elsif doctype_helper?(node)
|
63
|
+
return compile_doctype_helper(node)
|
64
|
+
elsif plain_helper?(node)
|
65
|
+
return compile_plain_helper(node)
|
66
|
+
elsif fragment_helper?(node)
|
67
|
+
return compile_fragment_helper(node)
|
68
|
+
elsif comment_helper?(node)
|
69
|
+
return compile_comment_helper(node)
|
70
|
+
elsif raw_helper?(node)
|
71
|
+
return compile_raw_helper(node)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
super(node)
|
76
|
+
end
|
77
|
+
|
78
|
+
visit Refract::BlockNode do |node|
|
79
|
+
node.copy(
|
80
|
+
body: compile_block_body_node(
|
81
|
+
node.body
|
82
|
+
)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def compile_standard_element(node, tag)
|
87
|
+
node => Refract::CallNode
|
88
|
+
|
89
|
+
Refract::StatementsNode.new(
|
90
|
+
body: [
|
91
|
+
buffer("<#{tag}"),
|
92
|
+
*(
|
93
|
+
if node.arguments
|
94
|
+
compile_phlex_attributes(node.arguments)
|
95
|
+
end
|
96
|
+
),
|
97
|
+
buffer(">"),
|
98
|
+
*(
|
99
|
+
if node.block
|
100
|
+
compile_phlex_block(node.block)
|
101
|
+
end
|
102
|
+
),
|
103
|
+
buffer("</#{tag}>"),
|
104
|
+
]
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def compile_void_element(node, tag)
|
109
|
+
node => Refract::CallNode
|
110
|
+
|
111
|
+
Refract::StatementsNode.new(
|
112
|
+
body: [
|
113
|
+
buffer("<#{tag}"),
|
114
|
+
*(
|
115
|
+
if node.arguments
|
116
|
+
compile_phlex_attributes(node.arguments)
|
117
|
+
end
|
118
|
+
),
|
119
|
+
buffer(">"),
|
120
|
+
]
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def compile_phlex_attributes(node)
|
125
|
+
arguments = node.arguments
|
126
|
+
|
127
|
+
if arguments.size == 1 && Refract::KeywordHashNode === (first_argument = arguments[0])
|
128
|
+
attributes = first_argument.elements
|
129
|
+
literal_attributes = attributes.all? do |attribute|
|
130
|
+
Refract::AssocNode === attribute && static_attribute_value_literal?(attribute)
|
131
|
+
end
|
132
|
+
|
133
|
+
if literal_attributes
|
134
|
+
return buffer(
|
135
|
+
Phlex::SGML::Attributes.generate_attributes(
|
136
|
+
eval(
|
137
|
+
"{#{Refract::Formatter.new.format_node(node)}}"
|
138
|
+
)
|
139
|
+
)
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
clear_buffer
|
144
|
+
|
145
|
+
Refract::CallNode.new(
|
146
|
+
name: :__render_attributes__,
|
147
|
+
arguments: Refract::ArgumentsNode.new(
|
148
|
+
arguments: [
|
149
|
+
node,
|
150
|
+
]
|
151
|
+
)
|
152
|
+
)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def compile_phlex_block(node)
|
157
|
+
case node
|
158
|
+
when Refract::BlockNode
|
159
|
+
if output_block?(node)
|
160
|
+
return visit(node.body)
|
161
|
+
elsif static_content_block?(node)
|
162
|
+
content = node.body.body.first
|
163
|
+
case content
|
164
|
+
when Refract::StringNode, Refract::SymbolNode
|
165
|
+
return buffer(Phlex::Escape.html_escape(content.unescaped))
|
166
|
+
when Refract::InterpolatedStringNode
|
167
|
+
return compile_interpolated_string_node(content)
|
168
|
+
when Refract::NilNode
|
169
|
+
return nil
|
170
|
+
else
|
171
|
+
raise
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
clear_buffer
|
177
|
+
Refract::CallNode.new(
|
178
|
+
name: :__yield_content__,
|
179
|
+
block: node
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
183
|
+
def compile_block_body_node(node)
|
184
|
+
node => Refract::StatementsNode
|
185
|
+
|
186
|
+
Refract::StatementsNode.new(
|
187
|
+
body: [
|
188
|
+
Refract::IfNode.new(
|
189
|
+
inline: false,
|
190
|
+
predicate: Refract::CallNode.new(
|
191
|
+
receiver: Refract::SelfNode.new,
|
192
|
+
name: :==,
|
193
|
+
arguments: Refract::ArgumentsNode.new(
|
194
|
+
arguments: [
|
195
|
+
Refract::LocalVariableReadNode.new(
|
196
|
+
name: self_local
|
197
|
+
),
|
198
|
+
]
|
199
|
+
)
|
200
|
+
),
|
201
|
+
statements: Refract::StatementsNode.new(
|
202
|
+
body: node.body.map { |n| visit(n) }
|
203
|
+
),
|
204
|
+
subsequent: Refract::ElseNode.new(
|
205
|
+
statements: node
|
206
|
+
)
|
207
|
+
),
|
208
|
+
]
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
def compile_interpolated_string_node(node)
|
213
|
+
node => Refract::InterpolatedStringNode
|
214
|
+
|
215
|
+
Refract::StatementsNode.new(
|
216
|
+
body: node.parts.map do |part|
|
217
|
+
case part
|
218
|
+
when Refract::StringNode
|
219
|
+
buffer(Phlex::Escape.html_escape(part.unescaped))
|
220
|
+
when Refract::EmbeddedVariableNode
|
221
|
+
interpolate(part.variable)
|
222
|
+
when Refract::EmbeddedStatementsNode
|
223
|
+
interpolate(part.statements)
|
224
|
+
else
|
225
|
+
raise Phlex::Compiler::Error, "Unexpected node type in InterpolatedStringNode: #{part.class}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
)
|
229
|
+
end
|
230
|
+
|
231
|
+
def compile_whitespace_helper(node)
|
232
|
+
node => Refract::CallNode
|
233
|
+
|
234
|
+
if node.block
|
235
|
+
Refract::StatementsNode.new(
|
236
|
+
body: [
|
237
|
+
buffer(" "),
|
238
|
+
compile_phlex_block(node.block),
|
239
|
+
buffer(" "),
|
240
|
+
]
|
241
|
+
)
|
242
|
+
else
|
243
|
+
buffer(" ")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def compile_doctype_helper(node)
|
248
|
+
node => Refract::CallNode
|
249
|
+
|
250
|
+
buffer("<!doctype html>")
|
251
|
+
end
|
252
|
+
|
253
|
+
def compile_plain_helper(node)
|
254
|
+
node => Refract::CallNode
|
255
|
+
|
256
|
+
if node.arguments in [Refract::StringNode]
|
257
|
+
buffer(node.arguments.arguments.first.unescaped)
|
258
|
+
else
|
259
|
+
node
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def compile_fragment_helper(node)
|
264
|
+
node => Refract::CallNode
|
265
|
+
|
266
|
+
node.copy(
|
267
|
+
block: compile_fragment_helper_block(node.block)
|
268
|
+
)
|
269
|
+
end
|
270
|
+
|
271
|
+
def compile_fragment_helper_block(node)
|
272
|
+
node => Refract::BlockNode
|
273
|
+
|
274
|
+
node.copy(
|
275
|
+
body: Refract::StatementsNode.new(
|
276
|
+
body: [
|
277
|
+
Refract::LocalVariableWriteNode.new(
|
278
|
+
name: :__phlex_original_should_render__,
|
279
|
+
value: Refract::LocalVariableReadNode.new(
|
280
|
+
name: should_render_local
|
281
|
+
)
|
282
|
+
),
|
283
|
+
Refract::LocalVariableWriteNode.new(
|
284
|
+
name: should_render_local,
|
285
|
+
value: Refract::CallNode.new(
|
286
|
+
receiver: Refract::LocalVariableReadNode.new(
|
287
|
+
name: state_local
|
288
|
+
),
|
289
|
+
name: :should_render?
|
290
|
+
)
|
291
|
+
),
|
292
|
+
visit(node.body),
|
293
|
+
Refract::LocalVariableWriteNode.new(
|
294
|
+
name: should_render_local,
|
295
|
+
value: Refract::LocalVariableReadNode.new(
|
296
|
+
name: :__phlex_original_should_render__
|
297
|
+
)
|
298
|
+
),
|
299
|
+
]
|
300
|
+
)
|
301
|
+
)
|
302
|
+
end
|
303
|
+
|
304
|
+
def compile_comment_helper(node)
|
305
|
+
node => Refract::CallNode
|
306
|
+
|
307
|
+
Refract::StatementsNode.new(
|
308
|
+
body: [
|
309
|
+
buffer("<!-- "),
|
310
|
+
compile_phlex_block(node.block),
|
311
|
+
buffer(" -->"),
|
312
|
+
]
|
313
|
+
)
|
314
|
+
end
|
315
|
+
|
316
|
+
def compile_raw_helper(node)
|
317
|
+
node => Refract::CallNode
|
318
|
+
|
319
|
+
node
|
320
|
+
end
|
321
|
+
|
322
|
+
private def buffer(value)
|
323
|
+
if @current_buffer
|
324
|
+
@current_buffer << Refract::StringNode.new(
|
325
|
+
unescaped: value
|
326
|
+
)
|
327
|
+
|
328
|
+
nil
|
329
|
+
else
|
330
|
+
new_buffer = [
|
331
|
+
Refract::StringNode.new(
|
332
|
+
unescaped: value
|
333
|
+
),
|
334
|
+
]
|
335
|
+
|
336
|
+
@current_buffer = new_buffer
|
337
|
+
|
338
|
+
Refract::IfNode.new(
|
339
|
+
inline: false,
|
340
|
+
predicate: Refract::LocalVariableReadNode.new(
|
341
|
+
name: should_render_local
|
342
|
+
),
|
343
|
+
statements: Refract::StatementsNode.new(
|
344
|
+
body: [
|
345
|
+
Refract::CallNode.new(
|
346
|
+
receiver: Refract::CallNode.new(
|
347
|
+
name: buffer_local,
|
348
|
+
),
|
349
|
+
name: :<<,
|
350
|
+
arguments: Refract::ArgumentsNode.new(
|
351
|
+
arguments: [
|
352
|
+
Refract::InterpolatedStringNode.new(
|
353
|
+
parts: new_buffer
|
354
|
+
),
|
355
|
+
]
|
356
|
+
)
|
357
|
+
),
|
358
|
+
]
|
359
|
+
)
|
360
|
+
)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
private def interpolate(statements, escape: true)
|
365
|
+
embedded_statement = Refract::EmbeddedStatementsNode.new(
|
366
|
+
statements: Refract::StatementsNode.new(
|
367
|
+
body: [
|
368
|
+
Refract::CallNode.new(
|
369
|
+
receiver: Refract::ConstantPathNode.new(
|
370
|
+
parent: Refract::ConstantPathNode.new(
|
371
|
+
name: "Phlex"
|
372
|
+
),
|
373
|
+
name: "Escape"
|
374
|
+
),
|
375
|
+
name: :html_escape,
|
376
|
+
arguments: Refract::ArgumentsNode.new(
|
377
|
+
arguments: [
|
378
|
+
Refract::CallNode.new(
|
379
|
+
receiver: Refract::ParenthesesNode.new(
|
380
|
+
body: statements
|
381
|
+
),
|
382
|
+
name: :to_s
|
383
|
+
),
|
384
|
+
]
|
385
|
+
)
|
386
|
+
),
|
387
|
+
]
|
388
|
+
)
|
389
|
+
)
|
390
|
+
|
391
|
+
if @current_buffer
|
392
|
+
@current_buffer << embedded_statement
|
393
|
+
|
394
|
+
nil
|
395
|
+
else
|
396
|
+
new_buffer = [embedded_statement]
|
397
|
+
|
398
|
+
@current_buffer = new_buffer
|
399
|
+
|
400
|
+
Refract::IfNode.new(
|
401
|
+
predicate: Refract::LocalVariableReadNode.new(
|
402
|
+
name: should_render_local
|
403
|
+
),
|
404
|
+
statements: Refract::StatementsNode.new(
|
405
|
+
body: [
|
406
|
+
Refract::CallNode.new(
|
407
|
+
receiver: Refract::CallNode.new(
|
408
|
+
name: buffer_local,
|
409
|
+
),
|
410
|
+
name: :<<,
|
411
|
+
arguments: Refract::ArgumentsNode.new(
|
412
|
+
arguments: [
|
413
|
+
Refract::InterpolatedStringNode.new(
|
414
|
+
parts: new_buffer
|
415
|
+
),
|
416
|
+
]
|
417
|
+
)
|
418
|
+
),
|
419
|
+
]
|
420
|
+
)
|
421
|
+
)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
private def clear_buffer
|
426
|
+
@current_buffer = nil
|
427
|
+
end
|
428
|
+
|
429
|
+
private def output_block?(node)
|
430
|
+
node.body.body.any? do |child|
|
431
|
+
Refract::CallNode === child && (
|
432
|
+
standard_element?(child) ||
|
433
|
+
void_element?(child) ||
|
434
|
+
plain_helper?(child) ||
|
435
|
+
whitespace_helper?(child) ||
|
436
|
+
raw_helper?(child)
|
437
|
+
)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
private def static_content_block?(node)
|
442
|
+
return false unless node.body.body.length == 1
|
443
|
+
node.body.body.first in Refract::StringNode | Refract::InterpolatedStringNode | Refract::SymbolNode | Refract::NilNode
|
444
|
+
end
|
445
|
+
|
446
|
+
private def standard_element?(node)
|
447
|
+
if (tag = Phlex::HTML::StandardElements.__registered_elements__[node.name]) &&
|
448
|
+
(Phlex::HTML::StandardElements == @component.instance_method(node.name).owner)
|
449
|
+
|
450
|
+
tag
|
451
|
+
else
|
452
|
+
false
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
private def void_element?(node)
|
457
|
+
if (tag = Phlex::HTML::VoidElements.__registered_elements__[node.name]) &&
|
458
|
+
(Phlex::HTML::VoidElements == @component.instance_method(node.name).owner)
|
459
|
+
|
460
|
+
tag
|
461
|
+
else
|
462
|
+
false
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
private def static_attribute_value_literal?(value)
|
467
|
+
case value
|
468
|
+
when Refract::SymbolNode, Refract::StringNode, Refract::IntegerNode, Refract::FloatNode, Refract::TrueNode, Refract::FalseNode, Refract::NilNode
|
469
|
+
true
|
470
|
+
when Refract::ArrayNode
|
471
|
+
value.elements.all? { |n| static_token_value_literal?(n) }
|
472
|
+
when Refract::HashNode
|
473
|
+
value.elements.all? { |n| static_attribute_value_literal?(n) }
|
474
|
+
when Refract::AssocNode
|
475
|
+
(Refract::StringNode === value.key || Refract::SymbolNode === value.key) && static_attribute_value_literal?(value.value)
|
476
|
+
when Refract::CallNode
|
477
|
+
if value in { receiver: Prism::ConstantReadNode[name: :Set]| Prism::ConstantPathNode[name: :Set, parent: nil], name: :[] }
|
478
|
+
value.arguments.arguments.all? { |n| static_token_value_literal?(n) }
|
479
|
+
else
|
480
|
+
false
|
481
|
+
end
|
482
|
+
else
|
483
|
+
false
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
private def static_token_value_literal?(value)
|
488
|
+
case value
|
489
|
+
when Prism::SymbolNode, Prism::StringNode, Prism::IntegerNode, Prism::FloatNode, Prism::NilNode
|
490
|
+
true
|
491
|
+
when Prism::ArrayNode
|
492
|
+
value.elements.all? { |n| static_token_value_literal?(n) }
|
493
|
+
else
|
494
|
+
false
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
private def whitespace_helper?(node)
|
499
|
+
node.name == :whitespace && own_method_without_scope?(node)
|
500
|
+
end
|
501
|
+
|
502
|
+
private def doctype_helper?(node)
|
503
|
+
node.name == :doctype && own_method_without_scope?(node)
|
504
|
+
end
|
505
|
+
|
506
|
+
private def plain_helper?(node)
|
507
|
+
node.name == :plain && own_method_without_scope?(node)
|
508
|
+
end
|
509
|
+
|
510
|
+
private def fragment_helper?(node)
|
511
|
+
node.name == :fragment && own_method_without_scope?(node)
|
512
|
+
end
|
513
|
+
|
514
|
+
private def comment_helper?(node)
|
515
|
+
node.name == :comment && own_method_without_scope?(node)
|
516
|
+
end
|
517
|
+
|
518
|
+
private def raw_helper?(node)
|
519
|
+
node.name == :raw && own_method_without_scope?(node)
|
520
|
+
end
|
521
|
+
|
522
|
+
ALLOWED_OWNERS = Set[Phlex::SGML, Phlex::HTML, Phlex::SVG]
|
523
|
+
private def own_method_without_scope?(node)
|
524
|
+
ALLOWED_OWNERS.include?(@component.instance_method(node.name).owner)
|
525
|
+
end
|
526
|
+
|
527
|
+
private def state_local
|
528
|
+
:__phlex_state__.tap do |local|
|
529
|
+
unless @state_local_set
|
530
|
+
@preamble << Refract::LocalVariableWriteNode.new(
|
531
|
+
name: local,
|
532
|
+
value: Refract::InstanceVariableReadNode.new(
|
533
|
+
name: :@_state
|
534
|
+
)
|
535
|
+
)
|
536
|
+
|
537
|
+
@state_local_set = true
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
private def buffer_local
|
543
|
+
:__phlex_buffer__.tap do |local|
|
544
|
+
unless @buffer_local_set
|
545
|
+
@preamble << Refract::LocalVariableWriteNode.new(
|
546
|
+
name: local,
|
547
|
+
value: Refract::CallNode.new(
|
548
|
+
receiver: Refract::LocalVariableReadNode.new(
|
549
|
+
name: state_local
|
550
|
+
),
|
551
|
+
name: :buffer,
|
552
|
+
)
|
553
|
+
)
|
554
|
+
|
555
|
+
@buffer_local_set = true
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
private def self_local
|
561
|
+
:__phlex_self__.tap do |local|
|
562
|
+
unless @self_local_set
|
563
|
+
@preamble << Refract::LocalVariableWriteNode.new(
|
564
|
+
name: local,
|
565
|
+
value: Refract::SelfNode.new
|
566
|
+
)
|
567
|
+
|
568
|
+
@self_local_set = true
|
569
|
+
end
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
private def should_render_local
|
574
|
+
:__phlex_should_render__.tap do |local|
|
575
|
+
unless @should_render_local_set
|
576
|
+
@preamble << Refract::LocalVariableWriteNode.new(
|
577
|
+
name: :__phlex_should_render__,
|
578
|
+
value: Refract::CallNode.new(
|
579
|
+
receiver: Refract::LocalVariableReadNode.new(
|
580
|
+
name: state_local
|
581
|
+
),
|
582
|
+
name: :should_render?
|
583
|
+
)
|
584
|
+
)
|
585
|
+
|
586
|
+
@should_render_local_set = true
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
end
|