liquid 2.5.5 → 2.6.0.rc1

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.
Files changed (47) hide show
  1. checksums.yaml +13 -5
  2. data/History.md +26 -11
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +6 -0
  5. data/lib/extras/liquid_view.rb +9 -9
  6. data/lib/liquid.rb +1 -0
  7. data/lib/liquid/block.rb +16 -5
  8. data/lib/liquid/context.rb +17 -9
  9. data/lib/liquid/document.rb +1 -1
  10. data/lib/liquid/errors.rb +2 -1
  11. data/lib/liquid/file_system.rb +12 -12
  12. data/lib/liquid/htmltags.rb +1 -1
  13. data/lib/liquid/module_ex.rb +1 -1
  14. data/lib/liquid/standardfilters.rb +44 -22
  15. data/lib/liquid/strainer.rb +3 -3
  16. data/lib/liquid/tag.rb +1 -1
  17. data/lib/liquid/tags/assign.rb +14 -12
  18. data/lib/liquid/tags/break.rb +2 -2
  19. data/lib/liquid/tags/capture.rb +1 -0
  20. data/lib/liquid/tags/case.rb +28 -28
  21. data/lib/liquid/tags/continue.rb +1 -1
  22. data/lib/liquid/tags/cycle.rb +21 -21
  23. data/lib/liquid/tags/decrement.rb +7 -7
  24. data/lib/liquid/tags/for.rb +26 -26
  25. data/lib/liquid/tags/if.rb +3 -3
  26. data/lib/liquid/tags/ifchanged.rb +9 -9
  27. data/lib/liquid/tags/include.rb +42 -14
  28. data/lib/liquid/tags/increment.rb +7 -7
  29. data/lib/liquid/tags/raw.rb +5 -4
  30. data/lib/liquid/tags/unless.rb +8 -8
  31. data/lib/liquid/template.rb +11 -5
  32. data/lib/liquid/utils.rb +0 -1
  33. data/lib/liquid/variable.rb +2 -2
  34. data/lib/liquid/version.rb +4 -0
  35. data/test/liquid/assign_test.rb +1 -1
  36. data/test/liquid/condition_test.rb +1 -1
  37. data/test/liquid/hash_ordering_test.rb +25 -0
  38. data/test/liquid/output_test.rb +2 -2
  39. data/test/liquid/standard_filter_test.rb +18 -0
  40. data/test/liquid/tags/for_tag_test.rb +47 -34
  41. data/test/liquid/tags/html_tag_test.rb +2 -2
  42. data/test/liquid/tags/if_else_tag_test.rb +0 -6
  43. data/test/liquid/tags/include_tag_test.rb +28 -1
  44. data/test/liquid/tags/raw_tag_test.rb +11 -2
  45. data/test/liquid/template_test.rb +72 -0
  46. data/test/liquid/variable_test.rb +6 -0
  47. metadata +8 -5
@@ -8,7 +8,7 @@ module Liquid
8
8
  # The Strainer only allows method calls defined in filters given to it via Strainer.global_filter,
9
9
  # Context#add_filters or Template.register_filter
10
10
  class Strainer #:nodoc:
11
- @@filters = {}
11
+ @@filters = []
12
12
  @@known_filters = Set.new
13
13
  @@known_methods = Set.new
14
14
 
@@ -19,7 +19,7 @@ module Liquid
19
19
  def self.global_filter(filter)
20
20
  raise ArgumentError, "Passed filter is not a module" unless filter.is_a?(Module)
21
21
  add_known_filter(filter)
22
- @@filters[filter.name] = filter
22
+ @@filters << filter unless @@filters.include?(filter)
23
23
  end
24
24
 
25
25
  def self.add_known_filter(filter)
@@ -34,7 +34,7 @@ module Liquid
34
34
 
35
35
  def self.create(context)
36
36
  strainer = Strainer.new(context)
37
- @@filters.each { |k,m| strainer.extend(m) }
37
+ @@filters.each { |m| strainer.extend(m) }
38
38
  strainer
39
39
  end
40
40
 
data/lib/liquid/tag.rb CHANGED
@@ -23,4 +23,4 @@ module Liquid
23
23
 
24
24
  end # Tag
25
25
 
26
- end # Tag
26
+ end # Liquid
@@ -10,24 +10,26 @@ module Liquid
10
10
  #
11
11
  class Assign < Tag
12
12
  Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/o
