liquid 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +16 -1
  3. data/README.md +2 -2
  4. data/lib/liquid/block_body.rb +4 -4
  5. data/lib/liquid/context.rb +6 -2
  6. data/lib/liquid/forloop_drop.rb +44 -1
  7. data/lib/liquid/locales/en.yml +6 -5
  8. data/lib/liquid/partial_cache.rb +3 -3
  9. data/lib/liquid/{static_registers.rb → registers.rb} +13 -10
  10. data/lib/liquid/standardfilters.rb +406 -57
  11. data/lib/liquid/strainer_factory.rb +4 -0
  12. data/lib/liquid/strainer_template.rb +4 -0
  13. data/lib/liquid/tablerowloop_drop.rb +58 -1
  14. data/lib/liquid/tags/assign.rb +12 -8
  15. data/lib/liquid/tags/break.rb +8 -0
  16. data/lib/liquid/tags/capture.rb +13 -10
  17. data/lib/liquid/tags/case.rb +21 -0
  18. data/lib/liquid/tags/comment.rb +13 -0
  19. data/lib/liquid/tags/continue.rb +8 -9
  20. data/lib/liquid/tags/cycle.rb +12 -11
  21. data/lib/liquid/tags/decrement.rb +16 -17
  22. data/lib/liquid/tags/echo.rb +16 -9
  23. data/lib/liquid/tags/for.rb +22 -43
  24. data/lib/liquid/tags/if.rb +11 -9
  25. data/lib/liquid/tags/include.rb +15 -13
  26. data/lib/liquid/tags/increment.rb +16 -14
  27. data/lib/liquid/tags/inline_comment.rb +43 -0
  28. data/lib/liquid/tags/raw.rb +11 -0
  29. data/lib/liquid/tags/render.rb +29 -4
  30. data/lib/liquid/tags/table_row.rb +22 -0
  31. data/lib/liquid/tags/unless.rb +15 -4
  32. data/lib/liquid/template.rb +2 -3
  33. data/lib/liquid/variable.rb +4 -4
  34. data/lib/liquid/variable_lookup.rb +10 -7
  35. data/lib/liquid/version.rb +1 -1
  36. data/lib/liquid.rb +2 -2
  37. metadata +7 -123
  38. data/lib/liquid/register.rb +0 -6
  39. data/test/fixtures/en_locale.yml +0 -9
  40. data/test/integration/assign_test.rb +0 -117
  41. data/test/integration/blank_test.rb +0 -109
  42. data/test/integration/block_test.rb +0 -58
  43. data/test/integration/capture_test.rb +0 -58
  44. data/test/integration/context_test.rb +0 -634
  45. data/test/integration/document_test.rb +0 -21
  46. data/test/integration/drop_test.rb +0 -257
  47. data/test/integration/error_handling_test.rb +0 -272
  48. data/test/integration/expression_test.rb +0 -46
  49. data/test/integration/filter_kwarg_test.rb +0 -24
  50. data/test/integration/filter_test.rb +0 -189
  51. data/test/integration/hash_ordering_test.rb +0 -25
  52. data/test/integration/output_test.rb +0 -125
  53. data/test/integration/parsing_quirks_test.rb +0 -134
  54. data/test/integration/profiler_test.rb +0 -240
  55. data/test/integration/security_test.rb +0 -89
  56. data/test/integration/standard_filter_test.rb +0 -925
  57. data/test/integration/tag/disableable_test.rb +0 -59
  58. data/test/integration/tag_test.rb +0 -45
  59. data/test/integration/tags/break_tag_test.rb +0 -17
  60. data/test/integration/tags/continue_tag_test.rb +0 -17
  61. data/test/integration/tags/echo_test.rb +0 -13
  62. data/test/integration/tags/for_tag_test.rb +0 -466
  63. data/test/integration/tags/if_else_tag_test.rb +0 -190
  64. data/test/integration/tags/include_tag_test.rb +0 -269
  65. data/test/integration/tags/increment_tag_test.rb +0 -25
  66. data/test/integration/tags/liquid_tag_test.rb +0 -116
  67. data/test/integration/tags/raw_tag_test.rb +0 -34
  68. data/test/integration/tags/render_tag_test.rb +0 -213
  69. data/test/integration/tags/standard_tag_test.rb +0 -303
  70. data/test/integration/tags/statements_test.rb +0 -113
  71. data/test/integration/tags/table_row_test.rb +0 -66
  72. data/test/integration/tags/unless_else_tag_test.rb +0 -28
  73. data/test/integration/template_test.rb +0 -340
  74. data/test/integration/trim_mode_test.rb +0 -563
  75. data/test/integration/variable_test.rb +0 -138
  76. data/test/test_helper.rb +0 -207
  77. data/test/unit/block_unit_test.rb +0 -53
  78. data/test/unit/condition_unit_test.rb +0 -181
  79. data/test/unit/file_system_unit_test.rb +0 -37
  80. data/test/unit/i18n_unit_test.rb +0 -39
  81. data/test/unit/lexer_unit_test.rb +0 -53
  82. data/test/unit/parse_tree_visitor_test.rb +0 -261
  83. data/test/unit/parser_unit_test.rb +0 -84
  84. data/test/unit/partial_cache_unit_test.rb +0 -128
  85. data/test/unit/regexp_unit_test.rb +0 -46
  86. data/test/unit/static_registers_unit_test.rb +0 -156
  87. data/test/unit/strainer_factory_unit_test.rb +0 -101
  88. data/test/unit/strainer_template_unit_test.rb +0 -82
  89. data/test/unit/tag_unit_test.rb +0 -23
  90. data/test/unit/tags/case_tag_unit_test.rb +0 -12
  91. data/test/unit/tags/for_tag_unit_test.rb +0 -15
  92. data/test/unit/tags/if_tag_unit_test.rb +0 -10
  93. data/test/unit/template_factory_unit_test.rb +0 -12
  94. data/test/unit/template_unit_test.rb +0 -87
  95. data/test/unit/tokenizer_unit_test.rb +0 -62
  96. data/test/unit/variable_unit_test.rb +0 -164
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class StrainerFactoryUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- module AccessScopeFilters
9
- def public_filter
10
- "public"
11
- end
12
-
13
- def private_filter
14
- "private"
15
- end
16
- private :private_filter
17
- end
18
-
19
- StrainerFactory.add_global_filter(AccessScopeFilters)
20
-
21
- module LateAddedFilter
22
- def late_added_filter(_input)
23
- "filtered"
24
- end
25
- end
26
-
27
- def setup
28
- @context = Context.build
29
- end
30
-
31
- def test_strainer
32
- strainer = StrainerFactory.create(@context)
33
- assert_equal(5, strainer.invoke('size', 'input'))
34
- assert_equal("public", strainer.invoke("public_filter"))
35
- end
36
-
37
- def test_stainer_raises_argument_error
38
- strainer = StrainerFactory.create(@context)
39
- assert_raises(Liquid::ArgumentError) do
40
- strainer.invoke("public_filter", 1)
41
- end
42
- end
43
-
44
- def test_stainer_argument_error_contains_backtrace
45
- strainer = StrainerFactory.create(@context)
46
-
47
- exception = assert_raises(Liquid::ArgumentError) do
48
- strainer.invoke("public_filter", 1)
49
- end
50
-
51
- assert_match(
52
- /\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/,
53
- exception.message
54
- )
55
- source = AccessScopeFilters.instance_method(:public_filter).source_location
56
- assert_equal(source.map(&:to_s), exception.backtrace[0].split(':')[0..1])
57
- end
58
-
59
- def test_strainer_only_invokes_public_filter_methods
60
- strainer = StrainerFactory.create(@context)
61
- assert_equal(false, strainer.class.invokable?('__test__'))
62
- assert_equal(false, strainer.class.invokable?('test'))
63
- assert_equal(false, strainer.class.invokable?('instance_eval'))
64
- assert_equal(false, strainer.class.invokable?('__send__'))
65
- assert_equal(true, strainer.class.invokable?('size')) # from the standard lib
66
- end
67
-
68
- def test_strainer_returns_nil_if_no_filter_method_found
69
- strainer = StrainerFactory.create(@context)
70
- assert_nil(strainer.invoke("private_filter"))
71
- assert_nil(strainer.invoke("undef_the_filter"))
72
- end
73
-
74
- def test_strainer_returns_first_argument_if_no_method_and_arguments_given
75
- strainer = StrainerFactory.create(@context)
76
- assert_equal("password", strainer.invoke("undef_the_method", "password"))
77
- end
78
-
79
- def test_strainer_only_allows_methods_defined_in_filters
80
- strainer = StrainerFactory.create(@context)
81
- assert_equal("1 + 1", strainer.invoke("instance_eval", "1 + 1"))
82
- assert_equal("puts", strainer.invoke("__send__", "puts", "Hi Mom"))
83
- assert_equal("has_method?", strainer.invoke("invoke", "has_method?", "invoke"))
84
- end
85
-
86
- def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation
87
- a = Module.new
88
- b = Module.new
89
- strainer = StrainerFactory.create(@context, [a, b])
90
- assert_kind_of(StrainerTemplate, strainer)
91
- assert_kind_of(a, strainer)
92
- assert_kind_of(b, strainer)
93
- assert_kind_of(Liquid::StandardFilters, strainer)
94
- end
95
-
96
- def test_add_global_filter_clears_cache
97
- assert_equal('input', StrainerFactory.create(@context).invoke('late_added_filter', 'input'))
98
- StrainerFactory.add_global_filter(LateAddedFilter)
99
- assert_equal('filtered', StrainerFactory.create(nil).invoke('late_added_filter', 'input'))
100
- end
101
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class StrainerTemplateUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_add_filter_when_wrong_filter_class
9
- c = Context.new
10
- s = c.strainer
11
- wrong_filter = ->(v) { v.reverse }
12
-
13
- exception = assert_raises(TypeError) do
14
- s.class.add_filter(wrong_filter)
15
- end
16
- assert_equal(exception.message, "wrong argument type Proc (expected Module)")
17
- end
18
-
19
- module PrivateMethodOverrideFilter
20
- private
21
-
22
- def public_filter
23
- "overriden as private"
24
- end
25
- end
26
-
27
- def test_add_filter_raises_when_module_privately_overrides_registered_public_methods
28
- strainer = Context.new.strainer
29
-
30
- error = assert_raises(Liquid::MethodOverrideError) do
31
- strainer.class.add_filter(PrivateMethodOverrideFilter)
32
- end
33
- assert_equal('Liquid error: Filter overrides registered public methods as non public: public_filter', error.message)
34
- end
35
-
36
- module ProtectedMethodOverrideFilter
37
- protected
38
-
39
- def public_filter
40
- "overriden as protected"
41
- end
42
- end
43
-
44
- def test_add_filter_raises_when_module_overrides_registered_public_method_as_protected
45
- strainer = Context.new.strainer
46
-
47
- error = assert_raises(Liquid::MethodOverrideError) do
48
- strainer.class.add_filter(ProtectedMethodOverrideFilter)
49
- end
50
- assert_equal('Liquid error: Filter overrides registered public methods as non public: public_filter', error.message)
51
- end
52
-
53
- module PublicMethodOverrideFilter
54
- def public_filter
55
- "public"
56
- end
57
- end
58
-
59
- def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method
60
- with_global_filter do
61
- strainer = Context.new.strainer
62
- strainer.class.add_filter(PublicMethodOverrideFilter)
63
- assert(strainer.class.send(:filter_methods).include?('public_filter'))
64
- end
65
- end
66
-
67
- def test_add_filter_does_not_include_already_included_module
68
- mod = Module.new do
69
- class << self
70
- attr_accessor :include_count
71
- def included(_mod)
72
- self.include_count += 1
73
- end
74
- end
75
- self.include_count = 0
76
- end
77
- strainer = Context.new.strainer
78
- strainer.class.add_filter(mod)
79
- strainer.class.add_filter(mod)
80
- assert_equal(1, mod.include_count)
81
- end
82
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TagUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_tag
9
- tag = Tag.parse('tag', "", Tokenizer.new(""), ParseContext.new)
10
- assert_equal('liquid::tag', tag.name)
11
- assert_equal('', tag.render(Context.new))
12
- end
13
-
14
- def test_return_raw_text_of_tag
15
- tag = Tag.parse("long_tag", "param1, param2, param3", Tokenizer.new(""), ParseContext.new)
16
- assert_equal("long_tag param1, param2, param3", tag.raw)
17
- end
18
-
19
- def test_tag_name_should_return_name_of_the_tag
20
- tag = Tag.parse("some_tag", "", Tokenizer.new(""), ParseContext.new)
21
- assert_equal('some_tag', tag.tag_name)
22
- end
23
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class CaseTagUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_case_nodelist
9
- template = Liquid::Template.parse('{% case var %}{% when true %}WHEN{% else %}ELSE{% endcase %}')
10
- assert_equal(['WHEN', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten)
11
- end
12
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class ForTagUnitTest < Minitest::Test
6
- def test_for_nodelist
7
- template = Liquid::Template.parse('{% for item in items %}FOR{% endfor %}')
8
- assert_equal(['FOR'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten)
9
- end
10
-
11
- def test_for_else_nodelist
12
- template = Liquid::Template.parse('{% for item in items %}FOR{% else %}ELSE{% endfor %}')
13
- assert_equal(['FOR', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten)
14
- end
15
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class IfTagUnitTest < Minitest::Test
6
- def test_if_nodelist
7
- template = Liquid::Template.parse('{% if true %}IF{% else %}ELSE{% endif %}')
8
- assert_equal(['IF', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten)
9
- end
10
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TemplateFactoryUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_for_returns_liquid_template_instance
9
- template = TemplateFactory.new.for("anything")
10
- assert_instance_of(Liquid::Template, template)
11
- end
12
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TemplateUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_sets_default_localization_in_document
9
- t = Template.new
10
- t.parse('{%comment%}{%endcomment%}')
11
- assert_instance_of(I18n, t.root.nodelist[0].options[:locale])
12
- end
13
-
14
- def test_sets_default_localization_in_context_with_quick_initialization
15
- t = Template.new
16
- t.parse('{%comment%}{%endcomment%}', locale: I18n.new(fixture("en_locale.yml")))
17
-
18
- locale = t.root.nodelist[0].options[:locale]
19
- assert_instance_of(I18n, locale)
20
- assert_equal(fixture("en_locale.yml"), locale.path)
21
- end
22
-
23
- def test_with_cache_classes_tags_returns_the_same_class
24
- original_cache_setting = Liquid.cache_classes
25
- Liquid.cache_classes = true
26
-
27
- original_klass = Class.new
28
- Object.send(:const_set, :CustomTag, original_klass)
29
- Template.register_tag('custom', CustomTag)
30
-
31
- Object.send(:remove_const, :CustomTag)
32
-
33
- new_klass = Class.new
34
- Object.send(:const_set, :CustomTag, new_klass)
35
-
36
- assert(Template.tags['custom'].equal?(original_klass))
37
- ensure
38
- Object.send(:remove_const, :CustomTag)
39
- Template.tags.delete('custom')
40
- Liquid.cache_classes = original_cache_setting
41
- end
42
-
43
- def test_without_cache_classes_tags_reloads_the_class
44
- original_cache_setting = Liquid.cache_classes
45
- Liquid.cache_classes = false
46
-
47
- original_klass = Class.new
48
- Object.send(:const_set, :CustomTag, original_klass)
49
- Template.register_tag('custom', CustomTag)
50
-
51
- Object.send(:remove_const, :CustomTag)
52
-
53
- new_klass = Class.new
54
- Object.send(:const_set, :CustomTag, new_klass)
55
-
56
- assert(Template.tags['custom'].equal?(new_klass))
57
- ensure
58
- Object.send(:remove_const, :CustomTag)
59
- Template.tags.delete('custom')
60
- Liquid.cache_classes = original_cache_setting
61
- end
62
-
63
- class FakeTag; end
64
-
65
- def test_tags_delete
66
- Template.register_tag('fake', FakeTag)
67
- assert_equal(FakeTag, Template.tags['fake'])
68
-
69
- Template.tags.delete('fake')
70
- assert_nil(Template.tags['fake'])
71
- end
72
-
73
- def test_tags_can_be_looped_over
74
- Template.register_tag('fake', FakeTag)
75
- result = Template.tags.map { |name, klass| [name, klass] }
76
- assert(result.include?(["fake", "TemplateUnitTest::FakeTag"]))
77
- ensure
78
- Template.tags.delete('fake')
79
- end
80
-
81
- class TemplateSubclass < Liquid::Template
82
- end
83
-
84
- def test_template_inheritance
85
- assert_equal("foo", TemplateSubclass.parse("foo").render)
86
- end
87
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TokenizerTest < Minitest::Test
6
- def test_tokenize_strings
7
- assert_equal([' '], tokenize(' '))
8
- assert_equal(['hello world'], tokenize('hello world'))
9
- end
10
-
11
- def test_tokenize_variables
12
- assert_equal(['{{funk}}'], tokenize('{{funk}}'))
13
- assert_equal([' ', '{{funk}}', ' '], tokenize(' {{funk}} '))
14
- assert_equal([' ', '{{funk}}', ' ', '{{so}}', ' ', '{{brother}}', ' '], tokenize(' {{funk}} {{so}} {{brother}} '))
15
- assert_equal([' ', '{{ funk }}', ' '], tokenize(' {{ funk }} '))
16
- end
17
-
18
- def test_tokenize_blocks
19
- assert_equal(['{%comment%}'], tokenize('{%comment%}'))
20
- assert_equal([' ', '{%comment%}', ' '], tokenize(' {%comment%} '))
21
-
22
- assert_equal([' ', '{%comment%}', ' ', '{%endcomment%}', ' '], tokenize(' {%comment%} {%endcomment%} '))
23
- assert_equal([' ', '{% comment %}', ' ', '{% endcomment %}', ' '], tokenize(" {% comment %} {% endcomment %} "))
24
- end
25
-
26
- def test_calculate_line_numbers_per_token_with_profiling
27
- assert_equal([1], tokenize_line_numbers("{{funk}}"))
28
- assert_equal([1, 1, 1], tokenize_line_numbers(" {{funk}} "))
29
- assert_equal([1, 2, 2], tokenize_line_numbers("\n{{funk}}\n"))
30
- assert_equal([1, 1, 3], tokenize_line_numbers(" {{\n funk \n}} "))
31
- end
32
-
33
- private
34
-
35
- def new_tokenizer(source, parse_context: Liquid::ParseContext.new, start_line_number: nil)
36
- parse_context.new_tokenizer(source, start_line_number: start_line_number)
37
- end
38
-
39
- def tokenize(source)
40
- tokenizer = new_tokenizer(source)
41
- tokens = []
42
- # shift is private in Liquid::C::Tokenizer, since it is only for unit testing
43
- while (t = tokenizer.send(:shift))
44
- tokens << t
45
- end
46
- tokens
47
- end
48
-
49
- def tokenize_line_numbers(source)
50
- tokenizer = new_tokenizer(source, start_line_number: 1)
51
- line_numbers = []
52
- loop do
53
- line_number = tokenizer.line_number
54
- if tokenizer.send(:shift)
55
- line_numbers << line_number
56
- else
57
- break
58
- end
59
- end
60
- line_numbers
61
- end
62
- end
@@ -1,164 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class VariableUnitTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_variable
9
- var = create_variable('hello')
10
- assert_equal(VariableLookup.new('hello'), var.name)
11
- end
12
-
13
- def test_filters
14
- var = create_variable('hello | textileze')
15
- assert_equal(VariableLookup.new('hello'), var.name)
16
- assert_equal([['textileze', []]], var.filters)
17
-
18
- var = create_variable('hello | textileze | paragraph')
19
- assert_equal(VariableLookup.new('hello'), var.name)
20
- assert_equal([['textileze', []], ['paragraph', []]], var.filters)
21
-
22
- var = create_variable(%( hello | strftime: '%Y'))
23
- assert_equal(VariableLookup.new('hello'), var.name)
24
- assert_equal([['strftime', ['%Y']]], var.filters)
25
-
26
- var = create_variable(%( 'typo' | link_to: 'Typo', true ))
27
- assert_equal('typo', var.name)
28
- assert_equal([['link_to', ['Typo', true]]], var.filters)
29
-
30
- var = create_variable(%( 'typo' | link_to: 'Typo', false ))
31
- assert_equal('typo', var.name)
32
- assert_equal([['link_to', ['Typo', false]]], var.filters)
33
-
34
- var = create_variable(%( 'foo' | repeat: 3 ))
35
- assert_equal('foo', var.name)
36
- assert_equal([['repeat', [3]]], var.filters)
37
-
38
- var = create_variable(%( 'foo' | repeat: 3, 3 ))
39
- assert_equal('foo', var.name)
40
- assert_equal([['repeat', [3, 3]]], var.filters)
41
-
42
- var = create_variable(%( 'foo' | repeat: 3, 3, 3 ))
43
- assert_equal('foo', var.name)
44
- assert_equal([['repeat', [3, 3, 3]]], var.filters)
45
-
46
- var = create_variable(%( hello | strftime: '%Y, okay?'))
47
- assert_equal(VariableLookup.new('hello'), var.name)
48
- assert_equal([['strftime', ['%Y, okay?']]], var.filters)
49
-
50
- var = create_variable(%( hello | things: "%Y, okay?", 'the other one'))
51
- assert_equal(VariableLookup.new('hello'), var.name)
52
- assert_equal([['things', ['%Y, okay?', 'the other one']]], var.filters)
53
- end
54
-
55
- def test_filter_with_date_parameter
56
- var = create_variable(%( '2006-06-06' | date: "%m/%d/%Y"))
57
- assert_equal('2006-06-06', var.name)
58
- assert_equal([['date', ['%m/%d/%Y']]], var.filters)
59
- end
60
-
61
- def test_filters_without_whitespace
62
- var = create_variable('hello | textileze | paragraph')
63
- assert_equal(VariableLookup.new('hello'), var.name)
64
- assert_equal([['textileze', []], ['paragraph', []]], var.filters)
65
-
66
- var = create_variable('hello|textileze|paragraph')
67
- assert_equal(VariableLookup.new('hello'), var.name)
68
- assert_equal([['textileze', []], ['paragraph', []]], var.filters)
69
-
70
- var = create_variable("hello|replace:'foo','bar'|textileze")
71
- assert_equal(VariableLookup.new('hello'), var.name)
72
- assert_equal([['replace', ['foo', 'bar']], ['textileze', []]], var.filters)
73
- end
74
-
75
- def test_symbol
76
- var = create_variable("http://disney.com/logo.gif | image: 'med' ", error_mode: :lax)
77
- assert_equal(VariableLookup.new('http://disney.com/logo.gif'), var.name)
78
- assert_equal([['image', ['med']]], var.filters)
79
- end
80
-
81
- def test_string_to_filter
82
- var = create_variable("'http://disney.com/logo.gif' | image: 'med' ")
83
- assert_equal('http://disney.com/logo.gif', var.name)
84
- assert_equal([['image', ['med']]], var.filters)
85
- end
86
-
87
- def test_string_single_quoted
88
- var = create_variable(%( "hello" ))
89
- assert_equal('hello', var.name)
90
- end
91
-
92
- def test_string_double_quoted
93
- var = create_variable(%( 'hello' ))
94
- assert_equal('hello', var.name)
95
- end
96
-
97
- def test_integer
98
- var = create_variable(%( 1000 ))
99
- assert_equal(1000, var.name)
100
- end
101
-
102
- def test_float
103
- var = create_variable(%( 1000.01 ))
104
- assert_equal(1000.01, var.name)
105
- end
106
-
107
- def test_dashes
108
- assert_equal(VariableLookup.new('foo-bar'), create_variable('foo-bar').name)
109
- assert_equal(VariableLookup.new('foo-bar-2'), create_variable('foo-bar-2').name)
110
-
111
- with_error_mode(:strict) do
112
- assert_raises(Liquid::SyntaxError) { create_variable('foo - bar') }
113
- assert_raises(Liquid::SyntaxError) { create_variable('-foo') }
114
- assert_raises(Liquid::SyntaxError) { create_variable('2foo') }
115
- end
116
- end
117
-
118
- def test_string_with_special_chars
119
- var = create_variable(%( 'hello! $!@.;"ddasd" ' ))
120
- assert_equal('hello! $!@.;"ddasd" ', var.name)
121
- end
122
-
123
- def test_string_dot
124
- var = create_variable(%( test.test ))
125
- assert_equal(VariableLookup.new('test.test'), var.name)
126
- end
127
-
128
- def test_filter_with_keyword_arguments
129
- var = create_variable(%( hello | things: greeting: "world", farewell: 'goodbye'))
130
- assert_equal(VariableLookup.new('hello'), var.name)
131
- assert_equal([['things', [], { 'greeting' => 'world', 'farewell' => 'goodbye' }]], var.filters)
132
- end
133
-
134
- def test_lax_filter_argument_parsing
135
- var = create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ), error_mode: :lax)
136
- assert_equal(VariableLookup.new('number_of_comments'), var.name)
137
- assert_equal([['pluralize', ['comment', 'comments']]], var.filters)
138
- end
139
-
140
- def test_strict_filter_argument_parsing
141
- with_error_mode(:strict) do
142
- assert_raises(SyntaxError) do
143
- create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ))
144
- end
145
- end
146
- end
147
-
148
- def test_output_raw_source_of_variable
149
- var = create_variable(%( name_of_variable | upcase ))
150
- assert_equal(" name_of_variable | upcase ", var.raw)
151
- end
152
-
153
- def test_variable_lookup_interface
154
- lookup = VariableLookup.new('a.b.c')
155
- assert_equal('a', lookup.name)
156
- assert_equal(['b', 'c'], lookup.lookups)
157
- end
158
-
159
- private
160
-
161
- def create_variable(markup, options = {})
162
- Variable.new(markup, ParseContext.new(options))
163
- end
164
- end