liquid 2.5.5 → 2.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +13 -5
  2. data/History.md +26 -11
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +6 -0
  5. data/lib/extras/liquid_view.rb +9 -9
  6. data/lib/liquid.rb +1 -0
  7. data/lib/liquid/block.rb +16 -5
  8. data/lib/liquid/context.rb +17 -9
  9. data/lib/liquid/document.rb +1 -1
  10. data/lib/liquid/errors.rb +2 -1
  11. data/lib/liquid/file_system.rb +12 -12
  12. data/lib/liquid/htmltags.rb +1 -1
  13. data/lib/liquid/module_ex.rb +1 -1
  14. data/lib/liquid/standardfilters.rb +44 -22
  15. data/lib/liquid/strainer.rb +3 -3
  16. data/lib/liquid/tag.rb +1 -1
  17. data/lib/liquid/tags/assign.rb +14 -12
  18. data/lib/liquid/tags/break.rb +2 -2
  19. data/lib/liquid/tags/capture.rb +1 -0
  20. data/lib/liquid/tags/case.rb +28 -28
  21. data/lib/liquid/tags/continue.rb +1 -1
  22. data/lib/liquid/tags/cycle.rb +21 -21
  23. data/lib/liquid/tags/decrement.rb +7 -7
  24. data/lib/liquid/tags/for.rb +26 -26
  25. data/lib/liquid/tags/if.rb +3 -3
  26. data/lib/liquid/tags/ifchanged.rb +9 -9
  27. data/lib/liquid/tags/include.rb +42 -14
  28. data/lib/liquid/tags/increment.rb +7 -7
  29. data/lib/liquid/tags/raw.rb +5 -4
  30. data/lib/liquid/tags/unless.rb +8 -8
  31. data/lib/liquid/template.rb +11 -5
  32. data/lib/liquid/utils.rb +0 -1
  33. data/lib/liquid/variable.rb +2 -2
  34. data/lib/liquid/version.rb +4 -0
  35. data/test/liquid/assign_test.rb +1 -1
  36. data/test/liquid/condition_test.rb +1 -1
  37. data/test/liquid/hash_ordering_test.rb +25 -0
  38. data/test/liquid/output_test.rb +2 -2
  39. data/test/liquid/standard_filter_test.rb +18 -0
  40. data/test/liquid/tags/for_tag_test.rb +47 -34
  41. data/test/liquid/tags/html_tag_test.rb +2 -2
  42. data/test/liquid/tags/if_else_tag_test.rb +0 -6
  43. data/test/liquid/tags/include_tag_test.rb +28 -1
  44. data/test/liquid/tags/raw_tag_test.rb +11 -2
  45. data/test/liquid/template_test.rb +72 -0
  46. data/test/liquid/variable_test.rb +6 -0
  47. metadata +8 -5
@@ -1,20 +1,20 @@
1
1
  module Liquid
2
2
  class Ifchanged < Block
3
-
3
+
4
4
  def render(context)
5
- context.stack do
6
-
5
+ context.stack do
6
+
7
7
  output = render_all(@nodelist, context)
8
-
8
+
9
9
  if output != context.registers[:ifchanged]
10
10
  context.registers[:ifchanged] = output
11
11
  output
12
12
  else
13
13
  ''
14
- end
14
+ end
15
15
  end
16
16
  end
17
- end
18
-
19
- Template.register_tag('ifchanged', Ifchanged)
20
- end
17
+ end
18
+
19
+ Template.register_tag('ifchanged', Ifchanged)
20
+ end
@@ -1,11 +1,26 @@
1
1
  module Liquid
2
+
3
+ # Include allows templates to relate with other templates
4
+ #
5
+ # Simply include another template:
6
+ #
7
+ # {% include 'product' %}
8
+ #
9
+ # Include a template with a local variable:
10
+ #
11
+ # {% include 'product' with products[0] %}
12
+ #
13
+ # Include a template for a collection:
14
+ #
15
+ # {% include 'product' for products %}
16
+ #
2
17
  class Include < Tag
