liquid 4.0.1 → 5.4.0

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +142 -0
  3. data/README.md +10 -4
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +169 -56
  6. data/lib/liquid/condition.rb +59 -23
  7. data/lib/liquid/context.rb +111 -52
  8. data/lib/liquid/document.rb +47 -9
  9. data/lib/liquid/drop.rb +4 -2
  10. data/lib/liquid/errors.rb +20 -18
  11. data/lib/liquid/expression.rb +29 -33
  12. data/lib/liquid/extensions.rb +2 -0
  13. data/lib/liquid/file_system.rb +6 -4
  14. data/lib/liquid/forloop_drop.rb +54 -4
  15. data/lib/liquid/i18n.rb +5 -3
  16. data/lib/liquid/interrupts.rb +3 -1
  17. data/lib/liquid/lexer.rb +31 -24
  18. data/lib/liquid/locales/en.yml +8 -5
  19. data/lib/liquid/parse_context.rb +20 -4
  20. data/lib/liquid/parse_tree_visitor.rb +42 -0
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +17 -3
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/range_lookup.rb +13 -3
  27. data/lib/liquid/registers.rb +51 -0
  28. data/lib/liquid/resource_limits.rb +47 -8
  29. data/lib/liquid/standardfilters.rb +616 -129
  30. data/lib/liquid/strainer_factory.rb +41 -0
  31. data/lib/liquid/strainer_template.rb +62 -0
  32. data/lib/liquid/tablerowloop_drop.rb +64 -5
  33. data/lib/liquid/tag/disableable.rb +22 -0
  34. data/lib/liquid/tag/disabler.rb +21 -0
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tags/assign.rb +44 -18
  37. data/lib/liquid/tags/break.rb +16 -3
  38. data/lib/liquid/tags/capture.rb +24 -18
  39. data/lib/liquid/tags/case.rb +69 -27
  40. data/lib/liquid/tags/comment.rb +18 -3
  41. data/lib/liquid/tags/continue.rb +16 -12
  42. data/lib/liquid/tags/cycle.rb +45 -25
  43. data/lib/liquid/tags/decrement.rb +22 -20
  44. data/lib/liquid/tags/echo.rb +41 -0
  45. data/lib/liquid/tags/for.rb +97 -89
  46. data/lib/liquid/tags/if.rb +61 -35
  47. data/lib/liquid/tags/ifchanged.rb +11 -10
  48. data/lib/liquid/tags/include.rb +56 -56
  49. data/lib/liquid/tags/increment.rb +23 -17
  50. data/lib/liquid/tags/inline_comment.rb +43 -0
  51. data/lib/liquid/tags/raw.rb +25 -11
  52. data/lib/liquid/tags/render.rb +109 -0
  53. data/lib/liquid/tags/table_row.rb +53 -19
  54. data/lib/liquid/tags/unless.rb +38 -19
  55. data/lib/liquid/template.rb +52 -72
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +18 -10
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +13 -3
  60. data/lib/liquid/variable.rb +52 -41
  61. data/lib/liquid/variable_lookup.rb +24 -10
  62. data/lib/liquid/version.rb +3 -1
  63. data/lib/liquid.rb +19 -6
  64. metadata +21 -104
  65. data/lib/liquid/strainer.rb +0 -66
  66. data/test/fixtures/en_locale.yml +0 -9
  67. data/test/integration/assign_test.rb +0 -48
  68. data/test/integration/blank_test.rb +0 -106
  69. data/test/integration/block_test.rb +0 -12
  70. data/test/integration/capture_test.rb +0 -50
  71. data/test/integration/context_test.rb +0 -32
  72. data/test/integration/document_test.rb +0 -19
  73. data/test/integration/drop_test.rb +0 -273
  74. data/test/integration/error_handling_test.rb +0 -260
  75. data/test/integration/filter_test.rb +0 -178
  76. data/test/integration/hash_ordering_test.rb +0 -23
  77. data/test/integration/output_test.rb +0 -123
  78. data/test/integration/parsing_quirks_test.rb +0 -122
  79. data/test/integration/render_profiling_test.rb +0 -154
  80. data/test/integration/security_test.rb +0 -80
  81. data/test/integration/standard_filter_test.rb +0 -626
  82. data/test/integration/tags/break_tag_test.rb +0 -15
  83. data/test/integration/tags/continue_tag_test.rb +0 -15
  84. data/test/integration/tags/for_tag_test.rb +0 -410
  85. data/test/integration/tags/if_else_tag_test.rb +0 -188
  86. data/test/integration/tags/include_tag_test.rb +0 -245
  87. data/test/integration/tags/increment_tag_test.rb +0 -23
  88. data/test/integration/tags/raw_tag_test.rb +0 -31
  89. data/test/integration/tags/standard_tag_test.rb +0 -296
  90. data/test/integration/tags/statements_test.rb +0 -111
  91. data/test/integration/tags/table_row_test.rb +0 -64
  92. data/test/integration/tags/unless_else_tag_test.rb +0 -26
  93. data/test/integration/template_test.rb +0 -332
  94. data/test/integration/trim_mode_test.rb +0 -529
  95. data/test/integration/variable_test.rb +0 -96
  96. data/test/test_helper.rb +0 -116
  97. data/test/unit/block_unit_test.rb +0 -58
  98. data/test/unit/condition_unit_test.rb +0 -166
  99. data/test/unit/context_unit_test.rb +0 -489
  100. data/test/unit/file_system_unit_test.rb +0 -35
  101. data/test/unit/i18n_unit_test.rb +0 -37
  102. data/test/unit/lexer_unit_test.rb +0 -51
  103. data/test/unit/parser_unit_test.rb +0 -82
  104. data/test/unit/regexp_unit_test.rb +0 -44
  105. data/test/unit/strainer_unit_test.rb +0 -164
  106. data/test/unit/tag_unit_test.rb +0 -21
  107. data/test/unit/tags/case_tag_unit_test.rb +0 -10
  108. data/test/unit/tags/for_tag_unit_test.rb +0 -13
  109. data/test/unit/tags/if_tag_unit_test.rb +0 -8
  110. data/test/unit/template_unit_test.rb +0 -78
  111. data/test/unit/tokenizer_unit_test.rb +0 -55
  112. data/test/unit/variable_unit_test.rb +0 -162
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Liquid
2
4
  class VariableLookup