13
-
14
- def initialize(tag_name, markup, tokens)
13
+
14
+ def initialize(tag_name, markup, tokens)
15
15
  if markup =~ Syntax
16
16
  @to = $1
17
17
  @from = Variable.new($2)
18
18
  else
19
19
  raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]")
20
20
  end
21
-
22
- super
21
+
22
+ super
23
23
  end
24
-
24
+
25
25
  def render(context)
26
- context.scopes.last[@to] = @from.render(context)
27
- ''
28
- end
29
-
30
- end
31
-
32
- Template.register_tag('assign', Assign)
26
+ val = @from.render(context)
27
+ context.scopes.last[@to] = val
28
+ context.resource_limits[:assign_score_current] += (val.respond_to?(:length) ? val.length : 1)
29
+ ''
30
+ end
31
+
32
+ end
33
+
34
+ Template.register_tag('assign', Assign)
33
35
  end
@@ -8,8 +8,8 @@ module Liquid
8
8
  # {% break %}
9
9
  # {% endif %}
10
10
  # {% endfor %}
11
- #
12
- class Break < Tag
11
+ #
12
+ class Break < Tag
13
13
 
14
14
  def interrupt
15
15
  BreakInterrupt.new
@@ -27,6 +27,7 @@ module Liquid
27
27
  def render(context)
28
28
  output = super
29
29
  context.scopes.last[@to] = output
30
+ context.resource_limits[:assign_score_current] += (output.respond_to?(:length) ? output.length : 1)
30
31
  ''
31
32
  end
32
33
  end
