liquid 2.6.3 → 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 (100) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +272 -26
  3. data/README.md +67 -3
  4. data/lib/liquid/block.rb +62 -94
  5. data/lib/liquid/block_body.rb +255 -0
  6. data/lib/liquid/condition.rb +96 -38
  7. data/lib/liquid/context.rb +172 -154
  8. data/lib/liquid/document.rb +57 -9
  9. data/lib/liquid/drop.rb +33 -14
  10. data/lib/liquid/errors.rb +56 -10
  11. data/lib/liquid/expression.rb +45 -0
  12. data/lib/liquid/extensions.rb +21 -7
  13. data/lib/liquid/file_system.rb +27 -14
  14. data/lib/liquid/forloop_drop.rb +92 -0
  15. data/lib/liquid/i18n.rb +41 -0
  16. data/lib/liquid/interrupts.rb +3 -2
  17. data/lib/liquid/lexer.rb +62 -0
  18. data/lib/liquid/locales/en.yml +29 -0
  19. data/lib/liquid/parse_context.rb +54 -0
  20. data/lib/liquid/parse_tree_visitor.rb +42 -0
  21. data/lib/liquid/parser.rb +102 -0
  22. data/lib/liquid/parser_switching.rb +45 -0
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +35 -0
  25. data/lib/liquid/profiler.rb +139 -0
  26. data/lib/liquid/range_lookup.rb +47 -0
  27. data/lib/liquid/registers.rb +51 -0
  28. data/lib/liquid/resource_limits.rb +62 -0
  29. data/lib/liquid/standardfilters.rb +789 -118
  30. data/lib/liquid/strainer_factory.rb +41 -0
  31. data/lib/liquid/strainer_template.rb +62 -0
  32. data/lib/liquid/tablerowloop_drop.rb +121 -0
  33. data/lib/liquid/tag/disableable.rb +22 -0
  34. data/lib/liquid/tag/disabler.rb +21 -0
  35. data/lib/liquid/tag.rb +49 -10
  36. data/lib/liquid/tags/assign.rb +61 -19
  37. data/lib/liquid/tags/break.rb +14 -4
  38. data/lib/liquid/tags/capture.rb +29 -21
  39. data/lib/liquid/tags/case.rb +80 -31
  40. data/lib/liquid/tags/comment.rb +24 -2
  41. data/lib/liquid/tags/continue.rb +14 -13
  42. data/lib/liquid/tags/cycle.rb +50 -32
  43. data/lib/liquid/tags/decrement.rb +24 -26
  44. data/lib/liquid/tags/echo.rb +41 -0
  45. data/lib/liquid/tags/for.rb +164 -100
  46. data/lib/liquid/tags/if.rb +105 -44
  47. data/lib/liquid/tags/ifchanged.rb +10 -11
  48. data/lib/liquid/tags/include.rb +85 -65
  49. data/lib/liquid/tags/increment.rb +24 -22
  50. data/lib/liquid/tags/inline_comment.rb +43 -0
  51. data/lib/liquid/tags/raw.rb +50 -11
  52. data/lib/liquid/tags/render.rb +109 -0
  53. data/lib/liquid/tags/table_row.rb +88 -0
  54. data/lib/liquid/tags/unless.rb +37 -21
  55. data/lib/liquid/template.rb +124 -46
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +39 -0
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +68 -5
  60. data/lib/liquid/variable.rb +128 -32
  61. data/lib/liquid/variable_lookup.rb +96 -0
  62. data/lib/liquid/version.rb +3 -1
  63. data/lib/liquid.rb +36 -13
  64. metadata +69 -77
  65. data/lib/extras/liquid_view.rb +0 -51
  66. data/lib/liquid/htmltags.rb +0 -73
  67. data/lib/liquid/module_ex.rb +0 -62
  68. data/lib/liquid/strainer.rb +0 -53
  69. data/test/liquid/assign_test.rb +0 -21
  70. data/test/liquid/block_test.rb +0 -58
  71. data/test/liquid/capture_test.rb +0 -40
  72. data/test/liquid/condition_test.rb +0 -127
  73. data/test/liquid/context_test.rb +0 -478
  74. data/test/liquid/drop_test.rb +0 -180
  75. data/test/liquid/error_handling_test.rb +0 -81
  76. data/test/liquid/file_system_test.rb +0 -29
  77. data/test/liquid/filter_test.rb +0 -125
  78. data/test/liquid/hash_ordering_test.rb +0 -25
  79. data/test/liquid/module_ex_test.rb +0 -87
  80. data/test/liquid/output_test.rb +0 -116
  81. data/test/liquid/parsing_quirks_test.rb +0 -52
  82. data/test/liquid/regexp_test.rb +0 -44
  83. data/test/liquid/security_test.rb +0 -64
  84. data/test/liquid/standard_filter_test.rb +0 -263
  85. data/test/liquid/strainer_test.rb +0 -52
  86. data/test/liquid/tags/break_tag_test.rb +0 -16
  87. data/test/liquid/tags/continue_tag_test.rb +0 -16
  88. data/test/liquid/tags/for_tag_test.rb +0 -297
  89. data/test/liquid/tags/html_tag_test.rb +0 -63
  90. data/test/liquid/tags/if_else_tag_test.rb +0 -166
  91. data/test/liquid/tags/include_tag_test.rb +0 -166
  92. data/test/liquid/tags/increment_tag_test.rb +0 -24
  93. data/test/liquid/tags/raw_tag_test.rb +0 -24
  94. data/test/liquid/tags/standard_tag_test.rb +0 -295
  95. data/test/liquid/tags/statements_test.rb +0 -134
  96. data/test/liquid/tags/unless_else_tag_test.rb +0 -26
  97. data/test/liquid/template_test.rb +0 -146
  98. data/test/liquid/variable_test.rb +0 -186
  99. data/test/test_helper.rb +0 -29
  100. /data/{MIT-LICENSE → LICENSE} +0 -0
