liquid 4.0.0.rc2 → 4.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a15813568dcc19866675ad50444b7939b5eecfa
4
- data.tar.gz: acfb1e49596e266170a25c584978ec8ade8bcf01
3
+ metadata.gz: 3d29364ce9b0e428bfcf9e63df9695f791d8e13e
4
+ data.tar.gz: 08cc19791695840bd1d6230ea9643cfa3ee9147c
5
5
  SHA512:
6
- metadata.gz: 20fa5f4ceec720a9c57219f71bb848c7b407529cf46bf7353fba196452bf9945e33d79e25aff8fb92aceb32ac0f6d2299e6204e7fc5d6eec04134224dae725ef
7
- data.tar.gz: 4ed81d181edfaf21bd25b303ec4e5085c9e734e3fb9679aa3b7a88f664bced5ab60825bb163ffaf7498b650cedf779901ce78917abad1fcbc5be1ec7b27573ee
6
+ metadata.gz: 12c6c427dca1570ce4eee3634d3d6fbfd2f35d231e32678f3d43f19583233a3af8fa2049e04edaf69b41d8df553b75da72a5f5431bfbe2a6d0f1f906b5a97add
7
+ data.tar.gz: 318e400a0ea7e6fedd5d066eda0995b438846d925167a2159885f9806747af683859d4fb5d2ca1853efc9c2bbebc9d3528a2a9013d04bc3c28eb223e56fee1d0
@@ -24,6 +24,7 @@ module Liquid
24
24
  ArgumentSeparator = ','.freeze
25
25
  FilterArgumentSeparator = ':'.freeze
26
26
  VariableAttributeSeparator = '.'.freeze
27
+ WhitespaceControl = '-'.freeze
27
28
  TagStart = /\{\%/
28
29
  TagEnd = /\%\}/
29
30
  VariableSignature = /\(?[\w\-\.\[\]]\)?/
@@ -34,7 +35,7 @@ module Liquid
34
35
  QuotedString = /"[^"]*"|'[^']*'/
35
36
  QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
36
37
  TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
