liquid 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/tags/for.rb
CHANGED
@@ -42,7 +42,7 @@ module Liquid
|
|
42
42
|
# forloop.last:: Returns true if the item is the last item.
|
43
43
|
#
|
44
44
|
class For < Block
|
45
|
-
Syntax = /(\w+)\s+in\s+(#{
|
45
|
+
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/
|
46
46
|
|
47
47
|
def initialize(tag_name, markup, tokens)
|
48
48
|
if markup =~ Syntax
|
data/lib/liquid/tags/if.rb
CHANGED
@@ -13,7 +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 = /(#{
|
16
|
+
Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/
|
17
|
+
ExpressionsAndOperators = /(?:and|or|(?:\s*(?!\b(?:and|or)\b)(?:#{QuotedFragment}|\S+)\s*)+)/
|
17
18
|
|
18
19
|
def initialize(tag_name, markup, tokens)
|
19
20
|
|
@@ -50,7 +51,7 @@ module Liquid
|
|
50
51
|
ElseCondition.new
|
51
52
|
else
|
52
53
|
|
53
|
-
expressions = markup.
|
54
|
+
expressions = markup.scan(ExpressionsAndOperators).reverse
|
54
55
|
raise(SyntaxError, SyntaxHelp) unless expressions.shift =~ Syntax
|
55
56
|
|
56
57
|
condition = Condition.new($1, $2, $3)
|
data/lib/liquid/tags/include.rb
CHANGED
@@ -24,7 +24,8 @@ module Liquid
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def render(context)
|
27
|
-
|
27
|
+
file_system = context.registers[:file_system] || Liquid::Template.file_system
|
28
|
+
source = file_system.read_template_file(context[@template_name])
|
28
29
|
partial = Liquid::Template.parse(source)
|
29
30
|
|
30
31
|
variable = context[@variable_name || @template_name[1..-2]]
|
data/lib/liquid/template.rb
CHANGED
@@ -1,120 +1,123 @@
|
|
1
1
|
module Liquid
|
2
2
|
|
3
|
-
# Templates are central to liquid.
|
4
|
-
# Interpretating templates is a two step process. First you compile the
|
5
|
-
# source code you got. During compile time some extensive error checking is performed.
|
6
|
-
# your code should expect to get some SyntaxErrors.
|
3
|
+
# Templates are central to liquid.
|
4
|
+
# Interpretating templates is a two step process. First you compile the
|
5
|
+
# source code you got. During compile time some extensive error checking is performed.
|
6
|
+
# your code should expect to get some SyntaxErrors.
|
7
7
|
#
|
8
|
-
# After you have a compiled template you can then <tt>render</tt> it.
|
9
|
-
# You can use a compiled template over and over again and keep it cached.
|
8
|
+
# After you have a compiled template you can then <tt>render</tt> it.
|
9
|
+
# You can use a compiled template over and over again and keep it cached.
|
10
|
+
#
|
11
|
+
# Example:
|
10
12
|
#
|
11
|
-
# Example:
|
12
|
-
#
|
13
13
|
# template = Liquid::Template.parse(source)
|
14
14
|
# template.render('user_name' => 'bob')
|
15
15
|
#
|
16
16
|
class Template
|
17
17
|
attr_accessor :root
|
18
18
|
@@file_system = BlankFileSystem.new
|
19
|
-
|
20
|
-
class <<self
|
19
|
+
|
20
|
+
class << self
|
21
21
|
def file_system
|
22
22
|
@@file_system
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def file_system=(obj)
|
26
26
|
@@file_system = obj
|
27
27
|
end
|
28
|
-
|
29
|
-
def register_tag(name, klass)
|
28
|
+
|
29
|
+
def register_tag(name, klass)
|
30
30
|
tags[name.to_s] = klass
|
31
|
-
end
|
32
|
-
|
31
|
+
end
|
32
|
+
|
33
33
|
def tags
|
34
34
|
@tags ||= {}
|
35
35
|
end
|
36
|
-
|
37
|
-
# Pass a module with filter methods which should be available
|
36
|
+
|
37
|
+
# Pass a module with filter methods which should be available
|
38
38
|
# to all liquid views. Good for registering the standard library
|
39
|
-
def register_filter(mod)
|
39
|
+
def register_filter(mod)
|
40
40
|
Strainer.global_filter(mod)
|
41
|
-
end
|
42
|
-
|
41
|
+
end
|
42
|
+
|
43
43
|
# creates a new <tt>Template</tt> object from liquid source code
|
44
44
|
def parse(source)
|
45
45
|
template = Template.new
|
46
46
|
template.parse(source)
|
47
47
|
template
|
48
|
-
end
|
48
|
+
end
|
49
49
|
end
|
50
50
|
|
51
51
|
# creates a new <tt>Template</tt> from an array of tokens. Use <tt>Template.parse</tt> instead
|
52
52
|
def initialize
|
53
53
|
end
|
54
|
-
|
55
|
-
# Parse source code.
|
56
|
-
# Returns self for easy chaining
|
54
|
+
|
55
|
+
# Parse source code.
|
56
|
+
# Returns self for easy chaining
|
57
57
|
def parse(source)
|
58
58
|
@root = Document.new(tokenize(source))
|
59
59
|
self
|
60
60
|
end
|
61
|
-
|
62
|
-
def registers
|
61
|
+
|
62
|
+
def registers
|
63
63
|
@registers ||= {}
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def assigns
|
67
67
|
@assigns ||= {}
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
|
+
def instance_assigns
|
71
|
+
@instance_assigns ||= {}
|
72
|
+
end
|
73
|
+
|
70
74
|
def errors
|
71
75
|
@errors ||= []
|
72
76
|
end
|
73
|
-
|
77
|
+
|
74
78
|
# Render takes a hash with local variables.
|
75
79
|
#
|
76
|
-
# if you use the same filters over and over again consider registering them globally
|
80
|
+
# if you use the same filters over and over again consider registering them globally
|
77
81
|
# with <tt>Template.register_filter</tt>
|
78
|
-
#
|
82
|
+
#
|
79
83
|
# Following options can be passed:
|
80
|
-
#
|
84
|
+
#
|
81
85
|
# * <tt>filters</tt> : array with local filters
|
82
|
-
# * <tt>registers</tt> : hash with register variables. Those can be accessed from
|
83
|
-
# filters and tags and might be useful to integrate liquid more with its host application
|
86
|
+
# * <tt>registers</tt> : hash with register variables. Those can be accessed from
|
87
|
+
# filters and tags and might be useful to integrate liquid more with its host application
|
84
88
|
#
|
85
89
|
def render(*args)
|
86
|
-
return '' if @root.nil?
|
87
|
-
|
90
|
+
return '' if @root.nil?
|
91
|
+
|
88
92
|
context = case args.first
|
89
93
|
when Liquid::Context
|
90
94
|
args.shift
|
91
95
|
when Hash
|
92
|
-
|
93
|
-
Context.new(assigns, registers, @rethrow_errors)
|
96
|
+
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors)
|
94
97
|
when nil
|
95
|
-
Context.new(assigns, registers, @rethrow_errors)
|
98
|
+
Context.new(assigns, instance_assigns, registers, @rethrow_errors)
|
96
99
|
else
|
97
100
|
raise ArgumentError, "Expect Hash or Liquid::Context as parameter"
|
98
101
|
end
|
99
|
-
|
102
|
+
|
100
103
|
case args.last
|
101
104
|
when Hash
|
102
105
|
options = args.pop
|
103
|
-
|
106
|
+
|
104
107
|
if options[:registers].is_a?(Hash)
|
105
|
-
self.registers.merge!(options[:registers])
|
108
|
+
self.registers.merge!(options[:registers])
|
106
109
|
end
|
107
110
|
|
108
111
|
if options[:filters]
|
109
112
|
context.add_filters(options[:filters])
|
110
|
-
end
|
111
|
-
|
113
|
+
end
|
114
|
+
|
112
115
|
when Module
|
113
|
-
context.add_filters(args.pop)
|
116
|
+
context.add_filters(args.pop)
|
114
117
|
when Array
|
115
|
-
context.add_filters(args.pop)
|
118
|
+
context.add_filters(args.pop)
|
116
119
|
end
|
117
|
-
|
120
|
+
|
118
121
|
begin
|
119
122
|
# render the nodelist.
|
120
123
|
# for performance reasons we get a array back here. join will make a string out of it
|
@@ -123,24 +126,24 @@ module Liquid
|
|
123
126
|
@errors = context.errors
|
124
127
|
end
|
125
128
|
end
|
126
|
-
|
129
|
+
|
127
130
|
def render!(*args)
|
128
131
|
@rethrow_errors = true; render(*args)
|
129
132
|
end
|
130
|
-
|
133
|
+
|
131
134
|
private
|
132
|
-
|
135
|
+
|
133
136
|
# Uses the <tt>Liquid::TemplateParser</tt> regexp to tokenize the passed source
|
134
137
|
def tokenize(source)
|
135
|
-
source = source.source if source.respond_to?(:source)
|
138
|
+
source = source.source if source.respond_to?(:source)
|
136
139
|
return [] if source.to_s.empty?
|
137
140
|
tokens = source.split(TemplateParser)
|
138
141
|
|
139
142
|
# removes the rogue empty element at the beginning of the array
|
140
|
-
tokens.shift if tokens[0] and tokens[0].empty?
|
143
|
+
tokens.shift if tokens[0] and tokens[0].empty?
|
141
144
|
|
142
145
|
tokens
|
143
146
|
end
|
144
|
-
|
145
|
-
end
|
147
|
+
|
148
|
+
end
|
146
149
|
end
|
data/lib/liquid/variable.rb
CHANGED
@@ -11,17 +11,18 @@ module Liquid
|
|
11
11
|
# {{ user | link }}
|
12
12
|
#
|
13
13
|
class Variable
|
14
|
+
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?!(?:#{FilterSeparator}))(?:#{QuotedFragment}|\S+)\s*)+)/
|
14
15
|
attr_accessor :filters, :name
|
15
16
|
|
16
17
|
def initialize(markup)
|
17
18
|
@markup = markup
|
18
19
|
@name = nil
|
19
20
|
@filters = []
|
20
|
-
if match = markup.match(/\s*(#{QuotedFragment})/)
|
21
|
+
if match = markup.match(/\s*(#{QuotedFragment})(.*)/)
|
21
22
|
@name = match[1]
|
22
|
-
if
|
23
|
-
filters = Regexp.last_match(1).
|
24
|
-
filters.each do |f|
|
23
|
+
if match[2].match(/#{FilterSeparator}\s*(.*)/)
|
24
|
+
filters = Regexp.last_match(1).scan(FilterParser)
|
25
|
+
filters.each do |f|
|
25
26
|
if matches = f.match(/\s*(\w+)/)
|
26
27
|
filtername = matches[1]
|
27
28
|
filterargs = f.scan(/(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*(#{QuotedFragment})/).flatten
|
@@ -34,8 +35,7 @@ module Liquid
|
|
34
35
|
|
35
36
|
def render(context)
|
36
37
|
return '' if @name.nil?
|
37
|
-
|
38
|
-
@filters.inject(output) do |output, filter|
|
38
|
+
@filters.inject(context[@name]) do |output, filter|
|
39
39
|
filterargs = filter[1].to_a.collect do |a|
|
40
40
|
context[a]
|
41
41
|
end
|
@@ -45,7 +45,6 @@ module Liquid
|
|
45
45
|
raise FilterNotFound, "Error - filter '#{filter[0]}' in '#{@markup.strip}' could not be found."
|
46
46
|
end
|
47
47
|
end
|
48
|
-
output
|
49
48
|
end
|
50
49
|
end
|
51
|
-
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: liquid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 11
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 2
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 2.1.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Tobias Luetke
|
@@ -9,20 +15,11 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2009-
|
18
|
+
date: 2009-04-13 00:00:00 -04:00
|
13
19
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
17
|
-
type: :development
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 1.8.2
|
24
|
-
version:
|
25
|
-
description: A secure non evaling end user template engine with aesthetic markup.
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: A secure, non-evaling end user template engine with aesthetic markup.
|
26
23
|
email: tobi@leetsoft.com
|
27
24
|
executables: []
|
28
25
|
|
@@ -39,7 +36,6 @@ files:
|
|
39
36
|
- Manifest.txt
|
40
37
|
- README.txt
|
41
38
|
- Rakefile
|
42
|
-
- init.rb
|
43
39
|
- lib/extras/liquid_view.rb
|
44
40
|
- lib/liquid.rb
|
45
41
|
- lib/liquid/block.rb
|
@@ -69,6 +65,8 @@ files:
|
|
69
65
|
- lib/liquid/variable.rb
|
70
66
|
has_rdoc: true
|
71
67
|
homepage: http://www.liquidmarkup.org
|
68
|
+
licenses: []
|
69
|
+
|
72
70
|
post_install_message:
|
73
71
|
rdoc_options:
|
74
72
|
- --main
|
@@ -76,23 +74,29 @@ rdoc_options:
|
|
76
74
|
require_paths:
|
77
75
|
- lib
|
78
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
79
78
|
requirements:
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
82
84
|
version: "0"
|
83
|
-
version:
|
84
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
85
87
|
requirements:
|
86
88
|
- - ">="
|
87
89
|
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
88
93
|
version: "0"
|
89
|
-
version:
|
90
94
|
requirements: []
|
91
95
|
|
92
96
|
rubyforge_project: liquid
|
93
|
-
rubygems_version: 1.3.
|
97
|
+
rubygems_version: 1.3.7
|
94
98
|
signing_key:
|
95
99
|
specification_version: 2
|
96
|
-
summary: A secure non
|
97
|
-
test_files:
|
98
|
-
|
100
|
+
summary: A secure, non-evaling end user template engine with aesthetic markup.
|
101
|
+
test_files: []
|
102
|
+
|
data/init.rb
DELETED
data/test/test_helper.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__)+ '/extra')
|
3
|
-
|
4
|
-
require 'test/unit'
|
5
|
-
require 'test/unit/assertions'
|
6
|
-
require 'caller'
|
7
|
-
require 'breakpoint'
|
8
|
-
require File.dirname(__FILE__) + '/../lib/liquid'
|
9
|
-
|
10
|
-
|
11
|
-
module Test
|
12
|
-
module Unit
|
13
|
-
module Assertions
|
14
|
-
include Liquid
|
15
|
-
def assert_template_result(expected, template, assigns={}, message=nil)
|
16
|
-
assert_equal expected, Template.parse(template).render(assigns)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|