liquid 3.0.6 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +98 -58
  3. data/README.md +31 -0
  4. data/lib/liquid/block.rb +31 -124
  5. data/lib/liquid/block_body.rb +75 -59
  6. data/lib/liquid/condition.rb +23 -22
  7. data/lib/liquid/context.rb +50 -46
  8. data/lib/liquid/document.rb +19 -9
  9. data/lib/liquid/drop.rb +17 -16
  10. data/lib/liquid/errors.rb +20 -24
  11. data/lib/liquid/expression.rb +15 -3
  12. data/lib/liquid/extensions.rb +13 -7
  13. data/lib/liquid/file_system.rb +11 -11
  14. data/lib/liquid/forloop_drop.rb +42 -0
  15. data/lib/liquid/i18n.rb +5 -5
  16. data/lib/liquid/interrupts.rb +1 -2
  17. data/lib/liquid/lexer.rb +6 -4
  18. data/lib/liquid/locales/en.yml +5 -1
  19. data/lib/liquid/parse_context.rb +37 -0
  20. data/lib/liquid/parser_switching.rb +4 -4
  21. data/lib/liquid/profiler/hooks.rb +7 -7
  22. data/lib/liquid/profiler.rb +18 -19
  23. data/lib/liquid/range_lookup.rb +16 -1
  24. data/lib/liquid/resource_limits.rb +23 -0
  25. data/lib/liquid/standardfilters.rb +121 -61
  26. data/lib/liquid/strainer.rb +14 -7
  27. data/lib/liquid/tablerowloop_drop.rb +62 -0
  28. data/lib/liquid/tag.rb +9 -8
  29. data/lib/liquid/tags/assign.rb +17 -4
  30. data/lib/liquid/tags/break.rb +0 -3
  31. data/lib/liquid/tags/capture.rb +1 -1
  32. data/lib/liquid/tags/case.rb +19 -12
  33. data/lib/liquid/tags/comment.rb +2 -2
  34. data/lib/liquid/tags/cycle.rb +6 -6
  35. data/lib/liquid/tags/decrement.rb +1 -4
  36. data/lib/liquid/tags/for.rb +95 -75
  37. data/lib/liquid/tags/if.rb +49 -44
  38. data/lib/liquid/tags/ifchanged.rb +0 -2
  39. data/lib/liquid/tags/include.rb +61 -52
  40. data/lib/liquid/tags/raw.rb +32 -4
  41. data/lib/liquid/tags/table_row.rb +12 -30
  42. data/lib/liquid/tags/unless.rb +3 -4
  43. data/lib/liquid/template.rb +42 -54
  44. data/lib/liquid/tokenizer.rb +31 -0
  45. data/lib/liquid/utils.rb +52 -8
  46. data/lib/liquid/variable.rb +46 -45
  47. data/lib/liquid/variable_lookup.rb +7 -5
  48. data/lib/liquid/version.rb +1 -1
  49. data/lib/liquid.rb +9 -7
  50. data/test/integration/assign_test.rb +8 -8
  51. data/test/integration/blank_test.rb +14 -14
  52. data/test/integration/context_test.rb +2 -2
  53. data/test/integration/document_test.rb +19 -0
  54. data/test/integration/drop_test.rb +42 -40
  55. data/test/integration/error_handling_test.rb +99 -46
  56. data/test/integration/filter_test.rb +60 -20
  57. data/test/integration/hash_ordering_test.rb +9 -9
  58. data/test/integration/output_test.rb +26 -27
  59. data/test/integration/parsing_quirks_test.rb +15 -13
  60. data/test/integration/render_profiling_test.rb +20 -20
  61. data/test/integration/security_test.rb +9 -7
  62. data/test/integration/standard_filter_test.rb +179 -40
  63. data/test/integration/tags/break_tag_test.rb +1 -2
  64. data/test/integration/tags/continue_tag_test.rb +0 -1
  65. data/test/integration/tags/for_tag_test.rb +133 -98
  66. data/test/integration/tags/if_else_tag_test.rb +75 -77
  67. data/test/integration/tags/include_tag_test.rb +34 -30
  68. data/test/integration/tags/increment_tag_test.rb +10 -11
  69. data/test/integration/tags/raw_tag_test.rb +7 -1
  70. data/test/integration/tags/standard_tag_test.rb +121 -122
  71. data/test/integration/tags/statements_test.rb +3 -5
  72. data/test/integration/tags/table_row_test.rb +20 -19
  73. data/test/integration/tags/unless_else_tag_test.rb +6 -6
  74. data/test/integration/template_test.rb +190 -49
  75. data/test/integration/trim_mode_test.rb +525 -0
  76. data/test/integration/variable_test.rb +23 -13
  77. data/test/test_helper.rb +33 -5
  78. data/test/unit/block_unit_test.rb +8 -5
  79. data/test/unit/condition_unit_test.rb +86 -77
  80. data/test/unit/context_unit_test.rb +48 -57
  81. data/test/unit/file_system_unit_test.rb +3 -3
  82. data/test/unit/i18n_unit_test.rb +2 -2
  83. data/test/unit/lexer_unit_test.rb +11 -8
  84. data/test/unit/parser_unit_test.rb +2 -2
  85. data/test/unit/regexp_unit_test.rb +1 -1
  86. data/test/unit/strainer_unit_test.rb +80 -1
  87. data/test/unit/tag_unit_test.rb +7 -2
  88. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  89. data/test/unit/tags/for_tag_unit_test.rb +2 -2
  90. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  91. data/test/unit/template_unit_test.rb +14 -5
  92. data/test/unit/tokenizer_unit_test.rb +24 -7
  93. data/test/unit/variable_unit_test.rb +60 -43
  94. metadata +19 -14
  95. data/lib/liquid/module_ex.rb +0 -62
  96. data/lib/liquid/token.rb +0 -18
  97. data/test/unit/module_ex_unit_test.rb +0 -87
  98. /data/{MIT-LICENSE → LICENSE} +0 -0
