liquid 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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+(#{Expression}+)\s*(reversed)?/
45
+ Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/
46
46
 
47
47
  def initialize(tag_name, markup, tokens)
48
48
  if markup =~ Syntax
@@ -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 = /(#{Expression})\s*([=!<>a-z_]+)?\s*(#{Expression})?/
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.split(/\b(and|or)\b/).reverse
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)
@@ -24,7 +24,8 @@ module Liquid
24
24
  end
25
25
 
26
26
  def render(context)
27
- source = Liquid::Template.file_system.read_template_file(context[@template_name])
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]]
@@ -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
- self.assigns.merge!(args.shift)
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
@@ -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 markup.match(/#{FilterSeparator}\s*(.*)/)
23
- filters = Regexp.last_match(1).split(/#{FilterSeparator}/)
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
- output = context[@name]
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
- version: 2.0.0
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-03-10 00:00:00 -04:00
18
+ date: 2009-04-13 00:00:00 -04:00
13
19
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: hoe
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.1
97
+ rubygems_version: 1.3.7
94
98
  signing_key:
95
99
  specification_version: 2
96
- summary: A secure non evaling end user template engine with aesthetic markup.
97
- test_files:
98
- - test/test_helper.rb
100
+ summary: A secure, non-evaling end user template engine with aesthetic markup.
101
+ test_files: []
102
+
data/init.rb DELETED
@@ -1,8 +0,0 @@
1
- require 'liquid'
2
- require 'extras/liquid_view'
3
-
4
- if defined? ActionView::Template and ActionView::Template.respond_to? :register_template_handler
5
- ActionView::Template
6
- else
7
- ActionView::Base
8
- end.register_template_handler(:liquid, LiquidView)
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