locomotive_liquid 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ module Liquid
2
+ class Ifchanged < Block
3
+
4
+ def render(context)
5
+ context.stack do
6
+
7
+ output = render_all(@nodelist, context)
8
+
9
+ if output != context.registers[:ifchanged]
10
+ context.registers[:ifchanged] = output
11
+ output
12
+ else
13
+ ''
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ Template.register_tag('ifchanged', Ifchanged)
20
+ end
@@ -0,0 +1,56 @@
1
+ module Liquid
2
+ class Include < Tag
3
+ Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/
4
+
5
+ def initialize(tag_name, markup, tokens, context)
6
+ if markup =~ Syntax
7
+
8
+ @template_name = $1
9
+ @variable_name = $3
10
+ @attributes = {}
11
+
12
+ markup.scan(TagAttributes) do |key, value|
13
+ @attributes[key] = value
14
+ end
15
+
16
+ else
17
+ raise SyntaxError.new("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]")
18
+ end
19
+
20
+ super
21
+ end
22
+
23
+ def parse(tokens)
24
+ end
25
+
26
+ def render(context)
27
+ file_system = context.registers[:file_system] || Liquid::Template.file_system
28
+ source = file_system.read_template_file(context[@template_name])
29
+ partial = Liquid::Template.parse(source)
30
+
31
+ variable = context[@variable_name || @template_name[1..-2]]
32
+
33
+ context.stack do
34
+ @attributes.each do |key, value|
35
+ context[key] = context[value]
36
+ end
37
+
38
+ if variable.is_a?(Array)
39
+
40
+ variable.collect do |variable|
41
+ context[@template_name[1..-2]] = variable
42
+ partial.render(context)
43
+ end
44
+
45
+ else
46
+
47
+ context[@template_name[1..-2]] = variable
48
+ partial.render(context)
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ Template.register_tag('include', Include)
56
+ end
@@ -0,0 +1,93 @@
1
+ module Liquid
2
+
3
+ # Blocks are used with the Extends tag to define
4
+ # the content of blocks. Nested blocks are allowed.
5
+ #
6
+ # {% extends home %}
7
+ # {% block content }Hello world{% endblock %}
8
+ #
9
+ class InheritedBlock < Block
10
+ Syntax = /(#{QuotedFragment}+)/
11
+
12
+ attr_accessor :parent
13
+ attr_reader :name
14
+
15
+ def initialize(tag_name, markup, tokens, context)
16
+ if markup =~ Syntax
17
+ @name = $1
18
+ else
19
+ raise SyntaxError.new("Error in tag 'block' - Valid syntax: block [name]")
20
+ end
21
+
22
+ (context[:block_stack] ||= []).push(self)
23
+ context[:current_block] = self
24
+
25
+ super if tokens
26
+ end
27
+
28
+ def render(context)
29
+ context.stack do
30
+ context['block'] = InheritedBlockDrop.new(self)
31
+ render_all(@nodelist, context)
32
+ end
33
+ end
34
+
35
+ def end_tag
36
+ self.register_current_block
37
+
38
+ @context[:block_stack].pop
39
+ @context[:current_block] = @context[:block_stack].last
40
+ end
41
+
42
+ def call_super(context)
43
+ if parent
44
+ parent.render(context)
45
+ else
46
+ ''
47
+ end
48
+ end
49
+
50
+ def self.clone_block(block)
51
+ new_block = self.new(block.send(:instance_variable_get, :"@tag_name"), block.name, nil, {})
52
+ new_block.parent = block.parent
53
+ new_block.nodelist = block.nodelist
54
+ new_block
55
+ end
56
+
57
+ protected
58
+
59
+ def register_current_block
60
+ @context[:blocks] ||= {}
61
+
62
+ block = @context[:blocks][@name]
63
+
64
+ if block
65
+ # copy the existing block in order to make it a parent of the parsed block
66
+ new_block = self.class.clone_block(block)
67
+
68
+ # replace the up-to-date version of the block in the parent template
69
+ block.parent = new_block
70
+ block.nodelist = @nodelist
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ class InheritedBlockDrop < Drop
77
+
78
+ def initialize(block)
79
+ @block = block
80
+ end
81
+
82
+ def name
83
+ @block.name
84
+ end
85
+
86
+ def super
87
+ @block.call_super(@context)
88
+ end
89
+
90
+ end
91
+
92
+ Template.register_tag('block', InheritedBlock)
93
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/if'
2
+
3
+ module Liquid
4
+
5
+ # Unless is a conditional just like 'if' but works on the inverse logic.
6
+ #
7
+ # {% unless x < 0 %} x is greater than zero {% end %}
8
+ #
9
+ class Unless < If
10
+ def render(context)
11
+ context.stack do
12
+
13
+ # First condition is interpreted backwards ( if not )
14
+ block = @blocks.first
15
+ unless block.evaluate(context)
16
+ return render_all(block.attachment, context)
17
+ end
18
+
19
+ # After the first condition unless works just like if
20
+ @blocks[1..-1].each do |block|
21
+ if block.evaluate(context)
22
+ return render_all(block.attachment, context)
23
+ end
24
+ end
25
+
26
+ ''
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ Template.register_tag('unless', Unless)
33
+ end
@@ -0,0 +1,149 @@
1
+ module Liquid
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.
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.
10
+ #
11
+ # Example:
12
+ #
13
+ # template = Liquid::Template.parse(source)
14
+ # template.render('user_name' => 'bob')
15
+ #
16
+ class Template
17
+ attr_accessor :root
18
+ @@file_system = BlankFileSystem.new
19
+
20
+ class << self
21
+ def file_system
22
+ @@file_system
23
+ end
24
+
25
+ def file_system=(obj)
26
+ @@file_system = obj
27
+ end
28
+
29
+ def register_tag(name, klass)
30
+ tags[name.to_s] = klass
31
+ end
32
+
33
+ def tags
34
+ @tags ||= {}
35
+ end
36
+
37
+ # Pass a module with filter methods which should be available
38
+ # to all liquid views. Good for registering the standard library
39
+ def register_filter(mod)
40
+ Strainer.global_filter(mod)
41
+ end
42
+
43
+ # creates a new <tt>Template</tt> object from liquid source code
44
+ def parse(source, context = {})
45
+ template = Template.new
46
+ template.parse(source, context)
47
+ template
48
+ end
49
+ end
50
+
51
+ # creates a new <tt>Template</tt> from an array of tokens. Use <tt>Template.parse</tt> instead
52
+ def initialize
53
+ end
54
+
55
+ # Parse source code.
56
+ # Returns self for easy chaining
57
+ def parse(source, context = {})
58
+ @root = Document.new(tokenize(source), context.merge!(:template => self))
59
+ self
60
+ end
61
+
62
+ def registers
63
+ @registers ||= {}
64
+ end
65
+
66
+ def assigns
67
+ @assigns ||= {}
68
+ end
69
+
70
+ def instance_assigns
71
+ @instance_assigns ||= {}
72
+ end
73
+
74
+ def errors
75
+ @errors ||= []
76
+ end
77
+
78
+ # Render takes a hash with local variables.
79
+ #
80
+ # if you use the same filters over and over again consider registering them globally
81
+ # with <tt>Template.register_filter</tt>
82
+ #
83
+ # Following options can be passed:
84
+ #
85
+ # * <tt>filters</tt> : array with local filters
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
88
+ #
89
+ def render(*args)
90
+ return '' if @root.nil?
91
+
92
+ context = case args.first
93
+ when Liquid::Context
94
+ args.shift
95
+ when Hash
96
+ Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors)
97
+ when nil
98
+ Context.new(assigns, instance_assigns, registers, @rethrow_errors)
99
+ else
100
+ raise ArgumentError, "Expect Hash or Liquid::Context as parameter"
101
+ end
102
+
103
+ case args.last
104
+ when Hash
105
+ options = args.pop
106
+
107
+ if options[:registers].is_a?(Hash)
108
+ self.registers.merge!(options[:registers])
109
+ end
110
+
111
+ if options[:filters]
112
+ context.add_filters(options[:filters])
113
+ end
114
+
115
+ when Module
116
+ context.add_filters(args.pop)
117
+ when Array
118
+ context.add_filters(args.pop)
119
+ end
120
+
121
+ begin
122
+ # render the nodelist.
123
+ # for performance reasons we get a array back here. join will make a string out of it
124
+ @root.render(context).join
125
+ ensure
126
+ @errors = context.errors
127
+ end
128
+ end
129
+
130
+ def render!(*args)
131
+ @rethrow_errors = true; render(*args)
132
+ end
133
+
134
+ private
135
+
136
+ # Uses the <tt>Liquid::TemplateParser</tt> regexp to tokenize the passed source
137
+ def tokenize(source)
138
+ source = source.source if source.respond_to?(:source)
139
+ return [] if source.to_s.empty?
140
+ tokens = source.split(TemplateParser)
141
+
142
+ # removes the rogue empty element at the beginning of the array
143
+ tokens.shift if tokens[0] and tokens[0].empty?
144
+
145
+ tokens
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,50 @@
1
+ module Liquid
2
+
3
+ # Holds variables. Variables are only loaded "just in time"
4
+ # and are not evaluated as part of the render stage
5
+ #
6
+ # {{ monkey }}
7
+ # {{ user.name }}
8
+ #
9
+ # Variables can be combined with filters:
10
+ #
11
+ # {{ user | link }}
12
+ #
13
+ class Variable
14
+ FilterParser = /(?:#{FilterSeparator}|(?:\s*(?!(?:#{FilterSeparator}))(?:#{QuotedFragment}|\S+)\s*)+)/
15
+ attr_accessor :filters, :name
16
+
17
+ def initialize(markup)
18
+ @markup = markup
19
+ @name = nil
20
+ @filters = []
21
+ if match = markup.match(/\s*(#{QuotedFragment})(.*)/)
22
+ @name = match[1]
23
+ if match[2].match(/#{FilterSeparator}\s*(.*)/)
24
+ filters = Regexp.last_match(1).scan(FilterParser)
25
+ filters.each do |f|
26
+ if matches = f.match(/\s*(\w+)/)
27
+ filtername = matches[1]
28
+ filterargs = f.scan(/(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*(#{QuotedFragment})/).flatten
29
+ @filters << [filtername.to_sym, filterargs]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def render(context)
37
+ return '' if @name.nil?
38
+ @filters.inject(context[@name]) do |output, filter|
39
+ filterargs = filter[1].to_a.collect do |a|
40
+ context[a]
41
+ end
42
+ begin
43
+ output = context.invoke(filter[0], output, *filterargs)
44
+ rescue FilterNotFound
45
+ raise FilterNotFound, "Error - filter '#{filter[0]}' in '#{@markup.strip}' could not be found."
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1 @@
1
+ require 'liquid'
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: locomotive_liquid
3
+ version: !ruby/object:Gem::Version
4
+ hash: 13
5
+ prerelease: false
6
+ segments:
7
+ - 2
8
+ - 1
9
+ - 3
10
+ version: 2.1.3
11
+ platform: ruby
12
+ authors:
13
+ - Tobias Luetke
14
+ - Didier Lafforgue
15
+ - Jacques Crocker
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2010-09-27 00:00:00 -07:00
21
+ default_executable:
22
+ dependencies: []
23
+
24
+ description: A secure, non-evaling end user template engine with aesthetic markup. Extended with liquid template inheritance for use in LocomotiveCMS
25
+ email:
26
+ - tobi@leetsoft.com
27
+ - didier@nocoffee.fr
28
+ - railsjedi@gmail.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - History.txt
35
+ - README.txt
36
+ files:
37
+ - CHANGELOG
38
+ - History.txt
39
+ - MIT-LICENSE
40
+ - README.txt
41
+ - Rakefile
42
+ - init.rb
43
+ - lib/extras/liquid_view.rb
44
+ - lib/liquid/block.rb
45
+ - lib/liquid/condition.rb
46
+ - lib/liquid/context.rb
47
+ - lib/liquid/document.rb
48
+ - lib/liquid/drop.rb
49
+ - lib/liquid/errors.rb
50
+ - lib/liquid/extensions.rb
51
+ - lib/liquid/file_system.rb
52
+ - lib/liquid/htmltags.rb
53
+ - lib/liquid/module_ex.rb
54
+ - lib/liquid/standardfilters.rb
55
+ - lib/liquid/strainer.rb
56
+ - lib/liquid/tag.rb
57
+ - lib/liquid/tags/assign.rb
58
+ - lib/liquid/tags/capture.rb
59
+ - lib/liquid/tags/case.rb
60
+ - lib/liquid/tags/comment.rb
61
+ - lib/liquid/tags/cycle.rb
62
+ - lib/liquid/tags/extends.rb
63
+ - lib/liquid/tags/for.rb
64
+ - lib/liquid/tags/if.rb
65
+ - lib/liquid/tags/ifchanged.rb
66
+ - lib/liquid/tags/include.rb
67
+ - lib/liquid/tags/inherited_block.rb
68
+ - lib/liquid/tags/unless.rb
69
+ - lib/liquid/template.rb
70
+ - lib/liquid/variable.rb
71
+ - lib/liquid.rb
72
+ - lib/locomotive_liquid.rb
73
+ has_rdoc: true
74
+ homepage: http://www.locomotiveapp.org
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --main
80
+ - README.txt
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 23
98
+ segments:
99
+ - 1
100
+ - 3
101
+ - 6
102
+ version: 1.3.6
103
+ requirements: []
104
+
105
+ rubyforge_project: locomotive_liquid
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 2
109
+ summary: A secure, non-evaling end user template engine with aesthetic markup.
110
+ test_files: []
111
+