@@ -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,78 @@ 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
69
148
  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
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liquid
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Tobias Luetke
7
+ - Tobias Lütke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-24 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '11.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '11.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -48,7 +48,7 @@ extra_rdoc_files:
48
48
  - README.md
49
49
  files:
50
50
  - History.md
51
- - MIT-LICENSE
51
+ - LICENSE
52
52
  - README.md
53
53
  - lib/liquid.rb
54
54
  - lib/liquid/block.rb
@@ -61,18 +61,21 @@ files:
61
61
  - lib/liquid/expression.rb
62
62
  - lib/liquid/extensions.rb
63
63
  - lib/liquid/file_system.rb
64
+ - lib/liquid/forloop_drop.rb
64
65
  - lib/liquid/i18n.rb
65
66
  - lib/liquid/interrupts.rb
66
67
  - lib/liquid/lexer.rb
67
68
  - lib/liquid/locales/en.yml
68
- - lib/liquid/module_ex.rb
69
+ - lib/liquid/parse_context.rb
69
70
  - lib/liquid/parser.rb
70
71
  - lib/liquid/parser_switching.rb
71
72
  - lib/liquid/profiler.rb
72
73
  - lib/liquid/profiler/hooks.rb
73
74
  - lib/liquid/range_lookup.rb
75
+ - lib/liquid/resource_limits.rb
74
76
  - lib/liquid/standardfilters.rb
75
77
  - lib/liquid/strainer.rb
78
+ - lib/liquid/tablerowloop_drop.rb
76
79
  - lib/liquid/tag.rb
77
80
  - lib/liquid/tags/assign.rb
78
81
  - lib/liquid/tags/break.rb
@@ -91,7 +94,7 @@ files:
91
94
  - lib/liquid/tags/table_row.rb
92
95
  - lib/liquid/tags/unless.rb
93
96
  - lib/liquid/template.rb
94
- - lib/liquid/token.rb
97
+ - lib/liquid/tokenizer.rb
95
98
  - lib/liquid/utils.rb
96
99
  - lib/liquid/variable.rb
97
100
  - lib/liquid/variable_lookup.rb
@@ -101,6 +104,7 @@ files:
101
104
  - test/integration/blank_test.rb
102
105
  - test/integration/capture_test.rb
103
106
  - test/integration/context_test.rb
107
+ - test/integration/document_test.rb
104
108
  - test/integration/drop_test.rb
105
109
  - test/integration/error_handling_test.rb
106
110
  - test/integration/filter_test.rb
@@ -122,6 +126,7 @@ files:
122
126
  - test/integration/tags/table_row_test.rb
123
127
  - test/integration/tags/unless_else_tag_test.rb
124
128
  - test/integration/template_test.rb
129
+ - test/integration/trim_mode_test.rb
125
130
  - test/integration/variable_test.rb
126
131
  - test/test_helper.rb
127
132
  - test/unit/block_unit_test.rb
@@ -130,7 +135,6 @@ files:
130
135
  - test/unit/file_system_unit_test.rb
131
136
  - test/unit/i18n_unit_test.rb
132
137
  - test/unit/lexer_unit_test.rb
