twig_ruby 0.0.1 → 0.0.3
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 +116 -0
- data/lib/tasks/twig_parity.rake +278 -0
- data/lib/twig/auto_hash.rb +7 -1
- data/lib/twig/callable.rb +28 -1
- data/lib/twig/compiler.rb +35 -3
- data/lib/twig/environment.rb +198 -41
- data/lib/twig/error/base.rb +81 -16
- data/lib/twig/error/loader.rb +8 -0
- data/lib/twig/error/logic.rb +8 -0
- data/lib/twig/error/runtime.rb +8 -0
- data/lib/twig/expression_parser/base.rb +30 -0
- data/lib/twig/expression_parser/expression_parsers.rb +57 -0
- data/lib/twig/expression_parser/infix/arrow.rb +31 -0
- data/lib/twig/expression_parser/infix/binary.rb +34 -0
- data/lib/twig/expression_parser/infix/conditional_ternary.rb +39 -0
- data/lib/twig/expression_parser/infix/dot.rb +72 -0
- data/lib/twig/expression_parser/infix/filter.rb +43 -0
- data/lib/twig/expression_parser/infix/function.rb +67 -0
- data/lib/twig/expression_parser/infix/is.rb +53 -0
- data/lib/twig/expression_parser/infix/is_not.rb +19 -0
- data/lib/twig/expression_parser/infix/parses_arguments.rb +84 -0
- data/lib/twig/expression_parser/infix/square_bracket.rb +66 -0
- data/lib/twig/expression_parser/infix_expression_parser.rb +34 -0
- data/lib/twig/expression_parser/prefix/grouping.rb +60 -0
- data/lib/twig/expression_parser/prefix/literal.rb +244 -0
- data/lib/twig/expression_parser/prefix/unary.rb +29 -0
- data/lib/twig/expression_parser/prefix_expression_parser.rb +18 -0
- data/lib/twig/extension/base.rb +26 -4
- data/lib/twig/extension/core.rb +1076 -48
- data/lib/twig/extension/debug.rb +25 -0
- data/lib/twig/extension/escaper.rb +73 -0
- data/lib/twig/extension/rails.rb +10 -57
- data/lib/twig/extension/string_loader.rb +19 -0
- data/lib/twig/extension_set.rb +117 -20
- data/lib/twig/file_extension_escaping_strategy.rb +35 -0
- data/lib/twig/lexer.rb +225 -81
- data/lib/twig/loader/array.rb +25 -8
- data/lib/twig/loader/chain.rb +93 -0
- data/lib/twig/loader/filesystem.rb +106 -7
- data/lib/twig/node/auto_escape.rb +18 -0
- data/lib/twig/node/base.rb +58 -2
- data/lib/twig/node/block.rb +2 -0
- data/lib/twig/node/block_reference.rb +5 -1
- data/lib/twig/node/body.rb +7 -0
- data/lib/twig/node/cache.rb +50 -0
- data/lib/twig/node/capture.rb +22 -0
- data/lib/twig/node/deprecated.rb +53 -0
- data/lib/twig/node/do.rb +19 -0
- data/lib/twig/node/embed.rb +43 -0
- data/lib/twig/node/expression/array.rb +29 -20
- data/lib/twig/node/expression/arrow_function.rb +55 -0
- data/lib/twig/node/expression/assign_name.rb +1 -1
- data/lib/twig/node/expression/binary/and.rb +17 -0
- data/lib/twig/node/expression/binary/base.rb +6 -4
- data/lib/twig/node/expression/binary/boolean.rb +24 -0
- data/lib/twig/node/expression/binary/concat.rb +20 -0
- data/lib/twig/node/expression/binary/elvis.rb +35 -0
- data/lib/twig/node/expression/binary/ends_with.rb +24 -0
- data/lib/twig/node/expression/binary/floor_div.rb +21 -0
- data/lib/twig/node/expression/binary/has_every.rb +20 -0
- data/lib/twig/node/expression/binary/has_some.rb +20 -0
- data/lib/twig/node/expression/binary/in.rb +20 -0
- data/lib/twig/node/expression/binary/matches.rb +24 -0
- data/lib/twig/node/expression/binary/not_in.rb +20 -0
- data/lib/twig/node/expression/binary/null_coalesce.rb +49 -0
- data/lib/twig/node/expression/binary/or.rb +15 -0
- data/lib/twig/node/expression/binary/starts_with.rb +24 -0
- data/lib/twig/node/expression/binary/xor.rb +17 -0
- data/lib/twig/node/expression/block_reference.rb +62 -0
- data/lib/twig/node/expression/call.rb +126 -6
- data/lib/twig/node/expression/constant.rb +3 -1
- data/lib/twig/node/expression/filter/default.rb +37 -0
- data/lib/twig/node/expression/filter/raw.rb +31 -0
- data/lib/twig/node/expression/filter.rb +2 -2
- data/lib/twig/node/expression/function.rb +37 -0
- data/lib/twig/node/expression/get_attribute.rb +51 -7
- data/lib/twig/node/expression/hash.rb +75 -0
- data/lib/twig/node/expression/helper_method.rb +6 -18
- data/lib/twig/node/expression/macro_reference.rb +43 -0
- data/lib/twig/node/expression/name.rb +42 -8
- data/lib/twig/node/expression/operator_escape.rb +13 -0
- data/lib/twig/node/expression/parent.rb +28 -0
- data/lib/twig/node/expression/support_defined_test.rb +23 -0
- data/lib/twig/node/expression/ternary.rb +7 -1
- data/lib/twig/node/expression/test/base.rb +26 -0
- data/lib/twig/node/expression/test/constant.rb +35 -0
- data/lib/twig/node/expression/test/defined.rb +33 -0
- data/lib/twig/node/expression/test/divisible_by.rb +23 -0
- data/lib/twig/node/expression/test/even.rb +21 -0
- data/lib/twig/node/expression/test/iterable.rb +21 -0
- data/lib/twig/node/expression/test/mapping.rb +21 -0
- data/lib/twig/node/expression/test/null.rb +21 -0
- data/lib/twig/node/expression/test/odd.rb +21 -0
- data/lib/twig/node/expression/test/same_as.rb +23 -0
- data/lib/twig/node/expression/test/sequence.rb +21 -0
- data/lib/twig/node/expression/unary/base.rb +3 -1
- data/lib/twig/node/expression/unary/not.rb +18 -0
- data/lib/twig/node/expression/unary/spread.rb +18 -0
- data/lib/twig/node/expression/unary/string_cast.rb +18 -0
- data/lib/twig/node/expression/variable/assign_template.rb +35 -0
- data/lib/twig/node/expression/variable/local.rb +35 -0
- data/lib/twig/node/expression/variable/template.rb +54 -0
- data/lib/twig/node/for.rb +38 -8
- data/lib/twig/node/for_loop.rb +0 -22
- data/lib/twig/node/if.rb +4 -1
- data/lib/twig/node/import.rb +32 -0
- data/lib/twig/node/include.rb +38 -8
- data/lib/twig/node/macro.rb +79 -0
- data/lib/twig/node/module.rb +278 -23
- data/lib/twig/node/output.rb +7 -0
- data/lib/twig/node/print.rb +4 -1
- data/lib/twig/node/set.rb +72 -0
- data/lib/twig/node/text.rb +4 -1
- data/lib/twig/node/with.rb +50 -0
- data/lib/twig/node/yield.rb +6 -1
- data/lib/twig/node_traverser.rb +50 -0
- data/lib/twig/node_visitor/base.rb +30 -0
- data/lib/twig/node_visitor/escaper.rb +165 -0
- data/lib/twig/node_visitor/safe_analysis.rb +127 -0
- data/lib/twig/node_visitor/spreader.rb +39 -0
- data/lib/twig/output_buffer.rb +14 -12
- data/lib/twig/parser.rb +281 -8
- data/lib/twig/rails/config.rb +33 -0
- data/lib/twig/rails/engine.rb +44 -0
- data/lib/twig/rails/renderer.rb +41 -0
- data/lib/twig/runtime/argument_spreader.rb +46 -0
- data/lib/twig/runtime/context.rb +154 -0
- data/lib/twig/runtime/enumerable_hash.rb +51 -0
- data/lib/twig/runtime/escaper.rb +155 -0
- data/lib/twig/runtime/loop_context.rb +81 -0
- data/lib/twig/runtime/loop_iterator.rb +60 -0
- data/lib/twig/runtime/spread.rb +21 -0
- data/lib/twig/runtime_loader/base.rb +12 -0
- data/lib/twig/runtime_loader/factory.rb +23 -0
- data/lib/twig/template.rb +267 -14
- data/lib/twig/template_wrapper.rb +42 -0
- data/lib/twig/token.rb +28 -2
- data/lib/twig/token_parser/apply.rb +48 -0
- data/lib/twig/token_parser/auto_escape.rb +45 -0
- data/lib/twig/token_parser/base.rb +26 -0
- data/lib/twig/token_parser/block.rb +4 -4
- data/lib/twig/token_parser/cache.rb +31 -0
- data/lib/twig/token_parser/deprecated.rb +40 -0
- data/lib/twig/token_parser/do.rb +19 -0
- data/lib/twig/token_parser/embed.rb +62 -0
- data/lib/twig/token_parser/extends.rb +4 -3
- data/lib/twig/token_parser/for.rb +14 -9
- data/lib/twig/token_parser/from.rb +57 -0
- data/lib/twig/token_parser/guard.rb +65 -0
- data/lib/twig/token_parser/if.rb +9 -9
- data/lib/twig/token_parser/import.rb +29 -0
- data/lib/twig/token_parser/include.rb +2 -2
- data/lib/twig/token_parser/macro.rb +109 -0
- data/lib/twig/token_parser/set.rb +76 -0
- data/lib/twig/token_parser/use.rb +54 -0
- data/lib/twig/token_parser/with.rb +36 -0
- data/lib/twig/token_parser/yield.rb +7 -7
- data/lib/twig/token_stream.rb +23 -3
- data/lib/twig/twig_filter.rb +20 -0
- data/lib/twig/twig_function.rb +37 -0
- data/lib/twig/twig_test.rb +31 -0
- data/lib/twig/util/callable_arguments_extractor.rb +227 -0
- data/lib/twig_ruby.rb +21 -2
- metadata +148 -6
- data/lib/twig/context.rb +0 -64
- data/lib/twig/expression_parser.rb +0 -517
- data/lib/twig/railtie.rb +0 -60
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Unary
|
|
7
|
+
class Not < Unary::Base
|
|
8
|
+
def compile(compiler)
|
|
9
|
+
compiler.
|
|
10
|
+
raw('!::Twig::Extension::Core.bool(').
|
|
11
|
+
subcompile(nodes[:node]).
|
|
12
|
+
raw(')')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Unary
|
|
7
|
+
class Spread < Unary::Base
|
|
8
|
+
def compile(compiler)
|
|
9
|
+
compiler.
|
|
10
|
+
raw('::Twig::Runtime::Spread.new(').
|
|
11
|
+
subcompile(nodes[:node]).
|
|
12
|
+
raw(')')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Unary
|
|
7
|
+
class StringCast < Unary::Base
|
|
8
|
+
def compile(compiler)
|
|
9
|
+
compiler.
|
|
10
|
+
raw('(').
|
|
11
|
+
subcompile(nodes[:node]).
|
|
12
|
+
raw('.to_s)')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Variable
|
|
7
|
+
class AssignTemplate < Expression::Base
|
|
8
|
+
# @param [Variable::Template] var
|
|
9
|
+
# @param [Boolean] global
|
|
10
|
+
def initialize(var, global: true)
|
|
11
|
+
super({ var: }, { global: }, var.lineno)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def compile(compiler)
|
|
15
|
+
# @var [Template] var
|
|
16
|
+
var = nodes[:var]
|
|
17
|
+
|
|
18
|
+
compiler.
|
|
19
|
+
add_debug_info(self).
|
|
20
|
+
write('macros[').
|
|
21
|
+
string(var.name(compiler)).
|
|
22
|
+
raw('] = ')
|
|
23
|
+
|
|
24
|
+
if attributes[:global]
|
|
25
|
+
compiler.
|
|
26
|
+
raw('@macros[').
|
|
27
|
+
string(var.name(compiler)).
|
|
28
|
+
raw('] = ')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Variable
|
|
7
|
+
class Local < Expression::Base
|
|
8
|
+
RESERVED_NAMES = %w[varargs context macros blocks self].freeze
|
|
9
|
+
|
|
10
|
+
# @param [String|Integer|nil]
|
|
11
|
+
def initialize(name, lineno)
|
|
12
|
+
if %w[true false none null nil].include?(name.to_s.downcase)
|
|
13
|
+
raise Error::Syntax.new("You cannot assign a value to \"#{name}\".", lineno)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Convert to integer if name is an integer or consists of digits only
|
|
17
|
+
if !name.nil? && (name.is_a?(Integer) || name == name.to_i.to_s)
|
|
18
|
+
name = name.to_i
|
|
19
|
+
elsif RESERVED_NAMES.include?(name)
|
|
20
|
+
name = "\u035C#{name}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
super({}, { name: }, lineno)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def compile(compiler)
|
|
27
|
+
attributes[:name] = compiler.var_name if attributes[:name].nil?
|
|
28
|
+
|
|
29
|
+
compiler.raw(attributes[:name].to_s)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Variable
|
|
7
|
+
class Template < Expression::Base
|
|
8
|
+
RESERVED_NAMES = %w[varargs context macros blocks self].freeze
|
|
9
|
+
|
|
10
|
+
# @param [String, Integer, nil] name
|
|
11
|
+
# @param [Integer] lineno
|
|
12
|
+
def initialize(name, lineno)
|
|
13
|
+
if name && %w[true false none null nil].include?(name.to_s.downcase)
|
|
14
|
+
raise Error::Syntax.new("You cannot assign a value to \"#{name}\".", lineno)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Convert to integer if name is an integer or consists of digits only
|
|
18
|
+
if !name.nil? && (name.is_a?(Integer) || name == name.to_i.to_s)
|
|
19
|
+
name = name.to_i
|
|
20
|
+
elsif RESERVED_NAMES.include?(name)
|
|
21
|
+
name = "\u035C#{name}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
super({}, { name: }, lineno)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param [Compiler] compiler
|
|
28
|
+
# @return [String]
|
|
29
|
+
def name(compiler)
|
|
30
|
+
if attributes[:name].nil?
|
|
31
|
+
attributes[:name] = compiler.var_name
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attributes[:name]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param [Compiler] compiler
|
|
38
|
+
def compile(compiler)
|
|
39
|
+
name_value = name(compiler)
|
|
40
|
+
|
|
41
|
+
if name_value == '_self'
|
|
42
|
+
compiler.raw('self')
|
|
43
|
+
else
|
|
44
|
+
compiler.
|
|
45
|
+
raw('macros[').
|
|
46
|
+
string(name_value).
|
|
47
|
+
raw(']')
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/twig/node/for.rb
CHANGED
|
@@ -4,6 +4,10 @@ module Twig
|
|
|
4
4
|
module Node
|
|
5
5
|
class For < Node::Base
|
|
6
6
|
def initialize(key_target, value_target, seq, if_expr, body, else_expr, lineno)
|
|
7
|
+
unless if_expr.nil?
|
|
8
|
+
body = If.new(Nodes.new(AutoHash.new.add(if_expr, body)), nil, lineno)
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
loop = ForLoop.new(lineno)
|
|
8
12
|
body = Nodes.new(AutoHash.new.add(body, loop))
|
|
9
13
|
|
|
@@ -22,27 +26,40 @@ module Twig
|
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def compile(compiler)
|
|
29
|
+
iteration_var = compiler.var_name
|
|
30
|
+
function_var = compiler.var_name
|
|
31
|
+
|
|
25
32
|
compiler.
|
|
26
|
-
|
|
27
|
-
write(
|
|
33
|
+
add_debug_info(self).
|
|
34
|
+
write("#{iteration_var} = ::Twig::Runtime::LoopIterator.new(").
|
|
28
35
|
subcompile(nodes[:seq]).
|
|
29
|
-
raw(")\n")
|
|
36
|
+
raw(")\n").
|
|
37
|
+
write("#{function_var} = lambda do |iterator, context, blocks, recurse, depth|\n").
|
|
38
|
+
indent.
|
|
39
|
+
write("parent = context.dup\n")
|
|
30
40
|
|
|
31
|
-
|
|
41
|
+
if attributes[:with_loop]
|
|
42
|
+
compiler.
|
|
43
|
+
write('context[:loop] = ::Twig::Runtime::LoopContext.new(').
|
|
44
|
+
raw("iterator, parent, blocks, recurse, depth)\n")
|
|
45
|
+
end
|
|
32
46
|
|
|
33
47
|
if nodes.key?(:else_expr)
|
|
34
48
|
compiler.write("context[:_iterated] = false\n")
|
|
35
49
|
end
|
|
36
50
|
|
|
51
|
+
key_var = compiler.var_name
|
|
52
|
+
value_var = compiler.var_name
|
|
53
|
+
|
|
37
54
|
compiler.
|
|
38
|
-
write("
|
|
55
|
+
write("iterator.each do |#{key_var}, #{value_var}|\n").
|
|
39
56
|
indent.
|
|
40
57
|
write('').
|
|
41
58
|
subcompile(nodes[:key_target]).
|
|
42
|
-
raw(" =
|
|
59
|
+
raw(" = #{key_var}\n").
|
|
43
60
|
write('').
|
|
44
61
|
subcompile(nodes[:value_target]).
|
|
45
|
-
raw(" =
|
|
62
|
+
raw(" = #{value_var}\n").
|
|
46
63
|
subcompile(nodes[:body]).
|
|
47
64
|
outdent.
|
|
48
65
|
write("end\n")
|
|
@@ -57,7 +74,20 @@ module Twig
|
|
|
57
74
|
end
|
|
58
75
|
|
|
59
76
|
compiler.
|
|
60
|
-
write("context.
|
|
77
|
+
write("context.remove!(:#{nodes[:key_target].attributes[:name]}, ").
|
|
78
|
+
raw(":#{nodes[:value_target].attributes[:name]}")
|
|
79
|
+
|
|
80
|
+
if attributes[:with_loop]
|
|
81
|
+
compiler.raw(', :loop')
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
compiler.
|
|
85
|
+
raw(")\n").
|
|
86
|
+
write("context.keep!(parent.keys)\n").
|
|
87
|
+
write("context.merge!(parent, overwrite: false)\n").
|
|
88
|
+
outdent.
|
|
89
|
+
write("end\n").
|
|
90
|
+
write("#{function_var}.call(#{iteration_var}, context, blocks, #{function_var}, 0)\n")
|
|
61
91
|
end
|
|
62
92
|
end
|
|
63
93
|
end
|
data/lib/twig/node/for_loop.rb
CHANGED
|
@@ -11,28 +11,6 @@ module Twig
|
|
|
11
11
|
if attributes.key?(:else_expr)
|
|
12
12
|
compiler.write("context[:_iterated] = true\n")
|
|
13
13
|
end
|
|
14
|
-
|
|
15
|
-
# @todo if with loop
|
|
16
|
-
compiler.
|
|
17
|
-
write("context[:loop] = {\n").
|
|
18
|
-
write(" index0: 0,\n").
|
|
19
|
-
write(" index: 1,\n").
|
|
20
|
-
write(" first: true,\n").
|
|
21
|
-
write("}\n")
|
|
22
|
-
|
|
23
|
-
if attributes.key?(:with_loop)
|
|
24
|
-
compiler.
|
|
25
|
-
write("context[:loop][:index0] += 1\n").
|
|
26
|
-
write("context[:loop][:index] += 1\n").
|
|
27
|
-
write("context[:loop][:first] = false\n").
|
|
28
|
-
write("if context[:loop].key?(:revindex0) && context[:loop].key?(:revindex)\n").
|
|
29
|
-
indent.
|
|
30
|
-
write("context[:loop][:revindex0] -= 1\n").
|
|
31
|
-
write("context[:loop][:revindex] -= 1\n").
|
|
32
|
-
write("context[:loop][:last] = (context[:loop][:revindex0] == 0)\n").
|
|
33
|
-
outdent.
|
|
34
|
-
write("end\n")
|
|
35
|
-
end
|
|
36
14
|
end
|
|
37
15
|
end
|
|
38
16
|
end
|
data/lib/twig/node/if.rb
CHANGED
|
@@ -11,6 +11,8 @@ module Twig
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def compile(compiler)
|
|
14
|
+
compiler.add_debug_info(self)
|
|
15
|
+
|
|
14
16
|
(0...nodes[:tests].nodes.length).step(2).each do |i|
|
|
15
17
|
if i.zero?
|
|
16
18
|
compiler.
|
|
@@ -23,8 +25,9 @@ module Twig
|
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
compiler.
|
|
28
|
+
raw('::Twig::Extension::Core.bool(').
|
|
26
29
|
subcompile(nodes[:tests].nodes[i]).
|
|
27
|
-
raw(")\n").
|
|
30
|
+
raw("))\n").
|
|
28
31
|
indent
|
|
29
32
|
|
|
30
33
|
if nodes[:tests].nodes.key?(i + 1)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
class Import < Node::Base
|
|
6
|
+
# @param [Expression::Base] expr
|
|
7
|
+
# @param [Expression::Base, Expression::Variable::AssignTemplate] var
|
|
8
|
+
# @param [Integer] lineno
|
|
9
|
+
def initialize(expr, var, lineno)
|
|
10
|
+
super({ expr:, var: }, {}, lineno)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @param [Compiler] compiler
|
|
14
|
+
def compile(compiler)
|
|
15
|
+
compiler.subcompile(nodes[:var])
|
|
16
|
+
|
|
17
|
+
if nodes[:expr].is_a?(Expression::Variable::Context) && nodes[:expr].attributes[:name] == '_self'
|
|
18
|
+
compiler.raw('self')
|
|
19
|
+
else
|
|
20
|
+
compiler.
|
|
21
|
+
raw('load(').
|
|
22
|
+
subcompile(nodes[:expr]).
|
|
23
|
+
raw(', ').
|
|
24
|
+
repr(lineno).
|
|
25
|
+
raw(').unwrap')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
compiler.raw("\n")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/twig/node/include.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
module Twig
|
|
4
4
|
module Node
|
|
5
5
|
class Include < Node::Base
|
|
6
|
+
include Output
|
|
7
|
+
|
|
6
8
|
# @param [Expression::Base] expr
|
|
7
9
|
# @param [Expression::Base, nil] variables
|
|
8
10
|
# @param [Boolean] only
|
|
@@ -19,9 +21,37 @@ module Twig
|
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def compile(compiler)
|
|
24
|
+
compiler.add_debug_info(self)
|
|
25
|
+
|
|
22
26
|
if attributes[:ignore_missing]
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
template = compiler.var_name
|
|
28
|
+
|
|
29
|
+
compiler.
|
|
30
|
+
write("begin\n").
|
|
31
|
+
indent.
|
|
32
|
+
write("#{template} = ")
|
|
33
|
+
|
|
34
|
+
add_get_template(compiler, template)
|
|
35
|
+
|
|
36
|
+
compiler.
|
|
37
|
+
raw("\n").
|
|
38
|
+
outdent.
|
|
39
|
+
write("rescue ::Twig::Error::Loader => e\n").
|
|
40
|
+
indent.
|
|
41
|
+
write("# ignore missing template\n").
|
|
42
|
+
write("#{template} = nil\n").
|
|
43
|
+
outdent.
|
|
44
|
+
write("end\n").
|
|
45
|
+
write("if #{template}\n").
|
|
46
|
+
indent.
|
|
47
|
+
write("#{template}.render_with_blocks(")
|
|
48
|
+
|
|
49
|
+
add_template_arguments(compiler)
|
|
50
|
+
|
|
51
|
+
compiler.
|
|
52
|
+
raw(");\n").
|
|
53
|
+
outdent.
|
|
54
|
+
write("end\n")
|
|
25
55
|
else
|
|
26
56
|
compiler.
|
|
27
57
|
write('')
|
|
@@ -41,13 +71,11 @@ module Twig
|
|
|
41
71
|
private
|
|
42
72
|
|
|
43
73
|
# @param [Compiler] compiler
|
|
44
|
-
def add_get_template(compiler)
|
|
74
|
+
def add_get_template(compiler, template = '')
|
|
45
75
|
compiler.
|
|
46
|
-
raw('
|
|
76
|
+
raw('load(').
|
|
47
77
|
subcompile(nodes[:expr]).
|
|
48
78
|
raw(', ').
|
|
49
|
-
repr(template_name).
|
|
50
|
-
raw(', ').
|
|
51
79
|
repr(lineno).
|
|
52
80
|
raw(')')
|
|
53
81
|
end
|
|
@@ -55,7 +83,7 @@ module Twig
|
|
|
55
83
|
# @param [Compiler] compiler
|
|
56
84
|
def add_template_arguments(compiler)
|
|
57
85
|
if !nodes.key?(:variables)
|
|
58
|
-
compiler.raw(attributes[:only] == false ? 'context' : '{}')
|
|
86
|
+
compiler.raw(attributes[:only] == false ? 'context' : 'context.only({})')
|
|
59
87
|
elsif attributes[:only] == false
|
|
60
88
|
compiler.
|
|
61
89
|
raw('context.merge(').
|
|
@@ -63,7 +91,9 @@ module Twig
|
|
|
63
91
|
raw(')')
|
|
64
92
|
else
|
|
65
93
|
compiler.
|
|
66
|
-
|
|
94
|
+
raw('context.only(').
|
|
95
|
+
subcompile(nodes[:variables]).
|
|
96
|
+
raw(')')
|
|
67
97
|
end
|
|
68
98
|
end
|
|
69
99
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
# Represents a macro node.
|
|
6
|
+
class Macro < Node::Base
|
|
7
|
+
VARARGS_NAME = 'varargs'
|
|
8
|
+
|
|
9
|
+
# @param [String] name
|
|
10
|
+
# @param [Body] body
|
|
11
|
+
# @param [Expression::Hash] arguments
|
|
12
|
+
# @param [Integer] lineno
|
|
13
|
+
def initialize(name, body, arguments, lineno)
|
|
14
|
+
arguments.key_value_pairs.each do |key, value|
|
|
15
|
+
next unless "\u035C#{VARARGS_NAME}" == key.attributes[:name]
|
|
16
|
+
|
|
17
|
+
raise Error::Syntax.new(
|
|
18
|
+
"The argument \"#{VARARGS_NAME}\" in macro \"#{name}\" cannot be defined because the variable " \
|
|
19
|
+
"\"#{VARARGS_NAME}\" is reserved for arbitrary arguments.",
|
|
20
|
+
value.lineno,
|
|
21
|
+
value.source_context
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
super({ body: body, arguments: arguments }, { name: name }, lineno)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @param [Compiler] compiler
|
|
29
|
+
def compile(compiler)
|
|
30
|
+
compiler.
|
|
31
|
+
add_debug_info(self).
|
|
32
|
+
write("def macro_#{attributes[:name]}(call_context, ")
|
|
33
|
+
|
|
34
|
+
arguments = nodes[:arguments]
|
|
35
|
+
arguments.key_value_pairs.each do |key, value|
|
|
36
|
+
compiler.
|
|
37
|
+
subcompile(key).
|
|
38
|
+
raw(': ').
|
|
39
|
+
subcompile(value).
|
|
40
|
+
raw(', ')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
compiler.
|
|
44
|
+
raw('**varargs').
|
|
45
|
+
raw(")\n").
|
|
46
|
+
write(" macros = @macros\n").
|
|
47
|
+
write(" context = ::Twig::Runtime::Context.new({\n")
|
|
48
|
+
|
|
49
|
+
arguments.key_value_pairs.each do |pair|
|
|
50
|
+
key = pair[0]
|
|
51
|
+
var = key.attributes[:name]
|
|
52
|
+
if var.start_with?("\u035C")
|
|
53
|
+
var = var[("\u035C".length)..]
|
|
54
|
+
end
|
|
55
|
+
compiler.
|
|
56
|
+
write(' ').
|
|
57
|
+
string(var).
|
|
58
|
+
raw(' => ').
|
|
59
|
+
subcompile(key).
|
|
60
|
+
raw(",\n")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
capture_node = Node::Capture.new(nodes[:body], nodes[:body].lineno)
|
|
64
|
+
|
|
65
|
+
compiler.
|
|
66
|
+
write(' ').
|
|
67
|
+
string(VARARGS_NAME).
|
|
68
|
+
raw(' => ').
|
|
69
|
+
raw("varargs,\n").
|
|
70
|
+
write(" }.merge(env.globals), call_context:)\n\n").
|
|
71
|
+
write(" blocks = {}\n\n").
|
|
72
|
+
write(' ').
|
|
73
|
+
subcompile(capture_node).
|
|
74
|
+
raw("\n").
|
|
75
|
+
write("end\n\n")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|