liquid 3.0.6 → 4.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.
Files changed (103) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +154 -58
  3. data/{MIT-LICENSE → LICENSE} +0 -0
  4. data/README.md +33 -0
  5. data/lib/liquid/block.rb +42 -125
  6. data/lib/liquid/block_body.rb +99 -79
  7. data/lib/liquid/condition.rb +52 -32
  8. data/lib/liquid/context.rb +57 -51
  9. data/lib/liquid/document.rb +19 -9
  10. data/lib/liquid/drop.rb +17 -16
  11. data/lib/liquid/errors.rb +20 -24
  12. data/lib/liquid/expression.rb +26 -10
  13. data/lib/liquid/extensions.rb +19 -7
  14. data/lib/liquid/file_system.rb +11 -11
  15. data/lib/liquid/forloop_drop.rb +42 -0
  16. data/lib/liquid/i18n.rb +6 -6
  17. data/lib/liquid/interrupts.rb +1 -2
  18. data/lib/liquid/lexer.rb +12 -8
  19. data/lib/liquid/locales/en.yml +6 -2
  20. data/lib/liquid/parse_context.rb +38 -0
  21. data/lib/liquid/parse_tree_visitor.rb +42 -0
  22. data/lib/liquid/parser_switching.rb +4 -4
  23. data/lib/liquid/profiler/hooks.rb +7 -7
  24. data/lib/liquid/profiler.rb +18 -19
  25. data/lib/liquid/range_lookup.rb +16 -1
  26. data/lib/liquid/resource_limits.rb +23 -0
  27. data/lib/liquid/standardfilters.rb +207 -61
  28. data/lib/liquid/strainer.rb +15 -8
  29. data/lib/liquid/tablerowloop_drop.rb +62 -0
  30. data/lib/liquid/tag.rb +9 -8
  31. data/lib/liquid/tags/assign.rb +25 -4
  32. data/lib/liquid/tags/break.rb +0 -3
  33. data/lib/liquid/tags/capture.rb +1 -1
  34. data/lib/liquid/tags/case.rb +27 -12
  35. data/lib/liquid/tags/comment.rb +2 -2
  36. data/lib/liquid/tags/cycle.rb +16 -8
  37. data/lib/liquid/tags/decrement.rb +1 -4
  38. data/lib/liquid/tags/for.rb +103 -75
  39. data/lib/liquid/tags/if.rb +60 -44
  40. data/lib/liquid/tags/ifchanged.rb +0 -2
  41. data/lib/liquid/tags/include.rb +71 -51
  42. data/lib/liquid/tags/raw.rb +32 -4
  43. data/lib/liquid/tags/table_row.rb +21 -31
  44. data/lib/liquid/tags/unless.rb +3 -4
  45. data/lib/liquid/template.rb +42 -54
  46. data/lib/liquid/tokenizer.rb +31 -0
  47. data/lib/liquid/truffle.rb +5 -0
  48. data/lib/liquid/utils.rb +52 -8
  49. data/lib/liquid/variable.rb +59 -46
  50. data/lib/liquid/variable_lookup.rb +14 -6
  51. data/lib/liquid/version.rb +2 -1
  52. data/lib/liquid.rb +10 -7
  53. data/test/integration/assign_test.rb +8 -8
  54. data/test/integration/blank_test.rb +14 -14
  55. data/test/integration/block_test.rb +12 -0
  56. data/test/integration/context_test.rb +2 -2
  57. data/test/integration/document_test.rb +19 -0
  58. data/test/integration/drop_test.rb +42 -40
  59. data/test/integration/error_handling_test.rb +96 -43
  60. data/test/integration/filter_test.rb +60 -20
  61. data/test/integration/hash_ordering_test.rb +9 -9
  62. data/test/integration/output_test.rb +26 -27
  63. data/test/integration/parse_tree_visitor_test.rb +247 -0
  64. data/test/integration/parsing_quirks_test.rb +19 -13
  65. data/test/integration/render_profiling_test.rb +20 -20
  66. data/test/integration/security_test.rb +23 -7
  67. data/test/integration/standard_filter_test.rb +426 -46
  68. data/test/integration/tags/break_tag_test.rb +1 -2
  69. data/test/integration/tags/continue_tag_test.rb +0 -1
  70. data/test/integration/tags/for_tag_test.rb +135 -100
  71. data/test/integration/tags/if_else_tag_test.rb +75 -77
  72. data/test/integration/tags/include_tag_test.rb +50 -31
  73. data/test/integration/tags/increment_tag_test.rb +10 -11
  74. data/test/integration/tags/raw_tag_test.rb +7 -1
  75. data/test/integration/tags/standard_tag_test.rb +121 -122
  76. data/test/integration/tags/statements_test.rb +3 -5
  77. data/test/integration/tags/table_row_test.rb +20 -19
  78. data/test/integration/tags/unless_else_tag_test.rb +6 -6
  79. data/test/integration/template_test.rb +199 -49
  80. data/test/integration/trim_mode_test.rb +529 -0
  81. data/test/integration/variable_test.rb +27 -13
  82. data/test/test_helper.rb +33 -6
  83. data/test/truffle/truffle_test.rb +9 -0
  84. data/test/unit/block_unit_test.rb +8 -5
  85. data/test/unit/condition_unit_test.rb +94 -77
  86. data/test/unit/context_unit_test.rb +69 -72
  87. data/test/unit/file_system_unit_test.rb +3 -3
  88. data/test/unit/i18n_unit_test.rb +2 -2
  89. data/test/unit/lexer_unit_test.rb +12 -9
  90. data/test/unit/parser_unit_test.rb +2 -2
  91. data/test/unit/regexp_unit_test.rb +1 -1
  92. data/test/unit/strainer_unit_test.rb +96 -1
  93. data/test/unit/tag_unit_test.rb +7 -2
  94. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  95. data/test/unit/tags/for_tag_unit_test.rb +2 -2
  96. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  97. data/test/unit/template_unit_test.rb +14 -5
  98. data/test/unit/tokenizer_unit_test.rb +24 -7
  99. data/test/unit/variable_unit_test.rb +60 -43
  100. metadata +62 -50
  101. data/lib/liquid/module_ex.rb +0 -62
  102. data/lib/liquid/token.rb +0 -18
  103. data/test/unit/module_ex_unit_test.rb +0 -87
