liquid 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +1 -1
- data/README.md +6 -6
- data/lib/liquid.rb +10 -9
- data/lib/liquid/block.rb +4 -4
- data/lib/liquid/context.rb +2 -2
- data/lib/liquid/drop.rb +4 -4
- data/lib/liquid/htmltags.rb +6 -7
- data/lib/liquid/standardfilters.rb +9 -1
- data/lib/liquid/tags/assign.rb +3 -3
- data/lib/liquid/tags/case.rb +2 -2
- data/lib/liquid/tags/cycle.rb +4 -4
- data/lib/liquid/tags/for.rb +11 -27
- data/lib/liquid/tags/if.rb +2 -2
- data/lib/liquid/tags/include.rb +2 -2
- data/lib/liquid/utils.rb +31 -0
- data/lib/liquid/variable.rb +4 -4
- data/test/liquid/assign_test.rb +6 -0
- data/test/liquid/condition_test.rb +5 -0
- data/test/liquid/filter_test.rb +6 -0
- data/test/liquid/standard_filter_test.rb +4 -0
- data/test/liquid/tags/for_tag_test.rb +202 -0
- data/test/liquid/tags/html_tag_test.rb +34 -0
- data/test/liquid/tags/standard_tag_test.rb +0 -166
- metadata +22 -39
data/History.md
CHANGED
data/README.md
CHANGED
@@ -6,15 +6,15 @@ Liquid is a template engine which was written with very specific requirements:
|
|
6
6
|
|
7
7
|
* It has to have beautiful and simple markup. Template engines which don't produce good looking markup are no fun to use.
|
8
8
|
* It needs to be non evaling and secure. Liquid templates are made so that users can edit them. You don't want to run code on your server which your users wrote.
|
9
|
-
* It has to be stateless. Compile and render steps have to be
|
9
|
+
* It has to be stateless. Compile and render steps have to be separate so that the expensive parsing and compiling can be done once and later on you can just render it passing in a hash with local variables and objects.
|
10
10
|
|
11
11
|
## Why you should use Liquid
|
12
12
|
|
13
13
|
* You want to allow your users to edit the appearance of your application but don't want them to run **insecure code on your server**.
|
14
|
-
* You want to render templates directly from the database
|
15
|
-
* You like smarty (PHP) style template engines
|
16
|
-
* You need a template engine which does HTML just as well as emails
|
17
|
-
* You don't like the markup of your current templating engine
|
14
|
+
* You want to render templates directly from the database.
|
15
|
+
* You like smarty (PHP) style template engines.
|
16
|
+
* You need a template engine which does HTML just as well as emails.
|
17
|
+
* You don't like the markup of your current templating engine.
|
18
18
|
|
19
19
|
## What does it look like?
|
20
20
|
|
@@ -31,7 +31,7 @@ Liquid is a template engine which was written with very specific requirements:
|
|
31
31
|
</ul>
|
32
32
|
```
|
33
33
|
|
34
|
-
##
|
34
|
+
## How to use Liquid
|
35
35
|
|
36
36
|
Liquid supports a very simple API based around the Liquid::Template class.
|
37
37
|
For standard use you can just pass it the content of a file and call render with a parameters hash.
|
data/lib/liquid.rb
CHANGED
@@ -32,17 +32,17 @@ module Liquid
|
|
32
32
|
VariableEnd = /\}\}/
|
33
33
|
VariableIncompleteEnd = /\}\}?/
|
34
34
|
QuotedString = /"[^"]*"|'[^']*'/
|
35
|
-
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/
|
35
|
+
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
|
36
36
|
StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/
|
37
|
-
FirstFilterArgument = /#{FilterArgumentSeparator}(?:#{StrictQuotedFragment})/
|
38
|
-
OtherFilterArgument = /#{ArgumentSeparator}(?:#{StrictQuotedFragment})/
|
39
|
-
SpacelessFilter = /^(?:'[^']+'|"[^"]+"|[^'"])*#{FilterSeparator}(?:#{StrictQuotedFragment})(?:#{FirstFilterArgument}(?:#{OtherFilterArgument})*)?/
|
40
|
-
Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/
|
41
|
-
TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/
|
37
|
+
FirstFilterArgument = /#{FilterArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
38
|
+
OtherFilterArgument = /#{ArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
39
|
+
SpacelessFilter = /^(?:'[^']+'|"[^"]+"|[^'"])*#{FilterSeparator}(?:#{StrictQuotedFragment})(?:#{FirstFilterArgument}(?:#{OtherFilterArgument})*)?/o
|
40
|
+
Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o
|
41
|
+
TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
|
42
42
|
AnyStartingTag = /\{\{|\{\%/
|
43
|
-
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/
|
44
|
-
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/
|
45
|
-
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/
|
43
|
+
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/o
|
44
|
+
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/o
|
45
|
+
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
|
46
46
|
end
|
47
47
|
|
48
48
|
require 'liquid/drop'
|
@@ -60,6 +60,7 @@ require 'liquid/htmltags'
|
|
60
60
|
require 'liquid/standardfilters'
|
61
61
|
require 'liquid/condition'
|
62
62
|
require 'liquid/module_ex'
|
63
|
+
require 'liquid/utils'
|
63
64
|
|
64
65
|
# Load all the tags of the standard library
|
65
66
|
#
|
data/lib/liquid/block.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Liquid
|
2
2
|
|
3
3
|
class Block < Tag
|
4
|
-
IsTag = /^#{TagStart}/
|
5
|
-
IsVariable = /^#{VariableStart}/
|
6
|
-
FullToken = /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/
|
7
|
-
ContentOfVariable = /^#{VariableStart}(.*)#{VariableEnd}$/
|
4
|
+
IsTag = /^#{TagStart}/o
|
5
|
+
IsVariable = /^#{VariableStart}/o
|
6
|
+
FullToken = /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/o
|
7
|
+
ContentOfVariable = /^#{VariableStart}(.*)#{VariableEnd}$/o
|
8
8
|
|
9
9
|
def parse(tokens)
|
10
10
|
@nodelist ||= []
|
data/lib/liquid/context.rb
CHANGED
@@ -136,11 +136,11 @@ module Liquid
|
|
136
136
|
$1
|
137
137
|
when /^"(.*)"$/ # Double quoted strings
|
138
138
|
$1
|
139
|
-
when /^(
|
139
|
+
when /^(-?\d+)$/ # Integer and floats
|
140
140
|
$1.to_i
|
141
141
|
when /^\((\S+)\.\.(\S+)\)$/ # Ranges
|
142
142
|
(resolve($1).to_i..resolve($2).to_i)
|
143
|
-
when /^(
|
143
|
+
when /^(-?\d[\d\.]+)$/ # Floats
|
144
144
|
$1.to_f
|
145
145
|
else
|
146
146
|
variable(key)
|
data/lib/liquid/drop.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Liquid
|
2
2
|
|
3
|
-
# A drop in liquid is a class which allows you to
|
3
|
+
# A drop in liquid is a class which allows you to export DOM like things to liquid.
|
4
4
|
# Methods of drops are callable.
|
5
|
-
# The main use for liquid drops is
|
5
|
+
# The main use for liquid drops is to implement lazy loaded objects.
|
6
6
|
# If you would like to make data available to the web designers which you don't want loaded unless needed then
|
7
|
-
# a drop is a great way to do that
|
7
|
+
# a drop is a great way to do that.
|
8
8
|
#
|
9
9
|
# Example:
|
10
10
|
#
|
@@ -18,7 +18,7 @@ module Liquid
|
|
18
18
|
# tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.
|
19
19
|
#
|
20
20
|
# Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
|
21
|
-
# catch all
|
21
|
+
# catch all.
|
22
22
|
class Drop
|
23
23
|
attr_writer :context
|
24
24
|
|
data/lib/liquid/htmltags.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Liquid
|
2
2
|
class TableRow < Block
|
3
|
-
Syntax = /(\w+)\s+in\s+(#{
|
3
|
+
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
|
4
4
|
|
5
5
|
def initialize(tag_name, markup, tokens)
|
6
6
|
if markup =~ Syntax
|
@@ -20,11 +20,10 @@ module Liquid
|
|
20
20
|
def render(context)
|
21
21
|
collection = context[@collection_name] or return ''
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
23
|
+
from = @attributes['offset'] ? context[@attributes['offset']].to_i : 0
|
24
|
+
to = @attributes['limit'] ? from + context[@attributes['limit']].to_i : nil
|
25
|
+
|
26
|
+
collection = Utils.slice_collection_using_each(collection, from, to)
|
28
27
|
|
29
28
|
length = collection.length
|
30
29
|
|
@@ -46,7 +45,7 @@ module Liquid
|
|
46
45
|
'col0' => col,
|
47
46
|
'index0' => index,
|
48
47
|
'rindex' => length - index,
|
49
|
-
'rindex0' => length - index -1,
|
48
|
+
'rindex0' => length - index - 1,
|
50
49
|
'first' => (index == 0),
|
51
50
|
'last' => (index == length - 1),
|
52
51
|
'col_first' => (col == 0),
|
@@ -54,12 +54,16 @@ module Liquid
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# Split input string into an array of substrings separated by given pattern.
|
57
|
+
#
|
58
|
+
# Example:
|
59
|
+
# <div class="summary">{{ post | split '//' | first }}</div>
|
60
|
+
#
|
57
61
|
def split(input, pattern)
|
58
62
|
input.split(pattern)
|
59
63
|
end
|
60
64
|
|
61
65
|
def strip_html(input)
|
62
|
-
input.to_s.gsub(/<script.*?<\/script>/, '').gsub(/<.*?>/, '')
|
66
|
+
input.to_s.gsub(/<script.*?<\/script>/, '').gsub(/<!--.*?-->/, '').gsub(/<.*?>/, '')
|
63
67
|
end
|
64
68
|
|
65
69
|
# Remove all newlines from the string
|
@@ -218,6 +222,10 @@ module Liquid
|
|
218
222
|
to_number(input) / to_number(operand)
|
219
223
|
end
|
220
224
|
|
225
|
+
def modulo(input, operand)
|
226
|
+
to_number(input) % to_number(operand)
|
227
|
+
end
|
228
|
+
|
221
229
|
private
|
222
230
|
|
223
231
|
def to_number(obj)
|
data/lib/liquid/tags/assign.rb
CHANGED
@@ -9,12 +9,12 @@ module Liquid
|
|
9
9
|
# {{ foo }}
|
10
10
|
#
|
11
11
|
class Assign < Tag
|
12
|
-
Syntax = /(#{VariableSignature}+)\s*=\s*(
|
12
|
+
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/o
|
13
13
|
|
14
14
|
def initialize(tag_name, markup, tokens)
|
15
15
|
if markup =~ Syntax
|
16
16
|
@to = $1
|
17
|
-
@from = $2
|
17
|
+
@from = Variable.new($2)
|
18
18
|
else
|
19
19
|
raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]")
|
20
20
|
end
|
@@ -23,7 +23,7 @@ module Liquid
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def render(context)
|
26
|
-
context.scopes.last[@to] =
|
26
|
+
context.scopes.last[@to] = @from.render(context)
|
27
27
|
''
|
28
28
|
end
|
29
29
|
|
data/lib/liquid/tags/case.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Liquid
|
2
2
|
class Case < Block
|
3
|
-
Syntax = /(#{QuotedFragment})/
|
4
|
-
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/
|
3
|
+
Syntax = /(#{QuotedFragment})/o
|
4
|
+
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/o
|
5
5
|
|
6
6
|
def initialize(tag_name, markup, tokens)
|
7
7
|
@blocks = []
|
data/lib/liquid/tags/cycle.rb
CHANGED
@@ -13,8 +13,8 @@ module Liquid
|
|
13
13
|
# <div class="green"> Item five</div>
|
14
14
|
#
|
15
15
|
class Cycle < Tag
|
16
|
-
SimpleSyntax = /^#{QuotedFragment}+/
|
17
|
-
NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/
|
16
|
+
SimpleSyntax = /^#{QuotedFragment}+/o
|
17
|
+
NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/o
|
18
18
|
|
19
19
|
def initialize(tag_name, markup, tokens)
|
20
20
|
case markup
|
@@ -48,7 +48,7 @@ module Liquid
|
|
48
48
|
|
49
49
|
def variables_from_string(markup)
|
50
50
|
markup.split(',').collect do |var|
|
51
|
-
var =~ /\s*(#{QuotedFragment})\s*/
|
51
|
+
var =~ /\s*(#{QuotedFragment})\s*/o
|
52
52
|
$1 ? $1 : nil
|
53
53
|
end.compact
|
54
54
|
end
|
@@ -56,4 +56,4 @@ module Liquid
|
|
56
56
|
end
|
57
57
|
|
58
58
|
Template.register_tag('cycle', Cycle)
|
59
|
-
end
|
59
|
+
end
|
data/lib/liquid/tags/for.rb
CHANGED
@@ -44,7 +44,7 @@ module Liquid
|
|
44
44
|
# forloop.last:: Returns true if the item is the last item.
|
45
45
|
#
|
46
46
|
class For < Block
|
47
|
-
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/
|
47
|
+
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
|
48
48
|
|
49
49
|
def initialize(tag_name, markup, tokens)
|
50
50
|
if markup =~ Syntax
|
@@ -75,7 +75,8 @@ module Liquid
|
|
75
75
|
collection = context[@collection_name]
|
76
76
|
collection = collection.to_a if collection.is_a?(Range)
|
77
77
|
|
78
|
-
|
78
|
+
# Maintains Ruby 1.8.7 String#each behaviour on 1.9
|
79
|
+
return render_else(context) unless iterable?(collection)
|
79
80
|
|
80
81
|
from = if @attributes['offset'] == 'continue'
|
81
82
|
context.registers[:for][@name].to_i
|
@@ -85,10 +86,10 @@ module Liquid
|
|
85
86
|
|
86
87
|
limit = context[@attributes['limit']]
|
87
88
|
to = limit ? limit.to_i + from : nil
|
88
|
-
|
89
|
-
|
90
|
-
segment = slice_collection_using_each(collection, from, to)
|
91
|
-
|
89
|
+
|
90
|
+
|
91
|
+
segment = Utils.slice_collection_using_each(collection, from, to)
|
92
|
+
|
92
93
|
return render_else(context) if segment.empty?
|
93
94
|
|
94
95
|
segment.reverse! if @reversed
|
@@ -109,7 +110,7 @@ module Liquid
|
|
109
110
|
'index' => index + 1,
|
110
111
|
'index0' => index,
|
111
112
|
'rindex' => length - index,
|
112
|
-
'rindex0' => length - index -1,
|
113
|
+
'rindex0' => length - index - 1,
|
113
114
|
'first' => (index == 0),
|
114
115
|
'last' => (index == length - 1) }
|
115
116
|
|
@@ -118,26 +119,6 @@ module Liquid
|
|
118
119
|
end
|
119
120
|
result
|
120
121
|
end
|
121
|
-
|
122
|
-
def slice_collection_using_each(collection, from, to)
|
123
|
-
segments = []
|
124
|
-
index = 0
|
125
|
-
yielded = 0
|
126
|
-
collection.each do |item|
|
127
|
-
|
128
|
-
if to && to <= index
|
129
|
-
break
|
130
|
-
end
|
131
|
-
|
132
|
-
if from <= index
|
133
|
-
segments << item
|
134
|
-
end
|
135
|
-
|
136
|
-
index += 1
|
137
|
-
end
|
138
|
-
|
139
|
-
segments
|
140
|
-
end
|
141
122
|
|
142
123
|
private
|
143
124
|
|
@@ -145,6 +126,9 @@ module Liquid
|
|
145
126
|
return @else_block ? [render_all(@else_block, context)] : ''
|
146
127
|
end
|
147
128
|
|
129
|
+
def iterable?(collection)
|
130
|
+
collection.respond_to?(:each) || Utils.non_blank_string?(collection)
|
131
|
+
end
|
148
132
|
end
|
149
133
|
|
150
134
|
Template.register_tag('for', For)
|
data/lib/liquid/tags/if.rb
CHANGED
@@ -13,8 +13,8 @@ module Liquid
|
|
13
13
|
#
|
14
14
|
class If < Block
|
15
15
|
SyntaxHelp = "Syntax Error in tag 'if' - Valid syntax: if [expression]"
|
16
|
-
Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/
|
17
|
-
ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/
|
16
|
+
Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
|
17
|
+
ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
|
18
18
|
|
19
19
|
def initialize(tag_name, markup, tokens)
|
20
20
|
@blocks = []
|
data/lib/liquid/tags/include.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Liquid
|
2
2
|
class Include < Tag
|
3
|
-
Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/
|
3
|
+
Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o
|
4
4
|
|
5
5
|
def initialize(tag_name, markup, tokens)
|
6
6
|
if markup =~ Syntax
|
@@ -62,4 +62,4 @@ module Liquid
|
|
62
62
|
end
|
63
63
|
|
64
64
|
Template.register_tag('include', Include)
|
65
|
-
end
|
65
|
+
end
|
data/lib/liquid/utils.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Liquid
|
2
|
+
module Utils
|
3
|
+
def self.slice_collection_using_each(collection, from, to)
|
4
|
+
segments = []
|
5
|
+
index = 0
|
6
|
+
yielded = 0
|
7
|
+
|
8
|
+
# Maintains Ruby 1.8.7 String#each behaviour on 1.9
|
9
|
+
return [collection] if non_blank_string?(collection)
|
10
|
+
|
11
|
+
collection.each do |item|
|
12
|
+
|
13
|
+
if to && to <= index
|
14
|
+
break
|
15
|
+
end
|
16
|
+
|
17
|
+
if from <= index
|
18
|
+
segments << item
|
19
|
+
end
|
20
|
+
|
21
|
+
index += 1
|
22
|
+
end
|
23
|
+
|
24
|
+
segments
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.non_blank_string?(collection)
|
28
|
+
collection.is_a?(String) && collection != ''
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/liquid/variable.rb
CHANGED
@@ -11,21 +11,21 @@ module Liquid
|
|
11
11
|
# {{ user | link }}
|
12
12
|
#
|
13
13
|
class Variable
|
14
|
-
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?!(?:#{FilterSeparator}))(?:#{QuotedFragment}|\S+)\s*)+)/
|
14
|
+
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?!(?:#{FilterSeparator}))(?:#{QuotedFragment}|\S+)\s*)+)/o
|
15
15
|
attr_accessor :filters, :name
|
16
16
|
|
17
17
|
def initialize(markup)
|
18
18
|
@markup = markup
|
19
19
|
@name = nil
|
20
20
|
@filters = []
|
21
|
-
if match = markup.match(/\s*(#{QuotedFragment})(.*)/)
|
21
|
+
if match = markup.match(/\s*(#{QuotedFragment})(.*)/o)
|
22
22
|
@name = match[1]
|
23
|
-
if match[2].match(/#{FilterSeparator}\s*(.*)/)
|
23
|
+
if match[2].match(/#{FilterSeparator}\s*(.*)/o)
|
24
24
|
filters = Regexp.last_match(1).scan(FilterParser)
|
25
25
|
filters.each do |f|
|
26
26
|
if matches = f.match(/\s*(\w+)/)
|
27
27
|
filtername = matches[1]
|
28
|
-
filterargs = f.scan(/(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*(#{QuotedFragment})/).flatten
|
28
|
+
filterargs = f.scan(/(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*(#{QuotedFragment})/o).flatten
|
29
29
|
@filters << [filtername.to_sym, filterargs]
|
30
30
|
end
|
31
31
|
end
|
data/test/liquid/assign_test.rb
CHANGED
@@ -12,4 +12,10 @@ class AssignTest < Test::Unit::TestCase
|
|
12
12
|
'{% assign foo = values %}.{{ foo[1] }}.',
|
13
13
|
'values' => %w{foo bar baz})
|
14
14
|
end
|
15
|
+
|
16
|
+
def test_assign_with_filter
|
17
|
+
assert_template_result('.bar.',
|
18
|
+
'{% assign foo = values | split: "," %}.{{ foo[1] }}.',
|
19
|
+
'values' => "foo,bar,baz")
|
20
|
+
end
|
15
21
|
end # AssignTest
|
@@ -18,6 +18,11 @@ class ConditionTest < Test::Unit::TestCase
|
|
18
18
|
assert_evalutes_true '2', '>=', '1'
|
19
19
|
assert_evalutes_true '1', '<=', '2'
|
20
20
|
assert_evalutes_true '1', '<=', '1'
|
21
|
+
# negative numbers
|
22
|
+
assert_evalutes_true '1', '>', '-1'
|
23
|
+
assert_evalutes_true '-1', '<', '1'
|
24
|
+
assert_evalutes_true '1.0', '>', '-1.0'
|
25
|
+
assert_evalutes_true '-1.0', '<', '1.0'
|
21
26
|
end
|
22
27
|
|
23
28
|
def test_default_operators_evalute_false
|
data/test/liquid/filter_test.rb
CHANGED
@@ -75,6 +75,12 @@ class FiltersTest < Test::Unit::TestCase
|
|
75
75
|
assert_equal "bla blub", Variable.new("var | strip_html").render(@context)
|
76
76
|
end
|
77
77
|
|
78
|
+
def test_strip_html_ignore_comments_with_html
|
79
|
+
@context['var'] = "<!-- split and some <ul> tag --><b>bla blub</a>"
|
80
|
+
|
81
|
+
assert_equal "bla blub", Variable.new("var | strip_html").render(@context)
|
82
|
+
end
|
83
|
+
|
78
84
|
def test_capitalize
|
79
85
|
@context['var'] = "blub"
|
80
86
|
|
@@ -173,6 +173,10 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
173
173
|
assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
|
174
174
|
end
|
175
175
|
|
176
|
+
def test_modulo
|
177
|
+
assert_template_result "1", "{{ 3 | modulo:2 }}"
|
178
|
+
end
|
179
|
+
|
176
180
|
def test_append
|
177
181
|
assigns = {'a' => 'bc', 'b' => 'd' }
|
178
182
|
assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
|
@@ -0,0 +1,202 @@
|
|
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
|
+
|
172
|
+
def test_for_tag_string
|
173
|
+
# ruby 1.8.7 "String".each => Enumerator with single "String" element.
|
174
|
+
# ruby 1.9.3 no longer supports .each on String though we mimic
|
175
|
+
# the functionality for backwards compatibility
|
176
|
+
|
177
|
+
assert_template_result('test string',
|
178
|
+
'{%for val in string%}{{val}}{%endfor%}',
|
179
|
+
'string' => "test string")
|
180
|
+
|
181
|
+
assert_template_result('test string',
|
182
|
+
'{%for val in string limit:1%}{{val}}{%endfor%}',
|
183
|
+
'string' => "test string")
|
184
|
+
|
185
|
+
assert_template_result('val-string-1-1-0-1-0-true-true-test string',
|
186
|
+
'{%for val in string%}' +
|
187
|
+
'{{forloop.name}}-' +
|
188
|
+
'{{forloop.index}}-' +
|
189
|
+
'{{forloop.length}}-' +
|
190
|
+
'{{forloop.index0}}-' +
|
191
|
+
'{{forloop.rindex}}-' +
|
192
|
+
'{{forloop.rindex0}}-' +
|
193
|
+
'{{forloop.first}}-' +
|
194
|
+
'{{forloop.last}}-' +
|
195
|
+
'{{val}}{%endfor%}',
|
196
|
+
'string' => "test string")
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_blank_string_not_iterable
|
200
|
+
assert_template_result('', "{% for char in characters %}I WILL NOT BE OUTPUT{% endfor %}", 'characters' => '')
|
201
|
+
end
|
202
|
+
end
|
@@ -3,6 +3,18 @@ require 'test_helper'
|
|
3
3
|
class HtmlTagTest < Test::Unit::TestCase
|
4
4
|
include Liquid
|
5
5
|
|
6
|
+
class ArrayDrop < Liquid::Drop
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(array)
|
10
|
+
@array = array
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@array.each(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
6
18
|
def test_html_table
|
7
19
|
|
8
20
|
assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
|
@@ -26,4 +38,26 @@ class HtmlTagTest < Test::Unit::TestCase
|
|
26
38
|
'{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
|
27
39
|
'numbers' => [1,2,3,4,5,6])
|
28
40
|
end
|
41
|
+
|
42
|
+
def test_quoted_fragment
|
43
|
+
assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
|
44
|
+
"{% tablerow n in collections.frontpage cols:3%} {{n}} {% endtablerow %}",
|
45
|
+
'collections' => {'frontpage' => [1,2,3,4,5,6]})
|
46
|
+
assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
|
47
|
+
"{% tablerow n in collections['frontpage'] cols:3%} {{n}} {% endtablerow %}",
|
48
|
+
'collections' => {'frontpage' => [1,2,3,4,5,6]})
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_enumerable_drop
|
53
|
+
assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
|
54
|
+
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
55
|
+
'numbers' => ArrayDrop.new([1,2,3,4,5,6]))
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_offset_and_limit
|
59
|
+
assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
|
60
|
+
'{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
|
61
|
+
'numbers' => [0,1,2,3,4,5,6,7])
|
62
|
+
end
|
29
63
|
end # HtmlTagTest
|
@@ -47,166 +47,6 @@ class StandardTagTest < Test::Unit::TestCase
|
|
47
47
|
{%endcomment%}bar')
|
48
48
|
end
|
49
49
|
|
50
|
-
def test_for
|
51
|
-
assert_template_result(' yo yo yo yo ','{%for item in array%} yo {%endfor%}','array' => [1,2,3,4])
|
52
|
-
assert_template_result('yoyo','{%for item in array%}yo{%endfor%}','array' => [1,2])
|
53
|
-
assert_template_result(' yo ','{%for item in array%} yo {%endfor%}','array' => [1])
|
54
|
-
assert_template_result('','{%for item in array%}{%endfor%}','array' => [1,2])
|
55
|
-
expected = <<HERE
|
56
|
-
|
57
|
-
yo
|
58
|
-
|
59
|
-
yo
|
60
|
-
|
61
|
-
yo
|
62
|
-
|
63
|
-
HERE
|
64
|
-
template = <<HERE
|
65
|
-
{%for item in array%}
|
66
|
-
yo
|
67
|
-
{%endfor%}
|
68
|
-
HERE
|
69
|
-
assert_template_result(expected,template,'array' => [1,2,3])
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_for_with_range
|
73
|
-
assert_template_result(' 1 2 3 ','{%for item in (1..3) %} {{item}} {%endfor%}')
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_for_with_variable
|
77
|
-
assert_template_result(' 1 2 3 ','{%for item in array%} {{item}} {%endfor%}','array' => [1,2,3])
|
78
|
-
assert_template_result('123','{%for item in array%}{{item}}{%endfor%}','array' => [1,2,3])
|
79
|
-
assert_template_result('123','{% for item in array %}{{item}}{% endfor %}','array' => [1,2,3])
|
80
|
-
assert_template_result('abcd','{%for item in array%}{{item}}{%endfor%}','array' => ['a','b','c','d'])
|
81
|
-
assert_template_result('a b c','{%for item in array%}{{item}}{%endfor%}','array' => ['a',' ','b',' ','c'])
|
82
|
-
assert_template_result('abc','{%for item in array%}{{item}}{%endfor%}','array' => ['a','','b','','c'])
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_for_helpers
|
86
|
-
assigns = {'array' => [1,2,3] }
|
87
|
-
assert_template_result(' 1/3 2/3 3/3 ',
|
88
|
-
'{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
|
89
|
-
assigns)
|
90
|
-
assert_template_result(' 1 2 3 ', '{%for item in array%} {{forloop.index}} {%endfor%}', assigns)
|
91
|
-
assert_template_result(' 0 1 2 ', '{%for item in array%} {{forloop.index0}} {%endfor%}', assigns)
|
92
|
-
assert_template_result(' 2 1 0 ', '{%for item in array%} {{forloop.rindex0}} {%endfor%}', assigns)
|
93
|
-
assert_template_result(' 3 2 1 ', '{%for item in array%} {{forloop.rindex}} {%endfor%}', assigns)
|
94
|
-
assert_template_result(' true false false ', '{%for item in array%} {{forloop.first}} {%endfor%}', assigns)
|
95
|
-
assert_template_result(' false false true ', '{%for item in array%} {{forloop.last}} {%endfor%}', assigns)
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_for_and_if
|
99
|
-
assigns = {'array' => [1,2,3] }
|
100
|
-
assert_template_result('+--',
|
101
|
-
'{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
|
102
|
-
assigns)
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_for_else
|
106
|
-
assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[1,2,3])
|
107
|
-
assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[])
|
108
|
-
assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>nil)
|
109
|
-
end
|
110
|
-
|
111
|
-
def test_limiting
|
112
|
-
assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
|
113
|
-
assert_template_result('12', '{%for i in array limit:2 %}{{ i }}{%endfor%}', assigns)
|
114
|
-
assert_template_result('1234', '{%for i in array limit:4 %}{{ i }}{%endfor%}', assigns)
|
115
|
-
assert_template_result('3456', '{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}', assigns)
|
116
|
-
assert_template_result('3456', '{%for i in array limit: 4 offset: 2 %}{{ i }}{%endfor%}', assigns)
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_dynamic_variable_limiting
|
120
|
-
assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
|
121
|
-
assigns['limit'] = 2
|
122
|
-
assigns['offset'] = 2
|
123
|
-
|
124
|
-
assert_template_result('34', '{%for i in array limit: limit offset: offset %}{{ i }}{%endfor%}', assigns)
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_nested_for
|
128
|
-
assigns = {'array' => [[1,2],[3,4],[5,6]] }
|
129
|
-
assert_template_result('123456', '{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}', assigns)
|
130
|
-
end
|
131
|
-
|
132
|
-
def test_offset_only
|
133
|
-
assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
|
134
|
-
assert_template_result('890', '{%for i in array offset:7 %}{{ i }}{%endfor%}', assigns)
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_pause_resume
|
138
|
-
assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
|
139
|
-
markup = <<-MKUP
|
140
|
-
{%for i in array.items limit: 3 %}{{i}}{%endfor%}
|
141
|
-
next
|
142
|
-
{%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
|
143
|
-
next
|
144
|
-
{%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
|
145
|
-
MKUP
|
146
|
-
expected = <<-XPCTD
|
147
|
-
123
|
148
|
-
next
|
149
|
-
456
|
150
|
-
next
|
151
|
-
789
|
152
|
-
XPCTD
|
153
|
-
assert_template_result(expected,markup,assigns)
|
154
|
-
end
|
155
|
-
|
156
|
-
def test_pause_resume_limit
|
157
|
-
assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
|
158
|
-
markup = <<-MKUP
|
159
|
-
{%for i in array.items limit:3 %}{{i}}{%endfor%}
|
160
|
-
next
|
161
|
-
{%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
|
162
|
-
next
|
163
|
-
{%for i in array.items offset:continue limit:1 %}{{i}}{%endfor%}
|
164
|
-
MKUP
|
165
|
-
expected = <<-XPCTD
|
166
|
-
123
|
167
|
-
next
|
168
|
-
456
|
169
|
-
next
|
170
|
-
7
|
171
|
-
XPCTD
|
172
|
-
assert_template_result(expected,markup,assigns)
|
173
|
-
end
|
174
|
-
|
175
|
-
def test_pause_resume_BIG_limit
|
176
|
-
assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
|
177
|
-
markup = <<-MKUP
|
178
|
-
{%for i in array.items limit:3 %}{{i}}{%endfor%}
|
179
|
-
next
|
180
|
-
{%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
|
181
|
-
next
|
182
|
-
{%for i in array.items offset:continue limit:1000 %}{{i}}{%endfor%}
|
183
|
-
MKUP
|
184
|
-
expected = <<-XPCTD
|
185
|
-
123
|
186
|
-
next
|
187
|
-
456
|
188
|
-
next
|
189
|
-
7890
|
190
|
-
XPCTD
|
191
|
-
assert_template_result(expected,markup,assigns)
|
192
|
-
end
|
193
|
-
|
194
|
-
|
195
|
-
def test_pause_resume_BIG_offset
|
196
|
-
assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
|
197
|
-
markup = %q({%for i in array.items limit:3 %}{{i}}{%endfor%}
|
198
|
-
next
|
199
|
-
{%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
|
200
|
-
next
|
201
|
-
{%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%})
|
202
|
-
expected = %q(123
|
203
|
-
next
|
204
|
-
456
|
205
|
-
next
|
206
|
-
)
|
207
|
-
assert_template_result(expected,markup,assigns)
|
208
|
-
end
|
209
|
-
|
210
50
|
def test_assign
|
211
51
|
assigns = {'var' => 'content' }
|
212
52
|
assert_template_result('var2: var2:content', 'var2:{{var2}} {%assign var2 = var%} var2:{{var2}}', assigns)
|
@@ -445,12 +285,6 @@ HERE
|
|
445
285
|
assert_template_result('', '{% if null == true %}?{% endif %}', {})
|
446
286
|
end
|
447
287
|
|
448
|
-
def test_for_reversed
|
449
|
-
assigns = {'array' => [ 1, 2, 3] }
|
450
|
-
assert_template_result('321','{%for item in array reversed %}{{item}}{%endfor%}',assigns)
|
451
|
-
end
|
452
|
-
|
453
|
-
|
454
288
|
def test_ifchanged
|
455
289
|
assigns = {'array' => [ 1, 1, 2, 2, 3, 3] }
|
456
290
|
assert_template_result('123','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
|
metadata
CHANGED
@@ -1,34 +1,25 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: liquid
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.4.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 2
|
8
|
-
- 3
|
9
|
-
- 0
|
10
|
-
version: 2.3.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Tobias Luetke
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-10-16 00:00:00 Z
|
12
|
+
date: 2012-08-03 00:00:00.000000000 Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
14
|
description:
|
22
|
-
email:
|
15
|
+
email:
|
23
16
|
- tobi@leetsoft.com
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
|
-
extra_rdoc_files:
|
19
|
+
extra_rdoc_files:
|
29
20
|
- History.md
|
30
21
|
- README.md
|
31
|
-
files:
|
22
|
+
files:
|
32
23
|
- lib/extras/liquid_view.rb
|
33
24
|
- lib/liquid/block.rb
|
34
25
|
- lib/liquid/condition.rb
|
@@ -57,6 +48,7 @@ files:
|
|
57
48
|
- lib/liquid/tags/raw.rb
|
58
49
|
- lib/liquid/tags/unless.rb
|
59
50
|
- lib/liquid/template.rb
|
51
|
+
- lib/liquid/utils.rb
|
60
52
|
- lib/liquid/variable.rb
|
61
53
|
- lib/liquid.rb
|
62
54
|
- MIT-LICENSE
|
@@ -77,6 +69,7 @@ files:
|
|
77
69
|
- test/liquid/security_test.rb
|
78
70
|
- test/liquid/standard_filter_test.rb
|
79
71
|
- test/liquid/strainer_test.rb
|
72
|
+
- test/liquid/tags/for_tag_test.rb
|
80
73
|
- test/liquid/tags/html_tag_test.rb
|
81
74
|
- test/liquid/tags/if_else_tag_test.rb
|
82
75
|
- test/liquid/tags/include_tag_test.rb
|
@@ -91,40 +84,29 @@ files:
|
|
91
84
|
- History.md
|
92
85
|
homepage: http://www.liquidmarkup.org
|
93
86
|
licenses: []
|
94
|
-
|
95
87
|
post_install_message:
|
96
88
|
rdoc_options: []
|
97
|
-
|
98
|
-
require_paths:
|
89
|
+
require_paths:
|
99
90
|
- lib
|
100
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
92
|
none: false
|
102
|
-
requirements:
|
103
|
-
- -
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
|
106
|
-
|
107
|
-
- 0
|
108
|
-
version: "0"
|
109
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
98
|
none: false
|
111
|
-
requirements:
|
112
|
-
- -
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
hash: 21
|
115
|
-
segments:
|
116
|
-
- 1
|
117
|
-
- 3
|
118
|
-
- 7
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
119
102
|
version: 1.3.7
|
120
103
|
requirements: []
|
121
|
-
|
122
104
|
rubyforge_project:
|
123
105
|
rubygems_version: 1.8.11
|
124
106
|
signing_key:
|
125
107
|
specification_version: 3
|
126
108
|
summary: A secure, non-evaling end user template engine with aesthetic markup.
|
127
|
-
test_files:
|
109
|
+
test_files:
|
128
110
|
- test/liquid/assign_test.rb
|
129
111
|
- test/liquid/block_test.rb
|
130
112
|
- test/liquid/capture_test.rb
|
@@ -141,6 +123,7 @@ test_files:
|
|
141
123
|
- test/liquid/security_test.rb
|
142
124
|
- test/liquid/standard_filter_test.rb
|
143
125
|
- test/liquid/strainer_test.rb
|
126
|
+
- test/liquid/tags/for_tag_test.rb
|
144
127
|
- test/liquid/tags/html_tag_test.rb
|
145
128
|
- test/liquid/tags/if_else_tag_test.rb
|
146
129
|
- test/liquid/tags/include_tag_test.rb
|