3
18
  Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o
4
-
5
- def initialize(tag_name, markup, tokens)
19
+
20
+ def initialize(tag_name, markup, tokens)
6
21
  if markup =~ Syntax
7
22
 
8
- @template_name = $1
23
+ @template_name = $1
9
24
  @variable_name = $3
10
25
  @attributes = {}
11
26
 
@@ -19,23 +34,22 @@ module Liquid
19
34
 
20
35
  super
21
36
  end
22
-
37
+
23
38
  def parse(tokens)
24
39
  end
25
-
40
+
26
41
  def render(context)
27
- source = _read_template_from_file_system(context)
28
- partial = Liquid::Template.parse(source)
42
+ partial = load_cached_partial(context)
29
43
  variable = context[@variable_name || @template_name[1..-2]]
30
-
44
+
31
45
  context.stack do
32
46
  @attributes.each do |key, value|
33
47
  context[key] = context[value]
34
48
  end
35
49
 
36
50
  if variable.is_a?(Array)
37
- variable.collect do |variable|
38
- context[@template_name[1..-2]] = variable
51
+ variable.collect do |var|
52
+ context[@template_name[1..-2]] = var
39
53
  partial.render(context)
40
54
  end
41
55
  else
@@ -44,11 +58,25 @@ module Liquid
44
58
  end
45
59
  end
46
60
  end
47
-
61
+
48
62
  private
49
- def _read_template_from_file_system(context)
63
+ def load_cached_partial(context)
64
+ cached_partials = context.registers[:cached_partials] || {}
65
+ template_name = context[@template_name]
66
+
67
+ if cached = cached_partials[template_name]
68
+ return cached
69
+ end
70
+ source = read_template_from_file_system(context)
71
+ partial = Liquid::Template.parse(source)
72
+ cached_partials[template_name] = partial
73
+ context.registers[:cached_partials] = cached_partials
74
+ partial
75
+ end
76
+
77
+ def read_template_from_file_system(context)
50
78
  file_system = context.registers[:file_system] || Liquid::Template.file_system
51
-
79
+
52
80
  # make read_template_file call backwards-compatible.
53
81
  case file_system.method(:read_template_file).arity
54
82
  when 1
@@ -61,5 +89,5 @@ module Liquid
61
89
  end
62
90
  end
63
91
 
64
- Template.register_tag('include', Include)
92
+ Template.register_tag('include', Include)
65
93
  end
@@ -1,5 +1,5 @@
1
1
  module Liquid
2
-
2
+
3
3
  # increment is used in a place where one needs to insert a counter
4
4
  # into a template, and needs the counter to survive across
5
5
  # multiple instantiations of the template.
@@ -16,20 +16,20 @@ module Liquid
16
16
  # Hello: 2
17
17
  #
18
18
  class Increment < Tag
19
- def initialize(tag_name, markup, tokens)
19
+ def initialize(tag_name, markup, tokens)
20
20
  @variable = markup.strip
21
21
 
22
- super
23
- end
24
-
22
+ super
23
+ end
24
+
25
25
  def render(context)
26
26
  value = context.environments.first[@variable] ||= 0
27
27
  context.environments.first[@variable] = value + 1
28
28
  value.to_s
29
29
  end
30
-
30
+
31
31
  private
32
32
  end
33
-
33
+
34
34
  Template.register_tag('increment', Increment)
35
35
  end
@@ -1,12 +1,14 @@
1
1
  module Liquid
2
2
  class Raw < Block
3
+ FullTokenPossiblyInvalid = /^(.*)#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/o
4
+
3
5
  def parse(tokens)
4
6
  @nodelist ||= []
5
7
  @nodelist.clear
6
-
7
8
  while token = tokens.shift
8
- if token =~ FullToken
9
- if block_delimiter == $1
9
+ if token =~ FullTokenPossiblyInvalid
10
+ @nodelist << $1 if $1 != ""
11
+ if block_delimiter == $2
10
12
  end_tag
11
13
  return
12
14
  end
@@ -18,4 +20,3 @@ module Liquid
18
20
 
