liquid 2.6.1 → 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 (130) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +194 -29
  3. data/{MIT-LICENSE → LICENSE} +0 -0
  4. data/README.md +60 -2
  5. data/lib/liquid.rb +25 -14
  6. data/lib/liquid/block.rb +47 -96
  7. data/lib/liquid/block_body.rb +143 -0
  8. data/lib/liquid/condition.rb +70 -39
  9. data/lib/liquid/context.rb +116 -157
  10. data/lib/liquid/document.rb +19 -9
  11. data/lib/liquid/drop.rb +31 -14
  12. data/lib/liquid/errors.rb +54 -10
  13. data/lib/liquid/expression.rb +49 -0
  14. data/lib/liquid/extensions.rb +19 -7
  15. data/lib/liquid/file_system.rb +25 -14
  16. data/lib/liquid/forloop_drop.rb +42 -0
  17. data/lib/liquid/i18n.rb +39 -0
  18. data/lib/liquid/interrupts.rb +2 -3
  19. data/lib/liquid/lexer.rb +55 -0
  20. data/lib/liquid/locales/en.yml +26 -0
  21. data/lib/liquid/parse_context.rb +38 -0
  22. data/lib/liquid/parse_tree_visitor.rb +42 -0
  23. data/lib/liquid/parser.rb +90 -0
  24. data/lib/liquid/parser_switching.rb +31 -0
  25. data/lib/liquid/profiler.rb +158 -0
  26. data/lib/liquid/profiler/hooks.rb +23 -0
  27. data/lib/liquid/range_lookup.rb +37 -0
  28. data/lib/liquid/resource_limits.rb +23 -0
  29. data/lib/liquid/standardfilters.rb +311 -77
  30. data/lib/liquid/strainer.rb +39 -26
  31. data/lib/liquid/tablerowloop_drop.rb +62 -0
  32. data/lib/liquid/tag.rb +28 -11
  33. data/lib/liquid/tags/assign.rb +34 -10
  34. data/lib/liquid/tags/break.rb +1 -4
  35. data/lib/liquid/tags/capture.rb +11 -9
  36. data/lib/liquid/tags/case.rb +37 -22
  37. data/lib/liquid/tags/comment.rb +10 -3
  38. data/lib/liquid/tags/continue.rb +1 -4
  39. data/lib/liquid/tags/cycle.rb +20 -14
  40. data/lib/liquid/tags/decrement.rb +4 -8
  41. data/lib/liquid/tags/for.rb +121 -60
  42. data/lib/liquid/tags/if.rb +73 -30
  43. data/lib/liquid/tags/ifchanged.rb +3 -5
  44. data/lib/liquid/tags/include.rb +77 -46
  45. data/lib/liquid/tags/increment.rb +4 -8
  46. data/lib/liquid/tags/raw.rb +35 -10
  47. data/lib/liquid/tags/table_row.rb +62 -0
  48. data/lib/liquid/tags/unless.rb +6 -9
  49. data/lib/liquid/template.rb +130 -32
  50. data/lib/liquid/tokenizer.rb +31 -0
  51. data/lib/liquid/truffle.rb +5 -0
  52. data/lib/liquid/utils.rb +57 -4
  53. data/lib/liquid/variable.rb +121 -30
  54. data/lib/liquid/variable_lookup.rb +88 -0
  55. data/lib/liquid/version.rb +2 -1
  56. data/test/fixtures/en_locale.yml +9 -0
  57. data/test/integration/assign_test.rb +48 -0
  58. data/test/integration/blank_test.rb +106 -0
  59. data/test/integration/block_test.rb +12 -0
  60. data/test/{liquid → integration}/capture_test.rb +13 -3
  61. data/test/integration/context_test.rb +32 -0
  62. data/test/integration/document_test.rb +19 -0
  63. data/test/integration/drop_test.rb +273 -0
  64. data/test/integration/error_handling_test.rb +260 -0
  65. data/test/integration/filter_test.rb +178 -0
  66. data/test/integration/hash_ordering_test.rb +23 -0
  67. data/test/integration/output_test.rb +123 -0
  68. data/test/integration/parse_tree_visitor_test.rb +247 -0
  69. data/test/integration/parsing_quirks_test.rb +122 -0
  70. data/test/integration/render_profiling_test.rb +154 -0
  71. data/test/integration/security_test.rb +80 -0
  72. data/test/integration/standard_filter_test.rb +776 -0
  73. data/test/{liquid → integration}/tags/break_tag_test.rb +2 -3
  74. data/test/{liquid → integration}/tags/continue_tag_test.rb +1 -2
  75. data/test/integration/tags/for_tag_test.rb +410 -0
  76. data/test/integration/tags/if_else_tag_test.rb +188 -0
  77. data/test/integration/tags/include_tag_test.rb +253 -0
  78. data/test/integration/tags/increment_tag_test.rb +23 -0
  79. data/test/{liquid → integration}/tags/raw_tag_test.rb +9 -2
  80. data/test/integration/tags/standard_tag_test.rb +296 -0
  81. data/test/integration/tags/statements_test.rb +111 -0
  82. data/test/{liquid/tags/html_tag_test.rb → integration/tags/table_row_test.rb} +25 -24
  83. data/test/integration/tags/unless_else_tag_test.rb +26 -0
  84. data/test/integration/template_test.rb +332 -0
  85. data/test/integration/trim_mode_test.rb +529 -0
  86. data/test/integration/variable_test.rb +96 -0
  87. data/test/test_helper.rb +106 -19
  88. data/test/truffle/truffle_test.rb +9 -0
  89. data/test/{liquid/block_test.rb → unit/block_unit_test.rb} +9 -9
  90. data/test/unit/condition_unit_test.rb +166 -0
  91. data/test/{liquid/context_test.rb → unit/context_unit_test.rb} +85 -74
  92. data/test/unit/file_system_unit_test.rb +35 -0
  93. data/test/unit/i18n_unit_test.rb +37 -0
  94. data/test/unit/lexer_unit_test.rb +51 -0
  95. data/test/unit/parser_unit_test.rb +82 -0
  96. data/test/{liquid/regexp_test.rb → unit/regexp_unit_test.rb} +4 -4
  97. data/test/unit/strainer_unit_test.rb +164 -0
  98. data/test/unit/tag_unit_test.rb +21 -0
  99. data/test/unit/tags/case_tag_unit_test.rb +10 -0
  100. data/test/unit/tags/for_tag_unit_test.rb +13 -0
  101. data/test/unit/tags/if_tag_unit_test.rb +8 -0
  102. data/test/unit/template_unit_test.rb +78 -0
  103. data/test/unit/tokenizer_unit_test.rb +55 -0
  104. data/test/unit/variable_unit_test.rb +162 -0
  105. metadata +157 -77
  106. data/lib/extras/liquid_view.rb +0 -51
  107. data/lib/liquid/htmltags.rb +0 -74
  108. data/lib/liquid/module_ex.rb +0 -62
  109. data/test/liquid/assign_test.rb +0 -21
  110. data/test/liquid/condition_test.rb +0 -127
  111. data/test/liquid/drop_test.rb +0 -180
  112. data/test/liquid/error_handling_test.rb +0 -81
  113. data/test/liquid/file_system_test.rb +0 -29
  114. data/test/liquid/filter_test.rb +0 -125
  115. data/test/liquid/hash_ordering_test.rb +0 -25
  116. data/test/liquid/module_ex_test.rb +0 -87
  117. data/test/liquid/output_test.rb +0 -116
  118. data/test/liquid/parsing_quirks_test.rb +0 -52
  119. data/test/liquid/security_test.rb +0 -64
  120. data/test/liquid/standard_filter_test.rb +0 -251
  121. data/test/liquid/strainer_test.rb +0 -52
  122. data/test/liquid/tags/for_tag_test.rb +0 -297
  123. data/test/liquid/tags/if_else_tag_test.rb +0 -166
  124. data/test/liquid/tags/include_tag_test.rb +0 -166
  125. data/test/liquid/tags/increment_tag_test.rb +0 -24
  126. data/test/liquid/tags/standard_tag_test.rb +0 -295
  127. data/test/liquid/tags/statements_test.rb +0 -134
  128. data/test/liquid/tags/unless_else_tag_test.rb +0 -26
  129. data/test/liquid/template_test.rb +0 -146
  130. data/test/liquid/variable_test.rb +0 -186