37
- AnyStartingTag = /\{\{|\{\%/
38
+ AnyStartingTag = /#{TagStart}|#{VariableStart}/o
38
39
  PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om
39
40
  TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om
40
41
  VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
@@ -1,7 +1,7 @@
1
1
  module Liquid
2
2
  class BlockBody
3
- FullToken = /\A#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}\z/om
4
- ContentOfVariable = /\A#{VariableStart}(.*)#{VariableEnd}\z/om
3
+ FullToken = /\A#{TagStart}#{WhitespaceControl}?\s*(\w+)\s*(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
4
+ ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
5
5
  TAGSTART = "{%".freeze
6
6
  VARSTART = "{{".freeze
7
7
 
@@ -18,6 +18,7 @@ module Liquid
18
18
  unless token.empty?
19
19
  case
20
20
  when token.start_with?(TAGSTART)
21
+ whitespace_handler(token, parse_context)
21
22
  if token =~ FullToken
22
23
  tag_name = $1
23
24
  markup = $2
@@ -35,9 +36,14 @@ module Liquid
35
36
  raise_missing_tag_terminator(token, parse_context)
36
37
  end
37
38
  when token.start_with?(VARSTART)
39
+ whitespace_handler(token, parse_context)
38
40
  @nodelist << create_variable(token, parse_context)
39
41
  @blank = false
40
42
  else
43
+ if parse_context.trim_whitespace
44
+ token.lstrip!
45
+ end
46
+ parse_context.trim_whitespace = false
41
47
  @nodelist << token
42
48
  @blank &&= !!(token =~ /\A\s*\z/)
43
49
  end
@@ -48,6 +54,16 @@ module Liquid
48
54
  yield nil, nil
49
55
  end
50
56
 
57
+ def whitespace_handler(token, parse_context)
58
+ if token[2] == WhitespaceControl
59
+ previous_token = @nodelist.last
60
+ if previous_token.is_a? String
61
+ previous_token.rstrip!
62
+ end
63
+ end
64
+ parse_context.trim_whitespace = (token[-3] == WhitespaceControl)
65
+ end
66
+
51
67
  def blank?
52
68
  @blank
53
69
  end
@@ -25,6 +25,12 @@ class Numeric # :nodoc:
25
25
  end
26
26
  end
27
27
 
28
+ class Range # :nodoc:
29
+ def to_liquid
30
+ self
31
+ end
32
+ end
33
+
28
34
  class Time # :nodoc:
29
35
  def to_liquid
30
36
  self
@@ -8,8 +8,8 @@ module Liquid
8
8
  #
9
9
  # Example:
10
10
  #
11
- # Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_path)
12
- # liquid = Liquid::Template.parse(template)
11
+ # Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_path)
12
+ # liquid = Liquid::Template.parse(template)
13
13
  #
14
14
  # This will parse the template with a LocalFileSystem implementation rooted at 'template_path'.
15
15
  class BlankFileSystem
@@ -26,10 +26,10 @@ module Liquid
26
26
  #
27
27
  # Example:
28
28
  #
29
- # file_system = Liquid::LocalFileSystem.new("/some/path")
29
+ # file_system = Liquid::LocalFileSystem.new("/some/path")
30
30
  #
31
- # file_system.full_path("mypartial") # => "/some/path/_mypartial.liquid"
32
- # file_system.full_path("dir/mypartial") # => "/some/path/dir/_mypartial.liquid"
31
+ # file_system.full_path("mypartial") # => "/some/path/_mypartial.liquid"
32
+ # file_system.full_path("dir/mypartial") # => "/some/path/dir/_mypartial.liquid"
33
33
  #
34
34
  # Optionally in the second argument you can specify a custom pattern for template filenames.
35
35
  # The Kernel::sprintf format specification is used.
@@ -37,9 +37,9 @@ module Liquid
37
37
  #
38
38
  # Example:
39
39
  #
40
- # file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html")
40
+ # file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html")
41
41
  #
42
- # file_system.full_path("index") # => "/some/path/index.html"
42
+ # file_system.full_path("index") # => "/some/path/index.html"
43
43
  #
44
44
  class LocalFileSystem
45
45
  attr_accessor :root
@@ -22,3 +22,5 @@
22
22
  tag_never_closed: "'%{block_name}' tag was never closed"
23
23
  meta_syntax_error: "Liquid syntax error: #{e.message}"
24
24
  table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
25
+ argument:
26
+ include: "Argument error in tag 'include' - Illegal template name"
@@ -1,6 +1,6 @@
1
1
  module Liquid
2
2
  class ParseContext
3
- attr_accessor :locale, :line_number
3
+ attr_accessor :locale, :line_number, :trim_whitespace
4
4
  attr_reader :partial, :warnings, :error_mode
5
5
 
6
6
  def initialize(options = {})
@@ -289,6 +289,12 @@ module Liquid
289
289
  array.last if array.respond_to?(:last)
290
290
  end
291
291
 
292
+ # absolute value
293
+ def abs(input)
294
+ result = Utils.to_number(input).abs
295
+ result.is_a?(BigDecimal) ? result.to_f : result
296
+ end
297
+
292
298
  # addition
293
299
  def plus(input, operand)
294
300
  apply_operation(input, operand, :+)
@@ -42,8 +42,9 @@ module Liquid
42
42
 
43
43
  def render(context)
44
44
  template_name = context.evaluate(@template_name_expr)
45
- partial = load_cached_partial(template_name, context)
45
+ raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
46
46
 
47
+ partial = load_cached_partial(template_name, context)
47
48
  context_variable_name = template_name.split('/'.freeze).last
48
49
 
49
50
  variable = if @variable_name_expr
@@ -6,9 +6,7 @@ module Liquid
6
6
  def initialize(tag_name, markup, parse_context)
7
7
  super
8
8
 
9
- unless markup =~ Syntax
10
- raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_unexpected_args".freeze, tag: tag_name))
11
- end
9
+ ensure_valid_markup(tag_name, markup, parse_context)
12
10
  end
13
11
 
14
12
  def parse(tokens)
@@ -35,6 +33,14 @@ module Liquid
35
33
  def blank?
36
34
  @body.empty?
37
35
  end
36
+
37
+ protected
38
+
39
+ def ensure_valid_markup(tag_name, markup, parse_context)
40
+ unless markup =~ Syntax
41
+ raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_unexpected_args".freeze, tag: tag_name))
42
+ end
43
+ end
38
44
  end
39
45
 
40
46
  Template.register_tag('raw'.freeze, Raw)
@@ -19,6 +19,8 @@ module Liquid
19
19
  @@file_system = BlankFileSystem.new
20
20
 
21
21
  class TagRegistry
22
+ include Enumerable
23
+
22
24
  def initialize
23
25
  @tags = {}
24
26
  @cache = {}
@@ -41,6 +43,10 @@ module Liquid
41
43
  @cache.delete(tag_name)
42
44
  end
43
45
 
46
+ def each(&block)
47
+ @tags.each(&block)
48
+ end
49
+
44
50
  private
45
51
 
46
52
  def lookup_class(name)
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Liquid
3
- VERSION = "4.0.0.rc2"
3
+ VERSION = "4.0.0.rc3"
4
4
  end
@@ -97,6 +97,22 @@ class ErrorHandlingTest < Minitest::Test
97
97
  assert_match(/Liquid syntax error \(line 4\)/, err.message)
98
98
  end
99
99
 
100
+ def test_with_line_numbers_adds_numbers_to_parser_errors_with_whitespace_trim
101
+ err = assert_raises(SyntaxError) do
102
+ Liquid::Template.parse(%q(
103
+ foobar
104
+
105
+ {%- "cat" | foobar -%}
106
+
107
+ bla
108
+ ),
109
+ line_numbers: true
110
+ )
111
+ end
112
+
113
+ assert_match(/Liquid syntax error \(line 4\)/, err.message)
114
+ end
115
+
100
116
  def test_parsing_warn_with_line_numbers_adds_numbers_to_lexer_errors
101
117
  template = Liquid::Template.parse('
102
118
  foobar
@@ -385,6 +385,19 @@ class StandardFiltersTest < Minitest::Test
385
385
  assert_template_result "5", "{{ price | minus:'2' }}", 'price' => NumberLikeThing.new(7)
386
386
  end
387
387
 
388
+ def test_abs
389
+ assert_template_result "17", "{{ 17 | abs }}"
390
+ assert_template_result "17", "{{ -17 | abs }}"
391
+ assert_template_result "17", "{{ '17' | abs }}"
392
+ assert_template_result "17", "{{ '-17' | abs }}"
393
+ assert_template_result "0", "{{ 0 | abs }}"
394
+ assert_template_result "0", "{{ '0' | abs }}"
395
+ assert_template_result "17.42", "{{ 17.42 | abs }}"
396
+ assert_template_result "17.42", "{{ -17.42 | abs }}"
397
+ assert_template_result "17.42", "{{ '17.42' | abs }}"
398
+ assert_template_result "17.42", "{{ '-17.42' | abs }}"
399
+ end
400
+
388
401
  def test_times
389
402
  assert_template_result "12", "{{ 3 | times:4 }}"
390
403
  assert_template_result "0", "{{ 'foo' | times:4 }}"
@@ -217,6 +217,17 @@ class IncludeTagTest < Minitest::Test
217
217
  end
218
218
  end
219
219
 
220
+ def test_render_raise_argument_error_when_template_is_undefined
221
+ assert_raises(Liquid::ArgumentError) do
222
+ template = Liquid::Template.parse('{% include undefined_variable %}')
223
+ template.render!
224
+ end
225
+ assert_raises(Liquid::ArgumentError) do
226
+ template = Liquid::Template.parse('{% include nil %}')
227
+ template.render!
228
+ end
229
+ end
230
+
220
231
  def test_including_via_variable_value
221
232
  assert_template_result "from TestFileSystem", "{% assign page = 'pick_a_source' %}{% include page %}"
222
233
 
@@ -306,4 +306,14 @@ class TemplateTest < Minitest::Test
306
306
  t.render!({ 'x' => 'foo' }, { strict_filters: true })
307
307
  end
308
308
  end
309
+
310
+ def test_using_range_literal_works_as_expected
311
+ t = Template.parse("{% assign foo = (x..y) %}{{ foo }}")
312
+ result = t.render({ 'x' => 1, 'y' => 5 })
313
+ assert_equal '1..5', result
314
+
315
+ t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}")
316
+ result = t.render({ 'x' => 1, 'y' => 5 })
317
+ assert_equal '12345', result
318
+ end
309
319
  end
@@ -0,0 +1,525 @@
1
+ require 'test_helper'
2
+
3
+ class TrimModeTest < Minitest::Test
4
+ include Liquid
5
+
6
+ # Make sure the trim isn't applied to standard output
7
+ def test_standard_output
8
+ text = <<-END_TEMPLATE
9
+ <div>
10
+ <p>
11
+ {{ 'John' }}
12
+ </p>
13
+ </div>
14
+ END_TEMPLATE
15
+ expected = <<-END_EXPECTED
16
+ <div>
17
+ <p>
18
+ John
19
+ </p>
20
+ </div>
21
+ END_EXPECTED
22
+ assert_template_result(expected, text)
23
+ end
24
+
25
+ def test_variable_output_with_multiple_blank_lines
26
+ text = <<-END_TEMPLATE
27
+ <div>
28
+ <p>
29
+
30
+
31
+ {{- 'John' -}}
32
+
33
+
34
+ </p>
35
+ </div>
36
+ END_TEMPLATE
37
+ expected = <<-END_EXPECTED
38
+ <div>
39
+ <p>John</p>
40
+ </div>
41
+ END_EXPECTED
42
+ assert_template_result(expected, text)
43
+ end
44
+
45
+ def test_tag_output_with_multiple_blank_lines
46
+ text = <<-END_TEMPLATE
47
+ <div>
48
+ <p>
49
+
50
+
51
+ {%- if true -%}
52
+ yes
53
+ {%- endif -%}
54
+
55
+
56
+ </p>
57
+ </div>
58
+ END_TEMPLATE
59
+ expected = <<-END_EXPECTED
60
+ <div>
61
+ <p>yes</p>
62
+ </div>
63
+ END_EXPECTED
64
+ assert_template_result(expected, text)
65
+ end
66
+
67
+ # Make sure the trim isn't applied to standard tags
68
+ def test_standard_tags
69
+ whitespace = ' '
70
+ text = <<-END_TEMPLATE
71
+ <div>
72
+ <p>
73
+ {% if true %}
74
+ yes
75
+ {% endif %}
76
+ </p>
77
+ </div>
78
+ END_TEMPLATE
79
+ expected = <<-END_EXPECTED
80
+ <div>
81
+ <p>
82
+ #{whitespace}
83
+ yes
84
+ #{whitespace}
85
+ </p>
86
+ </div>
87
+ END_EXPECTED
88
+ assert_template_result(expected, text)
89
+
90
+ text = <<-END_TEMPLATE
91
+ <div>
92
+ <p>
93
+ {% if false %}
94
+ no
95
+ {% endif %}
96
+ </p>
97
+ </div>
98
+ END_TEMPLATE
99
+ expected = <<-END_EXPECTED
100
+ <div>
101
+ <p>
102
+ #{whitespace}
103
+ </p>
104
+ </div>
105
+ END_EXPECTED
106
+ assert_template_result(expected, text)
107
+ end
108
+
109
+ # Make sure the trim isn't too agressive
110
+ def test_no_trim_output
111
+ text = '<p>{{- \'John\' -}}</p>'
112
+ expected = '<p>John</p>'
113
+ assert_template_result(expected, text)
114
+ end
115
+
116
+ # Make sure the trim isn't too agressive
117
+ def test_no_trim_tags
118
+ text = '<p>{%- if true -%}yes{%- endif -%}</p>'
119
+ expected = '<p>yes</p>'
120
+ assert_template_result(expected, text)
121
+
122
+ text = '<p>{%- if false -%}no{%- endif -%}</p>'
123
+ expected = '<p></p>'
124
+ assert_template_result(expected, text)
125
+ end
126
+
127
+ def test_single_line_outer_tag
128
+ text = '<p> {%- if true %} yes {% endif -%} </p>'
129
+ expected = '<p> yes </p>'
130
+ assert_template_result(expected, text)
131
+
132
+ text = '<p> {%- if false %} no {% endif -%} </p>'
133
+ expected = '<p></p>'
134
+ assert_template_result(expected, text)
135
+ end
136
+
137
+ def test_single_line_inner_tag
138
+ text = '<p> {% if true -%} yes {%- endif %} </p>'
139
+ expected = '<p> yes </p>'
140
+ assert_template_result(expected, text)
141
+
142
+ text = '<p> {% if false -%} no {%- endif %} </p>'
143
+ expected = '<p> </p>'
144
+ assert_template_result(expected, text)
145
+ end
146
+
147
+ def test_single_line_post_tag
148
+ text = '<p> {% if true -%} yes {% endif -%} </p>'
149
+ expected = '<p> yes </p>'
150
+ assert_template_result(expected, text)
151
+
152
+ text = '<p> {% if false -%} no {% endif -%} </p>'
153
+ expected = '<p> </p>'
154
+ assert_template_result(expected, text)
155
+ end
156
+
157
+ def test_single_line_pre_tag
158
+ text = '<p> {%- if true %} yes {%- endif %} </p>'
159
+ expected = '<p> yes </p>'
160
+ assert_template_result(expected, text)
161
+
162
+ text = '<p> {%- if false %} no {%- endif %} </p>'
163
+ expected = '<p> </p>'
164
+ assert_template_result(expected, text)
165
+ end
166
+
167
+ def test_pre_trim_output
168
+ text = <<-END_TEMPLATE
169
+ <div>
170
+ <p>
171
+ {{- 'John' }}
172
+ </p>
173
+ </div>
174
+ END_TEMPLATE
175
+ expected = <<-END_EXPECTED
176
+ <div>
177
+ <p>John
178
+ </p>
179
+ </div>
180
+ END_EXPECTED
181
+ assert_template_result(expected, text)
182
+ end
183
+
184
+ def test_pre_trim_tags
185
+ text = <<-END_TEMPLATE
186
+ <div>
187
+ <p>
188
+ {%- if true %}
189
+ yes
190
+ {%- endif %}
191
+ </p>
192
+ </div>
193
+ END_TEMPLATE
194
+ expected = <<-END_EXPECTED
195
+ <div>
196
+ <p>
197
+ yes
198
+ </p>
199
+ </div>
200
+ END_EXPECTED
201
+ assert_template_result(expected, text)
202
+
203
+ text = <<-END_TEMPLATE
204
+ <div>
205
+ <p>
206
+ {%- if false %}
207
+ no
208
+ {%- endif %}
209
+ </p>
210
+ </div>
211
+ END_TEMPLATE
212
+ expected = <<-END_EXPECTED
213
+ <div>
214
+ <p>
215
+ </p>
216
+ </div>
217
+ END_EXPECTED
218
+ assert_template_result(expected, text)
219
+ end
220
+
221
+ def test_post_trim_output
222
+ text = <<-END_TEMPLATE
223
+ <div>
224
+ <p>
225
+ {{ 'John' -}}
226
+ </p>
227
+ </div>
228
+ END_TEMPLATE
229
+ expected = <<-END_EXPECTED
230
+ <div>
231
+ <p>
232
+ John</p>
233
+ </div>
234
+ END_EXPECTED
235
+ assert_template_result(expected, text)
236
+ end
237
+
238
+ def test_post_trim_tags
239
+ text = <<-END_TEMPLATE
240
+ <div>
241
+ <p>
242
+ {% if true -%}
243
+ yes
244
+ {% endif -%}
245
+ </p>
246
+ </div>
247
+ END_TEMPLATE
248
+ expected = <<-END_EXPECTED
249
+ <div>
250
+ <p>
251
+ yes
252
+ </p>
253
+ </div>
254
+ END_EXPECTED
255
+ assert_template_result(expected, text)
256
+
257
+ text = <<-END_TEMPLATE
258
+ <div>
259
+ <p>
260
+ {% if false -%}
261
+ no
262
+ {% endif -%}
263
+ </p>
264
+ </div>
265
+ END_TEMPLATE
266
+ expected = <<-END_EXPECTED
267
+ <div>
268
+ <p>
269
+ </p>
270
+ </div>
271
+ END_EXPECTED
272
+ assert_template_result(expected, text)
273
+ end
274
+
275
+ def test_pre_and_post_trim_tags
276
+ text = <<-END_TEMPLATE
277
+ <div>
278
+ <p>
279
+ {%- if true %}
280
+ yes
281
+ {% endif -%}
282
+ </p>
283
+ </div>
284
+ END_TEMPLATE
285
+ expected = <<-END_EXPECTED
286
+ <div>
287
+ <p>
288
+ yes
289
+ </p>
290
+ </div>
291
+ END_EXPECTED
292
+ assert_template_result(expected, text)
293
+
294
+ text = <<-END_TEMPLATE
295
+ <div>
296
+ <p>
297
+ {%- if false %}
298
+ no
299
+ {% endif -%}
300
+ </p>
301
+ </div>
302
+ END_TEMPLATE
303
+ expected = <<-END_EXPECTED
304
+ <div>
305
+ <p></p>
306
+ </div>
307
+ END_EXPECTED
308
+ assert_template_result(expected, text)
309
+ end
310
+
311
+ def test_post_and_pre_trim_tags
312
+ text = <<-END_TEMPLATE
313
+ <div>
314
+ <p>
315
+ {% if true -%}
316
+ yes
317
+ {%- endif %}
318
+ </p>
319
+ </div>
320
+ END_TEMPLATE
321
+ expected = <<-END_EXPECTED
322
+ <div>
323
+ <p>
324
+ yes
325
+ </p>
326
+ </div>
327
+ END_EXPECTED
328
+ assert_template_result(expected, text)
329
+
330
+ whitespace = ' '
331
+ text = <<-END_TEMPLATE
332
+ <div>
333
+ <p>
334
+ {% if false -%}
335
+ no
336
+ {%- endif %}
337
+ </p>
338
+ </div>
339
+ END_TEMPLATE
340
+ expected = <<-END_EXPECTED
341
+ <div>
342
+ <p>
343
+ #{whitespace}
344
+ </p>
345
+ </div>
346
+ END_EXPECTED
347
+ assert_template_result(expected, text)
348
+ end
349
+
350
+ def test_trim_output
351
+ text = <<-END_TEMPLATE
352
+ <div>
353
+ <p>
354
+ {{- 'John' -}}
355
+ </p>
356
+ </div>
357
+ END_TEMPLATE
358
+ expected = <<-END_EXPECTED
359
+ <div>
360
+ <p>John</p>
361
+ </div>
362
+ END_EXPECTED
363
+ assert_template_result(expected, text)
364
+ end
365
+
366
+ def test_trim_tags
367
+ text = <<-END_TEMPLATE
368
+ <div>
369
+ <p>
370
+ {%- if true -%}
371
+ yes
372
+ {%- endif -%}
373
+ </p>
374
+ </div>
375
+ END_TEMPLATE
376
+ expected = <<-END_EXPECTED
377
+ <div>
378
+ <p>yes</p>
379
+ </div>
380
+ END_EXPECTED
381
+ assert_template_result(expected, text)
382
+
383
+ text = <<-END_TEMPLATE
384
+ <div>
385
+ <p>
386
+ {%- if false -%}
387
+ no
388
+ {%- endif -%}
389
+ </p>
390
+ </div>
391
+ END_TEMPLATE
392
+ expected = <<-END_EXPECTED
393
+ <div>
394
+ <p></p>
395
+ </div>
396
+ END_EXPECTED
397
+ assert_template_result(expected, text)
398
+ end
399
+
400
+ def test_whitespace_trim_output
401
+ text = <<-END_TEMPLATE
402
+ <div>
403
+ <p>
404
+ {{- 'John' -}},
405
+ {{- '30' -}}
406
+ </p>
407
+ </div>
408
+ END_TEMPLATE
409
+ expected = <<-END_EXPECTED
410
+ <div>
411
+ <p>John,30</p>
412
+ </div>
413
+ END_EXPECTED
414
+ assert_template_result(expected, text)
415
+ end
416
+
417
+ def test_whitespace_trim_tags
418
+ text = <<-END_TEMPLATE
419
+ <div>
420
+ <p>
421
+ {%- if true -%}
422
+ yes
423
+ {%- endif -%}
424
+ </p>
425
+ </div>
426
+ END_TEMPLATE
427
+ expected = <<-END_EXPECTED
428
+ <div>
429
+ <p>yes</p>
430
+ </div>
431
+ END_EXPECTED
432
+ assert_template_result(expected, text)
433
+
434
+ text = <<-END_TEMPLATE
435
+ <div>
436
+ <p>
437
+ {%- if false -%}
438
+ no
439
+ {%- endif -%}
440
+ </p>
441
+ </div>
442
+ END_TEMPLATE
443
+ expected = <<-END_EXPECTED
444
+ <div>
445
+ <p></p>
446
+ </div>
447
+ END_EXPECTED
448
+ assert_template_result(expected, text)
449
+ end
450
+
451
+ def test_complex_trim_output
452
+ text = <<-END_TEMPLATE
453
+ <div>
454
+ <p>
455
+ {{- 'John' -}}
456
+ {{- '30' -}}
457
+ </p>
458
+ <b>
459
+ {{ 'John' -}}
460
+ {{- '30' }}
461
+ </b>
462
+ <i>
463
+ {{- 'John' }}
464
+ {{ '30' -}}
465
+ </i>
466
+ </div>
467
+ END_TEMPLATE
468
+ expected = <<-END_EXPECTED
469
+ <div>
470
+ <p>John30</p>
471
+ <b>
472
+ John30
473
+ </b>
474
+ <i>John
475
+ 30</i>
476
+ </div>
477
+ END_EXPECTED
478
+ assert_template_result(expected, text)
479
+ end
480
+
481
+ def test_complex_trim
482
+ text = <<-END_TEMPLATE
483
+ <div>
484
+ {%- if true -%}
485
+ {%- if true -%}
486
+ <p>
487
+ {{- 'John' -}}
488
+ </p>
489
+ {%- endif -%}
490
+ {%- endif -%}
491
+ </div>
492
+ END_TEMPLATE
493
+ expected = <<-END_EXPECTED
494
+ <div><p>John</p></div>
495
+ END_EXPECTED
496
+ assert_template_result(expected, text)
497
+ end
498
+
499
+ def test_raw_output
500
+ whitespace = ' '
501
+ text = <<-END_TEMPLATE
502
+ <div>
503
+ {% raw %}
504
+ {%- if true -%}
505
+ <p>
506
+ {{- 'John' -}}
507
+ </p>
508
+ {%- endif -%}
509
+ {% endraw %}
510
+ </div>
511
+ END_TEMPLATE
512
+ expected = <<-END_EXPECTED
513
+ <div>
514
+ #{whitespace}
515
+ {%- if true -%}
516
+ <p>
517
+ {{- 'John' -}}
518
+ </p>
519
+ {%- endif -%}
520
+ #{whitespace}
521
+ </div>
522
+ END_EXPECTED
523
+ assert_template_result(expected, text)
524
+ end
525
+ end # TrimModeTest
@@ -46,6 +46,8 @@ class BlockUnitTest < Minitest::Test
46
46
  def test_with_custom_tag
47
47
  Liquid::Template.register_tag("testtag", Block)
48
48
  assert Liquid::Template.parse("{% testtag %} {% endtesttag %}")
49
+ ensure
50
+ Liquid::Template.tags.delete('testtag')
49
51
  end
50
52
 
51
53
  private
@@ -67,4 +67,12 @@ class TemplateUnitTest < Minitest::Test
67
67
  Template.tags.delete('fake')
68
68
  assert_nil Template.tags['fake']
69
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
70
78
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liquid
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.rc2
4
+ version: 4.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Lütke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-31 00:00:00.000000000 Z
11
+ date: 2016-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -126,6 +126,7 @@ files:
126
126
  - test/integration/tags/table_row_test.rb
127
127
  - test/integration/tags/unless_else_tag_test.rb
128
128
  - test/integration/template_test.rb
129
+ - test/integration/trim_mode_test.rb
129
130
  - test/integration/variable_test.rb
130
131
  - test/test_helper.rb
131
132
  - test/unit/block_unit_test.rb
@@ -164,53 +165,54 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
165
  version: 1.3.7
165
166
  requirements: []
166
167
  rubyforge_project:
167
- rubygems_version: 2.2.3
168
+ rubygems_version: 2.4.5
168
169
  signing_key:
169
170
  specification_version: 4
170
171
  summary: A secure, non-evaling end user template engine with aesthetic markup.
171
172
  test_files:
172
173
  - test/fixtures/en_locale.yml
173
- - test/test_helper.rb
174
- - test/unit/tokenizer_unit_test.rb
175
- - test/unit/regexp_unit_test.rb
176
- - test/unit/lexer_unit_test.rb
177
- - test/unit/strainer_unit_test.rb
178
- - test/unit/i18n_unit_test.rb
179
- - test/unit/condition_unit_test.rb
180
- - test/unit/variable_unit_test.rb
181
- - test/unit/context_unit_test.rb
182
- - test/unit/block_unit_test.rb
183
- - test/unit/template_unit_test.rb
184
- - test/unit/file_system_unit_test.rb
185
- - test/unit/parser_unit_test.rb
186
- - test/unit/tag_unit_test.rb
187
- - test/unit/tags/case_tag_unit_test.rb
188
- - test/unit/tags/if_tag_unit_test.rb
189
- - test/unit/tags/for_tag_unit_test.rb
174
+ - test/integration/assign_test.rb
175
+ - test/integration/blank_test.rb
176
+ - test/integration/capture_test.rb
177
+ - test/integration/context_test.rb
178
+ - test/integration/document_test.rb
190
179
  - test/integration/drop_test.rb
180
+ - test/integration/error_handling_test.rb
181
+ - test/integration/filter_test.rb
191
182
  - test/integration/hash_ordering_test.rb
192
- - test/integration/variable_test.rb
193
- - test/integration/assign_test.rb
194
183
  - test/integration/output_test.rb
195
- - test/integration/error_handling_test.rb
196
- - test/integration/security_test.rb
197
- - test/integration/template_test.rb
198
- - test/integration/document_test.rb
199
- - test/integration/capture_test.rb
200
- - test/integration/render_profiling_test.rb
201
184
  - test/integration/parsing_quirks_test.rb
202
- - test/integration/blank_test.rb
203
- - test/integration/filter_test.rb
204
- - test/integration/context_test.rb
185
+ - test/integration/render_profiling_test.rb
186
+ - test/integration/security_test.rb
205
187
  - test/integration/standard_filter_test.rb
206
- - test/integration/tags/statements_test.rb
207
- - test/integration/tags/increment_tag_test.rb
208
- - test/integration/tags/standard_tag_test.rb
209
188
  - test/integration/tags/break_tag_test.rb
210
189
  - test/integration/tags/continue_tag_test.rb
211
190
  - test/integration/tags/for_tag_test.rb
212
- - test/integration/tags/raw_tag_test.rb
191
+ - test/integration/tags/if_else_tag_test.rb
213
192
  - test/integration/tags/include_tag_test.rb
193
+ - test/integration/tags/increment_tag_test.rb
194
+ - test/integration/tags/raw_tag_test.rb
195
+ - test/integration/tags/standard_tag_test.rb
196
+ - test/integration/tags/statements_test.rb
214
197
  - test/integration/tags/table_row_test.rb
215
198
  - test/integration/tags/unless_else_tag_test.rb
216
- - test/integration/tags/if_else_tag_test.rb
199
+ - test/integration/template_test.rb
200
+ - test/integration/trim_mode_test.rb
201
+ - test/integration/variable_test.rb
202
+ - test/test_helper.rb
203
+ - test/unit/block_unit_test.rb
204
+ - test/unit/condition_unit_test.rb
205
+ - test/unit/context_unit_test.rb
206
+ - test/unit/file_system_unit_test.rb
207
+ - test/unit/i18n_unit_test.rb
208
+ - test/unit/lexer_unit_test.rb
209
+ - test/unit/parser_unit_test.rb
210
+ - test/unit/regexp_unit_test.rb
211
+ - test/unit/strainer_unit_test.rb
212
+ - test/unit/tag_unit_test.rb
213
+ - test/unit/tags/case_tag_unit_test.rb
214
+ - test/unit/tags/for_tag_unit_test.rb
215
+ - test/unit/tags/if_tag_unit_test.rb
216
+ - test/unit/template_unit_test.rb
217
+ - test/unit/tokenizer_unit_test.rb
218
+ - test/unit/variable_unit_test.rb