3
- SQUARE_BRACKETED = /\A\[(.*)\]\z/m
4
- COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze]
5
+ COMMAND_METHODS = ['size', 'first', 'last'].freeze
5
6
 
6
7
  attr_reader :name, :lookups
7
8
 
@@ -13,31 +14,38 @@ module Liquid
13
14
  lookups = markup.scan(VariableParser)
14
15
 
15
16
  name = lookups.shift
16
- if name =~ SQUARE_BRACKETED
17
- name = Expression.parse($1)
17
+ if name&.start_with?('[') && name&.end_with?(']')
18
+ name = Expression.parse(name[1..-2])
18
19
  end
19
20
  @name = name
20
21
 
21
- @lookups = lookups
22
+ @lookups = lookups
22
23
  @command_flags = 0
23
24
 
24
25
  @lookups.each_index do |i|
25
26
  lookup = lookups[i]
26
- if lookup =~ SQUARE_BRACKETED
27
- lookups[i] = Expression.parse($1)
27
+ if lookup&.start_with?('[') && lookup&.end_with?(']')
28
+ lookups[i] = Expression.parse(lookup[1..-2])
28
29
  elsif COMMAND_METHODS.include?(lookup)
29
30
  @command_flags |= 1 << i
30
31
  end
31
32
  end
32
33
  end
33
34
 
35
+ def lookup_command?(lookup_index)
36
+ @command_flags & (1 << lookup_index) != 0
37
+ end
38
+
34
39
  def evaluate(context)
35
- name = context.evaluate(@name)
40
+ name = context.evaluate(@name)
36
41
  object = context.find_variable(name)
37
42
 
38
43
  @lookups.each_index do |i|
