spinto-liquid 2.3.0.1

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 (62) hide show
  1. data/History.md +56 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +44 -0
  4. data/lib/extras/liquid_view.rb +51 -0
  5. data/lib/liquid/block.rb +101 -0
  6. data/lib/liquid/condition.rb +120 -0
  7. data/lib/liquid/context.rb +245 -0
  8. data/lib/liquid/document.rb +17 -0
  9. data/lib/liquid/drop.rb +49 -0
  10. data/lib/liquid/errors.rb +11 -0
  11. data/lib/liquid/extensions.rb +62 -0
  12. data/lib/liquid/file_system.rb +62 -0
  13. data/lib/liquid/htmltags.rb +75 -0
  14. data/lib/liquid/module_ex.rb +62 -0
  15. data/lib/liquid/standardfilters.rb +241 -0
  16. data/lib/liquid/strainer.rb +54 -0
  17. data/lib/liquid/tag.rb +26 -0
  18. data/lib/liquid/tags/assign.rb +33 -0
  19. data/lib/liquid/tags/capture.rb +35 -0
  20. data/lib/liquid/tags/case.rb +79 -0
  21. data/lib/liquid/tags/comment.rb +9 -0
  22. data/lib/liquid/tags/cycle.rb +59 -0
  23. data/lib/liquid/tags/decrement.rb +39 -0
  24. data/lib/liquid/tags/for.rb +190 -0
  25. data/lib/liquid/tags/if.rb +79 -0
  26. data/lib/liquid/tags/ifchanged.rb +20 -0
  27. data/lib/liquid/tags/include.rb +65 -0
  28. data/lib/liquid/tags/increment.rb +35 -0
  29. data/lib/liquid/tags/raw.rb +21 -0
  30. data/lib/liquid/tags/unless.rb +33 -0
  31. data/lib/liquid/template.rb +150 -0
  32. data/lib/liquid/variable.rb +50 -0
  33. data/lib/liquid.rb +66 -0
  34. data/test/liquid/assign_test.rb +21 -0
  35. data/test/liquid/block_test.rb +58 -0
  36. data/test/liquid/capture_test.rb +40 -0
  37. data/test/liquid/condition_test.rb +127 -0
  38. data/test/liquid/context_test.rb +478 -0
  39. data/test/liquid/drop_test.rb +162 -0
  40. data/test/liquid/error_handling_test.rb +81 -0
  41. data/test/liquid/file_system_test.rb +29 -0
  42. data/test/liquid/filter_test.rb +106 -0
  43. data/test/liquid/module_ex_test.rb +87 -0
  44. data/test/liquid/output_test.rb +116 -0
  45. data/test/liquid/parsing_quirks_test.rb +52 -0
  46. data/test/liquid/regexp_test.rb +44 -0
  47. data/test/liquid/security_test.rb +41 -0
  48. data/test/liquid/standard_filter_test.rb +195 -0
  49. data/test/liquid/strainer_test.rb +25 -0
  50. data/test/liquid/tags/for_tag_test.rb +215 -0
  51. data/test/liquid/tags/html_tag_test.rb +39 -0
  52. data/test/liquid/tags/if_else_tag_test.rb +160 -0
  53. data/test/liquid/tags/include_tag_test.rb +139 -0
  54. data/test/liquid/tags/increment_tag_test.rb +24 -0
  55. data/test/liquid/tags/raw_tag_test.rb +15 -0
  56. data/test/liquid/tags/standard_tag_test.rb +295 -0
  57. data/test/liquid/tags/statements_test.rb +134 -0
  58. data/test/liquid/tags/unless_else_tag_test.rb +26 -0
  59. data/test/liquid/template_test.rb +74 -0
  60. data/test/liquid/variable_test.rb +170 -0
  61. data/test/test_helper.rb +29 -0
  62. metadata +136 -0
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+
3
+ module FunnyFilter
4
+ def make_funny(input)
5
+ 'LOL'
6
+ end
7
+
8
+ def cite_funny(input)
9
+ "LOL: #{input}"
10
+ end
11
+
12
+ def add_smiley(input, smiley = ":-)")
13
+ "#{input} #{smiley}"
14
+ end
15
+
16
+ def add_tag(input, tag = "p", id = "foo")
17
+ %|<#{tag} id="#{id}">#{input}</#{tag}>|
18
+ end
19
+
20
+ def paragraph(input)
21
+ "<p>#{input}</p>"
22
+ end
23
+
24
+ def link_to(name, url)
25
+ %|<a href="#{url}">#{name}</a>|
26
+ end
27
+
28
+ end
29
+
30
+ class OutputTest < Test::Unit::TestCase
31
+ include Liquid
32
+
33
+ def setup
34
+ @assigns = {
35
+ 'best_cars' => 'bmw',
36
+ 'car' => {'bmw' => 'good', 'gm' => 'bad'}
37
+ }
38
+ end
39
+
40
+ def test_variable
41
+ text = %| {{best_cars}} |
42
+
43
+ expected = %| bmw |
44
+ assert_equal expected, Template.parse(text).render(@assigns)
45
+ end
46
+
47
+ def test_variable_traversing
48
+ text = %| {{car.bmw}} {{car.gm}} {{car.bmw}} |
49
+
50
+ expected = %| good bad good |
51
+ assert_equal expected, Template.parse(text).render(@assigns)
52
+ end
53
+
54
+ def test_variable_piping
55
+ text = %( {{ car.gm | make_funny }} )
56
+ expected = %| LOL |
57
+
58
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
59
+ end
60
+
61
+ def test_variable_piping_with_input
62
+ text = %( {{ car.gm | cite_funny }} )
63
+ expected = %| LOL: bad |
64
+
65
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
66
+ end
67
+
68
+ def test_variable_piping_with_args
69
+ text = %! {{ car.gm | add_smiley : ':-(' }} !
70
+ expected = %| bad :-( |
71
+
72
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
73
+ end
74
+
75
+ def test_variable_piping_with_no_args
76
+ text = %! {{ car.gm | add_smiley }} !
77
+ expected = %| bad :-) |
78
+
79
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
80
+ end
81
+
82
+ def test_multiple_variable_piping_with_args
83
+ text = %! {{ car.gm | add_smiley : ':-(' | add_smiley : ':-('}} !
84
+ expected = %| bad :-( :-( |
85
+
86
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
87
+ end
88
+
89
+ def test_variable_piping_with_args
90
+ text = %! {{ car.gm | add_tag : 'span', 'bar'}} !
91
+ expected = %| <span id="bar">bad</span> |
92
+
93
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
94
+ end
95
+
96
+ def test_variable_piping_with_variable_args
97
+ text = %! {{ car.gm | add_tag : 'span', car.bmw}} !
98
+ expected = %| <span id="good">bad</span> |
99
+
100
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
101
+ end
102
+
103
+ def test_multiple_pipings
104
+ text = %( {{ best_cars | cite_funny | paragraph }} )
105
+ expected = %| <p>LOL: bmw</p> |
106
+
107
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
108
+ end
109
+
110
+ def test_link_to
111
+ text = %( {{ 'Typo' | link_to: 'http://typo.leetsoft.com' }} )
112
+ expected = %| <a href="http://typo.leetsoft.com">Typo</a> |
113
+
114
+ assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
115
+ end
116
+ end # OutputTest
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,44 @@
1
+ require 'test_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
+ def test_words
15
+ assert_equal ['arg1', 'arg2'], 'arg1 arg2'.scan(QuotedFragment)
16
+ end
17
+
18
+ def test_tags
19
+ assert_equal ['<tr>', '</tr>'], '<tr> </tr>'.scan(QuotedFragment)
20
+ assert_equal ['<tr></tr>'], '<tr></tr>'.scan(QuotedFragment)
21
+ assert_equal ['<style', 'class="hello">', '</style>'], %|<style class="hello">' </style>|.scan(QuotedFragment)
22
+ end
23
+
24
+ def test_quoted_words
25
+ assert_equal ['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment)
26
+ end
27
+
28
+ def test_quoted_words
29
+ assert_equal ['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment)
30
+ end
31
+
32
+ def test_quoted_words_in_the_middle
33
+ assert_equal ['arg1', 'arg2', '"arg 3"', 'arg4'], 'arg1 arg2 "arg 3" arg4 '.scan(QuotedFragment)
34
+ end
35
+
36
+ def test_variable_parser
37
+ assert_equal ['var'], 'var'.scan(VariableParser)
38
+ assert_equal ['var', 'method'], 'var.method'.scan(VariableParser)
39
+ assert_equal ['var', '[method]'], 'var[method]'.scan(VariableParser)
40
+ assert_equal ['var', '[method]', '[0]'], 'var[method][0]'.scan(VariableParser)
41
+ assert_equal ['var', '["method"]', '[0]'], 'var["method"][0]'.scan(VariableParser)
42
+ assert_equal ['var', '[method]', '[0]', 'method'], 'var[method][0].method'.scan(VariableParser)
43
+ end
44
+ end # RegexpTest
@@ -0,0 +1,41 @@
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
+ end # SecurityTest
@@ -0,0 +1,195 @@
1
+ require 'test_helper'
2
+
3
+ class Filters
4
+ include Liquid::StandardFilters
5
+ end
6
+
7
+ class StandardFiltersTest < Test::Unit::TestCase
8
+ include Liquid
9
+
10
+ def setup
11
+ @filters = Filters.new
12
+ end
13
+
14
+ def test_size
15
+ assert_equal 3, @filters.size([1,2,3])
16
+ assert_equal 0, @filters.size([])
17
+ assert_equal 0, @filters.size(nil)
18
+ end
19
+
20
+ def test_downcase
21
+ assert_equal 'testing', @filters.downcase("Testing")
22
+ assert_equal '', @filters.downcase(nil)
23
+ end
24
+
25
+ def test_upcase
26
+ assert_equal 'TESTING', @filters.upcase("Testing")
27
+ assert_equal '', @filters.upcase(nil)
28
+ end
29
+
30
+ def test_upcase
31
+ assert_equal 'TESTING', @filters.upcase("Testing")
32
+ assert_equal '', @filters.upcase(nil)
33
+ end
34
+
35
+ def test_truncate
36
+ assert_equal '1234...', @filters.truncate('1234567890', 7)
37
+ assert_equal '1234567890', @filters.truncate('1234567890', 20)
38
+ assert_equal '...', @filters.truncate('1234567890', 0)
39
+ assert_equal '1234567890', @filters.truncate('1234567890')
40
+ end
41
+
42
+ def test_strip
43
+ assert_equal ['12','34'], @filters.split('12~34', '~')
44
+ assert_equal ['A? ',' ,Z'], @filters.split('A? ~ ~ ~ ,Z', '~ ~ ~')
45
+ assert_equal ['A?Z'], @filters.split('A?Z', '~')
46
+ # Regexp works although Liquid does not support.
47
+ assert_equal ['A','Z'], @filters.split('AxZ', /x/)
48
+ end
49
+
50
+ def test_escape
51
+ assert_equal '&lt;strong&gt;', @filters.escape('<strong>')
52
+ assert_equal '&lt;strong&gt;', @filters.h('<strong>')
53
+ end
54
+
55
+ def test_escape_once
56
+ assert_equal '&lt;strong&gt;', @filters.escape_once(@filters.escape('<strong>'))
57
+ end
58
+
59
+ def test_truncatewords
60
+ assert_equal 'one two three', @filters.truncatewords('one two three', 4)
61
+ assert_equal 'one two...', @filters.truncatewords('one two three', 2)
62
+ assert_equal 'one two three', @filters.truncatewords('one two three')
63
+ 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)
64
+ end
65
+
66
+ def test_strip_html
67
+ assert_equal 'test', @filters.strip_html("<div>test</div>")
68
+ assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
69
+ assert_equal '', @filters.strip_html("<script type='text/javascript'>document.write('some stuff');</script>")
70
+ assert_equal '', @filters.strip_html(nil)
71
+ end
72
+
73
+ def test_join
74
+ assert_equal '1 2 3 4', @filters.join([1,2,3,4])
75
+ assert_equal '1 - 2 - 3 - 4', @filters.join([1,2,3,4], ' - ')
76
+ end
77
+
78
+ def test_sort
79
+ assert_equal [1,2,3,4], @filters.sort([4,3,2,1])
80
+ assert_equal [{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], @filters.sort([{"a" => 4}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
81
+ end
82
+
83
+ def test_map
84
+ assert_equal [1,2,3,4], @filters.map([{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], 'a')
85
+ assert_template_result 'abc', "{{ ary | map:'foo' | map:'bar' }}",
86
+ 'ary' => [{'foo' => {'bar' => 'a'}}, {'foo' => {'bar' => 'b'}}, {'foo' => {'bar' => 'c'}}]
87
+ end
88
+
89
+ def test_date
90
+ assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
91
+ assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
92
+ assert_equal 'July', @filters.date(Time.parse("2006-07-05 10:00:00"), "%B")
93
+
94
+ assert_equal 'May', @filters.date("2006-05-05 10:00:00", "%B")
95
+ assert_equal 'June', @filters.date("2006-06-05 10:00:00", "%B")
96
+ assert_equal 'July', @filters.date("2006-07-05 10:00:00", "%B")
97
+
98
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
99
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
100
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
101
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", nil)
102
+
103
+ assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
104
+
105
+ assert_equal "07/16/2004", @filters.date("Fri Jul 16 01:00:00 2004", "%m/%d/%Y")
106
+
107
+ assert_equal nil, @filters.date(nil, "%B")
108
+
109
+ assert_equal "07/05/2006", @filters.date(1152098955, "%m/%d/%Y")
110
+ assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
111
+ end
112
+
113
+
114
+ def test_first_last
115
+ assert_equal 1, @filters.first([1,2,3])
116
+ assert_equal 3, @filters.last([1,2,3])
117
+ assert_equal nil, @filters.first([])
118
+ assert_equal nil, @filters.last([])
119
+ end
120
+
121
+ def test_replace
122
+ assert_equal 'b b b b', @filters.replace("a a a a", 'a', 'b')
123
+ assert_equal 'b a a a', @filters.replace_first("a a a a", 'a', 'b')
124
+ assert_template_result 'b a a a', "{{ 'a a a a' | replace_first: 'a', 'b' }}"
125
+ end
126
+
127
+ def test_remove
128
+ assert_equal ' ', @filters.remove("a a a a", 'a')
129
+ assert_equal 'a a a', @filters.remove_first("a a a a", 'a ')
130
+ assert_template_result 'a a a', "{{ 'a a a a' | remove_first: 'a ' }}"
131
+ end
132
+
133
+ def test_pipes_in_string_arguments
134
+ assert_template_result 'foobar', "{{ 'foo|bar' | remove: '|' }}"
135
+ end
136
+
137
+ def test_strip_newlines
138
+ assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
139
+ end
140
+
141
+ def test_newlines_to_br
142
+ assert_template_result "a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc"
143
+ end
144
+
145
+ def test_plus
146
+ assert_template_result "2", "{{ 1 | plus:1 }}"
147
+ assert_template_result "2.0", "{{ '1' | plus:'1.0' }}"
148
+ end
149
+
150
+ def test_minus
151
+ assert_template_result "4", "{{ input | minus:operand }}", 'input' => 5, 'operand' => 1
152
+ assert_template_result "2.3", "{{ '4.3' | minus:'2' }}"
153
+ end
154
+
155
+ def test_times
156
+ assert_template_result "12", "{{ 3 | times:4 }}"
157
+ assert_template_result "0", "{{ 'foo' | times:4 }}"
158
+
159
+ # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
160
+ assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
161
+
162
+ assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
163
+ end
164
+
165
+ def test_divided_by
166
+ assert_template_result "4", "{{ 12 | divided_by:3 }}"
167
+ assert_template_result "4", "{{ 14 | divided_by:3 }}"
168
+
169
+ # Ruby v1.9.2-rc1, or higher, backwards compatible Float test
170
+ assert_match(/4\.(6{13,14})7/, Template.parse("{{ 14 | divided_by:'3.0' }}").render)
171
+
172
+ assert_template_result "5", "{{ 15 | divided_by:3 }}"
173
+ assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
174
+ end
175
+
176
+ def test_modulo
177
+ assert_template_result "1", "{{ 3 | modulo:2 }}"
178
+ end
179
+
180
+ def test_append
181
+ assigns = {'a' => 'bc', 'b' => 'd' }
182
+ assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
183
+ assert_template_result('bcd',"{{ a | append: b}}",assigns)
184
+ end
185
+
186
+ def test_prepend
187
+ assigns = {'a' => 'bc', 'b' => 'a' }
188
+ assert_template_result('abc',"{{ a | prepend: 'a'}}",assigns)
189
+ assert_template_result('abc',"{{ a | prepend: b}}",assigns)
190
+ end
191
+
192
+ def test_cannot_access_private_methods
193
+ assert_template_result('a',"{{ 'a' | to_number }}")
194
+ end
195
+ end # StandardFiltersTest