19
21
  Template.register_tag('raw', Raw)
20
22
  end
21
-
@@ -9,25 +9,25 @@ module Liquid
9
9
  class Unless < If
10
10
  def render(context)
11
11
  context.stack do
12
-
12
+
13
13
  # First condition is interpreted backwards ( if not )
14
- block = @blocks.first
15
- unless block.evaluate(context)
16
- return render_all(block.attachment, context)
14
+ first_block = @blocks.first
15
+ unless first_block.evaluate(context)
16
+ return render_all(first_block.attachment, context)
17
17
  end
18
-
18
+
19
19
  # After the first condition unless works just like if
20
20
  @blocks[1..-1].each do |block|
21
21
  if block.evaluate(context)
22
22
  return render_all(block.attachment, context)
23
23
  end
24
24
  end
25
-
25
+
26
26
  ''
27
27
  end
28
28
  end
29
29
  end
30
-
30
+
31
31
 
32
32
  Template.register_tag('unless', Unless)
33
- end
33
+ end
@@ -14,7 +14,7 @@ module Liquid
14
14
  # template.render('user_name' => 'bob')
15
15
  #
16
16
  class Template
17
- attr_accessor :root
17
+ attr_accessor :root, :resource_limits
18
18
  @@file_system = BlankFileSystem.new
19
19
 
20
20
  class << self
@@ -50,6 +50,7 @@ module Liquid
50
50
 
51
51
  # creates a new <tt>Template</tt> from an array of tokens. Use <tt>Template.parse</tt> instead
52
52
  def initialize
53
+ @resource_limits = {}
53
54
  end
54
55
 
55
56
  # Parse source code.
@@ -88,14 +89,17 @@ module Liquid
88
89
  #
89
90
  def render(*args)
90
91
  return '' if @root.nil?
91
-
92
+
92
93
  context = case args.first
93
94
  when Liquid::Context
94
95
  args.shift
96
+ when Liquid::Drop
97
+ drop = args.shift
98
+ drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
95
99
  when Hash
96
- Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors)
100
+ Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
97
101
  when nil
98
- Context.new(assigns, instance_assigns, registers, @rethrow_errors)
102
+ Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
99
103
  else
100
104
  raise ArgumentError, "Expect Hash or Liquid::Context as parameter"
101
105
  end
@@ -120,9 +124,11 @@ module Liquid
120
124
 
121
125
  begin
122
126
  # render the nodelist.
123
- # for performance reasons we get a array back here. join will make a string out of it
127
+ # for performance reasons we get an array back here. join will make a string out of it.
124
128
  result = @root.render(context)
125
129
  result.respond_to?(:join) ? result.join : result
130
+ rescue Liquid::MemoryError => e
131
+ context.handle_error(e)
126
132
  ensure
127
133
  @errors = context.errors
128
134
  end
data/lib/liquid/utils.rb CHANGED
@@ -3,7 +3,6 @@ module Liquid
3
3
  def self.slice_collection_using_each(collection, from, to)
4
4
  segments = []
5
5
  index = 0
6
- yielded = 0
7
6
 
8
7
  # Maintains Ruby 1.8.7 String#each behaviour on 1.9
9
8
  return [collection] if non_blank_string?(collection)