@@ -4,23 +4,23 @@ class LexerUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_strings
7
- tokens = Lexer.new(%! 'this is a test""' "wat 'lol'"!).tokenize
8
- assert_equal [[:string,%!'this is a test""'!], [:string, %!"wat 'lol'"!], [:end_of_string]], tokens
7
+ tokens = Lexer.new(%( 'this is a test""' "wat 'lol'")).tokenize
8
+ assert_equal [[:string, %('this is a test""')], [:string, %("wat 'lol'")], [:end_of_string]], tokens
9
9
  end
10
10
 
11
11
  def test_integer
12
12
  tokens = Lexer.new('hi 50').tokenize
13
- assert_equal [[:id,'hi'], [:number, '50'], [:end_of_string]], tokens
13
+ assert_equal [[:id, 'hi'], [:number, '50'], [:end_of_string]], tokens
14
14
  end
15
15
 
16
16
  def test_float
17
17
  tokens = Lexer.new('hi 5.0').tokenize
18
- assert_equal [[:id,'hi'], [:number, '5.0'], [:end_of_string]], tokens
18
+ assert_equal [[:id, 'hi'], [:number, '5.0'], [:end_of_string]], tokens
19
19
  end
20
20
 
21
21
  def test_comparison
22
- tokens = Lexer.new('== <> contains').tokenize
23
- assert_equal [[:comparison,'=='], [:comparison, '<>'], [:comparison, 'contains'], [:end_of_string]], tokens
22
+ tokens = Lexer.new('== <> contains ').tokenize
23
+ assert_equal [[:comparison, '=='], [:comparison, '<>'], [:comparison, 'contains'], [:end_of_string]], tokens
24
24
  end