39
44
  key = context.evaluate(@lookups[i])
40
45
 
46
+ # Cast "key" to its liquid value to enable it to act as a primitive value
47
+ key = Liquid::Utils.to_liquid_value(key)
48
+
41
49
  # If object is a hash- or array-like object we look for the
42
50
  # presence of the key and if its available we return it
43
51
  if object.respond_to?(:[]) &&
@@ -45,13 +53,13 @@ module Liquid
45
53
  (object.respond_to?(:fetch) && key.is_a?(Integer)))
46
54
 
47
55
  # if its a proc we will replace the entry with the proc
48
- res = context.lookup_and_evaluate(object, key)
56
+ res = context.lookup_and_evaluate(object, key)
49
57
  object = res.to_liquid
50
58
 
51
59
  # Some special cases. If the part wasn't in square brackets and
52
60
  # no key with the same name was found we interpret following calls
53
61
  # as commands and call them on the current object
54
- elsif @command_flags & (1 << i) != 0 && object.respond_to?(key)
62
+ elsif lookup_command?(i) && object.respond_to?(key)
55
63
  object = object.send(key).to_liquid
56
64
 
57
65
  # No key was present with the desired value and it wasn't one of the directly supported
@@ -78,5 +86,11 @@ module Liquid
78
86
  def state
79
87
  [@name, @lookups, @command_flags]
80
88
  end
89
+
90
+ class ParseTreeVisitor < Liquid::ParseTreeVisitor
91
+ def children
92
+ @node.lookups
93
+ end
94
+ end
81
95
  end
82
96
  end
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  module Liquid
3
- VERSION = "4.0.1"
5
+ VERSION = "5.4.0"
4
6
  end
data/lib/liquid.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright (c) 2005 Tobias Luetke
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining
@@ -21,12 +23,13 @@
21
23
 
22
24
  module Liquid
23
25
  FilterSeparator = /\|/
24
- ArgumentSeparator = ','.freeze
25
- FilterArgumentSeparator = ':'.freeze
26
- VariableAttributeSeparator = '.'.freeze
27
- WhitespaceControl = '-'.freeze
26
+ ArgumentSeparator = ','
27
+ FilterArgumentSeparator = ':'
28
+ VariableAttributeSeparator = '.'
29
+ WhitespaceControl = '-'
28
30
  TagStart = /\{\%/
29
31
  TagEnd = /\%\}/
32
+ TagName = /#|\w+/
30
33
  VariableSignature = /\(?[\w\-\.\[\]]\)?/
31
34
  VariableSegment = /[\w\-]/
32
35
  VariableStart = /\{\{/
@@ -34,17 +37,20 @@ module Liquid
34
37
  VariableIncompleteEnd = /\}\}?/
35
38
  QuotedString = /"[^"]*"|'[^']*'/
36
39
  QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