@@ -1,263 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'test_helper'
4
-
5
- class Filters
6
- include Liquid::StandardFilters
7
- end
8
-
9
- class TestThing
10
- def initialize
11
- @foo = 0
12
- end
13
-
14
- def to_s
15
- "woot: #{@foo}"
16
- end
17
-
18
- def to_liquid
19
- @foo += 1
20
- self
21
- end
22
- end
23
-
24
- class TestDrop < Liquid::Drop
25
- def test
26
- "testfoo"
27
- end
28
- end
29
-
30
- class StandardFiltersTest < Test::Unit::TestCase
31
- include Liquid
32
-
33
- def setup
34
- @filters = Filters.new
35
- end
36
-
37
- def test_size
38
- assert_equal 3, @filters.size([1,2,3])
39
- assert_equal 0, @filters.size([])
40
- assert_equal 0, @filters.size(nil)
41
- end
42
-
43
- def test_downcase
44
- assert_equal 'testing', @filters.downcase("Testing")
45
- assert_equal '', @filters.downcase(nil)
46
- end
47
-
48
- def test_upcase
49
- assert_equal 'TESTING', @filters.upcase("Testing")
50
- assert_equal '', @filters.upcase(nil)
51
- end
52
-
53
- def test_upcase
54
- assert_equal 'TESTING', @filters.upcase("Testing")
55
- assert_equal '', @filters.upcase(nil)
56
- end
57
-
58
- def test_truncate
59
- assert_equal '1234...', @filters.truncate('1234567890', 7)
60
- assert_equal '1234567890', @filters.truncate('1234567890', 20)
61
- assert_equal '...', @filters.truncate('1234567890', 0)
62
- assert_equal '1234567890', @filters.truncate('1234567890')
63
- assert_equal "测试...", @filters.truncate("测试测试测试测试", 5)
64
- end
65
-
66
- def test_strip
67
- assert_equal ['12','34'], @filters.split('12~34', '~')
68
- assert_equal ['A? ',' ,Z'], @filters.split('A? ~ ~ ~ ,Z', '~ ~ ~')
69
- assert_equal ['A?Z'], @filters.split('A?Z', '~')
70
- # Regexp works although Liquid does not support.
71
- assert_equal ['A','Z'], @filters.split('AxZ', /x/)
72
- end
73
-
74
- def test_escape
75
- assert_equal '&lt;strong&gt;', @filters.escape('<strong>')
76
- assert_equal '&lt;strong&gt;', @filters.h('<strong>')
77
- end
78
-
79
- def test_escape_once
80
- assert_equal '&lt;strong&gt;', @filters.escape_once(@filters.escape('<strong>'))
81
- end
82
-
83
- def test_truncatewords
84
- assert_equal 'one two three', @filters.truncatewords('one two three', 4)
85
- assert_equal 'one two...', @filters.truncatewords('one two three', 2)
86
- assert_equal 'one two three', @filters.truncatewords('one two three')
87
- assert_equal 'Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221;...', @filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
88
- assert_equal "测试测试测试测试", @filters.truncatewords('测试测试测试测试', 5)
89
- end
90
-
91
- def test_strip_html
92
- assert_equal 'test', @filters.strip_html("<div>test</div>")
93
- assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
94
- assert_equal '', @filters.strip_html("<script type='text/javascript'>document.write('some stuff');</script>")
95
- assert_equal '', @filters.strip_html("<style type='text/css'>foo bar</style>")
96
- assert_equal 'test', @filters.strip_html("<div\nclass='multiline'>test</div>")
97
- assert_equal 'test', @filters.strip_html("<!-- foo bar \n test -->test")
98
- assert_equal '', @filters.strip_html(nil)
99
- end
100
-
101
- def test_join
102
- assert_equal '1 2 3 4', @filters.join([1,2,3,4])
103
- assert_equal '1 - 2 - 3 - 4', @filters.join([1,2,3,4], ' - ')
104
- end
105
-
106
- def test_sort
107
- assert_equal [1,2,3,4], @filters.sort([4,3,2,1])
108
- assert_equal [{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], @filters.sort([{"a" => 4}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
109
- end
110
-
111
- def test_reverse
112
- assert_equal [4,3,2,1], @filters.reverse([1,2,3,4])
113
- end
114
-
115
- def test_map
116
- assert_equal [1,2,3,4], @filters.map([{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], 'a')
117
- assert_template_result 'abc', "{{ ary | map:'foo' | map:'bar' }}",
118
- 'ary' => [{'foo' => {'bar' => 'a'}}, {'foo' => {'bar' => 'b'}}, {'foo' => {'bar' => 'c'}}]
119
- end
120
-
121
- def test_map_doesnt_call_arbitrary_stuff
122
- assert_equal "", Liquid::Template.parse('{{ "foo" | map: "__id__" }}').render
123
- assert_equal "", Liquid::Template.parse('{{ "foo" | map: "inspect" }}').render
124
- end
125
-
126
- def test_map_calls_to_liquid
127
- t = TestThing.new
128
- assert_equal "woot: 1", Liquid::Template.parse('{{ foo }}').render("foo" => t)
129
- end
130
-
131
- def test_map_over_proc
132
- drop = TestDrop.new
133
- p = Proc.new{ drop }
134
- templ = '{{ procs | map: "test" }}'
135
- assert_equal "testfoo", Liquid::Template.parse(templ).render("procs" => [p])
136
- end
137
-
138
- def test_date
139
- assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
140
- assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
141
- assert_equal 'July', @filters.date(Time.parse("2006-07-05 10:00:00"), "%B")
142
-
143
- assert_equal 'May', @filters.date("2006-05-05 10:00:00", "%B")
144
- assert_equal 'June', @filters.date("2006-06-05 10:00:00", "%B")
145
- assert_equal 'July', @filters.date("2006-07-05 10:00:00", "%B")
146
-
147
- assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
148
- assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
149
- assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
150
- assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", nil)
151
-
152
- assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
153
-
154
- assert_equal "07/16/2004", @filters.date("Fri Jul 16 01:00:00 2004", "%m/%d/%Y")
155
- assert_equal "#{Date.today.year}", @filters.date('now', '%Y')
156
- assert_equal "#{Date.today.year}", @filters.date('today', '%Y')
157
-
158
- assert_equal nil, @filters.date(nil, "%B")
159
-
160
- with_timezone("UTC") do
161
- assert_equal "07/05/2006", @filters.date(1152098955, "%m/%d/%Y")
162
- assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
163
- end
164
- end
165
-
166
-
167
- def test_first_last
168
- assert_equal 1, @filters.first([1,2,3])
169
- assert_equal 3, @filters.last([1,2,3])
170
- assert_equal nil, @filters.first([])
171
- assert_equal nil, @filters.last([])
172
- end
173
-
174
- def test_replace
175
- assert_equal '2 2 2 2', @filters.replace('1 1 1 1', '1', 2)
176
- assert_equal '2 1 1 1', @filters.replace_first('1 1 1 1', '1', 2)
177
- assert_template_result '2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}"
178
- end
179
-
180
- def test_remove
181
- assert_equal ' ', @filters.remove("a a a a", 'a')
182
- assert_equal 'a a a', @filters.remove_first("a a a a", 'a ')
183
- assert_template_result 'a a a', "{{ 'a a a a' | remove_first: 'a ' }}"
184
- end
185
-
186
- def test_pipes_in_string_arguments
187
- assert_template_result 'foobar', "{{ 'foo|bar' | remove: '|' }}"
188
- end
189
-
190
- def test_strip_newlines
191
- assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
192
- assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\r\nb\nc"
193
- end
194
-
195
- def test_newlines_to_br
196
- assert_template_result "a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc"
197
- end
198
-
199
- def test_plus
200
- assert_template_result "2", "{{ 1 | plus:1 }}"
201
- assert_template_result "2.0", "{{ '1' | plus:'1.0' }}"
202
- end
203
-
204
- def test_minus
205
- assert_template_result "4", "{{ input | minus:operand }}", 'input' => 5, 'operand' => 1
206
- assert_template_result "2.3", "{{ '4.3' | minus:'2' }}"
207
- end
208
-
209
- def test_times
210
- assert_template_result "12", "{{ 3 | times:4 }}"
211
- assert_template_result "0", "{{ 'foo' | times:4 }}"
212
-
213
- # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
214
- assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
215
-
216
- assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
217
-
218
- assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
219
- end
220
-
221
- def test_divided_by
222
- assert_template_result "4", "{{ 12 | divided_by:3 }}"
223
- assert_template_result "4", "{{ 14 | divided_by:3 }}"
224
-
225
- # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
226
- assert_match(/4\.(6{13,14})7/, Template.parse("{{ 14 | divided_by:'3.0' }}").render)
227
-
228
- assert_template_result "5", "{{ 15 | divided_by:3 }}"
229
- assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
230
-
231
- assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
232
- end
233
-
234
- def test_modulo
235
- assert_template_result "1", "{{ 3 | modulo:2 }}"
236
- end
237
-
238
- def test_append
239
- assigns = {'a' => 'bc', 'b' => 'd' }
240
- assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
241
- assert_template_result('bcd',"{{ a | append: b}}",assigns)
242
- end
243
-
244
- def test_prepend
245
- assigns = {'a' => 'bc', 'b' => 'a' }
246
- assert_template_result('abc',"{{ a | prepend: 'a'}}",assigns)
247
- assert_template_result('abc',"{{ a | prepend: b}}",assigns)
248
- end
249
-
250
- def test_cannot_access_private_methods
251
- assert_template_result('a',"{{ 'a' | to_number }}")
252
- end
253
-
254
- private
255
-
256
- def with_timezone(tz)
257
- old_tz = ENV['TZ']
258
- ENV['TZ'] = tz
259
- yield
260
- ensure
261
- ENV['TZ'] = old_tz
262
- end
263
- end # StandardFiltersTest
@@ -1,52 +0,0 @@
1
- require 'test_helper'
2
-
3
- class StrainerTest < Test::Unit::TestCase
4
- include Liquid
5
-
6
- module AccessScopeFilters
7
- def public_filter
8
- "public"
9
- end
10
-
11
- def private_filter
12
- "private"
13
- end
14
- private :private_filter
15
- end
16
-
17
- Strainer.global_filter(AccessScopeFilters)
18
-
19
- def test_strainer
20
- strainer = Strainer.create(nil)
21
- assert_equal 5, strainer.invoke('size', 'input')
22
- assert_equal "public", strainer.invoke("public_filter")
23
- end
24
-
25
- def test_strainer_only_invokes_public_filter_methods
26
- strainer = Strainer.create(nil)
27
- assert_equal false, strainer.invokable?('__test__')
28
- assert_equal false, strainer.invokable?('test')
29
- assert_equal false, strainer.invokable?('instance_eval')
30
- assert_equal false, strainer.invokable?('__send__')
31
- assert_equal true, strainer.invokable?('size') # from the standard lib
32
- end
33
-
34
- def test_strainer_returns_nil_if_no_filter_method_found
35
- strainer = Strainer.create(nil)
36
- assert_nil strainer.invoke("private_filter")
37
- assert_nil strainer.invoke("undef_the_filter")
38
- end
39
-
40
- def test_strainer_returns_first_argument_if_no_method_and_arguments_given
41
- strainer = Strainer.create(nil)
42
- assert_equal "password", strainer.invoke("undef_the_method", "password")
43
- end
44
-
45
- def test_strainer_only_allows_methods_defined_in_filters
46
- strainer = Strainer.create(nil)
47
- assert_equal "1 + 1", strainer.invoke("instance_eval", "1 + 1")
48
- assert_equal "puts", strainer.invoke("__send__", "puts", "Hi Mom")
49
- assert_equal "has_method?", strainer.invoke("invoke", "has_method?", "invoke")
50
- end
51
-
52
- end # StrainerTest
@@ -1,16 +0,0 @@
1
- require 'test_helper'
2
-
3
- class BreakTagTest < Test::Unit::TestCase
4
- include Liquid
5
-
6
- # tests that no weird errors are raised if break is called outside of a
7
- # block
8
- def test_break_with_no_block
9
- assigns = {'i' => 1}
10
- markup = '{% break %}'
11
- expected = ''
12
-
13
- assert_template_result(expected, markup, assigns)
14
- end
15
-
16
- end
@@ -1,16 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ContinueTagTest < Test::Unit::TestCase
4
- include Liquid
5
-
6
- # tests that no weird errors are raised if continue is called outside of a
7
- # block
8
- def test_continue_with_no_block
9
- assigns = {}
10
- markup = '{% continue %}'
11
- expected = ''
12
-
13
- assert_template_result(expected, markup, assigns)
14
- end
15
-
16
- end
@@ -1,297 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ForTagTest < Test::Unit::TestCase
4
- include Liquid
5
-
6
- def test_for
7
- assert_template_result(' yo yo yo yo ','{%for item in array%} yo {%endfor%}','array' => [1,2,3,4])
8
- assert_template_result('yoyo','{%for item in array%}yo{%endfor%}','array' => [1,2])
9
- assert_template_result(' yo ','{%for item in array%} yo {%endfor%}','array' => [1])
10
- assert_template_result('','{%for item in array%}{%endfor%}','array' => [1,2])
11
- expected = <<HERE
12
-
13
- yo
14
-
15
- yo
16
-
17
- yo
18
-
19
- HERE
20
- template = <<HERE
21
- {%for item in array%}
22
- yo
23
- {%endfor%}
24
- HERE
25
- assert_template_result(expected,template,'array' => [1,2,3])
26
- end
27
-
28
- def test_for_reversed
29
- assigns = {'array' => [ 1, 2, 3] }
30
- assert_template_result('321','{%for item in array reversed %}{{item}}{%endfor%}',assigns)
31
- end
32
-
33
- def test_for_with_range
34
- assert_template_result(' 1 2 3 ','{%for item in (1..3) %} {{item}} {%endfor%}')
35
- end
36
-
37
- def test_for_with_variable
38
- assert_template_result(' 1 2 3 ','{%for item in array%} {{item}} {%endfor%}','array' => [1,2,3])
39
- assert_template_result('123','{%for item in array%}{{item}}{%endfor%}','array' => [1,2,3])
40
- assert_template_result('123','{% for item in array %}{{item}}{% endfor %}','array' => [1,2,3])
41
- assert_template_result('abcd','{%for item in array%}{{item}}{%endfor%}','array' => ['a','b','c','d'])
42
- assert_template_result('a b c','{%for item in array%}{{item}}{%endfor%}','array' => ['a',' ','b',' ','c'])
43
- assert_template_result('abc','{%for item in array%}{{item}}{%endfor%}','array' => ['a','','b','','c'])
44
- end
45
-
46
- def test_for_helpers
47
- assigns = {'array' => [1,2,3] }
48
- assert_template_result(' 1/3 2/3 3/3 ',
49
- '{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
50
- assigns)
51
- assert_template_result(' 1 2 3 ', '{%for item in array%} {{forloop.index}} {%endfor%}', assigns)
52
- assert_template_result(' 0 1 2 ', '{%for item in array%} {{forloop.index0}} {%endfor%}', assigns)
53
- assert_template_result(' 2 1 0 ', '{%for item in array%} {{forloop.rindex0}} {%endfor%}', assigns)
54
- assert_template_result(' 3 2 1 ', '{%for item in array%} {{forloop.rindex}} {%endfor%}', assigns)
55
- assert_template_result(' true false false ', '{%for item in array%} {{forloop.first}} {%endfor%}', assigns)
56
- assert_template_result(' false false true ', '{%for item in array%} {{forloop.last}} {%endfor%}', assigns)
57
- end
58
-
59
- def test_for_and_if
60
- assigns = {'array' => [1,2,3] }
61
- assert_template_result('+--',
62
- '{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
63
- assigns)
64
- end
65
-
66
- def test_for_else
67
- assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[1,2,3])
68
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[])
69
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>nil)
70
- end
71
-
72
- def test_limiting
73
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
74
- assert_template_result('12', '{%for i in array limit:2 %}{{ i }}{%endfor%}', assigns)
75
- assert_template_result('1234', '{%for i in array limit:4 %}{{ i }}{%endfor%}', assigns)
76
- assert_template_result('3456', '{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}', assigns)
77
- assert_template_result('3456', '{%for i in array limit: 4 offset: 2 %}{{ i }}{%endfor%}', assigns)
78
- end
79
-
80
- def test_dynamic_variable_limiting
81
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
82
- assigns['limit'] = 2
83
- assigns['offset'] = 2
84
-
85
- assert_template_result('34', '{%for i in array limit: limit offset: offset %}{{ i }}{%endfor%}', assigns)
86
- end
87
-
88
- def test_nested_for
89
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
90
- assert_template_result('123456', '{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}', assigns)
91
- end
92
-
93
- def test_offset_only
94
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
95
- assert_template_result('890', '{%for i in array offset:7 %}{{ i }}{%endfor%}', assigns)
96
- end
97
-
98
- def test_pause_resume
99
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
100
- markup = <<-MKUP
101
- {%for i in array.items limit: 3 %}{{i}}{%endfor%}
102
- next
103
- {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
104
- next
105
- {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
106
- MKUP
107
- expected = <<-XPCTD
108
- 123
109
- next
110
- 456
111
- next
112
- 789
113
- XPCTD
114
- assert_template_result(expected,markup,assigns)
115
- end
116
-
117
- def test_pause_resume_limit
118
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
119
- markup = <<-MKUP
120
- {%for i in array.items limit:3 %}{{i}}{%endfor%}
121
- next
122
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
123
- next
124
- {%for i in array.items offset:continue limit:1 %}{{i}}{%endfor%}
125
- MKUP
126
- expected = <<-XPCTD
127
- 123
128
- next
129
- 456
130
- next
131
- 7
132
- XPCTD
133
- assert_template_result(expected,markup,assigns)
134
- end
135
-
136
- def test_pause_resume_BIG_limit
137
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
138
- markup = <<-MKUP
139
- {%for i in array.items limit:3 %}{{i}}{%endfor%}
140
- next
141
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
142
- next
143
- {%for i in array.items offset:continue limit:1000 %}{{i}}{%endfor%}
144
- MKUP
145
- expected = <<-XPCTD
146
- 123
147
- next
148
- 456
149
- next
150
- 7890
151
- XPCTD
152
- assert_template_result(expected,markup,assigns)
153
- end
154
-
155
-
156
- def test_pause_resume_BIG_offset
157
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
158
- markup = %q({%for i in array.items limit:3 %}{{i}}{%endfor%}
159
- next
160
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
161
- next
162
- {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%})
163
- expected = %q(123
164
- next
165
- 456
166
- next
167
- )
168
- assert_template_result(expected,markup,assigns)
169
- end
170
-
171
- def test_for_with_break
172
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,10]}}
173
-
174
- markup = '{% for i in array.items %}{% break %}{% endfor %}'
175
- expected = ""
176
- assert_template_result(expected,markup,assigns)
177
-
178
- markup = '{% for i in array.items %}{{ i }}{% break %}{% endfor %}'
179
- expected = "1"
180
- assert_template_result(expected,markup,assigns)
181
-
182
- markup = '{% for i in array.items %}{% break %}{{ i }}{% endfor %}'
183
- expected = ""
184
- assert_template_result(expected,markup,assigns)
185
-
186
- markup = '{% for i in array.items %}{{ i }}{% if i > 3 %}{% break %}{% endif %}{% endfor %}'
187
- expected = "1234"
188
- assert_template_result(expected,markup,assigns)
189
-
190
- # tests to ensure it only breaks out of the local for loop
191
- # and not all of them.
192
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
193
- markup = '{% for item in array %}' +
194
- '{% for i in item %}' +
195
- '{% if i == 1 %}' +
196
- '{% break %}' +
197
- '{% endif %}' +
198
- '{{ i }}' +
199
- '{% endfor %}' +
200
- '{% endfor %}'
201
- expected = '3456'
202
- assert_template_result(expected, markup, assigns)
203
-
204
- # test break does nothing when unreached
205
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
206
- markup = '{% for i in array.items %}{% if i == 9999 %}{% break %}{% endif %}{{ i }}{% endfor %}'
207
- expected = '12345'
208
- assert_template_result(expected, markup, assigns)
209
- end
210
-
211
- def test_for_with_continue
212
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
213
-
214
- markup = '{% for i in array.items %}{% continue %}{% endfor %}'
215
- expected = ""
216
- assert_template_result(expected,markup,assigns)
217
-
218
- markup = '{% for i in array.items %}{{ i }}{% continue %}{% endfor %}'
219
- expected = "12345"
220
- assert_template_result(expected,markup,assigns)
221
-
222
- markup = '{% for i in array.items %}{% continue %}{{ i }}{% endfor %}'
223
- expected = ""
224
- assert_template_result(expected,markup,assigns)
225
-
226
- markup = '{% for i in array.items %}{% if i > 3 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
227
- expected = "123"
228
- assert_template_result(expected,markup,assigns)
229
-
230
- markup = '{% for i in array.items %}{% if i == 3 %}{% continue %}{% else %}{{ i }}{% endif %}{% endfor %}'
231
- expected = "1245"
232
- assert_template_result(expected,markup,assigns)
233
-
234
- # tests to ensure it only continues the local for loop and not all of them.
235
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
236
- markup = '{% for item in array %}' +
237
- '{% for i in item %}' +
238
- '{% if i == 1 %}' +
239
- '{% continue %}' +
240
- '{% endif %}' +
241
- '{{ i }}' +
242
- '{% endfor %}' +
243
- '{% endfor %}'
244
- expected = '23456'
245
- assert_template_result(expected, markup, assigns)
246
-
247
- # test continue does nothing when unreached
248
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
249
- markup = '{% for i in array.items %}{% if i == 9999 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
250
- expected = '12345'
251
- assert_template_result(expected, markup, assigns)
252
- end
253
-
254
- def test_for_tag_string
255
- # ruby 1.8.7 "String".each => Enumerator with single "String" element.
256
- # ruby 1.9.3 no longer supports .each on String though we mimic
257
- # the functionality for backwards compatibility
258
-
259
- assert_template_result('test string',
260
- '{%for val in string%}{{val}}{%endfor%}',
261
- 'string' => "test string")
262
-
263
- assert_template_result('test string',
264
- '{%for val in string limit:1%}{{val}}{%endfor%}',
265
- 'string' => "test string")
266
-
267
- assert_template_result('val-string-1-1-0-1-0-true-true-test string',
268
- '{%for val in string%}' +
269
- '{{forloop.name}}-' +
270
- '{{forloop.index}}-' +
271
- '{{forloop.length}}-' +
272
- '{{forloop.index0}}-' +
273
- '{{forloop.rindex}}-' +
274
- '{{forloop.rindex0}}-' +
275
- '{{forloop.first}}-' +
276
- '{{forloop.last}}-' +
277
- '{{val}}{%endfor%}',
278
- 'string' => "test string")
279
- end
280
-
281
- def test_blank_string_not_iterable
282
- assert_template_result('', "{% for char in characters %}I WILL NOT BE OUTPUT{% endfor %}", 'characters' => '')
283
- end
284
-
285
- def test_bad_variable_naming_in_for_loop
286
- assert_raise(Liquid::SyntaxError) do
287
- Liquid::Template.parse('{% for a/b in x %}{% endfor %}')
288
- end
289
- end
290
-
291
- def test_spacing_with_variable_naming_in_for_loop
292
- expected = '12345'
293
- template = '{% for item in items %}{{item}}{% endfor %}'
294
- assigns = {'items' => [1,2,3,4,5]}
295
- assert_template_result(expected, template, assigns)
296
- end
297
- end