liquid 3.0.6 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
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