25
25
 
26
26
  def test_specials
@@ -31,13 +31,16 @@ class LexerUnitTest < Minitest::Test
31
31
  end
32
32
 
33
33
  def test_fancy_identifiers
34
- tokens = Lexer.new('hi! five?').tokenize
35
- assert_equal [[:id,'hi!'], [:id, 'five?'], [:end_of_string]], tokens
34
+ tokens = Lexer.new('hi five?').tokenize
35
+ assert_equal [[:id, 'hi'], [:id, 'five?'], [:end_of_string]], tokens
36
+
37
+ tokens = Lexer.new('2foo').tokenize
38
+ assert_equal [[:number, '2'], [:id, 'foo'], [:end_of_string]], tokens
36
39
  end
37
40
 
38
41
  def test_whitespace
39
42
  tokens = Lexer.new("five|\n\t ==").tokenize
40
- assert_equal [[:id,'five'], [:pipe, '|'], [:comparison, '=='], [:end_of_string]], tokens
43
+ assert_equal [[:id, 'five'], [:pipe, '|'], [:comparison, '=='], [:end_of_string]], tokens
41
44
  end
42
45
 
43
46
  def test_unexpected_character
@@ -44,9 +44,9 @@ class ParserUnitTest < Minitest::Test
44
44
  end
45
45
 
46
46
  def test_expressions
47
- p = Parser.new("hi.there hi[5].! hi.there.bob")
47
+ p = Parser.new("hi.there hi?[5].there? hi.there.bob")
48
48
  assert_equal 'hi.there', p.expression
49
- assert_equal 'hi[5].!', p.expression
49
+ assert_equal 'hi?[5].there?', p.expression
50
50
  assert_equal 'hi.there.bob', p.expression
51
51
 
52
52
  p = Parser.new("567 6.0 'lol' \"wut\"")
@@ -18,7 +18,7 @@ class RegexpUnitTest < Minitest::Test
18
18
  def test_tags
19
19
  assert_equal ['<tr>', '</tr>'], '<tr> </tr>'.scan(QuotedFragment)
20
20
  assert_equal ['<tr></tr>'], '<tr></tr>'.scan(QuotedFragment)