133
- - test/unit/module_ex_unit_test.rb
134
138
  - test/unit/parser_unit_test.rb
135
139
  - test/unit/regexp_unit_test.rb
136
140
  - test/unit/strainer_unit_test.rb
@@ -153,7 +157,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
153
157
  requirements:
154
158
  - - ">="
155
159
  - !ruby/object:Gem::Version
156
- version: '0'
160
+ version: 2.1.0
157
161
  required_rubygems_version: !ruby/object:Gem::Requirement
158
162
  requirements:
159
163
  - - ">="
@@ -161,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
165
  version: 1.3.7
162
166
  requirements: []
163
167
  rubyforge_project:
164
- rubygems_version: 2.2.1
168
+ rubygems_version: 2.4.5
165
169
  signing_key:
166
170
  specification_version: 4
167
171
  summary: A secure, non-evaling end user template engine with aesthetic markup.
@@ -171,6 +175,7 @@ test_files:
171
175
  - test/integration/blank_test.rb
172
176
  - test/integration/capture_test.rb
173
177
  - test/integration/context_test.rb
178
+ - test/integration/document_test.rb
174
179
  - test/integration/drop_test.rb
175
180
  - test/integration/error_handling_test.rb
176
181
  - test/integration/filter_test.rb
@@ -192,6 +197,7 @@ test_files:
192
197
  - test/integration/tags/table_row_test.rb
193
198
  - test/integration/tags/unless_else_tag_test.rb
194
199
  - test/integration/template_test.rb
200
+ - test/integration/trim_mode_test.rb
195
201
  - test/integration/variable_test.rb
196
202
  - test/test_helper.rb
197
203
  - test/unit/block_unit_test.rb
@@ -200,7 +206,6 @@ test_files:
200
206
  - test/unit/file_system_unit_test.rb
201
207
  - test/unit/i18n_unit_test.rb
202
208
  - test/unit/lexer_unit_test.rb
203
- - test/unit/module_ex_unit_test.rb
204
209
  - test/unit/parser_unit_test.rb
205
210
  - test/unit/regexp_unit_test.rb
206
211
  - test/unit/strainer_unit_test.rb
@@ -1,62 +0,0 @@
1
- # Copyright 2007 by Domizio Demichelis
2
- # This library is free software. It may be used, redistributed and/or modified
3
- # under the same terms as Ruby itself
4
- #
5
- # This extension is used in order to expose the object of the implementing class
6
- # to liquid as it were a Drop. It also limits the liquid-callable methods of the instance
7
- # to the allowed method passed with the liquid_methods call
8
- # Example:
9
- #
10
- # class SomeClass
11
- # liquid_methods :an_allowed_method
12
- #
13
- # def an_allowed_method
14
- # 'this comes from an allowed method'
15
- # end
16
- # def unallowed_method
17
- # 'this will never be an output'
18
- # end
19
- # end
20
- #
21
- # if you want to extend the drop to other methods you can defines more methods
22
- # in the class <YourClass>::LiquidDropClass
23
- #
24
- # class SomeClass::LiquidDropClass
25
- # def another_allowed_method
26
- # 'and this from another allowed method'
27
- # end
28
- # end
29
- # end
30
- #
31
- # usage:
32
- # @something = SomeClass.new
33
- #
34
- # template:
35
- # {{something.an_allowed_method}}{{something.unallowed_method}} {{something.another_allowed_method}}
36
- #
37
- # output:
38
- # 'this comes from an allowed method and this from another allowed method'
39
- #
40
- # You can also chain associations, by adding the liquid_method call in the
41
- # association models.
42
- #
43
- class Module
44
-
45
- def liquid_methods(*allowed_methods)
46
- drop_class = eval "class #{self.to_s}::LiquidDropClass < Liquid::Drop; self; end"
47
- define_method :to_liquid do
48
- drop_class.new(self)
49
- end
50
- drop_class.class_eval do
51
- def initialize(object)
52
- @object = object
53
- end
54
- allowed_methods.each do |sym|
55
- define_method sym do
56
- @object.send sym
57
- end
58
- end
59
- end
60
- end
61
-
62
- end
data/lib/liquid/token.rb DELETED
@@ -1,18 +0,0 @@
1
- module Liquid
2
- class Token < String
3
- attr_reader :line_number
4
-
5
- def initialize(content, line_number)
6
- super(content)
7
- @line_number = line_number
8
- end
9
-
10
- def raw
11
- "<raw>"
12
- end
13
-
14
- def child(string)
15
- Token.new(string, @line_number)
16
- end
17
- end
18
- end