37
- TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
40
+ TagAttributes = /(\w[\w-]*)\s*\:\s*(#{QuotedFragment})/o
38
41
  AnyStartingTag = /#{TagStart}|#{VariableStart}/o
39
42
  PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om
40
43
  TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om
41
44
  VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
42
45
 
46
+ RAISE_EXCEPTION_LAMBDA = ->(_e) { raise }
47
+
43
48
  singleton_class.send(:attr_accessor, :cache_classes)
44
49
  self.cache_classes = true
45
50
  end
46
51
 
47
52
  require "liquid/version"
53
+ require 'liquid/parse_tree_visitor'
48
54
  require 'liquid/lexer'
49
55
  require 'liquid/parser'
50
56
  require 'liquid/i18n'
@@ -54,11 +60,14 @@ require 'liquid/forloop_drop'
54
60
  require 'liquid/extensions'
55
61
  require 'liquid/errors'
56
62
  require 'liquid/interrupts'
57
- require 'liquid/strainer'
63
+ require 'liquid/strainer_template'
64
+ require 'liquid/strainer_factory'
58
65
  require 'liquid/expression'
59
66
  require 'liquid/context'
60
67
  require 'liquid/parser_switching'
61
68
  require 'liquid/tag'
69
+ require 'liquid/tag/disabler'
70
+ require 'liquid/tag/disableable'
62
71
  require 'liquid/block'
63
72
  require 'liquid/block_body'
64
73
  require 'liquid/document'
@@ -73,6 +82,10 @@ require 'liquid/condition'
73
82
  require 'liquid/utils'
74
83
  require 'liquid/tokenizer'
75
84
  require 'liquid/parse_context'
85
+ require 'liquid/partial_cache'
86
+ require 'liquid/usage'
87
+ require 'liquid/registers'
88
+ require 'liquid/template_factory'
76
89
 
77
90
  # Load all the tags of the standard library
78
91
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liquid
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Lütke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-09 00:00:00.000000000 Z
11
+ date: 2022-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '11.3'
19
+ version: '13.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '11.3'
26
+ version: '13.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -67,16 +67,22 @@ files:
67
67
  - lib/liquid/lexer.rb
68
68
  - lib/liquid/locales/en.yml
69
69
  - lib/liquid/parse_context.rb
70
+ - lib/liquid/parse_tree_visitor.rb
70
71
  - lib/liquid/parser.rb
71
72
  - lib/liquid/parser_switching.rb
73
+ - lib/liquid/partial_cache.rb
72
74
  - lib/liquid/profiler.rb
73
75
  - lib/liquid/profiler/hooks.rb
74
76
  - lib/liquid/range_lookup.rb
77
+ - lib/liquid/registers.rb
75
78
  - lib/liquid/resource_limits.rb
76
79
  - lib/liquid/standardfilters.rb
77
- - lib/liquid/strainer.rb
80
+ - lib/liquid/strainer_factory.rb
81
+ - lib/liquid/strainer_template.rb
78
82
  - lib/liquid/tablerowloop_drop.rb
79
83
  - lib/liquid/tag.rb
84
+ - lib/liquid/tag/disableable.rb
85
+ - lib/liquid/tag/disabler.rb
80
86
  - lib/liquid/tags/assign.rb
81
87
  - lib/liquid/tags/break.rb
82
88
  - lib/liquid/tags/capture.rb
@@ -85,71 +91,30 @@ files:
85
91
  - lib/liquid/tags/continue.rb
86
92
  - lib/liquid/tags/cycle.rb
87
93
  - lib/liquid/tags/decrement.rb
94
+ - lib/liquid/tags/echo.rb
88
95
  - lib/liquid/tags/for.rb
89
96
  - lib/liquid/tags/if.rb
90
97
  - lib/liquid/tags/ifchanged.rb
91
98
  - lib/liquid/tags/include.rb
92
99
  - lib/liquid/tags/increment.rb
100
+ - lib/liquid/tags/inline_comment.rb
93
101
  - lib/liquid/tags/raw.rb
102
+ - lib/liquid/tags/render.rb
94
103
  - lib/liquid/tags/table_row.rb
95
104
  - lib/liquid/tags/unless.rb
96
105
  - lib/liquid/template.rb
106
+ - lib/liquid/template_factory.rb
97
107
  - lib/liquid/tokenizer.rb
108
+ - lib/liquid/usage.rb
98
109
  - lib/liquid/utils.rb
99
110
  - lib/liquid/variable.rb
100
111
  - lib/liquid/variable_lookup.rb
101
112
  - lib/liquid/version.rb
102
- - test/fixtures/en_locale.yml
103
- - test/integration/assign_test.rb
104
- - test/integration/blank_test.rb
105
- - test/integration/block_test.rb
106
- - test/integration/capture_test.rb
107
- - test/integration/context_test.rb
108
- - test/integration/document_test.rb
109
- - test/integration/drop_test.rb
110
- - test/integration/error_handling_test.rb
111
- - test/integration/filter_test.rb
112
- - test/integration/hash_ordering_test.rb
113
- - test/integration/output_test.rb
114
- - test/integration/parsing_quirks_test.rb
115
- - test/integration/render_profiling_test.rb
116
- - test/integration/security_test.rb
117
- - test/integration/standard_filter_test.rb
118
- - test/integration/tags/break_tag_test.rb
119
- - test/integration/tags/continue_tag_test.rb
120
- - test/integration/tags/for_tag_test.rb
121
- - test/integration/tags/if_else_tag_test.rb
122
- - test/integration/tags/include_tag_test.rb
123
- - test/integration/tags/increment_tag_test.rb
124
- - test/integration/tags/raw_tag_test.rb
125
- - test/integration/tags/standard_tag_test.rb
126
- - test/integration/tags/statements_test.rb
127
- - test/integration/tags/table_row_test.rb
128
- - test/integration/tags/unless_else_tag_test.rb
129
- - test/integration/template_test.rb
130
- - test/integration/trim_mode_test.rb
131
- - test/integration/variable_test.rb
132
- - test/test_helper.rb
133
- - test/unit/block_unit_test.rb
134
- - test/unit/condition_unit_test.rb
135
- - test/unit/context_unit_test.rb
136
- - test/unit/file_system_unit_test.rb
137
- - test/unit/i18n_unit_test.rb
138
- - test/unit/lexer_unit_test.rb
139
- - test/unit/parser_unit_test.rb
140
- - test/unit/regexp_unit_test.rb
141
- - test/unit/strainer_unit_test.rb
142
- - test/unit/tag_unit_test.rb
143
- - test/unit/tags/case_tag_unit_test.rb
144
- - test/unit/tags/for_tag_unit_test.rb
145
- - test/unit/tags/if_tag_unit_test.rb
146
- - test/unit/template_unit_test.rb
147
- - test/unit/tokenizer_unit_test.rb
148
- - test/unit/variable_unit_test.rb
149
113
  homepage: http://www.liquidmarkup.org
150
114
  licenses:
151
115
  - MIT
152
- metadata: {}
116
+ metadata:
117
+ allowed_push_host: https://rubygems.org
153
118
  post_install_message:
154
119
  rdoc_options: []
155
120
  require_paths:
@@ -158,63 +123,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
123
  requirements:
159
124
  - - ">="
160
125
  - !ruby/object:Gem::Version
161
- version: 2.1.0
126
+ version: 2.7.0
162
127
  required_rubygems_version: !ruby/object:Gem::Requirement
163
128
  requirements:
164
129
  - - ">="
165
130
  - !ruby/object:Gem::Version
166
131
  version: 1.3.7
167
132
  requirements: []
168
- rubyforge_project:
169
- rubygems_version: 2.7.6
133
+ rubygems_version: 3.3.3
170
134
  signing_key:
171
135
  specification_version: 4
172
136
  summary: A secure, non-evaling end user template engine with aesthetic markup.
173
- test_files:
174
- - test/unit/lexer_unit_test.rb
175
- - test/unit/block_unit_test.rb
176
- - test/unit/variable_unit_test.rb
177
- - test/unit/parser_unit_test.rb
178
- - test/unit/tags/if_tag_unit_test.rb
179
- - test/unit/tags/case_tag_unit_test.rb
180
- - test/unit/tags/for_tag_unit_test.rb
181
- - test/unit/context_unit_test.rb
182
- - test/unit/tokenizer_unit_test.rb
183
- - test/unit/tag_unit_test.rb
184
- - test/unit/i18n_unit_test.rb
185
- - test/unit/template_unit_test.rb
186
- - test/unit/condition_unit_test.rb
187
- - test/unit/file_system_unit_test.rb
188
- - test/unit/regexp_unit_test.rb
189
- - test/unit/strainer_unit_test.rb
190
- - test/integration/output_test.rb
191
- - test/integration/hash_ordering_test.rb
192
- - test/integration/variable_test.rb
193
- - test/integration/blank_test.rb
194
- - test/integration/assign_test.rb
195
- - test/integration/trim_mode_test.rb
196
- - test/integration/context_test.rb
197
- - test/integration/capture_test.rb
198
- - test/integration/tags/increment_tag_test.rb
199
- - test/integration/tags/for_tag_test.rb
200
- - test/integration/tags/standard_tag_test.rb
201
- - test/integration/tags/table_row_test.rb
202
- - test/integration/tags/include_tag_test.rb
203
- - test/integration/tags/raw_tag_test.rb
204
- - test/integration/tags/statements_test.rb
205
- - test/integration/tags/if_else_tag_test.rb
206
- - test/integration/tags/unless_else_tag_test.rb
207
- - test/integration/tags/continue_tag_test.rb
208
- - test/integration/tags/break_tag_test.rb
209
- - test/integration/block_test.rb
210
- - test/integration/standard_filter_test.rb
211
- - test/integration/drop_test.rb
212
- - test/integration/error_handling_test.rb
213
- - test/integration/template_test.rb
214
- - test/integration/document_test.rb
215
- - test/integration/security_test.rb
216
- - test/integration/render_profiling_test.rb
217
- - test/integration/parsing_quirks_test.rb
218
- - test/integration/filter_test.rb
219
- - test/fixtures/en_locale.yml
220
- - test/test_helper.rb
137
+ test_files: []
@@ -1,66 +0,0 @@
1
- require 'set'
2
-
3
- module Liquid
4
- # Strainer is the parent class for the filters system.
5
- # New filters are mixed into the strainer class which is then instantiated for each liquid template render run.
6
- #
7
- # The Strainer only allows method calls defined in filters given to it via Strainer.global_filter,
8
- # Context#add_filters or Template.register_filter
9
- class Strainer #:nodoc:
10
- @@global_strainer = Class.new(Strainer) do
11
- @filter_methods = Set.new
12
- end
13
- @@strainer_class_cache = Hash.new do |hash, filters|
14
- hash[filters] = Class.new(@@global_strainer) do
15
- @filter_methods = @@global_strainer.filter_methods.dup
16
- filters.each { |f| add_filter(f) }
17
- end
18
- end
19
-
20
- def initialize(context)
21
- @context = context
22
- end
23
-
24
- class << self
25
- attr_reader :filter_methods
26
- end
27
-
28
- def self.add_filter(filter)
29
- raise ArgumentError, "Expected module but got: #{filter.class}" unless filter.is_a?(Module)
30
- unless self.include?(filter)
31
- invokable_non_public_methods = (filter.private_instance_methods + filter.protected_instance_methods).select { |m| invokable?(m) }
32
- if invokable_non_public_methods.any?
33
- raise MethodOverrideError, "Filter overrides registered public methods as non public: #{invokable_non_public_methods.join(', ')}"
34
- else
35
- send(:include, filter)
36
- @filter_methods.merge(filter.public_instance_methods.map(&:to_s))
37
- end
38
- end
39
- end
40
-
41
- def self.global_filter(filter)
42
- @@strainer_class_cache.clear
43
- @@global_strainer.add_filter(filter)
44
- end
45
-
46
- def self.invokable?(method)
47
- @filter_methods.include?(method.to_s)
48
- end
49
-
50
- def self.create(context, filters = [])
51
- @@strainer_class_cache[filters].new(context)
52
- end
53
-
54
- def invoke(method, *args)
55
- if self.class.invokable?(method)
56
- send(method, *args)
57
- elsif @context && @context.strict_filters
58
- raise Liquid::UndefinedFilter, "undefined filter #{method}"
59
- else
60
- args.first
61
- end
62
- rescue ::ArgumentError => e
63
- raise Liquid::ArgumentError, e.message, e.backtrace
64
- end
65
- end
66
- end
@@ -1,9 +0,0 @@
1
- ---
2
- simple: "less is more"
3
- whatever: "something %{something}"
4
- errors:
5
- i18n:
6
- undefined_interpolation: "undefined key %{key}"
7
- unknown_translation: "translation '%{name}' wasn't found"
8
- syntax:
9
- oops: "something wasn't right"
@@ -1,48 +0,0 @@
1
- require 'test_helper'
2
-
3
- class AssignTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_assign_with_hyphen_in_variable_name
7
- template_source = <<-END_TEMPLATE
8
- {% assign this-thing = 'Print this-thing' %}
9
- {{ this-thing }}
10
- END_TEMPLATE
11
- template = Template.parse(template_source)
12
- rendered = template.render!
13
- assert_equal "Print this-thing", rendered.strip
14
- end
15
-
16
- def test_assigned_variable
17
- assert_template_result('.foo.',
18
- '{% assign foo = values %}.{{ foo[0] }}.',
19
- 'values' => %w(foo bar baz))
20
-
21
- assert_template_result('.bar.',
22
- '{% assign foo = values %}.{{ foo[1] }}.',
23
- 'values' => %w(foo bar baz))
24
- end
25
-
26
- def test_assign_with_filter
27
- assert_template_result('.bar.',
28
- '{% assign foo = values | split: "," %}.{{ foo[1] }}.',
29
- 'values' => "foo,bar,baz")
30
- end
31
-
32
- def test_assign_syntax_error
33
- assert_match_syntax_error(/assign/,
34
- '{% assign foo not values %}.',
35
- 'values' => "foo,bar,baz")
36
- end
37
-
38
- def test_assign_uses_error_mode
39
- with_error_mode(:strict) do
40
- assert_raises(SyntaxError) do
41
- Template.parse("{% assign foo = ('X' | downcase) %}")
42
- end
43
- end
44
- with_error_mode(:lax) do
45
- assert Template.parse("{% assign foo = ('X' | downcase) %}")
46
- end
47
- end
48
- end # AssignTest
@@ -1,106 +0,0 @@
1
- require 'test_helper'
2
-
3
- class FoobarTag < Liquid::Tag
4
- def render(*args)
5
- " "
6
- end
7
-
8
- Liquid::Template.register_tag('foobar', FoobarTag)
9
- end
10
-
11
- class BlankTestFileSystem
12
- def read_template_file(template_path)
13
- template_path
14
- end
15
- end
16
-
17
- class BlankTest < Minitest::Test
18
- include Liquid
19
- N = 10
20
-
21
- def wrap_in_for(body)
22
- "{% for i in (1..#{N}) %}#{body}{% endfor %}"
23
- end
24
-
25
- def wrap_in_if(body)
26
- "{% if true %}#{body}{% endif %}"
27
- end
28
-
29
- def wrap(body)
30
- wrap_in_for(body) + wrap_in_if(body)
31
- end
32
-
33
- def test_new_tags_are_not_blank_by_default
34
- assert_template_result(" " * N, wrap_in_for("{% foobar %}"))
35
- end
36
-
37
- def test_loops_are_blank
38
- assert_template_result("", wrap_in_for(" "))
39
- end
40
-
41
- def test_if_else_are_blank
42
- assert_template_result("", "{% if true %} {% elsif false %} {% else %} {% endif %}")
43
- end
44
-
45
- def test_unless_is_blank
46
- assert_template_result("", wrap("{% unless true %} {% endunless %}"))
47
- end
48
-
49
- def test_mark_as_blank_only_during_parsing
50
- assert_template_result(" " * (N + 1), wrap(" {% if false %} this never happens, but still, this block is not blank {% endif %}"))
51
- end
52
-
53
- def test_comments_are_blank
54
- assert_template_result("", wrap(" {% comment %} whatever {% endcomment %} "))
55
- end
56
-
57
- def test_captures_are_blank
58
- assert_template_result("", wrap(" {% capture foo %} whatever {% endcapture %} "))
59
- end
60
-
61
- def test_nested_blocks_are_blank_but_only_if_all_children_are
62
- assert_template_result("", wrap(wrap(" ")))
63
- assert_template_result("\n but this is not " * (N + 1),
64
- wrap('{% if true %} {% comment %} this is blank {% endcomment %} {% endif %}
65
- {% if true %} but this is not {% endif %}'))
66
- end
67
-
68
- def test_assigns_are_blank
69
- assert_template_result("", wrap(' {% assign foo = "bar" %} '))
70
- end
71
-
72
- def test_whitespace_is_blank
73
- assert_template_result("", wrap(" "))
74
- assert_template_result("", wrap("\t"))
75
- end
76
-
77
- def test_whitespace_is_not_blank_if_other_stuff_is_present
78
- body = " x "
79
- assert_template_result(body * (N + 1), wrap(body))
80
- end
81
-
82
- def test_increment_is_not_blank
83
- assert_template_result(" 0" * 2 * (N + 1), wrap("{% assign foo = 0 %} {% increment foo %} {% decrement foo %}"))
84
- end
85
-
86
- def test_cycle_is_not_blank
87
- assert_template_result(" " * ((N + 1) / 2) + " ", wrap("{% cycle ' ', ' ' %}"))
88
- end
89
-
90
- def test_raw_is_not_blank
91
- assert_template_result(" " * (N + 1), wrap(" {% raw %} {% endraw %}"))
92
- end
93
-
94
- def test_include_is_blank
95
- Liquid::Template.file_system = BlankTestFileSystem.new
96
- assert_template_result "foobar" * (N + 1), wrap("{% include 'foobar' %}")
97
- assert_template_result " foobar " * (N + 1), wrap("{% include ' foobar ' %}")
98
- assert_template_result " " * (N + 1), wrap(" {% include ' ' %} ")
99
- end
100
-
101
- def test_case_is_blank
102
- assert_template_result("", wrap(" {% assign foo = 'bar' %} {% case foo %} {% when 'bar' %} {% when 'whatever' %} {% else %} {% endcase %} "))
103
- assert_template_result("", wrap(" {% assign foo = 'else' %} {% case foo %} {% when 'bar' %} {% when 'whatever' %} {% else %} {% endcase %} "))
104
- assert_template_result(" x " * (N + 1), wrap(" {% assign foo = 'else' %} {% case foo %} {% when 'bar' %} {% when 'whatever' %} {% else %} x {% endcase %} "))
105
- end
106
- end
@@ -1,12 +0,0 @@
1
- require 'test_helper'
2
-
3
- class BlockTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_unexpected_end_tag
7
- exc = assert_raises(SyntaxError) do
8
- Template.parse("{% if true %}{% endunless %}")
9
- end
10
- assert_equal exc.message, "Liquid syntax error: 'endunless' is not a valid delimiter for if tags. use endif"
11
- end
12
- end
@@ -1,50 +0,0 @@
1
- require 'test_helper'
2
-
3
- class CaptureTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_captures_block_content_in_variable
7
- assert_template_result("test string", "{% capture 'var' %}test string{% endcapture %}{{var}}", {})
8
- end
9
-
10
- def test_capture_with_hyphen_in_variable_name
11
- template_source = <<-END_TEMPLATE
12
- {% capture this-thing %}Print this-thing{% endcapture %}
13
- {{ this-thing }}
14
- END_TEMPLATE
15
- template = Template.parse(template_source)
16
- rendered = template.render!
17
- assert_equal "Print this-thing", rendered.strip
18
- end
19
-
20
- def test_capture_to_variable_from_outer_scope_if_existing
21
- template_source = <<-END_TEMPLATE
22
- {% assign var = '' %}
23
- {% if true %}
24
- {% capture var %}first-block-string{% endcapture %}
25
- {% endif %}
26
- {% if true %}
27
- {% capture var %}test-string{% endcapture %}
28
- {% endif %}
29
- {{var}}
30
- END_TEMPLATE
31
- template = Template.parse(template_source)
32
- rendered = template.render!
33
- assert_equal "test-string", rendered.gsub(/\s/, '')
34
- end
35
-
36
- def test_assigning_from_capture
37
- template_source = <<-END_TEMPLATE
38
- {% assign first = '' %}
39
- {% assign second = '' %}
40
- {% for number in (1..3) %}
41
- {% capture first %}{{number}}{% endcapture %}
42
- {% assign second = first %}
43
- {% endfor %}
44
- {{ first }}-{{ second }}
45
- END_TEMPLATE
46
- template = Template.parse(template_source)
47
- rendered = template.render!
48
- assert_equal "3-3", rendered.gsub(/\s/, '')
49
- end
50
- end # CaptureTest