locomotive_liquid 2.1.3

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.
@@ -0,0 +1,74 @@
1
+ module Liquid
2
+ class TableRow < Block
3
+ Syntax = /(\w+)\s+in\s+(#{VariableSignature}+)/
4
+
5
+ def initialize(tag_name, markup, tokens, context)
6
+ if markup =~ Syntax
7
+ @variable_name = $1
8
+ @collection_name = $2
9
+ @attributes = {}
10
+ markup.scan(TagAttributes) do |key, value|
11
+ @attributes[key] = value
12
+ end
13
+ else
14
+ raise SyntaxError.new("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3")
15
+ end
16
+
17
+ super
18
+ end
19
+
20
+ def render(context)
21
+ collection = context[@collection_name] or return ''
22
+
23
+ if @attributes['limit'] or @attributes['offset']
24
+ limit = context[@attributes['limit']] || -1
25
+ offset = context[@attributes['offset']] || 0
26
+ collection = collection[offset.to_i..(limit.to_i + offset.to_i - 1)]
27
+ end
28
+
29
+ length = collection.length
30
+
31
+ cols = context[@attributes['cols']].to_i
32
+
33
+ row = 1
34
+ col = 0
35
+
36
+ result = ["<tr class=\"row1\">\n"]
37
+ context.stack do
38
+
39
+ collection.each_with_index do |item, index|
40
+ context[@variable_name] = item
41
+ context['tablerowloop'] = {
42
+ 'length' => length,
43
+ 'index' => index + 1,
44
+ 'index0' => index,
45
+ 'col' => col + 1,
46
+ 'col0' => col,
47
+ 'index0' => index,
48
+ 'rindex' => length - index,
49
+ 'rindex0' => length - index -1,
50
+ 'first' => (index == 0),
51
+ 'last' => (index == length - 1),
52
+ 'col_first' => (col == 0),
53
+ 'col_last' => (col == cols - 1)
54
+ }
55
+
56
+
57
+ col += 1
58
+
59
+ result << ["<td class=\"col#{col}\">"] + render_all(@nodelist, context) + ['</td>']
60
+
61
+ if col == cols and not (index == length - 1)
62
+ col = 0
63
+ row += 1
64
+ result << ["</tr>\n<tr class=\"row#{row}\">"]
65
+ end
66
+
67
+ end
68
+ end
69
+ result + ["</tr>\n"]
70
+ end
71
+ end
72
+
73
+ Template.register_tag('tablerow', TableRow)
74
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright 2007 by Domizio Demichelis
2
+ # This library is free software. It may be used, redistributed and/or modified
3
+ # under the same terms as Ruby itself
4
+ #
5
+ # This extension is usesd in order to expose the object of the implementing class
6
+ # to liquid as it were a Drop. It also limits the liquid-callable methods of the instance
7
+ # to the allowed method passed with the liquid_methods call
8
+ # Example:
9
+ #
10
+ # class SomeClass
11
+ # liquid_methods :an_allowed_method
12
+ #
13
+ # def an_allowed_method
14
+ # 'this comes from an allowed method'
15
+ # end
16
+ # def unallowed_method
17
+ # 'this will never be an output'
18
+ # end
19
+ # end
20
+ #
21
+ # if you want to extend the drop to other methods you can defines more methods
22
+ # in the class <YourClass>::LiquidDropClass
23
+ #
24
+ # class SomeClass::LiquidDropClass
25
+ # def another_allowed_method
26
+ # 'and this from another allowed method'
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # usage:
32
+ # @something = SomeClass.new
33
+ #
34
+ # template:
35
+ # {{something.an_allowed_method}}{{something.unallowed_method}} {{something.another_allowed_method}}
36
+ #
37
+ # output:
38
+ # 'this comes from an allowed method and this from another allowed method'
39
+ #
40
+ # You can also chain associations, by adding the liquid_method call in the
41
+ # association models.
42
+ #
43
+ class Module
44
+
45
+ def liquid_methods(*allowed_methods)
46
+ drop_class = eval "class #{self.to_s}::LiquidDropClass < Liquid::Drop; self; end"
47
+ define_method :to_liquid do
48
+ drop_class.new(self)
49
+ end
50
+ drop_class.class_eval do
51
+ def initialize(object)
52
+ @object = object
53
+ end
54
+ allowed_methods.each do |sym|
55
+ define_method sym do
56
+ @object.send sym
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,222 @@
1
+ require 'cgi'
2
+
3
+ module Liquid
4
+
5
+ module StandardFilters
6
+
7
+ # Return the size of an array or of an string
8
+ def size(input)
9
+
10
+ input.respond_to?(:size) ? input.size : 0
11
+ end
12
+
13
+ # convert a input string to DOWNCASE
14
+ def downcase(input)
15
+ input.to_s.downcase
16
+ end
17
+
18
+ # convert a input string to UPCASE
19
+ def upcase(input)
20
+ input.to_s.upcase
21
+ end
22
+
23
+ # capitalize words in the input centence
24
+ def capitalize(input)
25
+ input.to_s.capitalize
26
+ end
27
+
28
+ def escape(input)
29
+ CGI.escapeHTML(input) rescue input
30
+ end
31
+
32
+ alias_method :h, :escape
33
+
34
+ # Truncate a string down to x characters
35
+ def truncate(input, length = 50, truncate_string = "...")
36
+ if input.nil? then return end
37
+ l = length.to_i - truncate_string.length
38
+ l = 0 if l < 0
39
+ input.length > length.to_i ? input[0...l] + truncate_string : input
40
+ end
41
+
42
+ def truncatewords(input, words = 15, truncate_string = "...")
43
+ if input.nil? then return end
44
+ wordlist = input.to_s.split
45
+ l = words.to_i - 1
46
+ l = 0 if l < 0
47
+ wordlist.length > l ? wordlist[0..l].join(" ") + truncate_string : input
48
+ end
49
+
50
+ def strip_html(input)
51
+ input.to_s.gsub(/<script.*?<\/script>/, '').gsub(/<.*?>/, '')
52
+ end
53
+
54
+ # Remove all newlines from the string
55
+ def strip_newlines(input)
56
+ input.to_s.gsub(/\n/, '')
57
+ end
58
+
59
+
60
+ # Join elements of the array with certain character between them
61
+ def join(input, glue = ' ')
62
+ [input].flatten.join(glue)
63
+ end
64
+
65
+ # Sort elements of the array
66
+ # provide optional property with which to sort an array of hashes or drops
67
+ def sort(input, property = nil)
68
+ ary = [input].flatten
69
+ if property.nil?
70
+ ary.sort
71
+ elsif ary.first.respond_to?('[]') and !ary.first[property].nil?
72
+ ary.sort {|a,b| a[property] <=> b[property] }
73
+ elsif ary.first.respond_to?(property)
74
+ ary.sort {|a,b| a.send(property) <=> b.send(property) }
75
+ end
76
+ end
77
+
78
+ # map/collect on a given property
79
+ def map(input, property)
80
+ ary = [input].flatten
81
+ if ary.first.respond_to?('[]') and !ary.first[property].nil?
82
+ ary.map {|e| e[property] }
83
+ elsif ary.first.respond_to?(property)
84
+ ary.map {|e| e.send(property) }
85
+ end
86
+ end
87
+
88
+ # Replace occurrences of a string with another
89
+ def replace(input, string, replacement = '')
90
+ input.to_s.gsub(string, replacement)
91
+ end
92
+
93
+ # Replace the first occurrences of a string with another
94
+ def replace_first(input, string, replacement = '')
95
+ input.to_s.sub(string, replacement)
96
+ end
97
+
98
+ # remove a substring
99
+ def remove(input, string)
100
+ input.to_s.gsub(string, '')
101
+ end
102
+
103
+ # remove the first occurrences of a substring
104
+ def remove_first(input, string)
105
+ input.to_s.sub(string, '')
106
+ end
107
+
108
+ # add one string to another
109
+ def append(input, string)
110
+ input.to_s + string.to_s
111
+ end
112
+
113
+ # prepend a string to another
114
+ def prepend(input, string)
115
+ string.to_s + input.to_s
116
+ end
117
+
118
+ # Add <br /> tags in front of all newlines in input string
119
+ def newline_to_br(input)
120
+ input.to_s.gsub(/\n/, "<br />\n")
121
+ end
122
+
123
+ # Reformat a date
124
+ #
125
+ # %a - The abbreviated weekday name (``Sun'')
126
+ # %A - The full weekday name (``Sunday'')
127
+ # %b - The abbreviated month name (``Jan'')
128
+ # %B - The full month name (``January'')
129
+ # %c - The preferred local date and time representation
130
+ # %d - Day of the month (01..31)
131
+ # %H - Hour of the day, 24-hour clock (00..23)
132
+ # %I - Hour of the day, 12-hour clock (01..12)
133
+ # %j - Day of the year (001..366)
134
+ # %m - Month of the year (01..12)
135
+ # %M - Minute of the hour (00..59)
136
+ # %p - Meridian indicator (``AM'' or ``PM'')
137
+ # %S - Second of the minute (00..60)
138
+ # %U - Week number of the current year,
139
+ # starting with the first Sunday as the first
140
+ # day of the first week (00..53)
141
+ # %W - Week number of the current year,
142
+ # starting with the first Monday as the first
143
+ # day of the first week (00..53)
144
+ # %w - Day of the week (Sunday is 0, 0..6)
145
+ # %x - Preferred representation for the date alone, no time
146
+ # %X - Preferred representation for the time alone, no date
147
+ # %y - Year without a century (00..99)
148
+ # %Y - Year with century
149
+ # %Z - Time zone name
150
+ # %% - Literal ``%'' character
151
+ def date(input, format)
152
+
153
+ if format.to_s.empty?
154
+ return input.to_s
155
+ end
156
+
157
+ date = input.is_a?(String) ? Time.parse(input) : input
158
+
159
+ if date.respond_to?(:strftime)
160
+ date.strftime(format.to_s)
161
+ else
162
+ input
163
+ end
164
+ rescue => e
165
+ input
166
+ end
167
+
168
+ # Get the first element of the passed in array
169
+ #
170
+ # Example:
171
+ # {{ product.images | first | to_img }}
172
+ #
173
+ def first(array)
174
+ array.first if array.respond_to?(:first)
175
+ end
176
+
177
+ # Get the last element of the passed in array
178
+ #
179
+ # Example:
180
+ # {{ product.images | last | to_img }}
181
+ #
182
+ def last(array)
183
+ array.last if array.respond_to?(:last)
184
+ end
185
+
186
+ # addition
187
+ def plus(input, operand)
188
+ to_number(input) + to_number(operand)
189
+ end
190
+
191
+ # subtraction
192
+ def minus(input, operand)
193
+ to_number(input) - to_number(operand)
194
+ end
195
+
196
+ # multiplication
197
+ def times(input, operand)
198
+ to_number(input) * to_number(operand)
199
+ end
200
+
201
+ # division
202
+ def divided_by(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
217
+ end
218
+
219
+ end
220
+
221
+ Template.register_filter(StandardFilters)
222
+ end
@@ -0,0 +1,51 @@
1
+ require 'set'
2
+
3
+ module Liquid
4
+
5
+ parent_object = if defined? BlankObject
6
+ BlankObject
7
+ else
8
+ Object
9
+ end
10
+
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.
13
+ #
14
+ # One of the strainer's responsibilities is to keep malicious method calls out
15
+ class Strainer < parent_object #:nodoc:
16
+ INTERNAL_METHOD = /^__/
17
+ @@required_methods = Set.new([:__id__, :__send__, :respond_to?, :extend, :methods, :class, :object_id])
18
+
19
+ @@filters = {}
20
+
21
+ def initialize(context)
22
+ @context = context
23
+ end
24
+
25
+ def self.global_filter(filter)
26
+ raise ArgumentError, "Passed filter is not a module" unless filter.is_a?(Module)
27
+ @@filters[filter.name] = filter
28
+ end
29
+
30
+ def self.create(context)
31
+ strainer = Strainer.new(context)
32
+ @@filters.each { |k,m| strainer.extend(m) }
33
+ strainer
34
+ end
35
+
36
+ def respond_to?(method, include_private = false)
37
+ method_name = method.to_s
38
+ return false if method_name =~ INTERNAL_METHOD
39
+ return false if @@required_methods.include?(method_name)
40
+ super
41
+ end
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)
47
+ undef_method m
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,27 @@
1
+ module Liquid
2
+
3
+ class Tag
4
+ attr_accessor :nodelist, :context
5
+
6
+ def initialize(tag_name, markup, tokens, context)
7
+ @tag_name = tag_name
8
+ @markup = markup
9
+ @context = context
10
+ parse(tokens)
11
+ end
12
+
13
+ def parse(tokens)
14
+ end
15
+
16
+ def name
17
+ self.class.name.downcase
18
+ end
19
+
20
+ def render(context)
21
+ ''
22
+ end
23
+ end
24
+
25
+
26
+ end
27
+
@@ -0,0 +1,33 @@
1
+ module Liquid
2
+
3
+ # Assign sets a variable in your template.
4
+ #
5
+ # {% assign foo = 'monkey' %}
6
+ #
7
+ # You can then use the variable later in the page.
8
+ #
9
+ # {{ foo }}
10
+ #
11
+ class Assign < Tag
12
+ Syntax = /(#{VariableSignature}+)\s*=\s*(#{QuotedFragment}+)/
13
+
14
+ def initialize(tag_name, markup, tokens, context)
15
+ if markup =~ Syntax
16
+ @to = $1
17
+ @from = $2
18
+ else
19
+ raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]")
20
+ end
21
+
22
+ super
23
+ end
24
+
25
+ def render(context)
26
+ context.scopes.last[@to] = context[@from]
27
+ ''
28
+ end
29
+
30
+ end
31
+
32
+ Template.register_tag('assign', Assign)
33
+ end