21
- assert_equal ['<style', 'class="hello">', '</style>'], %|<style class="hello">' </style>|.scan(QuotedFragment)
21
+ assert_equal ['<style', 'class="hello">', '</style>'], %(<style class="hello">' </style>).scan(QuotedFragment)
22
22
  end
23
23
 
24
24
  def test_double_quoted_words
@@ -29,6 +29,18 @@ class StrainerUnitTest < Minitest::Test
29
29
  end
30
30
  end
31
31
 
32
+ def test_stainer_argument_error_contains_backtrace
33
+ strainer = Strainer.create(nil)
34
+ begin
35
+ strainer.invoke("public_filter", 1)
36
+ rescue Liquid::ArgumentError => e
37
+ assert_match(
38
+ /\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/,
39
+ e.message)
40
+ assert_equal e.backtrace[0].split(':')[0], __FILE__
41
+ end
42
+ end
43
+
32
44
  def test_strainer_only_invokes_public_filter_methods
33
45
  strainer = Strainer.create(nil)
34
46
  assert_equal false, strainer.class.invokable?('__test__')
@@ -59,11 +71,94 @@ class StrainerUnitTest < Minitest::Test
59
71
  def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation
60
72
  a = Module.new
61
73
  b = Module.new
62
- strainer = Strainer.create(nil, [a,b])
74
+ strainer = Strainer.create(nil, [a, b])
63
75
  assert_kind_of Strainer, strainer
64
76
  assert_kind_of a, strainer
65
77
  assert_kind_of b, strainer
66
78
  assert_kind_of Liquid::StandardFilters, strainer
67
79
  end
68
80
 
81
+ def test_add_filter_when_wrong_filter_class
82
+ c = Context.new
83
+ s = c.strainer
84
+ wrong_filter = ->(v) { v.reverse }
85
+
86
+ assert_raises ArgumentError do
87
+ s.class.add_filter(wrong_filter)
88
+ end
89
+ end
90
+
91
+ module PrivateMethodOverrideFilter
92
+ private
93
+
94
+ def public_filter
95
+ "overriden as private"
96
+ end
97
+ end
98
+
99
+ def test_add_filter_raises_when_module_privately_overrides_registered_public_methods
100
+ strainer = Context.new.strainer
101
+
102
+ error = assert_raises(Liquid::MethodOverrideError) do
103
+ strainer.class.add_filter(PrivateMethodOverrideFilter)
104
+ end
105
+ assert_equal 'Liquid error: Filter overrides registered public methods as non public: public_filter', error.message
106
+ end
107
+
108
+ module ProtectedMethodOverrideFilter
109
+ protected
110
+
111
+ def public_filter
112
+ "overriden as protected"
113
+ end
114
+ end
115
+
116
+ def test_add_filter_raises_when_module_overrides_registered_public_method_as_protected
117
+ strainer = Context.new.strainer
118
+
119
+ error = assert_raises(Liquid::MethodOverrideError) do
120
+ strainer.class.add_filter(ProtectedMethodOverrideFilter)
121
+ end
122
+ assert_equal 'Liquid error: Filter overrides registered public methods as non public: public_filter', error.message
123
+ end
124
+
125
+ module PublicMethodOverrideFilter
126
+ def public_filter
127
+ "public"
128
+ end
129
+ end
130
+
131
+ def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method
132
+ strainer = Context.new.strainer
133
+ strainer.class.add_filter(PublicMethodOverrideFilter)
134
+ assert strainer.class.filter_methods.include?('public_filter')
135
+ end
136
+
137
+ module LateAddedFilter
138
+ def late_added_filter(input)
139
+ "filtered"
140
+ end
141
+ end
142
+
143
+ def test_global_filter_clears_cache
144
+ assert_equal 'input', Strainer.create(nil).invoke('late_added_filter', 'input')
145
+ Strainer.global_filter(LateAddedFilter)
146
+ assert_equal 'filtered', Strainer.create(nil).invoke('late_added_filter', 'input')
147
+ end
148
+
149
+ def test_add_filter_does_not_include_already_included_module
150
+ mod = Module.new do
151
+ class << self
152
+ attr_accessor :include_count
153
+ def included(mod)
154
+ self.include_count += 1
155
+ end
156
+ end
157
+ self.include_count = 0
158
+ end
159
+ strainer = Context.new.strainer
160
+ strainer.class.add_filter(mod)
161
+ strainer.class.add_filter(mod)
162
+ assert_equal 1, mod.include_count
163
+ end
69
164
  end # StrainerTest
@@ -4,13 +4,18 @@ class TagUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_tag
7
- tag = Tag.parse('tag', [], [], {})
7
+ tag = Tag.parse('tag', "", Tokenizer.new(""), ParseContext.new)
8
8
  assert_equal 'liquid::tag', tag.name
9
9
  assert_equal '', tag.render(Context.new)
10
10
  end
11
11
 
12
12
  def test_return_raw_text_of_tag
13
- tag = Tag.parse("long_tag", "param1, param2, param3", [], {})
13
+ tag = Tag.parse("long_tag", "param1, param2, param3", Tokenizer.new(""), ParseContext.new)
14
14
  assert_equal("long_tag param1, param2, param3", tag.raw)
15
15
  end
16
+
17
+ def test_tag_name_should_return_name_of_the_tag
18
+ tag = Tag.parse("some_tag", "", Tokenizer.new(""), ParseContext.new)
19
+ assert_equal 'some_tag', tag.tag_name
20
+ end
16
21
  end
@@ -5,6 +5,6 @@ class CaseTagUnitTest < Minitest::Test
5
5
 
6
6
  def test_case_nodelist
7
7
  template = Liquid::Template.parse('{% case var %}{% when true %}WHEN{% else %}ELSE{% endcase %}')
8
- assert_equal ['WHEN', 'ELSE'], template.root.nodelist[0].nodelist
8
+ assert_equal ['WHEN', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten
9
9
  end
10
10
  end
@@ -3,11 +3,11 @@ require 'test_helper'
3
3
  class ForTagUnitTest < Minitest::Test
4
4
  def test_for_nodelist
5
5
  template = Liquid::Template.parse('{% for item in items %}FOR{% endfor %}')
6
- assert_equal ['FOR'], template.root.nodelist[0].nodelist
6
+ assert_equal ['FOR'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten
7
7
  end
8
8
 
9
9
  def test_for_else_nodelist
10
10
  template = Liquid::Template.parse('{% for item in items %}FOR{% else %}ELSE{% endfor %}')
11
- assert_equal ['FOR', 'ELSE'], template.root.nodelist[0].nodelist
11
+ assert_equal ['FOR', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten
12
12
  end
13
13
  end
@@ -3,6 +3,6 @@ require 'test_helper'
3
3
  class IfTagUnitTest < Minitest::Test
4
4
  def test_if_nodelist
5
5
  template = Liquid::Template.parse('{% if true %}IF{% else %}ELSE{% endif %}')
6
- assert_equal ['IF', 'ELSE'], template.root.nodelist[0].nodelist
6
+ assert_equal ['IF', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten
7
7
  end
8
8
  end
@@ -5,16 +5,17 @@ class TemplateUnitTest < Minitest::Test
5
5
 
6
6
  def test_sets_default_localization_in_document
7
7
  t = Template.new
8
- t.parse('')
9
- assert_instance_of I18n, t.root.options[:locale]
8
+ t.parse('{%comment%}{%endcomment%}')
9
+ assert_instance_of I18n, t.root.nodelist[0].options[:locale]
10
10
  end
11
11
 
12
12
  def test_sets_default_localization_in_context_with_quick_initialization
13
13
  t = Template.new
14
- t.parse('{{foo}}', :locale => I18n.new(fixture("en_locale.yml")))
14
+ t.parse('{%comment%}{%endcomment%}', locale: I18n.new(fixture("en_locale.yml")))
15
15
 
16
- assert_instance_of I18n, t.root.options[:locale]
17
- assert_equal fixture("en_locale.yml"), t.root.options[:locale].path
16
+ locale = t.root.nodelist[0].options[:locale]
17
+ assert_instance_of I18n, locale
18
+ assert_equal fixture("en_locale.yml"), locale.path
18
19
  end
19
20
 
20
21
  def test_with_cache_classes_tags_returns_the_same_class
@@ -66,4 +67,12 @@ class TemplateUnitTest < Minitest::Test
66
67
  Template.tags.delete('fake')
67
68
  assert_nil Template.tags['fake']
68
69
  end
70
+
71
+ def test_tags_can_be_looped_over
72
+ Template.register_tag('fake', FakeTag)
73
+ result = Template.tags.map { |name, klass| [name, klass] }
74
+ assert result.include?(["fake", "TemplateUnitTest::FakeTag"])
75
+ ensure
76
+ Template.tags.delete('fake')
77
+ end
69
78
  end
@@ -22,17 +22,34 @@ class TokenizerTest < Minitest::Test
22
22
  end
23
23
 
24
24
  def test_calculate_line_numbers_per_token_with_profiling
25
- template = Liquid::Template.parse("", :profile => true)
26
-
27
- assert_equal [1], template.send(:tokenize, "{{funk}}").map(&:line_number)
28
- assert_equal [1, 1, 1], template.send(:tokenize, " {{funk}} ").map(&:line_number)
29
- assert_equal [1, 2, 2], template.send(:tokenize, "\n{{funk}}\n").map(&:line_number)
30
- assert_equal [1, 1, 3], template.send(:tokenize, " {{\n funk \n}} ").map(&:line_number)
25
+ assert_equal [1], tokenize_line_numbers("{{funk}}")
26
+ assert_equal [1, 1, 1], tokenize_line_numbers(" {{funk}} ")
27
+ assert_equal [1, 2, 2], tokenize_line_numbers("\n{{funk}}\n")
28
+ assert_equal [1, 1, 3], tokenize_line_numbers(" {{\n funk \n}} ")
31
29
  end
32
30
 
33
31
  private
34
32
 
35
33
  def tokenize(source)
36
- Liquid::Template.new.send(:tokenize, source)
34
+ tokenizer = Liquid::Tokenizer.new(source)
35
+ tokens = []
36
+ while t = tokenizer.shift
37
+ tokens << t
38
+ end
39
+ tokens
40
+ end
41
+
42
+ def tokenize_line_numbers(source)
43
+ tokenizer = Liquid::Tokenizer.new(source, true)
44
+ line_numbers = []
45
+ loop do
46
+ line_number = tokenizer.line_number
47
+ if tokenizer.shift
48
+ line_numbers << line_number
49
+ else
50
+ break
51
+ end
52
+ end
53
+ line_numbers
37
54
  end
38
55
  end
@@ -4,136 +4,147 @@ class VariableUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_variable
7
- var = Variable.new('hello')
7
+ var = create_variable('hello')
8
8
  assert_equal VariableLookup.new('hello'), var.name
9
9
  end
10
10
 
11
11
  def test_filters
12
- var = Variable.new('hello | textileze')
12
+ var = create_variable('hello | textileze')
13
13
  assert_equal VariableLookup.new('hello'), var.name
14
- assert_equal [['textileze',[]]], var.filters
14
+ assert_equal [['textileze', []]], var.filters
15
15
 
16
- var = Variable.new('hello | textileze | paragraph')
16
+ var = create_variable('hello | textileze | paragraph')
17
17
  assert_equal VariableLookup.new('hello'), var.name
18
- assert_equal [['textileze',[]], ['paragraph',[]]], var.filters
18
+ assert_equal [['textileze', []], ['paragraph', []]], var.filters
19
19
 
20
- var = Variable.new(%! hello | strftime: '%Y'!)
20
+ var = create_variable(%( hello | strftime: '%Y'))
21
21
  assert_equal VariableLookup.new('hello'), var.name
22
- assert_equal [['strftime',['%Y']]], var.filters
22
+ assert_equal [['strftime', ['%Y']]], var.filters
23
23
 
24
- var = Variable.new(%! 'typo' | link_to: 'Typo', true !)
24
+ var = create_variable(%( 'typo' | link_to: 'Typo', true ))
25
25
  assert_equal 'typo', var.name
26
- assert_equal [['link_to',['Typo', true]]], var.filters
26
+ assert_equal [['link_to', ['Typo', true]]], var.filters
27
27
 
28
- var = Variable.new(%! 'typo' | link_to: 'Typo', false !)
28
+ var = create_variable(%( 'typo' | link_to: 'Typo', false ))
29
29
  assert_equal 'typo', var.name
30
- assert_equal [['link_to',['Typo', false]]], var.filters
30
+ assert_equal [['link_to', ['Typo', false]]], var.filters
31
31
 
32
- var = Variable.new(%! 'foo' | repeat: 3 !)
32
+ var = create_variable(%( 'foo' | repeat: 3 ))
33
33
  assert_equal 'foo', var.name
34
- assert_equal [['repeat',[3]]], var.filters
34
+ assert_equal [['repeat', [3]]], var.filters
35
35
 
36
- var = Variable.new(%! 'foo' | repeat: 3, 3 !)
36
+ var = create_variable(%( 'foo' | repeat: 3, 3 ))
37
37
  assert_equal 'foo', var.name
38
- assert_equal [['repeat',[3,3]]], var.filters
38
+ assert_equal [['repeat', [3, 3]]], var.filters
39
39
 
40
- var = Variable.new(%! 'foo' | repeat: 3, 3, 3 !)
40
+ var = create_variable(%( 'foo' | repeat: 3, 3, 3 ))
41
41
  assert_equal 'foo', var.name
42
- assert_equal [['repeat',[3,3,3]]], var.filters
42
+ assert_equal [['repeat', [3, 3, 3]]], var.filters
43
43
 
44
- var = Variable.new(%! hello | strftime: '%Y, okay?'!)
44
+ var = create_variable(%( hello | strftime: '%Y, okay?'))
45
45
  assert_equal VariableLookup.new('hello'), var.name
46
- assert_equal [['strftime',['%Y, okay?']]], var.filters
46
+ assert_equal [['strftime', ['%Y, okay?']]], var.filters
47
47
 
48
- var = Variable.new(%! hello | things: "%Y, okay?", 'the other one'!)
48
+ var = create_variable(%( hello | things: "%Y, okay?", 'the other one'))
49
49
  assert_equal VariableLookup.new('hello'), var.name
50
- assert_equal [['things',['%Y, okay?','the other one']]], var.filters
50
+ assert_equal [['things', ['%Y, okay?', 'the other one']]], var.filters
51
51
  end
52
52
 
53
53
  def test_filter_with_date_parameter
54
- var = Variable.new(%! '2006-06-06' | date: "%m/%d/%Y"!)
54
+ var = create_variable(%( '2006-06-06' | date: "%m/%d/%Y"))
55
55
  assert_equal '2006-06-06', var.name
56
- assert_equal [['date',['%m/%d/%Y']]], var.filters
56
+ assert_equal [['date', ['%m/%d/%Y']]], var.filters
57
57
  end
58
58
 
59
59
  def test_filters_without_whitespace
60
- var = Variable.new('hello | textileze | paragraph')
60
+ var = create_variable('hello | textileze | paragraph')
61
61
  assert_equal VariableLookup.new('hello'), var.name
62
- assert_equal [['textileze',[]], ['paragraph',[]]], var.filters
62
+ assert_equal [['textileze', []], ['paragraph', []]], var.filters
63
63
 
64
- var = Variable.new('hello|textileze|paragraph')
64
+ var = create_variable('hello|textileze|paragraph')
65
65
  assert_equal VariableLookup.new('hello'), var.name
66
- assert_equal [['textileze',[]], ['paragraph',[]]], var.filters
66
+ assert_equal [['textileze', []], ['paragraph', []]], var.filters
67
67
 
68
- var = Variable.new("hello|replace:'foo','bar'|textileze")
68
+ var = create_variable("hello|replace:'foo','bar'|textileze")
69
69
  assert_equal VariableLookup.new('hello'), var.name
70
70
  assert_equal [['replace', ['foo', 'bar']], ['textileze', []]], var.filters
71
71
  end
72
72
 
73
73
  def test_symbol
74
- var = Variable.new("http://disney.com/logo.gif | image: 'med' ", :error_mode => :lax)
74
+ var = create_variable("http://disney.com/logo.gif | image: 'med' ", error_mode: :lax)
75
75
  assert_equal VariableLookup.new('http://disney.com/logo.gif'), var.name
76
- assert_equal [['image',['med']]], var.filters
76
+ assert_equal [['image', ['med']]], var.filters
77
77
  end
78
78
 
79
79
  def test_string_to_filter
80
- var = Variable.new("'http://disney.com/logo.gif' | image: 'med' ")
80
+ var = create_variable("'http://disney.com/logo.gif' | image: 'med' ")
81
81
  assert_equal 'http://disney.com/logo.gif', var.name
82
- assert_equal [['image',['med']]], var.filters
82
+ assert_equal [['image', ['med']]], var.filters
83
83
  end
84
84
 
85
85
  def test_string_single_quoted
86
- var = Variable.new(%| "hello" |)
86
+ var = create_variable(%( "hello" ))
87
87
  assert_equal 'hello', var.name
88
88
  end
89
89
 
90
90
  def test_string_double_quoted
91
- var = Variable.new(%| 'hello' |)
91
+ var = create_variable(%( 'hello' ))
92
92
  assert_equal 'hello', var.name
93
93
  end
94
94
 
95
95
  def test_integer
96
- var = Variable.new(%| 1000 |)
96
+ var = create_variable(%( 1000 ))
97
97
  assert_equal 1000, var.name
98
98
  end
99
99
 
100
100
  def test_float
101
- var = Variable.new(%| 1000.01 |)
101
+ var = create_variable(%( 1000.01 ))
102
102
  assert_equal 1000.01, var.name
103
103
  end
104
104
 
105
+ def test_dashes
106
+ assert_equal VariableLookup.new('foo-bar'), create_variable('foo-bar').name
107
+ assert_equal VariableLookup.new('foo-bar-2'), create_variable('foo-bar-2').name
108
+
109
+ with_error_mode :strict do
110
+ assert_raises(Liquid::SyntaxError) { create_variable('foo - bar') }
111
+ assert_raises(Liquid::SyntaxError) { create_variable('-foo') }
112
+ assert_raises(Liquid::SyntaxError) { create_variable('2foo') }
113
+ end
114
+ end
115
+
105
116
  def test_string_with_special_chars
106
- var = Variable.new(%| 'hello! $!@.;"ddasd" ' |)
117
+ var = create_variable(%( 'hello! $!@.;"ddasd" ' ))
107
118
  assert_equal 'hello! $!@.;"ddasd" ', var.name
108
119
  end
109
120
 
110
121
  def test_string_dot
111
- var = Variable.new(%| test.test |)
122
+ var = create_variable(%( test.test ))
112
123
  assert_equal VariableLookup.new('test.test'), var.name
113
124
  end
114
125
 
115
126
  def test_filter_with_keyword_arguments
116
- var = Variable.new(%! hello | things: greeting: "world", farewell: 'goodbye'!)
127
+ var = create_variable(%( hello | things: greeting: "world", farewell: 'goodbye'))
117
128
  assert_equal VariableLookup.new('hello'), var.name
118
129
  assert_equal [['things', [], { 'greeting' => 'world', 'farewell' => 'goodbye' }]], var.filters
119
130
  end
120
131
 
121
132
  def test_lax_filter_argument_parsing
122
- var = Variable.new(%! number_of_comments | pluralize: 'comment': 'comments' !, :error_mode => :lax)
133
+ var = create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ), error_mode: :lax)
123
134
  assert_equal VariableLookup.new('number_of_comments'), var.name
124
- assert_equal [['pluralize',['comment','comments']]], var.filters
135
+ assert_equal [['pluralize', ['comment', 'comments']]], var.filters
125
136
  end
126
137
 
127
138
  def test_strict_filter_argument_parsing
128
139
  with_error_mode(:strict) do
129
140
  assert_raises(SyntaxError) do
130
- Variable.new(%! number_of_comments | pluralize: 'comment': 'comments' !)
141
+ create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ))
131
142
  end
132
143
  end
133
144
  end
134
145
 
135
146
  def test_output_raw_source_of_variable
136
- var = Variable.new(%! name_of_variable | upcase !)
147
+ var = create_variable(%( name_of_variable | upcase ))
137
148
  assert_equal " name_of_variable | upcase ", var.raw
138
149
  end
139
150
 
@@ -142,4 +153,10 @@ class VariableUnitTest < Minitest::Test
142
153
  assert_equal 'a', lookup.name
143
154
  assert_equal ['b', 'c'], lookup.lookups
144
155
  end
156
+
157
+ private
158
+
159
+ def create_variable(markup, options = {})
160
+ Variable.new(markup, ParseContext.new(options))
161
+ end
145
162
  end