twig_ruby 0.0.1 → 0.0.2
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/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 +145 -6
- data/lib/twig/context.rb +0 -64
- data/lib/twig/expression_parser.rb +0 -517
- data/lib/twig/railtie.rb +0 -60
|
@@ -4,25 +4,69 @@ module Twig
|
|
|
4
4
|
module Node
|
|
5
5
|
module Expression
|
|
6
6
|
class GetAttribute < Expression::Base
|
|
7
|
+
include SupportDefinedTest
|
|
8
|
+
|
|
7
9
|
def initialize(node, attribute, arguments, type, lineno)
|
|
8
10
|
nodes = { node:, attribute: }
|
|
9
11
|
nodes[:arguments] = arguments if arguments
|
|
10
12
|
|
|
11
|
-
super(nodes, { type: }, lineno)
|
|
13
|
+
super(nodes, { type:, ignore_strict_check: false }, lineno)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def enable_defined_test
|
|
17
|
+
super
|
|
18
|
+
change_ignore_strict_check(self)
|
|
12
19
|
end
|
|
13
20
|
|
|
14
21
|
def compile(compiler)
|
|
15
|
-
|
|
22
|
+
compiler.
|
|
23
|
+
raw('::Twig::Extension::Core.get_attribute(env, source_context, ')
|
|
24
|
+
|
|
25
|
+
if attributes[:ignore_strict_check]
|
|
26
|
+
nodes[:node].attributes[:ignore_strict_check] = true
|
|
27
|
+
end
|
|
16
28
|
|
|
17
29
|
compiler.
|
|
18
|
-
raw("(#{var} = ").
|
|
19
30
|
subcompile(nodes[:node]).
|
|
20
|
-
raw(
|
|
21
|
-
write("::Twig::Extension::Core.get_attribute(#{var}, ").
|
|
31
|
+
raw(', ').
|
|
22
32
|
subcompile(nodes[:attribute]).
|
|
23
33
|
raw(', ').
|
|
24
|
-
repr(attributes[:type])
|
|
25
|
-
|
|
34
|
+
repr(attributes[:type])
|
|
35
|
+
|
|
36
|
+
if nodes.key?(:arguments)
|
|
37
|
+
compiler.
|
|
38
|
+
raw(', arguments: ').
|
|
39
|
+
subcompile(nodes[:arguments])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if define_test_enabled?
|
|
43
|
+
compiler.
|
|
44
|
+
raw(', defined_test: true')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if attributes[:ignore_strict_check]
|
|
48
|
+
compiler.
|
|
49
|
+
raw(', ignore_strict_check: true')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
compiler.
|
|
53
|
+
raw(', lineno: ').
|
|
54
|
+
repr(lineno).
|
|
55
|
+
raw(')')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# @param [GetAttribute] node]
|
|
61
|
+
def change_ignore_strict_check(node)
|
|
62
|
+
node.attributes[:optimizable] = false
|
|
63
|
+
node.attributes[:ignore_strict_check] = true
|
|
64
|
+
|
|
65
|
+
object_node = node.nodes[:node]
|
|
66
|
+
|
|
67
|
+
if object_node.is_a?(GetAttribute)
|
|
68
|
+
change_ignore_strict_check(object_node)
|
|
69
|
+
end
|
|
26
70
|
end
|
|
27
71
|
end
|
|
28
72
|
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
class Hash < Expression::Base
|
|
7
|
+
include Expression::SupportDefinedTest
|
|
8
|
+
|
|
9
|
+
def initialize(elements, lineno)
|
|
10
|
+
super(elements, {}, lineno)
|
|
11
|
+
|
|
12
|
+
@index = -1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param [Expression::Base] value
|
|
16
|
+
# @param [Expression::Base|nil] key
|
|
17
|
+
def add_element(value, key = nil)
|
|
18
|
+
if key.nil?
|
|
19
|
+
@index += 1
|
|
20
|
+
key = Constant.new(@index, value.lineno)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
nodes.add(key, value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def compile(compiler)
|
|
27
|
+
if define_test_enabled?
|
|
28
|
+
return compiler.repr(true)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
compiler.
|
|
32
|
+
raw('{').
|
|
33
|
+
indent
|
|
34
|
+
|
|
35
|
+
first = true
|
|
36
|
+
|
|
37
|
+
key_value_pairs.each do |key, value|
|
|
38
|
+
unless first
|
|
39
|
+
compiler.raw(', ')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
first = false
|
|
43
|
+
|
|
44
|
+
unless value.is_a?(Expression::Unary::HashSpread)
|
|
45
|
+
case key
|
|
46
|
+
when Variable::Context
|
|
47
|
+
key = Unary::StringCast.new(key, key.lineno)
|
|
48
|
+
when Variable::Local
|
|
49
|
+
key_value = key.attributes[:name]
|
|
50
|
+
key = Constant.new(key_value, key.lineno)
|
|
51
|
+
when Constant
|
|
52
|
+
key.attributes[:value]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
compiler.
|
|
56
|
+
subcompile(key).
|
|
57
|
+
raw(' => ')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
compiler.
|
|
61
|
+
subcompile(value)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
compiler.
|
|
65
|
+
outdent.
|
|
66
|
+
raw('}')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def key_value_pairs
|
|
70
|
+
nodes.each_value.each_slice(2)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -3,27 +3,15 @@
|
|
|
3
3
|
module Twig
|
|
4
4
|
module Node
|
|
5
5
|
module Expression
|
|
6
|
-
class HelperMethod <
|
|
7
|
-
def initialize(name,
|
|
8
|
-
super({
|
|
6
|
+
class HelperMethod < Call
|
|
7
|
+
def initialize(name, arguments, lineno)
|
|
8
|
+
super({ arguments: }, { name: }, lineno)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
compiler.
|
|
13
|
-
raw("@call_context.#{attributes[:name]}(")
|
|
11
|
+
private
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
compiler.raw("#{key}: ")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
compiler.
|
|
21
|
-
subcompile(value).
|
|
22
|
-
raw(',')
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
compiler.
|
|
26
|
-
raw(')')
|
|
13
|
+
def callable_method
|
|
14
|
+
"context.call_context.method(:#{attributes[:name]})"
|
|
27
15
|
end
|
|
28
16
|
end
|
|
29
17
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
# Represents a macro call node.
|
|
7
|
+
class MacroReference < Expression::Base
|
|
8
|
+
include SupportDefinedTest
|
|
9
|
+
|
|
10
|
+
# @param [Variable::Template] template
|
|
11
|
+
# @param [String] name
|
|
12
|
+
# @param [Expression::Base] arguments
|
|
13
|
+
# @param [Integer] lineno
|
|
14
|
+
def initialize(template, name, arguments, lineno)
|
|
15
|
+
super({ template:, arguments: }, { name: }, lineno)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param [Compiler] compiler
|
|
19
|
+
def compile(compiler)
|
|
20
|
+
if define_test_enabled?
|
|
21
|
+
compiler.
|
|
22
|
+
subcompile(nodes[:template]).
|
|
23
|
+
raw('.macro?(').
|
|
24
|
+
repr(attributes[:name]).
|
|
25
|
+
raw(', context').
|
|
26
|
+
raw(')')
|
|
27
|
+
return
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
compiler.
|
|
31
|
+
subcompile(nodes[:template]).
|
|
32
|
+
raw('.render_macro(').
|
|
33
|
+
repr(attributes[:name]).
|
|
34
|
+
raw(', context, ').
|
|
35
|
+
subcompile(nodes[:arguments]).
|
|
36
|
+
raw(', ').
|
|
37
|
+
repr(lineno).
|
|
38
|
+
raw(', source_context)')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'support_defined_test'
|
|
4
|
+
|
|
3
5
|
module Twig
|
|
4
6
|
module Node
|
|
5
7
|
module Expression
|
|
6
8
|
class Name < Expression::Base
|
|
9
|
+
include Expression::SupportDefinedTest
|
|
10
|
+
|
|
7
11
|
SPECIAL_VARS = {
|
|
8
|
-
'_self' => '
|
|
12
|
+
'_self' => 'template_name',
|
|
9
13
|
'_context' => 'context',
|
|
10
14
|
'_charset' => 'env.charset',
|
|
11
15
|
}.freeze
|
|
@@ -17,19 +21,49 @@ module Twig
|
|
|
17
21
|
name:,
|
|
18
22
|
is_defined_test: false,
|
|
19
23
|
ignore_strict_check: false,
|
|
20
|
-
|
|
24
|
+
always_defined: false,
|
|
21
25
|
}, lineno)
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def compile(compiler)
|
|
25
29
|
name = attributes[:name]
|
|
26
30
|
|
|
27
|
-
compiler.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
compiler.add_debug_info(self)
|
|
32
|
+
|
|
33
|
+
if attributes[:name][0] == '@'
|
|
34
|
+
check = "context.call_context.instance_variable_defined?('#{name}')"
|
|
35
|
+
get = "context.call_context.instance_variable_get('#{name}')"
|
|
36
|
+
else
|
|
37
|
+
check = "context.key?(:#{name})"
|
|
38
|
+
get = "context[:#{name}]"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if define_test_enabled?
|
|
42
|
+
if attributes[:always_defined] || SPECIAL_VARS.key?(name)
|
|
43
|
+
compiler.repr(true)
|
|
44
|
+
else
|
|
45
|
+
compiler.raw(check)
|
|
46
|
+
end
|
|
47
|
+
elsif SPECIAL_VARS.key?(name)
|
|
48
|
+
compiler.raw(SPECIAL_VARS[name])
|
|
49
|
+
elsif attributes[:always_defined]
|
|
50
|
+
compiler.
|
|
51
|
+
raw(get)
|
|
52
|
+
elsif attributes[:ignore_strict_check] || !compiler.environment.strict_variables?
|
|
53
|
+
compiler.
|
|
54
|
+
raw('(').
|
|
55
|
+
raw(get).
|
|
56
|
+
raw(' || nil)')
|
|
57
|
+
else
|
|
58
|
+
compiler.
|
|
59
|
+
raw("(#{check}").
|
|
60
|
+
raw(" ? #{get}").
|
|
61
|
+
raw(' : raise(::Twig::Error::Runtime.new("Variable \"#{').
|
|
62
|
+
string(name).
|
|
63
|
+
raw('}\" does not exist.", ').
|
|
64
|
+
repr(lineno).
|
|
65
|
+
raw(', source_context)))')
|
|
66
|
+
end
|
|
33
67
|
end
|
|
34
68
|
end
|
|
35
69
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
# Represents a parent node
|
|
7
|
+
class Parent < Expression::Base
|
|
8
|
+
# @param [String] name
|
|
9
|
+
# @param [Integer] lineno
|
|
10
|
+
def initialize(name, lineno)
|
|
11
|
+
super({}, { output: false, name: }, lineno)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def compile(compiler)
|
|
15
|
+
if attributes[:output]
|
|
16
|
+
compiler.add_debug_info(self)
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
else
|
|
19
|
+
compiler.
|
|
20
|
+
raw('render_parent_block(').
|
|
21
|
+
string(attributes[:name]).
|
|
22
|
+
raw(', context, blocks)')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module SupportDefinedTest
|
|
7
|
+
def enable_defined_test
|
|
8
|
+
self.defined_test = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def define_test_enabled?
|
|
12
|
+
defined_test
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# @param [Boolean] defined_test
|
|
18
|
+
# @return [Boolean]
|
|
19
|
+
attr_accessor :defined_test
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -4,6 +4,8 @@ module Twig
|
|
|
4
4
|
module Node
|
|
5
5
|
module Expression
|
|
6
6
|
class Ternary < Expression::Base
|
|
7
|
+
include OperatorEscape
|
|
8
|
+
|
|
7
9
|
def initialize(test, left, right, lineno)
|
|
8
10
|
super({
|
|
9
11
|
test:,
|
|
@@ -14,7 +16,7 @@ module Twig
|
|
|
14
16
|
|
|
15
17
|
def compile(compiler)
|
|
16
18
|
compiler.
|
|
17
|
-
raw('((').
|
|
19
|
+
raw('(::Twig::Extension::Core.bool(').
|
|
18
20
|
subcompile(nodes[:test]).
|
|
19
21
|
raw(') ? (').
|
|
20
22
|
subcompile(nodes[:left]).
|
|
@@ -22,6 +24,10 @@ module Twig
|
|
|
22
24
|
subcompile(nodes[:right]).
|
|
23
25
|
raw('))')
|
|
24
26
|
end
|
|
27
|
+
|
|
28
|
+
def operand_names_to_escape
|
|
29
|
+
%i[left right]
|
|
30
|
+
end
|
|
25
31
|
end
|
|
26
32
|
end
|
|
27
33
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
class Base < Call
|
|
8
|
+
# @param [Node::Expression::Base] node
|
|
9
|
+
# @param [TwigTest] test
|
|
10
|
+
# @param [Node::Base] arguments
|
|
11
|
+
# @param [Integer] lineno
|
|
12
|
+
def initialize(node, test, arguments, lineno)
|
|
13
|
+
super({
|
|
14
|
+
node:,
|
|
15
|
+
arguments: arguments || Node::Empty.new,
|
|
16
|
+
}, {
|
|
17
|
+
name: test.name,
|
|
18
|
+
type: :test,
|
|
19
|
+
twig_callable: test,
|
|
20
|
+
}, lineno)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is the exact same value as a constant.
|
|
8
|
+
#
|
|
9
|
+
# {% if post.status is constant('Post::PUBLISHED') %}
|
|
10
|
+
# the status attribute is exactly the same as Post::PUBLISHED
|
|
11
|
+
# {% endif %}
|
|
12
|
+
#
|
|
13
|
+
class Constant < Test::Base
|
|
14
|
+
def compile(compiler)
|
|
15
|
+
compiler.
|
|
16
|
+
raw('(').
|
|
17
|
+
subcompile(nodes[:node]).
|
|
18
|
+
raw(' == ::Twig::Extension::Core.constant(')
|
|
19
|
+
|
|
20
|
+
compiler.
|
|
21
|
+
subcompile(nodes[:arguments].nodes[0])
|
|
22
|
+
|
|
23
|
+
if nodes[:arguments].nodes.key?(1)
|
|
24
|
+
compiler.
|
|
25
|
+
raw(', ').
|
|
26
|
+
subcompile(nodes[:arguments].nodes[1])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
compiler.raw('))')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if an expression is defined
|
|
8
|
+
#
|
|
9
|
+
# {{ var is defined }}
|
|
10
|
+
class Defined < Test::Base
|
|
11
|
+
# @param [Node::Expression::Base] node
|
|
12
|
+
# @param [TwigTest] name
|
|
13
|
+
# @param [Node::Base] arguments
|
|
14
|
+
# @param [Integer] lineno
|
|
15
|
+
def initialize(node, name, arguments, lineno)
|
|
16
|
+
unless node.is_a?(SupportDefinedTest)
|
|
17
|
+
raise Error::Syntax.new('The "defined" test only works with simple variables.', lineno)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
node.enable_defined_test
|
|
21
|
+
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def compile(compiler)
|
|
26
|
+
compiler.
|
|
27
|
+
subcompile(nodes[:node])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a number is divisible by another.
|
|
8
|
+
#
|
|
9
|
+
# {{ var is divisible by(3) }}
|
|
10
|
+
class DivisibleBy < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(' % ').
|
|
16
|
+
subcompile(nodes[:arguments].nodes[0]).
|
|
17
|
+
raw(' == 0)')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a number is even.
|
|
8
|
+
#
|
|
9
|
+
# {{ var is even }}
|
|
10
|
+
class Even < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(' % 2 == 0)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is iterable
|
|
8
|
+
#
|
|
9
|
+
# {{ var is iterable }}
|
|
10
|
+
class Iterable < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(').respond_to?(:each)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is a mapping (Hash)
|
|
8
|
+
#
|
|
9
|
+
# {{ var is mapping }}
|
|
10
|
+
class Mapping < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(').is_a?(Hash)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is null.
|
|
8
|
+
#
|
|
9
|
+
# {{ var is null }}
|
|
10
|
+
class Null < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(' == nil)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a number is odd.
|
|
8
|
+
#
|
|
9
|
+
# {{ var is odd }}
|
|
10
|
+
class Odd < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(' % 2 != 0)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is the same as another.
|
|
8
|
+
#
|
|
9
|
+
# {{ var is same as(other) }}
|
|
10
|
+
class SameAs < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(' == ').
|
|
16
|
+
subcompile(nodes[:arguments].nodes[0]).
|
|
17
|
+
raw(')')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Twig
|
|
4
|
+
module Node
|
|
5
|
+
module Expression
|
|
6
|
+
module Test
|
|
7
|
+
# Checks if a variable is a sequence (array)
|
|
8
|
+
#
|
|
9
|
+
# {{ var is sequence }}
|
|
10
|
+
class Sequence < Test::Base
|
|
11
|
+
def compile(compiler)
|
|
12
|
+
compiler.
|
|
13
|
+
raw('(').
|
|
14
|
+
subcompile(nodes[:node]).
|
|
15
|
+
raw(').is_a?(Array)')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|