@@ -23,9 +23,9 @@ module Liquid
23
23
  if match[2].match(/#{FilterSeparator}\s*(.*)/o)
24
24
  filters = Regexp.last_match(1).scan(FilterParser)
25
25
  filters.each do |f|
26
- if matches = f.match(/\s*(\w+)(?:\s*#{FilterArgumentSeparator}(.*))?/)
26
+ if matches = f.match(/\s*(\w+)/)
27
27
  filtername = matches[1]
28
- filterargs = matches[2].to_s.scan(/(?:\A|#{ArgumentSeparator})\s*((?:\w+\s*\:\s*)?#{QuotedFragment})/o).flatten
28
+ filterargs = f.scan(/(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*((?:\w+\s*\:\s*)?#{QuotedFragment})/o).flatten
29
29
  @filters << [filtername, filterargs]
30
30
  end
31
31
  end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ module Liquid
3
+ VERSION = "2.6.0.rc1"
4
+ end
@@ -12,7 +12,7 @@ class AssignTest < Test::Unit::TestCase
12
12
  '{% assign foo = values %}.{{ foo[1] }}.',
13
13
  'values' => %w{foo bar baz})
14
14
  end
15
-
15
+
16
16
  def test_assign_with_filter
17
17
  assert_template_result('.bar.',
18
18
  '{% assign foo = values | split: "," %}.{{ foo[1] }}.',
@@ -124,4 +124,4 @@ class ConditionTest < Test::Unit::TestCase
124
124
  assert !Condition.new(left, op, right).evaluate(@context || Liquid::Context.new),
125
125
  "Evaluated true: #{left} #{op} #{right}"
126
126
  end
127
- end # ConditionTest
127
+ end # ConditionTest
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ module MoneyFilter
4
+ def money(input)
5
+ sprintf(' %d$ ', input)
6
+ end
7
+ end
8
+
9
+ module CanadianMoneyFilter
10
+ def money(input)
11
+ sprintf(' %d$ CAD ', input)
12
+ end
13
+ end
14
+
15
+ class HashOrderingTest < Test::Unit::TestCase
16
+ include Liquid
17
+
18
+ def test_global_register_order
19
+ Template.register_filter(MoneyFilter)
20
+ Template.register_filter(CanadianMoneyFilter)
21
+
22
+ assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, nil)
23
+ end
24
+
25
+ end
@@ -49,7 +49,7 @@ class OutputTest < Test::Unit::TestCase
49
49
 
50
50
  expected = %| good bad good |
51
51
  assert_equal expected, Template.parse(text).render(@assigns)
52
- end
52
+ end
53
53
 
54
54
  def test_variable_piping
55
55
  text = %( {{ car.gm | make_funny }} )
@@ -113,4 +113,4 @@ class OutputTest < Test::Unit::TestCase
113
113
 
114
114
  assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
115
115
  end
116
- end # OutputTest
116
+ end # OutputTest
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class Filters
@@ -58,6 +60,7 @@ class StandardFiltersTest < Test::Unit::TestCase
58
60
  assert_equal '1234567890', @filters.truncate('1234567890', 20)
59
61
  assert_equal '...', @filters.truncate('1234567890', 0)
60
62
  assert_equal '1234567890', @filters.truncate('1234567890')
63
+ assert_equal "测试...", @filters.truncate("测试测试测试测试", 5)
61
64
  end
62
65
 
63
66
  def test_strip
@@ -82,12 +85,16 @@ class StandardFiltersTest < Test::Unit::TestCase
82
85
  assert_equal 'one two...', @filters.truncatewords('one two three', 2)
83
86
  assert_equal 'one two three', @filters.truncatewords('one two three')
84
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)
85
89
  end
86
90
 
87
91
  def test_strip_html
88
92
  assert_equal 'test', @filters.strip_html("<div>test</div>")
89
93
  assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
90
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")
91
98
  assert_equal '', @filters.strip_html(nil)
92
99
  end
93
100
 
@@ -101,6 +108,10 @@ class StandardFiltersTest < Test::Unit::TestCase
101
108
  assert_equal [{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], @filters.sort([{"a" => 4}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
102
109
  end
103
110
 
111
+ def test_reverse
112
+ assert_equal [4,3,2,1], @filters.reverse([1,2,3,4])
113
+ end
114
+
104
115
  def test_map
105
116
  assert_equal [1,2,3,4], @filters.map([{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], 'a')
106
117
  assert_template_result 'abc', "{{ ary | map:'foo' | map:'bar' }}",
@@ -141,6 +152,8 @@ class StandardFiltersTest < Test::Unit::TestCase
141
152
  assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
142
153
 
143
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')
144
157
 
145
158
  assert_equal nil, @filters.date(nil, "%B")
146
159
 
@@ -174,6 +187,7 @@ class StandardFiltersTest < Test::Unit::TestCase
174
187
 
175
188
  def test_strip_newlines
176
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"
177
191
  end
178
192
 
179
193
  def test_newlines_to_br
@@ -198,6 +212,8 @@ class StandardFiltersTest < Test::Unit::TestCase
198
212
  assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
199
213
 
200
214
  assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
215
+
216
+ assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
201
217
  end
202
218
 
203
219
  def test_divided_by
@@ -209,6 +225,8 @@ class StandardFiltersTest < Test::Unit::TestCase
209
225
 
210
226
  assert_template_result "5", "{{ 15 | divided_by:3 }}"
211
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 }}"
212
230
  end
213
231
 
214
232
  def test_modulo
@@ -187,16 +187,16 @@ HERE
187
187
  expected = "1234"
188
188
  assert_template_result(expected,markup,assigns)
189
189
 
190
- # tests to ensure it only breaks out of the local for loop
190
+ # tests to ensure it only breaks out of the local for loop
191
191
  # and not all of them.
192
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 %}' +
193
+ markup = '{% for item in array %}' +
194
+ '{% for i in item %}' +
195
+ '{% if i == 1 %}' +
196
+ '{% break %}' +
197
+ '{% endif %}' +
198
+ '{{ i }}' +
199
+ '{% endfor %}' +
200
200
  '{% endfor %}'
201
201
  expected = '3456'
202
202
  assert_template_result(expected, markup, assigns)
@@ -213,15 +213,15 @@ HERE
213
213
 
214
214
  markup = '{% for i in array.items %}{% continue %}{% endfor %}'
215
215
  expected = ""
216
- assert_template_result(expected,markup,assigns)
216
+ assert_template_result(expected,markup,assigns)
217
217
 
218
218
  markup = '{% for i in array.items %}{{ i }}{% continue %}{% endfor %}'
219
219
  expected = "12345"
220
- assert_template_result(expected,markup,assigns)
220
+ assert_template_result(expected,markup,assigns)
221
221
 
222
222
  markup = '{% for i in array.items %}{% continue %}{{ i }}{% endfor %}'
223
223
  expected = ""
224
- assert_template_result(expected,markup,assigns)
224
+ assert_template_result(expected,markup,assigns)
225
225
 
226
226
  markup = '{% for i in array.items %}{% if i > 3 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
227
227
  expected = "123"
@@ -233,13 +233,13 @@ HERE
233
233
 
234
234
  # tests to ensure it only continues the local for loop and not all of them.
235
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 %}' +
236
+ markup = '{% for item in array %}' +
237
+ '{% for i in item %}' +
238
+ '{% if i == 1 %}' +
239
+ '{% continue %}' +
240
+ '{% endif %}' +
241
+ '{{ i }}' +
242
+ '{% endfor %}' +
243
243
  '{% endfor %}'
244
244
  expected = '23456'
245
245
  assert_template_result(expected, markup, assigns)
@@ -253,32 +253,45 @@ HERE
253
253
 
254
254
  def test_for_tag_string
255
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
256
+ # ruby 1.9.3 no longer supports .each on String though we mimic
257
257
  # the functionality for backwards compatibility
258
258
 
259
- assert_template_result('test string',
260
- '{%for val in string%}{{val}}{%endfor%}',
259
+ assert_template_result('test string',
260
+ '{%for val in string%}{{val}}{%endfor%}',
261
261
  'string' => "test string")
262
262
 
263
- assert_template_result('test string',
264
- '{%for val in string limit:1%}{{val}}{%endfor%}',
263
+ assert_template_result('test string',
264
+ '{%for val in string limit:1%}{{val}}{%endfor%}',
265
265
  'string' => "test string")
266
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%}',
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
278
  'string' => "test string")
279
279
  end
280
280
 
281
281
  def test_blank_string_not_iterable
282
282
  assert_template_result('', "{% for char in characters %}I WILL NOT BE OUTPUT{% endfor %}", 'characters' => '')
283
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
284
297
  end