@@ -3,15 +3,15 @@ module Liquid
3
3
  Syntax = /(#{QuotedFragment})/o
4
4
  WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/o
5
5
 
6
- def initialize(tag_name, markup, tokens)
6
+ def initialize(tag_name, markup, tokens)
7
7
  @blocks = []
8
-
8
+
9
9
  if markup =~ Syntax
10
10
  @left = $1
11
11
  else
12
12
  raise SyntaxError.new("Syntax Error in tag 'case' - Valid syntax: case [condition]")
13
13
  end
14
-
14
+
15
15
  super
16
16
  end
17
17
 
@@ -27,53 +27,53 @@ module Liquid
27
27
  end
28
28
  end
29
29
 
30
- def render(context)
31
- context.stack do
30
+ def render(context)
31
+ context.stack do
32
32
  execute_else_block = true
33
-
33
+
34
34
  output = ''
35
35
  @blocks.each do |block|
36
- if block.else?
36
+ if block.else?
37
37
  return render_all(block.attachment, context) if execute_else_block
38
38
  elsif block.evaluate(context)
39
- execute_else_block = false
39
+ execute_else_block = false
40
40
  output << render_all(block.attachment, context)
41
- end
41
+ end
42
42
  end
43
43
  output
44
- end
44
+ end
45
45
  end
46
-
46
+
47
47
  private
48
-
49
- def record_when_condition(markup)
48
+
49
+ def record_when_condition(markup)
50
50
  while markup
51
- # Create a new nodelist and assign it to the new block
52
- if not markup =~ WhenSyntax
53
- raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ")
54
- end
51
+ # Create a new nodelist and assign it to the new block
52
+ if not markup =~ WhenSyntax
53
+ raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ")
54
+ end
55
55
 
56
- markup = $2
56
+ markup = $2
57
57
 
58
- block = Condition.new(@left, '==', $1)
59
- block.attach(@nodelist)
60
- @blocks.push(block)
58
+ block = Condition.new(@left, '==', $1)
59
+ block.attach(@nodelist)
60
+ @blocks.push(block)
61
61
  end
62
62
  end
63
63
 
64
- def record_else_condition(markup)
64
+ def record_else_condition(markup)
65
65
 
66
66
  if not markup.strip.empty?
67
67
  raise SyntaxError.new("Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) ")
68
68
  end
69
-
70
- block = ElseCondition.new
69
+
70
+ block = ElseCondition.new
71
71
  block.attach(@nodelist)
72
72
  @blocks << block
73
73
  end
74
-
75
-
76
- end
77
-
74
+
75
+
76
+ end
77
+
78
78
  Template.register_tag('case', Case)
79
79
  end
@@ -8,7 +8,7 @@ module Liquid
8
8
  # {% continue %}
9
9
  # {% endif %}
10
10
  # {% endfor %}
11
- #
11
+ #
12
12
  class Continue < Tag
13
13
 
14
14
  def interrupt
@@ -1,5 +1,5 @@
1
1
  module Liquid
2
-
2
+
3
3
  # Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
4
4
  #
5
5
  # {% for item in items %}
@@ -15,45 +15,45 @@ module Liquid
15
15
  class Cycle < Tag
16
16
  SimpleSyntax = /^#{QuotedFragment}+/o
17
17
  NamedSyntax = /^(#{QuotedFragment})\s*\:\s*(.*)/o
18
-
19
- def initialize(tag_name, markup, tokens)
18
+
19
+ def initialize(tag_name, markup, tokens)
20
20
  case markup
21
21
  when NamedSyntax
22
- @variables = variables_from_string($2)
23
- @name = $1
22
+ @variables = variables_from_string($2)
23
+ @name = $1
24
24
  when SimpleSyntax
25
25
  @variables = variables_from_string(markup)
26
- @name = "'#{@variables.to_s}'"
26
+ @name = "'#{@variables.to_s}'"
27
27
  else
28
28
  raise SyntaxError.new("Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]")
29
29
  end
30
- super
31
- end
32
-
30
+ super
31
+ end
32
+
33
33
  def render(context)
34
34
  context.registers[:cycle] ||= Hash.new(0)
35
-
35
+
36
36
  context.stack do
37
- key = context[@name]
37
+ key = context[@name]
38
38
  iteration = context.registers[:cycle][key]
39
39
  result = context[@variables[iteration]]
40
- iteration += 1
41
- iteration = 0 if iteration >= @variables.size
40
+ iteration += 1
41
+ iteration = 0 if iteration >= @variables.size
42
42
  context.registers[:cycle][key] = iteration
43
- result
43
+ result
44
44
  end
45
45
  end
46
-
46
+
47
47
  private
48
-
48
+
49
49
  def variables_from_string(markup)
50
50
  markup.split(',').collect do |var|
51
- var =~ /\s*(#{QuotedFragment})\s*/o
52
- $1 ? $1 : nil
53
- end.compact
51
+ var =~ /\s*(#{QuotedFragment})\s*/o
52
+ $1 ? $1 : nil
53
+ end.compact
54
54
  end
55
-
55
+
56
56
  end
57
-
57
+
58
58
  Template.register_tag('cycle', Cycle)
59
59
  end
@@ -1,5 +1,5 @@
1
1
  module Liquid
2
-
2
+
3
3
  # decrement is used in a place where one needs to insert a counter
4
4
  # into a template, and needs the counter to survive across
5
5
  # multiple instantiations of the template.
@@ -19,21 +19,21 @@ module Liquid
19
19
  # Hello: -3
20
20
  #
21
21
  class Decrement < Tag
22
- def initialize(tag_name, markup, tokens)
22
+ def initialize(tag_name, markup, tokens)
23
23
  @variable = markup.strip
24
24
 
25
- super
26
- end
27
-
25
+ super
26
+ end
27
+
28
28
  def render(context)
29
29
  value = context.environments.first[@variable] ||= 0
30
30
  value = value - 1
31
31
  context.environments.first[@variable] = value
32
32
  value.to_s
33
33
  end
34
-
34
+
35
35
  private
36
36
  end
37
-
37
+
38
38
  Template.register_tag('decrement', Decrement)
39
39
  end
@@ -1,6 +1,6 @@
1
1
  module Liquid
2
2
 
3
- # "For" iterates over an array or collection.
3
+ # "For" iterates over an array or collection.
4
4
  # Several useful variables are available to you within the loop.
5
5
  #
6
6
  # == Basic usage:
@@ -22,7 +22,7 @@ module Liquid
22
22
  #
23
23
  # {% for item in collection limit:5 offset:10 %}
24
24
  # {{ item.name }}
25
- # {% end %}
25
+ # {% end %}
26
26
  #
27
27
  # To reverse the for loop simply use {% for item in collection reversed %}
28
28
  #
@@ -31,7 +31,7 @@ module Liquid
31
31
  # forloop.name:: 'item-collection'
32
32
  # forloop.length:: Length of the loop
33
33
  # forloop.index:: The current item's position in the collection;
34
- # forloop.index starts at 1.
34
+ # forloop.index starts at 1.
35
35
  # This is helpful for non-programmers who start believe
36
36
  # the first item in an array is 1, not 0.
37
37
  # forloop.index0:: The current item's position in the collection
@@ -43,19 +43,19 @@ module Liquid
43
43
  # forloop.first:: Returns true if the item is the first item.
44
44
  # forloop.last:: Returns true if the item is the last item.
45
45
  #
46
- class For < Block
47
- Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
48
-
46
+ class For < Block
47
+ Syntax = /\A(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
48
+
49
49
  def initialize(tag_name, markup, tokens)
50
50
  if markup =~ Syntax
51
51
  @variable_name = $1
52
52
  @collection_name = $2
53
- @name = "#{$1}-#{$2}"
54
- @reversed = $3
53
+ @name = "#{$1}-#{$2}"
54
+ @reversed = $3
55
55
  @attributes = {}
56
56
  markup.scan(TagAttributes) do |key, value|
57
57
  @attributes[key] = value
58
- end
58
+ end
59
59
  else
60
60
  raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]")
61
61
  end
@@ -68,51 +68,51 @@ module Liquid
68
68
  return super unless tag == 'else'
69
69
  @nodelist = @else_block = []
70
70
  end
71
-
72
- def render(context)
71
+
72
+ def render(context)
73
73
  context.registers[:for] ||= Hash.new(0)
74
-
74
+
75
75
  collection = context[@collection_name]
76
76
  collection = collection.to_a if collection.is_a?(Range)
77
-
77
+
78
78
  # Maintains Ruby 1.8.7 String#each behaviour on 1.9
79
79
  return render_else(context) unless iterable?(collection)
80
-
80
+
81
81
  from = if @attributes['offset'] == 'continue'
82
82
  context.registers[:for][@name].to_i
83
83
  else
84
84
  context[@attributes['offset']].to_i
85
85
  end
86
-
86
+
87
87
  limit = context[@attributes['limit']]
88
- to = limit ? limit.to_i + from : nil
88
+ to = limit ? limit.to_i + from : nil
89
89
 
90
90
 
91
91
  segment = Utils.slice_collection_using_each(collection, from, to)
92
92
 
93
93
  return render_else(context) if segment.empty?
94
-
94
+
95
95
  segment.reverse! if @reversed
96
96
 
97
97
  result = ''
98
-
99
- length = segment.length
100
-
98
+
99
+ length = segment.length
100
+
101
101
  # Store our progress through the collection for the continue flag
102
102
  context.registers[:for][@name] = from + segment.length
103
-
103
+
104
104
  context.stack do
105
105
  segment.each_with_index do |item, index|
106
106
  context[@variable_name] = item
107
107
  context['forloop'] = {
108
108
  'name' => @name,
109
109
  'length' => length,
110
- 'index' => index + 1,
111
- 'index0' => index,
110
+ 'index' => index + 1,
111
+ 'index0' => index,
112
112
  'rindex' => length - index,
113
113
  'rindex0' => length - index - 1,
114
114
  'first' => (index == 0),
115
- 'last' => (index == length - 1) }
115
+ 'last' => (index == length - 1) }
116
116
 
117
117
  result << render_all(@for_block, context)
118
118
 
@@ -124,8 +124,8 @@ module Liquid
124
124
  end
125
125
  end
126
126
  end
127
- result
128
- end
127
+ result
128
+ end
129
129
 
130
130
  private
131
131
 
@@ -15,7 +15,6 @@ module Liquid
15
15
  SyntaxHelp = "Syntax Error in tag 'if' - Valid syntax: if [expression]"
16
16
  Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
17
17
  ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
18
- BOOLEAN_OPERATORS = %w(and or)
19
18
 
20
19
  def initialize(tag_name, markup, tokens)
21
20
  @blocks = []
@@ -62,8 +61,7 @@ module Liquid
62
61
  raise(SyntaxError, SyntaxHelp) unless expressions.shift.to_s =~ Syntax
63
62
 
64
63
  new_condition = Condition.new($1, $2, $3)
65
- raise SyntaxError, "invalid boolean operator" unless BOOLEAN_OPERATORS.include?(operator)
66
- new_condition.send(operator, condition)
64
+ new_condition.send(operator.to_sym, condition)
67
65
  condition = new_condition
68
66
  end
69
67
 
@@ -73,6 +71,8 @@ module Liquid
73
71
  @blocks.push(block)
74
72
  @nodelist = block.attach(Array.new)
75
73
  end
74
+
75
+
76
76
  end
77
77
 
78
78
  Template.register_tag('if', If)