@@ -1,52 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ParsingQuirksTest < Test::Unit::TestCase
4
- include Liquid
5
-
6
- def test_error_with_css
7
- text = %| div { font-weight: bold; } |
8
- template = Template.parse(text)
9
-
10
- assert_equal text, template.render
11
- assert_equal [String], template.root.nodelist.collect {|i| i.class}
12
- end
13
-
14
- def test_raise_on_single_close_bracet
15
- assert_raise(SyntaxError) do
16
- Template.parse("text {{method} oh nos!")
17
- end
18
- end
19
-
20
- def test_raise_on_label_and_no_close_bracets
21
- assert_raise(SyntaxError) do
22
- Template.parse("TEST {{ ")
23
- end
24
- end
25
-
26
- def test_raise_on_label_and_no_close_bracets_percent
27
- assert_raise(SyntaxError) do
28
- Template.parse("TEST {% ")
29
- end
30
- end
31
-
32
- def test_error_on_empty_filter
33
- assert_nothing_raised do
34
- Template.parse("{{test |a|b|}}")
35
- Template.parse("{{test}}")
36
- Template.parse("{{|test|}}")
37
- end
38
- end
39
-
40
- def test_meaningless_parens
41
- assigns = {'b' => 'bar', 'c' => 'baz'}
42
- markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
43
- assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}", assigns)
44
- end
45
-
46
- def test_unexpected_characters_silently_eat_logic
47
- markup = "true && false"
48
- assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}")
49
- markup = "false || true"
50
- assert_template_result('',"{% if #{markup} %} YES {% endif %}")
51
- end
52
- end # ParsingQuirksTest
@@ -1,64 +0,0 @@
1
- require 'test_helper'
2
-
3
- module SecurityFilter
4
- def add_one(input)
5
- "#{input} + 1"
6
- end
7
- end
8
-
9
- class SecurityTest < Test::Unit::TestCase
10
- include Liquid
11
-
12
- def test_no_instance_eval
13
- text = %( {{ '1+1' | instance_eval }} )
14
- expected = %| 1+1 |
15
-
16
- assert_equal expected, Template.parse(text).render(@assigns)
17
- end
18
-
19
- def test_no_existing_instance_eval
20
- text = %( {{ '1+1' | __instance_eval__ }} )
21
- expected = %| 1+1 |
22
-
23
- assert_equal expected, Template.parse(text).render(@assigns)
24
- end
25
-
26
-
27
- def test_no_instance_eval_after_mixing_in_new_filter
28
- text = %( {{ '1+1' | instance_eval }} )
29
- expected = %| 1+1 |
30
-
31
- assert_equal expected, Template.parse(text).render(@assigns)
32
- end
33
-
34
-
35
- def test_no_instance_eval_later_in_chain
36
- text = %( {{ '1+1' | add_one | instance_eval }} )
37
- expected = %| 1+1 + 1 |
38
-
39
- assert_equal expected, Template.parse(text).render(@assigns, :filters => SecurityFilter)
40
- end
41
-
42
- def test_does_not_add_filters_to_symbol_table
43
- current_symbols = Symbol.all_symbols
44
-
45
- test = %( {{ "some_string" | a_bad_filter }} )
46
-
47
- template = Template.parse(test)
48
- assert_equal [], (Symbol.all_symbols - current_symbols)
49
-
50
- template.render
51
- assert_equal [], (Symbol.all_symbols - current_symbols)
52
- end
53
-
54
- def test_does_not_add_drop_methods_to_symbol_table
55
- current_symbols = Symbol.all_symbols
56
-
57
- drop = Drop.new
58
- drop.invoke_drop("custom_method_1")
59
- drop.invoke_drop("custom_method_2")
60
- drop.invoke_drop("custom_method_3")
61
-
62
- assert_equal [], (Symbol.all_symbols - current_symbols)
63
- end
64
- end # SecurityTest
@@ -1,251 +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
- assert_equal "07/05/2006", @filters.date(1152098955, "%m/%d/%Y")
161
- assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
162
- end
163
-
164
-
165
- def test_first_last
166
- assert_equal 1, @filters.first([1,2,3])
167
- assert_equal 3, @filters.last([1,2,3])
168
- assert_equal nil, @filters.first([])
169
- assert_equal nil, @filters.last([])
170
- end
171
-
172
- def test_replace
173
- assert_equal '2 2 2 2', @filters.replace('1 1 1 1', '1', 2)
174
- assert_equal '2 1 1 1', @filters.replace_first('1 1 1 1', '1', 2)
175
- assert_template_result '2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}"
176
- end
177
-
178
- def test_remove
179
- assert_equal ' ', @filters.remove("a a a a", 'a')
180
- assert_equal 'a a a', @filters.remove_first("a a a a", 'a ')
181
- assert_template_result 'a a a', "{{ 'a a a a' | remove_first: 'a ' }}"
182
- end
183
-
184
- def test_pipes_in_string_arguments
185
- assert_template_result 'foobar', "{{ 'foo|bar' | remove: '|' }}"
186
- end
187
-
188
- def test_strip_newlines
189
- assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
190
- assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\r\nb\nc"
191
- end
192
-
193
- def test_newlines_to_br
194
- assert_template_result "a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc"
195
- end
196
-
197
- def test_plus
198
- assert_template_result "2", "{{ 1 | plus:1 }}"
199
- assert_template_result "2.0", "{{ '1' | plus:'1.0' }}"
200
- end
201
-
202
- def test_minus
203
- assert_template_result "4", "{{ input | minus:operand }}", 'input' => 5, 'operand' => 1
204
- assert_template_result "2.3", "{{ '4.3' | minus:'2' }}"
205
- end
206
-
207
- def test_times
208
- assert_template_result "12", "{{ 3 | times:4 }}"
209
- assert_template_result "0", "{{ 'foo' | times:4 }}"
210
-
211
- # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
212
- assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
213
-
214
- assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
215
-
216
- assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
217
- end
218
-
219
- def test_divided_by
220
- assert_template_result "4", "{{ 12 | divided_by:3 }}"
221
- assert_template_result "4", "{{ 14 | divided_by:3 }}"
222
-
223
- # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
224
- assert_match(/4\.(6{13,14})7/, Template.parse("{{ 14 | divided_by:'3.0' }}").render)
225
-
226
- assert_template_result "5", "{{ 15 | divided_by:3 }}"
227
- assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
228
-
229
- assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
230
- end
231
-
232
- def test_modulo
233
- assert_template_result "1", "{{ 3 | modulo:2 }}"
234
- end
235
-
236
- def test_append
237
- assigns = {'a' => 'bc', 'b' => 'd' }
238
- assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
239
- assert_template_result('bcd',"{{ a | append: b}}",assigns)
240
- end
241
-
242
- def test_prepend
243
- assigns = {'a' => 'bc', 'b' => 'a' }
244
- assert_template_result('abc',"{{ a | prepend: 'a'}}",assigns)
245
- assert_template_result('abc',"{{ a | prepend: b}}",assigns)
246
- end
247
-
248
- def test_cannot_access_private_methods
249
- assert_template_result('a',"{{ 'a' | to_number }}")
250
- end
251
- 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,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