liquid 1.7.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 (61) hide show
  1. data/CHANGELOG +38 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Manifest.txt +60 -0
  4. data/README +38 -0
  5. data/Rakefile +24 -0
  6. data/example/server/example_servlet.rb +37 -0
  7. data/example/server/liquid_servlet.rb +28 -0
  8. data/example/server/server.rb +12 -0
  9. data/example/server/templates/index.liquid +6 -0
  10. data/example/server/templates/products.liquid +45 -0
  11. data/init.rb +6 -0
  12. data/lib/extras/liquid_view.rb +27 -0
  13. data/lib/liquid.rb +66 -0
  14. data/lib/liquid/block.rb +101 -0
  15. data/lib/liquid/condition.rb +91 -0
  16. data/lib/liquid/context.rb +216 -0
  17. data/lib/liquid/document.rb +17 -0
  18. data/lib/liquid/drop.rb +48 -0
  19. data/lib/liquid/errors.rb +7 -0
  20. data/lib/liquid/extensions.rb +56 -0
  21. data/lib/liquid/file_system.rb +62 -0
  22. data/lib/liquid/htmltags.rb +64 -0
  23. data/lib/liquid/standardfilters.rb +125 -0
  24. data/lib/liquid/strainer.rb +43 -0
  25. data/lib/liquid/tag.rb +25 -0
  26. data/lib/liquid/tags/assign.rb +22 -0
  27. data/lib/liquid/tags/capture.rb +22 -0
  28. data/lib/liquid/tags/case.rb +68 -0
  29. data/lib/liquid/tags/comment.rb +9 -0
  30. data/lib/liquid/tags/cycle.rb +46 -0
  31. data/lib/liquid/tags/for.rb +81 -0
  32. data/lib/liquid/tags/if.rb +51 -0
  33. data/lib/liquid/tags/ifchanged.rb +20 -0
  34. data/lib/liquid/tags/include.rb +56 -0
  35. data/lib/liquid/tags/unless.rb +29 -0
  36. data/lib/liquid/template.rb +150 -0
  37. data/lib/liquid/variable.rb +39 -0
  38. data/test/block_test.rb +50 -0
  39. data/test/context_test.rb +340 -0
  40. data/test/drop_test.rb +139 -0
  41. data/test/error_handling_test.rb +65 -0
  42. data/test/extra/breakpoint.rb +547 -0
  43. data/test/extra/caller.rb +80 -0
  44. data/test/file_system_test.rb +30 -0
  45. data/test/filter_test.rb +98 -0
  46. data/test/helper.rb +20 -0
  47. data/test/html_tag_test.rb +24 -0
  48. data/test/if_else_test.rb +95 -0
  49. data/test/include_tag_test.rb +91 -0
  50. data/test/output_test.rb +121 -0
  51. data/test/parsing_quirks_test.rb +14 -0
  52. data/test/regexp_test.rb +39 -0
  53. data/test/security_test.rb +41 -0
  54. data/test/standard_filter_test.rb +101 -0
  55. data/test/standard_tag_test.rb +336 -0
  56. data/test/statements_test.rb +137 -0
  57. data/test/strainer_test.rb +16 -0
  58. data/test/template_test.rb +26 -0
  59. data/test/unless_else_test.rb +19 -0
  60. data/test/variable_test.rb +135 -0
  61. metadata +114 -0
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/helper'
3
+
4
+ module FunnyFilter
5
+
6
+ def make_funny(input)
7
+ 'LOL'
8
+ end
9
+
10
+ def cite_funny(input)
11
+ "LOL: #{input}"
12
+ end
13
+
14
+ def add_smiley(input, smiley = ":-)")
15
+ "#{input} #{smiley}"
16
+ end
17
+
18
+ def add_tag(input, tag = "p", id = "foo")
19
+ %|<#{tag} id="#{id}">#{input}</#{tag}>|
20
+ end
21
+
22
+ def paragraph(input)
23
+ "<p>#{input}</p>"
24
+ end
25
+
26
+ def link_to(name, url)
27
+ %|<a href="#{url}">#{name}</a>|
28
+ end
29
+ end
30
+
31
+
32
+ class OutputTest < Test::Unit::TestCase
33
+ include Liquid
34
+
35
+ def setup
36
+ @assigns = {
37
+ 'best_cars' => 'bmw',
38
+ 'car' => {'bmw' => 'good', 'gm' => 'bad'}
39
+ }
40
+
41
+ end
42
+
43
+ def test_variable
44
+ text = %| {{best_cars}} |
45
+
46
+ expected = %| bmw |
47
+ assert_equal expected, Template.parse(text).render(@assigns)
48
+ end
49
+
50
+ def test_variable_traversing
51
+ text = %| {{car.bmw}} {{car.gm}} {{car.bmw}} |
52
+
53
+ expected = %| good bad good |
54
+ assert_equal expected, Template.parse(text).render(@assigns)
55
+ end
56
+
57
+ def test_variable_piping
58
+ text = %( {{ car.gm | make_funny }} )
59
+ expected = %| LOL |
60
+
61
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
62
+ end
63
+
64
+ def test_variable_piping_with_input
65
+ text = %( {{ car.gm | cite_funny }} )
66
+ expected = %| LOL: bad |
67
+
68
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
69
+ end
70
+
71
+ def test_variable_piping_with_args
72
+ text = %! {{ car.gm | add_smiley : ':-(' }} !
73
+ expected = %| bad :-( |
74
+
75
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
76
+ end
77
+
78
+ def test_variable_piping_with_no_args
79
+ text = %! {{ car.gm | add_smiley }} !
80
+ expected = %| bad :-) |
81
+
82
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
83
+ end
84
+
85
+ def test_multiple_variable_piping_with_args
86
+ text = %! {{ car.gm | add_smiley : ':-(' | add_smiley : ':-('}} !
87
+ expected = %| bad :-( :-( |
88
+
89
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
90
+ end
91
+
92
+ def test_variable_piping_with_args
93
+ text = %! {{ car.gm | add_tag : 'span', 'bar'}} !
94
+ expected = %| <span id="bar">bad</span> |
95
+
96
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
97
+ end
98
+
99
+ def test_variable_piping_with_variable_args
100
+ text = %! {{ car.gm | add_tag : 'span', car.bmw}} !
101
+ expected = %| <span id="good">bad</span> |
102
+
103
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
104
+ end
105
+
106
+ def test_multiple_pipings
107
+ text = %( {{ best_cars | cite_funny | paragraph }} )
108
+ expected = %| <p>LOL: bmw</p> |
109
+
110
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
111
+ end
112
+
113
+ def test_link_to
114
+ text = %( {{ 'Typo' | link_to: 'http://typo.leetsoft.com' }} )
115
+ expected = %| <a href="http://typo.leetsoft.com">Typo</a> |
116
+
117
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
118
+ end
119
+
120
+
121
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/helper'
3
+
4
+ class ParsingQuirksTest < Test::Unit::TestCase
5
+ include Liquid
6
+
7
+ def test_error_with_css
8
+ text = %| div { font-weight: bold; } |
9
+ template = Template.parse(text)
10
+
11
+ assert_equal text, template.render
12
+ assert_equal [String], template.root.nodelist.collect {|i| i.class}
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class RegexpTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_empty
7
+ assert_equal [], ''.scan(QuotedFragment)
8
+ end
9
+
10
+ def test_quote
11
+ assert_equal ['"arg 1"'], '"arg 1"'.scan(QuotedFragment)
12
+ end
13
+
14
+
15
+ def test_words
16
+ assert_equal ['arg1', 'arg2'], 'arg1 arg2'.scan(QuotedFragment)
17
+ end
18
+
19
+ def test_quoted_words
20
+ assert_equal ['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment)
21
+ end
22
+
23
+ def test_quoted_words
24
+ assert_equal ['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment)
25
+ end
26
+
27
+ def test_quoted_words_in_the_middle
28
+ assert_equal ['arg1', 'arg2', '"arg 3"', 'arg4'], 'arg1 arg2 "arg 3" arg4 '.scan(QuotedFragment)
29
+ end
30
+
31
+ def test_variable_parser
32
+ assert_equal ['var'], 'var'.scan(VariableParser)
33
+ assert_equal ['var', 'method'], 'var.method'.scan(VariableParser)
34
+ assert_equal ['var', 'method'], 'var[method]'.scan(VariableParser)
35
+ assert_equal ['var', 'method', '0'], 'var[method][0]'.scan(VariableParser)
36
+ assert_equal ['var', 'method', '0', 'method'], 'var[method][0].method'.scan(VariableParser)
37
+ end
38
+
39
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/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
+ end
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/helper'
3
+
4
+
5
+ class Filters
6
+ include Liquid::StandardFilters
7
+ end
8
+
9
+
10
+ class StandardFiltersTest < Test::Unit::TestCase
11
+ include Liquid
12
+
13
+ def setup
14
+ @filters = Filters.new
15
+ end
16
+
17
+ def test_size
18
+ assert_equal 3, @filters.size([1,2,3])
19
+ assert_equal 0, @filters.size([])
20
+ assert_equal 0, @filters.size(nil)
21
+ end
22
+
23
+ def test_downcase
24
+ assert_equal 'testing', @filters.downcase("Testing")
25
+ assert_equal '', @filters.downcase(nil)
26
+ end
27
+
28
+ def test_upcase
29
+ assert_equal 'TESTING', @filters.upcase("Testing")
30
+ assert_equal '', @filters.upcase(nil)
31
+ end
32
+
33
+ def test_upcase
34
+ assert_equal 'TESTING', @filters.upcase("Testing")
35
+ assert_equal '', @filters.upcase(nil)
36
+ end
37
+
38
+ def test_truncate
39
+ assert_equal '1234...', @filters.truncate('1234567890', 7)
40
+ assert_equal '1234567890', @filters.truncate('1234567890', 20)
41
+ assert_equal '...', @filters.truncate('1234567890', 0)
42
+ assert_equal '1234567890', @filters.truncate('1234567890')
43
+ end
44
+
45
+ def test_truncatewords
46
+ assert_equal 'one two three', @filters.truncatewords('one two three', 4)
47
+ assert_equal 'one two...', @filters.truncatewords('one two three', 2)
48
+ assert_equal 'one two three', @filters.truncatewords('one two three')
49
+ end
50
+
51
+ def test_strip_html
52
+ assert_equal 'test', @filters.strip_html("<div>test</div>")
53
+ assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
54
+ assert_equal '', @filters.strip_html(nil)
55
+ end
56
+
57
+ def test_join
58
+ assert_equal '1 2 3 4', @filters.join([1,2,3,4])
59
+ assert_equal '1 - 2 - 3 - 4', @filters.join([1,2,3,4], ' - ')
60
+ end
61
+
62
+ def test_sort
63
+ assert_equal [1,2,3,4], @filters.sort([4,3,2,1])
64
+ end
65
+
66
+ def test_date
67
+ assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
68
+ assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
69
+ assert_equal 'July', @filters.date(Time.parse("2006-07-05 10:00:00"), "%B")
70
+
71
+ assert_equal 'May', @filters.date("2006-05-05 10:00:00", "%B")
72
+ assert_equal 'June', @filters.date("2006-06-05 10:00:00", "%B")
73
+ assert_equal 'July', @filters.date("2006-07-05 10:00:00", "%B")
74
+
75
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
76
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
77
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
78
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", nil)
79
+
80
+ assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
81
+ assert_equal nil, @filters.date(nil, "%B")
82
+ end
83
+
84
+
85
+ def test_first_last
86
+ assert_equal 1, @filters.first([1,2,3])
87
+ assert_equal 3, @filters.last([1,2,3])
88
+ assert_equal nil, @filters.first([])
89
+ assert_equal nil, @filters.last([])
90
+ end
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ end
101
+
@@ -0,0 +1,336 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+
4
+ class TemplateTest < Test::Unit::TestCase
5
+ include Liquid
6
+
7
+
8
+ def test_tag
9
+ tag = Tag.new([], [])
10
+ assert_equal 'liquid::tag', tag.name
11
+ assert_equal '', tag.render(Context.new(Liquid::Template.new))
12
+ end
13
+
14
+ def test_no_transform
15
+ assert_template_result('this text should come out of the template without change...',
16
+ 'this text should come out of the template without change...')
17
+ assert_template_result('blah','blah')
18
+ assert_template_result('<blah>','<blah>')
19
+ assert_template_result('|,.:','|,.:')
20
+ assert_template_result('','')
21
+
22
+ text = %|this shouldnt see any transformation either but has multiple lines
23
+ as you can clearly see here ...|
24
+ assert_template_result(text,text)
25
+ end
26
+
27
+ def test_has_a_block_which_does_nothing
28
+ assert_template_result(%|the comment block should be removed .. right?|,
29
+ %|the comment block should be removed {%comment%} be gone.. {%endcomment%} .. right?|)
30
+
31
+ assert_template_result('','{%comment%}{%endcomment%}')
32
+ assert_template_result('','{%comment%}{% endcomment %}')
33
+ assert_template_result('','{% comment %}{%endcomment%}')
34
+ assert_template_result('','{% comment %}{% endcomment %}')
35
+ assert_template_result('','{%comment%}comment{%endcomment%}')
36
+ assert_template_result('','{% comment %}comment{% endcomment %}')
37
+
38
+ assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar')
39
+ assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar')
40
+ assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar')
41
+ assert_template_result('foobar','foo{% comment %} comment {% endcomment %}bar')
42
+
43
+ assert_template_result('foo bar','foo {%comment%} {%endcomment%} bar')
44
+ assert_template_result('foo bar','foo {%comment%}comment{%endcomment%} bar')
45
+ assert_template_result('foo bar','foo {%comment%} comment {%endcomment%} bar')
46
+
47
+ assert_template_result('foobar','foo{%comment%}
48
+ {%endcomment%}bar')
49
+ end
50
+
51
+ def test_for
52
+ assert_template_result(' yo yo yo yo ','{%for item in array%} yo {%endfor%}','array' => [1,2,3,4])
53
+ assert_template_result('yoyo','{%for item in array%}yo{%endfor%}','array' => [1,2])
54
+ assert_template_result(' yo ','{%for item in array%} yo {%endfor%}','array' => [1])
55
+ assert_template_result('','{%for item in array%}{%endfor%}','array' => [1,2])
56
+ expected = <<HERE
57
+
58
+ yo
59
+
60
+ yo
61
+
62
+ yo
63
+
64
+ HERE
65
+ template = <<HERE
66
+ {%for item in array%}
67
+ yo
68
+ {%endfor%}
69
+ HERE
70
+ assert_template_result(expected,template,'array' => [1,2,3])
71
+ end
72
+
73
+ def test_for_with_variable
74
+ assert_template_result(' 1 2 3 ','{%for item in array%} {{item}} {%endfor%}','array' => [1,2,3])
75
+ assert_template_result('123','{%for item in array%}{{item}}{%endfor%}','array' => [1,2,3])
76
+ assert_template_result('123','{% for item in array %}{{item}}{% endfor %}','array' => [1,2,3])
77
+ assert_template_result('abcd','{%for item in array%}{{item}}{%endfor%}','array' => ['a','b','c','d'])
78
+ assert_template_result('a b c','{%for item in array%}{{item}}{%endfor%}','array' => ['a',' ','b',' ','c'])
79
+ assert_template_result('abc','{%for item in array%}{{item}}{%endfor%}','array' => ['a','','b','','c'])
80
+ end
81
+
82
+ def test_for_helpers
83
+ assigns = {'array' => [1,2,3] }
84
+ assert_template_result(' 1/3 2/3 3/3 ','{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',assigns)
85
+ assert_template_result(' 1 2 3 ','{%for item in array%} {{forloop.index}} {%endfor%}',assigns)
86
+ assert_template_result(' 0 1 2 ','{%for item in array%} {{forloop.index0}} {%endfor%}',assigns)
87
+ assert_template_result(' 2 1 0 ','{%for item in array%} {{forloop.rindex0}} {%endfor%}',assigns)
88
+ assert_template_result(' 3 2 1 ','{%for item in array%} {{forloop.rindex}} {%endfor%}',assigns)
89
+ assert_template_result(' true false false ','{%for item in array%} {{forloop.first}} {%endfor%}',assigns)
90
+ assert_template_result(' false false true ','{%for item in array%} {{forloop.last}} {%endfor%}',assigns)
91
+ end
92
+
93
+ def test_for_and_if
94
+ assigns = {'array' => [1,2,3] }
95
+ assert_template_result(' yay ',
96
+ '{%for item in array%} {% if forloop.first %}yay{% endif %} {%endfor%}',
97
+ assigns)
98
+ assert_template_result(' yay boo boo ',
99
+ '{%for item in array%} {% if forloop.first %}yay{% else %}boo{% endif %} {%endfor%}',
100
+ assigns)
101
+ assert_template_result(' boo boo ',
102
+ '{%for item in array%} {% if forloop.first %}{% else %}boo{% endif %} {%endfor%}',
103
+ assigns)
104
+ end
105
+
106
+ def test_limiting
107
+ assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
108
+ assert_template_result('12','{%for i in array limit:2 %}{{ i }}{%endfor%}',assigns)
109
+ assert_template_result('1234','{%for i in array limit:4 %}{{ i }}{%endfor%}',assigns)
110
+ assert_template_result('3456','{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}',assigns)
111
+ assert_template_result('3456','{%for i in array limit: 4 offset: 2 %}{{ i }}{%endfor%}',assigns)
112
+
113
+ assigns['limit'] = 2
114
+ assigns['offset'] = 2
115
+ assert_template_result('34','{%for i in array limit: limit offset: offset %}{{ i }}{%endfor%}',assigns)
116
+ end
117
+
118
+ def test_nested_for
119
+ assigns = {'array' => [[1,2],[3,4],[5,6]] }
120
+ assert_template_result('123456','{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}',assigns)
121
+ end
122
+
123
+ def test_offset_only
124
+ assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
125
+ assert_template_result('890','{%for i in array offset:7 %}{{ i }}{%endfor%}',assigns)
126
+ end
127
+
128
+ def test_pause_resume
129
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
130
+ markup = <<-MKUP
131
+ {%for i in array.items limit: 3 %}{{i}}{%endfor%}
132
+ next
133
+ {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
134
+ next
135
+ {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
136
+ MKUP
137
+ expected = <<-XPCTD
138
+ 123
139
+ next
140
+ 456
141
+ next
142
+ 789
143
+ XPCTD
144
+ assert_template_result(expected,markup,assigns)
145
+ end
146
+
147
+ def test_pause_resume_limit
148
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
149
+ markup = <<-MKUP
150
+ {%for i in array.items limit:3 %}{{i}}{%endfor%}
151
+ next
152
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
153
+ next
154
+ {%for i in array.items offset:continue limit:1 %}{{i}}{%endfor%}
155
+ MKUP
156
+ expected = <<-XPCTD
157
+ 123
158
+ next
159
+ 456
160
+ next
161
+ 7
162
+ XPCTD
163
+ assert_template_result(expected,markup,assigns)
164
+ end
165
+
166
+ def test_pause_resume_BIG_limit
167
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
168
+ markup = <<-MKUP
169
+ {%for i in array.items limit:3 %}{{i}}{%endfor%}
170
+ next
171
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
172
+ next
173
+ {%for i in array.items offset:continue limit:1000 %}{{i}}{%endfor%}
174
+ MKUP
175
+ expected = <<-XPCTD
176
+ 123
177
+ next
178
+ 456
179
+ next
180
+ 7890
181
+ XPCTD
182
+ assert_template_result(expected,markup,assigns)
183
+ end
184
+
185
+
186
+ def test_pause_resume_BIG_offset
187
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
188
+ markup = <<-MKUP
189
+ {%for i in array.items limit:3 %}{{i}}{%endfor%}
190
+ next
191
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
192
+ next
193
+ {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%}
194
+ MKUP
195
+ expected = <<-XPCTD
196
+ 123
197
+ next
198
+ 456
199
+ next
200
+
201
+ XPCTD
202
+ assert_template_result(expected,markup,assigns)
203
+ end
204
+
205
+ def test_assign
206
+ assigns = {'var' => 'content' }
207
+ assert_template_result('var2: var2:content','var2:{{var2}} {%assign var2 = var%} var2:{{var2}}',assigns)
208
+
209
+ end
210
+
211
+ def test_capture
212
+ assigns = {'var' => 'content' }
213
+ assert_template_result('content foo content foo ','{{ var2 }}{% capture var2 %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}', assigns)
214
+ end
215
+
216
+ def test_capture_detects_bad_syntax
217
+ assert_raise(SyntaxError) do
218
+ assert_template_result('content foo content foo ','{{ var2 }}{% capture %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}', {'var' => 'content' })
219
+ end
220
+ end
221
+
222
+ def test_case
223
+ assigns = {'condition' => 2 }
224
+ assert_template_result(' its 2 ','{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}', assigns)
225
+
226
+ assigns = {'condition' => 1 }
227
+ assert_template_result(' its 1 ','{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}', assigns)
228
+
229
+ assigns = {'condition' => 3 }
230
+ assert_template_result('','{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}', assigns)
231
+
232
+ assigns = {'condition' => "string here" }
233
+ assert_template_result(' hit ','{% case condition %}{% when "string here" %} hit {% endcase %}', assigns)
234
+
235
+ assigns = {'condition' => "bad string here" }
236
+ assert_template_result('','{% case condition %}{% when "string here" %} hit {% endcase %}', assigns)
237
+ end
238
+
239
+ def test_case_with_else
240
+
241
+ assigns = {'condition' => 5 }
242
+ assert_template_result(' hit ','{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}', assigns)
243
+
244
+ assigns = {'condition' => 6 }
245
+ assert_template_result(' else ','{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}', assigns)
246
+
247
+ assigns = {'condition' => 6 }
248
+ assert_template_result(' else ','{% case condition %} {% when 5 %} hit {% else %} else {% endcase %}', assigns)
249
+
250
+
251
+ end
252
+
253
+ def test_case_on_size
254
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [])
255
+ assert_template_result('1' , '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1])
256
+ assert_template_result('2' , '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1])
257
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1])
258
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1])
259
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1, 1])
260
+ end
261
+
262
+ def test_case_on_size_with_else
263
+ assert_template_result('else', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [])
264
+ assert_template_result('1', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [1])
265
+ assert_template_result('2', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [1, 1])
266
+ assert_template_result('else', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [1, 1, 1])
267
+ assert_template_result('else', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [1, 1, 1, 1])
268
+ assert_template_result('else', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}', 'a' => [1, 1, 1, 1, 1])
269
+ end
270
+
271
+ def test_case_on_length_with_else
272
+ assert_template_result('else', '{% case a.empty? %}{% when true %}true{% when false %}false{% else %}else{% endcase %}', {})
273
+ assert_template_result('false', '{% case false %}{% when true %}true{% when false %}false{% else %}else{% endcase %}', {})
274
+ assert_template_result('true', '{% case true %}{% when true %}true{% when false %}false{% else %}else{% endcase %}', {})
275
+ assert_template_result('else', '{% case NULL %}{% when true %}true{% when false %}false{% else %}else{% endcase %}', {})
276
+ end
277
+
278
+ def test_case_detects_bad_syntax
279
+ assert_raise(SyntaxError) do
280
+ assert_template_result('', '{% case false %}{% when %}true{% endcase %}', {})
281
+ end
282
+
283
+ assert_raise(SyntaxError) do
284
+ assert_template_result('', '{% case false %}{% huh %}true{% endcase %}', {})
285
+ end
286
+
287
+ end
288
+
289
+
290
+
291
+ def test_cycle
292
+
293
+ assert_template_result('one','{%cycle "one", "two"%}')
294
+ assert_template_result('one two','{%cycle "one", "two"%} {%cycle "one", "two"%}')
295
+
296
+ assert_template_result('one two one','{%cycle "one", "two"%} {%cycle "one", "two"%} {%cycle "one", "two"%}')
297
+ end
298
+
299
+ def test_multiple_cycles
300
+ assert_template_result('1 2 1 1 2 3 1','{%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%}')
301
+ end
302
+
303
+ def test_multiple_named_cycles
304
+ assert_template_result('one one two two one one','{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}')
305
+ end
306
+
307
+ def test_multiple_named_cycles_with_names_from_context
308
+ assigns = {"var1" => 1, "var2" => 2 }
309
+ assert_template_result('one one two two one one','{%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %}', assigns)
310
+ end
311
+
312
+ def test_size_of_array
313
+ assigns = {"array" => [1,2,3,4]}
314
+ assert_template_result('array has 4 elements', "array has {{ array.size }} elements", assigns)
315
+ end
316
+
317
+ def test_size_of_hash
318
+ assigns = {"hash" => {:a => 1, :b => 2, :c=> 3, :d => 4}}
319
+ assert_template_result('hash has 4 elements', "hash has {{ hash.size }} elements", assigns)
320
+ end
321
+
322
+ def test_illegal_symbols
323
+ assert_template_result('', '{% if true == empty %}?{% endif %}', {})
324
+ assert_template_result('', '{% if true == null %}?{% endif %}', {})
325
+ assert_template_result('', '{% if empty == true %}?{% endif %}', {})
326
+ assert_template_result('', '{% if null == true %}?{% endif %}', {})
327
+ end
328
+
329
+ def test_ifchanged
330
+ assigns = {'array' => [ 1, 1, 2, 2, 3, 3] }
331
+ assert_template_result('123','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
332
+
333
+ assigns = {'array' => [ 1, 1, 1, 1] }
334
+ assert_template_result('1','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
335
+ end
336
+ end