liquid 2.0.0 → 2.1.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.
- data/CHANGELOG +10 -6
- data/Rakefile +27 -12
- data/lib/extras/liquid_view.rb +27 -16
- data/lib/liquid.rb +3 -3
- data/lib/liquid/block.rb +30 -26
- data/lib/liquid/condition.rb +31 -34
- data/lib/liquid/context.rb +47 -25
- data/lib/liquid/document.rb +7 -7
- data/lib/liquid/drop.rb +17 -16
- data/lib/liquid/htmltags.rb +27 -27
- data/lib/liquid/module_ex.rb +4 -4
- data/lib/liquid/standardfilters.rb +18 -5
- data/lib/liquid/strainer.rb +17 -18
- data/lib/liquid/tag.rb +8 -8
- data/lib/liquid/tags/assign.rb +1 -1
- data/lib/liquid/tags/capture.rb +9 -9
- data/lib/liquid/tags/case.rb +2 -2
- data/lib/liquid/tags/cycle.rb +3 -3
- data/lib/liquid/tags/for.rb +1 -1
- data/lib/liquid/tags/if.rb +3 -2
- data/lib/liquid/tags/include.rb +2 -1
- data/lib/liquid/template.rb +57 -54
- data/lib/liquid/variable.rb +7 -8
- metadata +25 -21
- data/init.rb +0 -8
- data/test/test_helper.rb +0 -20
data/lib/liquid/document.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module Liquid
|
2
|
-
class Document < Block
|
2
|
+
class Document < Block
|
3
3
|
# we don't need markup to open this block
|
4
4
|
def initialize(tokens)
|
5
5
|
parse(tokens)
|
6
|
-
end
|
7
|
-
|
8
|
-
# There isn't a real delimter
|
6
|
+
end
|
7
|
+
|
8
|
+
# There isn't a real delimter
|
9
9
|
def block_delimiter
|
10
10
|
[]
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# Document blocks don't need to be terminated since they are not actually opened
|
14
14
|
def assert_missing_delimitation!
|
15
|
-
end
|
15
|
+
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
data/lib/liquid/drop.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
2
|
+
|
3
3
|
# A drop in liquid is a class which allows you to to export DOM like things to liquid
|
4
|
-
# Methods of drops are callable.
|
5
|
-
# The main use for liquid drops is the implement lazy loaded objects.
|
6
|
-
# If you would like to make data available to the web designers which you don't want loaded unless needed then
|
4
|
+
# Methods of drops are callable.
|
5
|
+
# The main use for liquid drops is the implement lazy loaded objects.
|
6
|
+
# If you would like to make data available to the web designers which you don't want loaded unless needed then
|
7
7
|
# a drop is a great way to do that
|
8
8
|
#
|
9
9
|
# Example:
|
@@ -13,38 +13,39 @@ module Liquid
|
|
13
13
|
# Shop.current.products.find(:all, :order => 'sales', :limit => 10 )
|
14
14
|
# end
|
15
15
|
# end
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# tmpl = Liquid::Template.parse( ' {% for product in product.top_sales %} {{ product.name }} {%endfor%} ' )
|
18
|
-
# tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.
|
18
|
+
# tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.
|
19
19
|
#
|
20
|
-
# Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
|
20
|
+
# Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
|
21
21
|
# catch all
|
22
22
|
class Drop
|
23
23
|
attr_writer :context
|
24
24
|
|
25
|
-
# Catch all for the method
|
25
|
+
# Catch all for the method
|
26
26
|
def before_method(method)
|
27
27
|
nil
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# called by liquid to invoke a drop
|
31
|
-
def invoke_drop(method)
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
def invoke_drop(method)
|
32
|
+
# for backward compatibility with Ruby 1.8
|
33
|
+
methods = self.class.public_instance_methods.map { |m| m.to_s }
|
34
|
+
if methods.include?(method.to_s)
|
35
|
+
send(method.to_sym)
|
36
|
+
else
|
35
37
|
before_method(method)
|
36
38
|
end
|
37
39
|
end
|
38
|
-
|
40
|
+
|
39
41
|
def has_key?(name)
|
40
42
|
true
|
41
43
|
end
|
42
|
-
|
44
|
+
|
43
45
|
def to_liquid
|
44
46
|
self
|
45
47
|
end
|
46
48
|
|
47
49
|
alias :[] :invoke_drop
|
48
50
|
end
|
49
|
-
|
50
51
|
end
|
data/lib/liquid/htmltags.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Liquid
|
2
|
-
class TableRow < Block
|
3
|
-
Syntax = /(\w+)\s+in\s+(#{VariableSignature}+)/
|
4
|
-
|
2
|
+
class TableRow < Block
|
3
|
+
Syntax = /(\w+)\s+in\s+(#{VariableSignature}+)/
|
4
|
+
|
5
5
|
def initialize(tag_name, markup, tokens)
|
6
6
|
if markup =~ Syntax
|
7
7
|
@variable_name = $1
|
@@ -13,62 +13,62 @@ module Liquid
|
|
13
13
|
else
|
14
14
|
raise SyntaxError.new("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3")
|
15
15
|
end
|
16
|
-
|
17
|
-
super
|
16
|
+
|
17
|
+
super
|
18
18
|
end
|
19
|
-
|
20
|
-
def render(context)
|
19
|
+
|
20
|
+
def render(context)
|
21
21
|
collection = context[@collection_name] or return ''
|
22
|
-
|
22
|
+
|
23
23
|
if @attributes['limit'] or @attributes['offset']
|
24
24
|
limit = context[@attributes['limit']] || -1
|
25
25
|
offset = context[@attributes['offset']] || 0
|
26
26
|
collection = collection[offset.to_i..(limit.to_i + offset.to_i - 1)]
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
length = collection.length
|
30
|
-
|
30
|
+
|
31
31
|
cols = context[@attributes['cols']].to_i
|
32
32
|
|
33
33
|
row = 1
|
34
34
|
col = 0
|
35
35
|
|
36
36
|
result = ["<tr class=\"row1\">\n"]
|
37
|
-
context.stack do
|
37
|
+
context.stack do
|
38
38
|
|
39
39
|
collection.each_with_index do |item, index|
|
40
40
|
context[@variable_name] = item
|
41
41
|
context['tablerowloop'] = {
|
42
42
|
'length' => length,
|
43
|
-
'index' => index + 1,
|
44
|
-
'index0' => index,
|
45
|
-
'col' => col + 1,
|
46
|
-
'col0' => col,
|
47
|
-
'index0' => index,
|
43
|
+
'index' => index + 1,
|
44
|
+
'index0' => index,
|
45
|
+
'col' => col + 1,
|
46
|
+
'col0' => col,
|
47
|
+
'index0' => index,
|
48
48
|
'rindex' => length - index,
|
49
49
|
'rindex0' => length - index -1,
|
50
50
|
'first' => (index == 0),
|
51
51
|
'last' => (index == length - 1),
|
52
52
|
'col_first' => (col == 0),
|
53
53
|
'col_last' => (col == cols - 1)
|
54
|
-
}
|
55
|
-
|
56
|
-
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
57
|
col += 1
|
58
|
-
|
58
|
+
|
59
59
|
result << ["<td class=\"col#{col}\">"] + render_all(@nodelist, context) + ['</td>']
|
60
60
|
|
61
|
-
if col == cols and not (index == length - 1)
|
61
|
+
if col == cols and not (index == length - 1)
|
62
62
|
col = 0
|
63
63
|
row += 1
|
64
|
-
result << ["</tr>\n<tr class=\"row#{row}\">"]
|
64
|
+
result << ["</tr>\n<tr class=\"row#{row}\">"]
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
end
|
68
68
|
end
|
69
69
|
result + ["</tr>\n"]
|
70
|
-
end
|
70
|
+
end
|
71
71
|
end
|
72
|
-
|
73
|
-
Template.register_tag('tablerow', TableRow)
|
74
|
-
end
|
72
|
+
|
73
|
+
Template.register_tag('tablerow', TableRow)
|
74
|
+
end
|
data/lib/liquid/module_ex.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
# end
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
# if you want to extend the drop to other methods you can defines more methods
|
21
|
+
# if you want to extend the drop to other methods you can defines more methods
|
22
22
|
# in the class <YourClass>::LiquidDropClass
|
23
23
|
#
|
24
24
|
# class SomeClass::LiquidDropClass
|
@@ -37,11 +37,11 @@
|
|
37
37
|
# output:
|
38
38
|
# 'this comes from an allowed method and this from another allowed method'
|
39
39
|
#
|
40
|
-
# You can also chain associations, by adding the liquid_method call in the
|
40
|
+
# You can also chain associations, by adding the liquid_method call in the
|
41
41
|
# association models.
|
42
42
|
#
|
43
43
|
class Module
|
44
|
-
|
44
|
+
|
45
45
|
def liquid_methods(*allowed_methods)
|
46
46
|
drop_class = eval "class #{self.to_s}::LiquidDropClass < Liquid::Drop; self; end"
|
47
47
|
define_method :to_liquid do
|
@@ -58,5 +58,5 @@ class Module
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
end
|
@@ -48,7 +48,7 @@ module Liquid
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def strip_html(input)
|
51
|
-
input.to_s.gsub(/<.*?>/, '')
|
51
|
+
input.to_s.gsub(/<script.*?<\/script>/, '').gsub(/<.*?>/, '')
|
52
52
|
end
|
53
53
|
|
54
54
|
# Remove all newlines from the string
|
@@ -185,22 +185,35 @@ module Liquid
|
|
185
185
|
|
186
186
|
# addition
|
187
187
|
def plus(input, operand)
|
188
|
-
input + operand
|
188
|
+
to_number(input) + to_number(operand)
|
189
189
|
end
|
190
190
|
|
191
191
|
# subtraction
|
192
192
|
def minus(input, operand)
|
193
|
-
input - operand
|
193
|
+
to_number(input) - to_number(operand)
|
194
194
|
end
|
195
195
|
|
196
196
|
# multiplication
|
197
197
|
def times(input, operand)
|
198
|
-
input * operand
|
198
|
+
to_number(input) * to_number(operand)
|
199
199
|
end
|
200
200
|
|
201
201
|
# division
|
202
202
|
def divided_by(input, operand)
|
203
|
-
input / operand
|
203
|
+
to_number(input) / to_number(operand)
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def to_number(obj)
|
209
|
+
case obj
|
210
|
+
when Numeric
|
211
|
+
obj
|
212
|
+
when String
|
213
|
+
(obj.strip =~ /^\d+\.\d+$/) ? obj.to_f : obj.to_i
|
214
|
+
else
|
215
|
+
0
|
216
|
+
end
|
204
217
|
end
|
205
218
|
|
206
219
|
end
|
data/lib/liquid/strainer.rb
CHANGED
@@ -1,52 +1,51 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
3
|
module Liquid
|
4
|
-
|
5
|
-
|
4
|
+
|
6
5
|
parent_object = if defined? BlankObject
|
7
6
|
BlankObject
|
8
7
|
else
|
9
8
|
Object
|
10
9
|
end
|
11
10
|
|
12
|
-
# Strainer is the parent class for the filters system.
|
13
|
-
# New filters are mixed into the strainer class which is then instanciated for each liquid template render run.
|
11
|
+
# Strainer is the parent class for the filters system.
|
12
|
+
# New filters are mixed into the strainer class which is then instanciated for each liquid template render run.
|
14
13
|
#
|
15
|
-
# One of the strainer's responsibilities is to keep malicious method calls out
|
14
|
+
# One of the strainer's responsibilities is to keep malicious method calls out
|
16
15
|
class Strainer < parent_object #:nodoc:
|
17
|
-
INTERNAL_METHOD = /^__/
|
18
|
-
@@required_methods = Set.new([:
|
19
|
-
|
16
|
+
INTERNAL_METHOD = /^__/
|
17
|
+
@@required_methods = Set.new([:__id__, :__send__, :respond_to?, :extend, :methods, :class, :object_id])
|
18
|
+
|
20
19
|
@@filters = {}
|
21
|
-
|
20
|
+
|
22
21
|
def initialize(context)
|
23
22
|
@context = context
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
def self.global_filter(filter)
|
27
26
|
raise ArgumentError, "Passed filter is not a module" unless filter.is_a?(Module)
|
28
27
|
@@filters[filter.name] = filter
|
29
28
|
end
|
30
|
-
|
29
|
+
|
31
30
|
def self.create(context)
|
32
31
|
strainer = Strainer.new(context)
|
33
32
|
@@filters.each { |k,m| strainer.extend(m) }
|
34
33
|
strainer
|
35
34
|
end
|
36
|
-
|
35
|
+
|
37
36
|
def respond_to?(method, include_private = false)
|
38
37
|
method_name = method.to_s
|
39
38
|
return false if method_name =~ INTERNAL_METHOD
|
40
39
|
return false if @@required_methods.include?(method_name)
|
41
40
|
super
|
42
41
|
end
|
43
|
-
|
44
|
-
# remove all standard methods from the bucket so circumvent security
|
45
|
-
# problems
|
46
|
-
instance_methods.each do |m|
|
47
|
-
unless @@required_methods.include?(m.to_sym)
|
42
|
+
|
43
|
+
# remove all standard methods from the bucket so circumvent security
|
44
|
+
# problems
|
45
|
+
instance_methods.each do |m|
|
46
|
+
unless @@required_methods.include?(m.to_sym)
|
48
47
|
undef_method m
|
49
48
|
end
|
50
|
-
end
|
49
|
+
end
|
51
50
|
end
|
52
51
|
end
|
data/lib/liquid/tag.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
2
|
+
|
3
3
|
class Tag
|
4
4
|
attr_accessor :nodelist
|
5
|
-
|
5
|
+
|
6
6
|
def initialize(tag_name, markup, tokens)
|
7
7
|
@tag_name = tag_name
|
8
8
|
@markup = markup
|
9
9
|
parse(tokens)
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def parse(tokens)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def name
|
16
16
|
self.class.name.downcase
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def render(context)
|
20
20
|
''
|
21
|
-
end
|
21
|
+
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
|
25
25
|
end
|
26
|
-
|
26
|
+
|
data/lib/liquid/tags/assign.rb
CHANGED
data/lib/liquid/tags/capture.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
2
|
+
|
3
3
|
# Capture stores the result of a block into a variable without rendering it inplace.
|
4
4
|
#
|
5
5
|
# {% capture heading %}
|
@@ -8,28 +8,28 @@ module Liquid
|
|
8
8
|
# ...
|
9
9
|
# <h1>{{ monkeys }}</h1>
|
10
10
|
#
|
11
|
-
# Capture is useful for saving content for use later in your template, such as
|
11
|
+
# Capture is useful for saving content for use later in your template, such as
|
12
12
|
# in a sidebar or footer.
|
13
13
|
#
|
14
14
|
class Capture < Block
|
15
15
|
Syntax = /(\w+)/
|
16
16
|
|
17
|
-
def initialize(tag_name, markup, tokens)
|
17
|
+
def initialize(tag_name, markup, tokens)
|
18
18
|
if markup =~ Syntax
|
19
19
|
@to = $1
|
20
20
|
else
|
21
21
|
raise SyntaxError.new("Syntax Error in 'capture' - Valid syntax: capture [var]")
|
22
22
|
end
|
23
|
-
|
24
|
-
super
|
23
|
+
|
24
|
+
super
|
25
25
|
end
|
26
26
|
|
27
27
|
def render(context)
|
28
28
|
output = super
|
29
|
-
context[@to] = output.
|
29
|
+
context[@to] = output.join
|
30
30
|
''
|
31
31
|
end
|
32
|
-
end
|
33
|
-
|
32
|
+
end
|
33
|
+
|
34
34
|
Template.register_tag('capture', Capture)
|
35
|
-
end
|
35
|
+
end
|
data/lib/liquid/tags/case.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Liquid
|
2
2
|
class Case < Block
|
3
|
-
Syntax = /(#{
|
4
|
-
WhenSyntax = /(#{
|
3
|
+
Syntax = /(#{QuotedFragment})/
|
4
|
+
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/
|
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 = /^#{
|
17
|
-
NamedSyntax = /^(#{
|
16
|
+
SimpleSyntax = /^#{QuotedFragment}+/
|
17
|
+
NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/
|
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*(#{
|
51
|
+
var =~ /\s*(#{QuotedFragment})\s*/
|
52
52
|
$1 ? $1 : nil
|
53
53
|
end.compact
|
54
54
|
end
|