liquid 4.0.0 → 5.0.1

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 (123) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +101 -2
  3. data/README.md +8 -0
  4. data/lib/liquid.rb +18 -5
  5. data/lib/liquid/block.rb +47 -20
  6. data/lib/liquid/block_body.rb +192 -76
  7. data/lib/liquid/condition.rb +69 -29
  8. data/lib/liquid/context.rb +110 -53
  9. data/lib/liquid/document.rb +47 -9
  10. data/lib/liquid/drop.rb +4 -2
  11. data/lib/liquid/errors.rb +20 -18
  12. data/lib/liquid/expression.rb +30 -31
  13. data/lib/liquid/extensions.rb +8 -0
  14. data/lib/liquid/file_system.rb +6 -4
  15. data/lib/liquid/forloop_drop.rb +11 -4
  16. data/lib/liquid/i18n.rb +5 -3
  17. data/lib/liquid/interrupts.rb +3 -1
  18. data/lib/liquid/lexer.rb +35 -26
  19. data/lib/liquid/locales/en.yml +4 -2
  20. data/lib/liquid/parse_context.rb +21 -4
  21. data/lib/liquid/parse_tree_visitor.rb +42 -0
  22. data/lib/liquid/parser.rb +30 -18
  23. data/lib/liquid/parser_switching.rb +17 -3
  24. data/lib/liquid/partial_cache.rb +24 -0
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/profiler/hooks.rb +26 -14
  27. data/lib/liquid/range_lookup.rb +5 -3
  28. data/lib/liquid/register.rb +6 -0
  29. data/lib/liquid/resource_limits.rb +47 -8
  30. data/lib/liquid/standardfilters.rb +170 -63
  31. data/lib/liquid/static_registers.rb +44 -0
  32. data/lib/liquid/strainer_factory.rb +36 -0
  33. data/lib/liquid/strainer_template.rb +53 -0
  34. data/lib/liquid/tablerowloop_drop.rb +6 -4
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tag/disableable.rb +22 -0
  37. data/lib/liquid/tag/disabler.rb +21 -0
  38. data/lib/liquid/tags/assign.rb +32 -10
  39. data/lib/liquid/tags/break.rb +8 -3
  40. data/lib/liquid/tags/capture.rb +11 -8
  41. data/lib/liquid/tags/case.rb +41 -27
  42. data/lib/liquid/tags/comment.rb +5 -3
  43. data/lib/liquid/tags/continue.rb +8 -3
  44. data/lib/liquid/tags/cycle.rb +35 -16
  45. data/lib/liquid/tags/decrement.rb +6 -3
  46. data/lib/liquid/tags/echo.rb +34 -0
  47. data/lib/liquid/tags/for.rb +79 -47
  48. data/lib/liquid/tags/if.rb +53 -30
  49. data/lib/liquid/tags/ifchanged.rb +11 -10
  50. data/lib/liquid/tags/include.rb +42 -44
  51. data/lib/liquid/tags/increment.rb +7 -3
  52. data/lib/liquid/tags/raw.rb +14 -11
  53. data/lib/liquid/tags/render.rb +84 -0
  54. data/lib/liquid/tags/table_row.rb +32 -20
  55. data/lib/liquid/tags/unless.rb +15 -15
  56. data/lib/liquid/template.rb +53 -72
  57. data/lib/liquid/template_factory.rb +9 -0
  58. data/lib/liquid/tokenizer.rb +17 -9
  59. data/lib/liquid/usage.rb +8 -0
  60. data/lib/liquid/utils.rb +6 -4
  61. data/lib/liquid/variable.rb +55 -38
  62. data/lib/liquid/variable_lookup.rb +14 -6
  63. data/lib/liquid/version.rb +3 -1
  64. data/test/integration/assign_test.rb +74 -5
  65. data/test/integration/blank_test.rb +11 -8
  66. data/test/integration/block_test.rb +58 -0
  67. data/test/integration/capture_test.rb +18 -10
  68. data/test/integration/context_test.rb +609 -5
  69. data/test/integration/document_test.rb +4 -2
  70. data/test/integration/drop_test.rb +67 -83
  71. data/test/integration/error_handling_test.rb +73 -61
  72. data/test/integration/expression_test.rb +46 -0
  73. data/test/integration/filter_test.rb +53 -42
  74. data/test/integration/hash_ordering_test.rb +5 -3
  75. data/test/integration/output_test.rb +26 -24
  76. data/test/integration/parsing_quirks_test.rb +24 -8
  77. data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
  78. data/test/integration/security_test.rb +41 -18
  79. data/test/integration/standard_filter_test.rb +513 -210
  80. data/test/integration/tag/disableable_test.rb +59 -0
  81. data/test/integration/tag_test.rb +45 -0
  82. data/test/integration/tags/break_tag_test.rb +4 -2
  83. data/test/integration/tags/continue_tag_test.rb +4 -2
  84. data/test/integration/tags/echo_test.rb +13 -0
  85. data/test/integration/tags/for_tag_test.rb +109 -53
  86. data/test/integration/tags/if_else_tag_test.rb +5 -3
  87. data/test/integration/tags/include_tag_test.rb +83 -52
  88. data/test/integration/tags/increment_tag_test.rb +4 -2
  89. data/test/integration/tags/liquid_tag_test.rb +116 -0
  90. data/test/integration/tags/raw_tag_test.rb +14 -11
  91. data/test/integration/tags/render_tag_test.rb +213 -0
  92. data/test/integration/tags/standard_tag_test.rb +38 -31
  93. data/test/integration/tags/statements_test.rb +23 -21
  94. data/test/integration/tags/table_row_test.rb +2 -0
  95. data/test/integration/tags/unless_else_tag_test.rb +4 -2
  96. data/test/integration/template_test.rb +123 -120
  97. data/test/integration/trim_mode_test.rb +82 -44
  98. data/test/integration/variable_test.rb +46 -31
  99. data/test/test_helper.rb +75 -23
  100. data/test/unit/block_unit_test.rb +19 -24
  101. data/test/unit/condition_unit_test.rb +82 -72
  102. data/test/unit/file_system_unit_test.rb +6 -4
  103. data/test/unit/i18n_unit_test.rb +7 -5
  104. data/test/unit/lexer_unit_test.rb +12 -10
  105. data/test/unit/parse_tree_visitor_test.rb +254 -0
  106. data/test/unit/parser_unit_test.rb +37 -35
  107. data/test/unit/partial_cache_unit_test.rb +128 -0
  108. data/test/unit/regexp_unit_test.rb +17 -15
  109. data/test/unit/static_registers_unit_test.rb +156 -0
  110. data/test/unit/strainer_factory_unit_test.rb +100 -0
  111. data/test/unit/strainer_template_unit_test.rb +82 -0
  112. data/test/unit/tag_unit_test.rb +5 -3
  113. data/test/unit/tags/case_tag_unit_test.rb +3 -1
  114. data/test/unit/tags/for_tag_unit_test.rb +4 -2
  115. data/test/unit/tags/if_tag_unit_test.rb +3 -1
  116. data/test/unit/template_factory_unit_test.rb +12 -0
  117. data/test/unit/template_unit_test.rb +19 -10
  118. data/test/unit/tokenizer_unit_test.rb +26 -19
  119. data/test/unit/variable_unit_test.rb +51 -49
  120. metadata +79 -46
  121. data/lib/liquid/strainer.rb +0 -66
  122. data/test/unit/context_unit_test.rb +0 -483
  123. data/test/unit/strainer_unit_test.rb +0 -148
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.0
4
+ version: 5.0.1
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: 2016-12-14 00:00:00.000000000 Z
11
+ date: 2021-03-24 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,23 @@ 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/register.rb
75
78
  - lib/liquid/resource_limits.rb
76
79
  - lib/liquid/standardfilters.rb
77
- - lib/liquid/strainer.rb
80
+ - lib/liquid/static_registers.rb
81
+ - lib/liquid/strainer_factory.rb
82
+ - lib/liquid/strainer_template.rb
78
83
  - lib/liquid/tablerowloop_drop.rb
79
84
  - lib/liquid/tag.rb
85
+ - lib/liquid/tag/disableable.rb
86
+ - lib/liquid/tag/disabler.rb
80
87
  - lib/liquid/tags/assign.rb
81
88
  - lib/liquid/tags/break.rb
82
89
  - lib/liquid/tags/capture.rb
@@ -85,16 +92,20 @@ files:
85
92
  - lib/liquid/tags/continue.rb
86
93
  - lib/liquid/tags/cycle.rb
87
94
  - lib/liquid/tags/decrement.rb
95
+ - lib/liquid/tags/echo.rb
88
96
  - lib/liquid/tags/for.rb
89
97
  - lib/liquid/tags/if.rb
90
98
  - lib/liquid/tags/ifchanged.rb
91
99
  - lib/liquid/tags/include.rb
92
100
  - lib/liquid/tags/increment.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
@@ -102,25 +113,32 @@ files:
102
113
  - test/fixtures/en_locale.yml
103
114
  - test/integration/assign_test.rb
104
115
  - test/integration/blank_test.rb
116
+ - test/integration/block_test.rb
105
117
  - test/integration/capture_test.rb
106
118
  - test/integration/context_test.rb
107
119
  - test/integration/document_test.rb
108
120
  - test/integration/drop_test.rb
109
121
  - test/integration/error_handling_test.rb
122
+ - test/integration/expression_test.rb
110
123
  - test/integration/filter_test.rb
111
124
  - test/integration/hash_ordering_test.rb
112
125
  - test/integration/output_test.rb
113
126
  - test/integration/parsing_quirks_test.rb
114
- - test/integration/render_profiling_test.rb
127
+ - test/integration/profiler_test.rb
115
128
  - test/integration/security_test.rb
116
129
  - test/integration/standard_filter_test.rb
130
+ - test/integration/tag/disableable_test.rb
131
+ - test/integration/tag_test.rb
117
132
  - test/integration/tags/break_tag_test.rb
118
133
  - test/integration/tags/continue_tag_test.rb
134
+ - test/integration/tags/echo_test.rb
119
135
  - test/integration/tags/for_tag_test.rb
120
136
  - test/integration/tags/if_else_tag_test.rb
121
137
  - test/integration/tags/include_tag_test.rb
122
138
  - test/integration/tags/increment_tag_test.rb
139
+ - test/integration/tags/liquid_tag_test.rb
123
140
  - test/integration/tags/raw_tag_test.rb
141
+ - test/integration/tags/render_tag_test.rb
124
142
  - test/integration/tags/standard_tag_test.rb
125
143
  - test/integration/tags/statements_test.rb
126
144
  - test/integration/tags/table_row_test.rb
@@ -131,24 +149,29 @@ files:
131
149
  - test/test_helper.rb
132
150
  - test/unit/block_unit_test.rb
133
151
  - test/unit/condition_unit_test.rb
134
- - test/unit/context_unit_test.rb
135
152
  - test/unit/file_system_unit_test.rb
136
153
  - test/unit/i18n_unit_test.rb
137
154
  - test/unit/lexer_unit_test.rb
155
+ - test/unit/parse_tree_visitor_test.rb
138
156
  - test/unit/parser_unit_test.rb
157
+ - test/unit/partial_cache_unit_test.rb
139
158
  - test/unit/regexp_unit_test.rb
140
- - test/unit/strainer_unit_test.rb
159
+ - test/unit/static_registers_unit_test.rb
160
+ - test/unit/strainer_factory_unit_test.rb
161
+ - test/unit/strainer_template_unit_test.rb
141
162
  - test/unit/tag_unit_test.rb
142
163
  - test/unit/tags/case_tag_unit_test.rb
143
164
  - test/unit/tags/for_tag_unit_test.rb
144
165
  - test/unit/tags/if_tag_unit_test.rb
166
+ - test/unit/template_factory_unit_test.rb
145
167
  - test/unit/template_unit_test.rb
146
168
  - test/unit/tokenizer_unit_test.rb
147
169
  - test/unit/variable_unit_test.rb
148
170
  homepage: http://www.liquidmarkup.org
149
171
  licenses:
150
172
  - MIT
151
- metadata: {}
173
+ metadata:
174
+ allowed_push_host: https://rubygems.org
152
175
  post_install_message:
153
176
  rdoc_options: []
154
177
  require_paths:
@@ -157,62 +180,72 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
180
  requirements:
158
181
  - - ">="
159
182
  - !ruby/object:Gem::Version
160
- version: 2.1.0
183
+ version: 2.5.0
161
184
  required_rubygems_version: !ruby/object:Gem::Requirement
162
185
  requirements:
163
186
  - - ">="
164
187
  - !ruby/object:Gem::Version
165
188
  version: 1.3.7
166
189
  requirements: []
167
- rubyforge_project:
168
- rubygems_version: 2.4.5
190
+ rubygems_version: 3.0.3
169
191
  signing_key:
170
192
  specification_version: 4
171
193
  summary: A secure, non-evaling end user template engine with aesthetic markup.
172
194
  test_files:
173
195
  - test/fixtures/en_locale.yml
174
- - test/integration/assign_test.rb
196
+ - test/unit/condition_unit_test.rb
197
+ - test/unit/variable_unit_test.rb
198
+ - test/unit/template_unit_test.rb
199
+ - test/unit/strainer_template_unit_test.rb
200
+ - test/unit/file_system_unit_test.rb
201
+ - test/unit/static_registers_unit_test.rb
202
+ - test/unit/tags/for_tag_unit_test.rb
203
+ - test/unit/tags/if_tag_unit_test.rb
204
+ - test/unit/tags/case_tag_unit_test.rb
205
+ - test/unit/strainer_factory_unit_test.rb
206
+ - test/unit/parse_tree_visitor_test.rb
207
+ - test/unit/lexer_unit_test.rb
208
+ - test/unit/block_unit_test.rb
209
+ - test/unit/regexp_unit_test.rb
210
+ - test/unit/partial_cache_unit_test.rb
211
+ - test/unit/parser_unit_test.rb
212
+ - test/unit/tag_unit_test.rb
213
+ - test/unit/i18n_unit_test.rb
214
+ - test/unit/tokenizer_unit_test.rb
215
+ - test/unit/template_factory_unit_test.rb
216
+ - test/test_helper.rb
175
217
  - test/integration/blank_test.rb
176
- - test/integration/capture_test.rb
218
+ - test/integration/standard_filter_test.rb
219
+ - test/integration/parsing_quirks_test.rb
220
+ - test/integration/tag/disableable_test.rb
177
221
  - test/integration/context_test.rb
178
- - test/integration/document_test.rb
179
- - test/integration/drop_test.rb
180
222
  - test/integration/error_handling_test.rb
181
- - test/integration/filter_test.rb
182
- - test/integration/hash_ordering_test.rb
183
- - test/integration/output_test.rb
184
- - test/integration/parsing_quirks_test.rb
185
- - test/integration/render_profiling_test.rb
186
223
  - test/integration/security_test.rb
187
- - test/integration/standard_filter_test.rb
224
+ - test/integration/capture_test.rb
225
+ - test/integration/assign_test.rb
226
+ - test/integration/tags/increment_tag_test.rb
188
227
  - test/integration/tags/break_tag_test.rb
189
- - test/integration/tags/continue_tag_test.rb
190
- - test/integration/tags/for_tag_test.rb
191
228
  - test/integration/tags/if_else_tag_test.rb
229
+ - test/integration/tags/liquid_tag_test.rb
230
+ - test/integration/tags/for_tag_test.rb
231
+ - test/integration/tags/unless_else_tag_test.rb
192
232
  - test/integration/tags/include_tag_test.rb
193
- - test/integration/tags/increment_tag_test.rb
194
- - test/integration/tags/raw_tag_test.rb
195
- - test/integration/tags/standard_tag_test.rb
233
+ - test/integration/tags/echo_test.rb
196
234
  - test/integration/tags/statements_test.rb
235
+ - test/integration/tags/render_tag_test.rb
236
+ - test/integration/tags/raw_tag_test.rb
237
+ - test/integration/tags/continue_tag_test.rb
197
238
  - test/integration/tags/table_row_test.rb
198
- - test/integration/tags/unless_else_tag_test.rb
239
+ - test/integration/tags/standard_tag_test.rb
240
+ - test/integration/variable_test.rb
199
241
  - test/integration/template_test.rb
242
+ - test/integration/block_test.rb
243
+ - test/integration/profiler_test.rb
244
+ - test/integration/drop_test.rb
245
+ - test/integration/expression_test.rb
246
+ - test/integration/filter_test.rb
247
+ - test/integration/document_test.rb
200
248
  - test/integration/trim_mode_test.rb
201
- - test/integration/variable_test.rb
202
- - test/test_helper.rb
203
- - test/unit/block_unit_test.rb
204
- - test/unit/condition_unit_test.rb
205
- - test/unit/context_unit_test.rb
206
- - test/unit/file_system_unit_test.rb
207
- - test/unit/i18n_unit_test.rb
208
- - test/unit/lexer_unit_test.rb
209
- - test/unit/parser_unit_test.rb
210
- - test/unit/regexp_unit_test.rb
211
- - test/unit/strainer_unit_test.rb
212
- - test/unit/tag_unit_test.rb
213
- - test/unit/tags/case_tag_unit_test.rb
214
- - test/unit/tags/for_tag_unit_test.rb
215
- - test/unit/tags/if_tag_unit_test.rb
216
- - test/unit/template_unit_test.rb
217
- - test/unit/tokenizer_unit_test.rb
218
- - test/unit/variable_unit_test.rb
249
+ - test/integration/output_test.rb
250
+ - test/integration/hash_ordering_test.rb
251
+ - test/integration/tag_test.rb
@@ -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.class.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,483 +0,0 @@
1
- require 'test_helper'
2
-
3
- class HundredCentes
4
- def to_liquid
5
- 100
6
- end
7
- end
8
-
9
- class CentsDrop < Liquid::Drop
10
- def amount
11
- HundredCentes.new
12
- end
13
-
14
- def non_zero?
15
- true
16
- end
17
- end
18
-
19
- class ContextSensitiveDrop < Liquid::Drop
20
- def test
21
- @context['test']
22
- end
23
- end
24
-
25
- class Category < Liquid::Drop
26
- attr_accessor :name
27
-
28
- def initialize(name)
29
- @name = name
30
- end
31
-
32
- def to_liquid
33
- CategoryDrop.new(self)
34
- end
35
- end
36
-
37
- class CategoryDrop
38
- attr_accessor :category, :context
39
- def initialize(category)
40
- @category = category
41
- end
42
- end
43
-
44
- class CounterDrop < Liquid::Drop
45
- def count
46
- @count ||= 0
47
- @count += 1
48
- end
49
- end
50
-
51
- class ArrayLike
52
- def fetch(index)
53
- end
54
-
55
- def [](index)
56
- @counts ||= []
57
- @counts[index] ||= 0
58
- @counts[index] += 1
59
- end
60
-
61
- def to_liquid
62
- self
63
- end
64
- end
65
-
66
- class ContextUnitTest < Minitest::Test
67
- include Liquid
68
-
69
- def setup
70
- @context = Liquid::Context.new
71
- end
72
-
73
- def teardown
74
- Spy.teardown
75
- end
76
-
77
- def test_variables
78
- @context['string'] = 'string'
79
- assert_equal 'string', @context['string']
80
-
81
- @context['num'] = 5
82
- assert_equal 5, @context['num']
83
-
84
- @context['time'] = Time.parse('2006-06-06 12:00:00')
85
- assert_equal Time.parse('2006-06-06 12:00:00'), @context['time']
86
-
87
- @context['date'] = Date.today
88
- assert_equal Date.today, @context['date']
89
-
90
- now = DateTime.now
91
- @context['datetime'] = now
92
- assert_equal now, @context['datetime']
93
-
94
- @context['bool'] = true
95
- assert_equal true, @context['bool']
96
-
97
- @context['bool'] = false
98
- assert_equal false, @context['bool']
99
-
100
- @context['nil'] = nil
101
- assert_equal nil, @context['nil']
102
- assert_equal nil, @context['nil']
103
- end
104
-
105
- def test_variables_not_existing
106
- assert_equal nil, @context['does_not_exist']
107
- end
108
-
109
- def test_scoping
110
- @context.push
111
- @context.pop
112
-
113
- assert_raises(Liquid::ContextError) do
114
- @context.pop
115
- end
116
-
117
- assert_raises(Liquid::ContextError) do
118
- @context.push
119
- @context.pop
120
- @context.pop
121
- end
122
- end
123
-
124
- def test_length_query
125
- @context['numbers'] = [1, 2, 3, 4]
126
-
127
- assert_equal 4, @context['numbers.size']
128
-
129
- @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }
130
-
131
- assert_equal 4, @context['numbers.size']
132
-
133
- @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 'size' => 1000 }
134
-
135
- assert_equal 1000, @context['numbers.size']
136
- end
137
-
138
- def test_hyphenated_variable
139
- @context['oh-my'] = 'godz'
140
- assert_equal 'godz', @context['oh-my']
141
- end
142
-
143
- def test_add_filter
144
- filter = Module.new do
145
- def hi(output)
146
- output + ' hi!'
147
- end
148
- end
149
-
150
- context = Context.new
151
- context.add_filters(filter)
152
- assert_equal 'hi? hi!', context.invoke(:hi, 'hi?')
153
-
154
- context = Context.new
155
- assert_equal 'hi?', context.invoke(:hi, 'hi?')
156
-
157
- context.add_filters(filter)
158
- assert_equal 'hi? hi!', context.invoke(:hi, 'hi?')
159
- end
160
-
161
- def test_only_intended_filters_make_it_there
162
- filter = Module.new do
163
- def hi(output)
164
- output + ' hi!'
165
- end
166
- end
167
-
168
- context = Context.new
169
- assert_equal "Wookie", context.invoke("hi", "Wookie")
170
-
171
- context.add_filters(filter)
172
- assert_equal "Wookie hi!", context.invoke("hi", "Wookie")
173
- end
174
-
175
- def test_add_item_in_outer_scope
176
- @context['test'] = 'test'
177
- @context.push
178
- assert_equal 'test', @context['test']
179
- @context.pop
180
- assert_equal 'test', @context['test']
181
- end
182
-
183
- def test_add_item_in_inner_scope
184
- @context.push
185
- @context['test'] = 'test'
186
- assert_equal 'test', @context['test']
187
- @context.pop
188
- assert_equal nil, @context['test']
189
- end
190
-
191
- def test_hierachical_data
192
- @context['hash'] = { "name" => 'tobi' }
193
- assert_equal 'tobi', @context['hash.name']
194
- assert_equal 'tobi', @context['hash["name"]']
195
- end
196
-
197
- def test_keywords
198
- assert_equal true, @context['true']
199
- assert_equal false, @context['false']
200
- end
201
-
202
- def test_digits
203
- assert_equal 100, @context['100']
204
- assert_equal 100.00, @context['100.00']
205
- end
206
-
207
- def test_strings
208
- assert_equal "hello!", @context['"hello!"']
209
- assert_equal "hello!", @context["'hello!'"]
210
- end
211
-
212
- def test_merge
213
- @context.merge({ "test" => "test" })
214
- assert_equal 'test', @context['test']
215
- @context.merge({ "test" => "newvalue", "foo" => "bar" })
216
- assert_equal 'newvalue', @context['test']
217
- assert_equal 'bar', @context['foo']
218
- end
219
-
220
- def test_array_notation
221
- @context['test'] = [1, 2, 3, 4, 5]
222
-
223
- assert_equal 1, @context['test[0]']
224
- assert_equal 2, @context['test[1]']
225
- assert_equal 3, @context['test[2]']
226
- assert_equal 4, @context['test[3]']
227
- assert_equal 5, @context['test[4]']
228
- end
229
-
230
- def test_recoursive_array_notation
231
- @context['test'] = { 'test' => [1, 2, 3, 4, 5] }
232
-
233
- assert_equal 1, @context['test.test[0]']
234
-
235
- @context['test'] = [{ 'test' => 'worked' }]
236
-
237
- assert_equal 'worked', @context['test[0].test']
238
- end
239
-
240
- def test_hash_to_array_transition
241
- @context['colors'] = {
242
- 'Blue' => ['003366', '336699', '6699CC', '99CCFF'],
243
- 'Green' => ['003300', '336633', '669966', '99CC99'],
244
- 'Yellow' => ['CC9900', 'FFCC00', 'FFFF99', 'FFFFCC'],
245
- 'Red' => ['660000', '993333', 'CC6666', 'FF9999']
246
- }
247
-
248
- assert_equal '003366', @context['colors.Blue[0]']
249
- assert_equal 'FF9999', @context['colors.Red[3]']
250
- end
251
-
252
- def test_try_first
253
- @context['test'] = [1, 2, 3, 4, 5]
254
-
255
- assert_equal 1, @context['test.first']
256
- assert_equal 5, @context['test.last']
257
-
258
- @context['test'] = { 'test' => [1, 2, 3, 4, 5] }
259
-
260
- assert_equal 1, @context['test.test.first']
261
- assert_equal 5, @context['test.test.last']
262
-
263
- @context['test'] = [1]
264
- assert_equal 1, @context['test.first']
265
- assert_equal 1, @context['test.last']
266
- end
267
-
268
- def test_access_hashes_with_hash_notation
269
- @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
270
- @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] }
271
-
272
- assert_equal 5, @context['products["count"]']
273
- assert_equal 'deepsnow', @context['products["tags"][0]']
274
- assert_equal 'deepsnow', @context['products["tags"].first']
275
- assert_equal 'draft151cm', @context['product["variants"][0]["title"]']
276
- assert_equal 'element151cm', @context['product["variants"][1]["title"]']
277
- assert_equal 'draft151cm', @context['product["variants"][0]["title"]']
278
- assert_equal 'element151cm', @context['product["variants"].last["title"]']
279
- end
280
-
281
- def test_access_variable_with_hash_notation
282
- @context['foo'] = 'baz'
283
- @context['bar'] = 'foo'
284
-
285
- assert_equal 'baz', @context['["foo"]']
286
- assert_equal 'baz', @context['[bar]']
287
- end
288
-
289
- def test_access_hashes_with_hash_access_variables
290
- @context['var'] = 'tags'
291
- @context['nested'] = { 'var' => 'tags' }
292
- @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
293
-
294
- assert_equal 'deepsnow', @context['products[var].first']
295
- assert_equal 'freestyle', @context['products[nested.var].last']
296
- end
297
-
298
- def test_hash_notation_only_for_hash_access
299
- @context['array'] = [1, 2, 3, 4, 5]
300
- @context['hash'] = { 'first' => 'Hello' }
301
-
302
- assert_equal 1, @context['array.first']
303
- assert_equal nil, @context['array["first"]']
304
- assert_equal 'Hello', @context['hash["first"]']
305
- end
306
-
307
- def test_first_can_appear_in_middle_of_callchain
308
- @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] }
309
-
310
- assert_equal 'draft151cm', @context['product.variants[0].title']
311
- assert_equal 'element151cm', @context['product.variants[1].title']
312
- assert_equal 'draft151cm', @context['product.variants.first.title']
313
- assert_equal 'element151cm', @context['product.variants.last.title']
314
- end
315
-
316
- def test_cents
317
- @context.merge("cents" => HundredCentes.new)
318
- assert_equal 100, @context['cents']
319
- end
320
-
321
- def test_nested_cents
322
- @context.merge("cents" => { 'amount' => HundredCentes.new })
323
- assert_equal 100, @context['cents.amount']
324
-
325
- @context.merge("cents" => { 'cents' => { 'amount' => HundredCentes.new } })
326
- assert_equal 100, @context['cents.cents.amount']
327
- end
328
-
329
- def test_cents_through_drop
330
- @context.merge("cents" => CentsDrop.new)
331
- assert_equal 100, @context['cents.amount']
332
- end
333
-
334
- def test_nested_cents_through_drop
335
- @context.merge("vars" => { "cents" => CentsDrop.new })
336
- assert_equal 100, @context['vars.cents.amount']
337
- end
338
-
339
- def test_drop_methods_with_question_marks
340
- @context.merge("cents" => CentsDrop.new)
341
- assert @context['cents.non_zero?']
342
- end
343
-
344
- def test_context_from_within_drop
345
- @context.merge("test" => '123', "vars" => ContextSensitiveDrop.new)
346
- assert_equal '123', @context['vars.test']
347
- end
348
-
349
- def test_nested_context_from_within_drop
350
- @context.merge("test" => '123', "vars" => { "local" => ContextSensitiveDrop.new })
351
- assert_equal '123', @context['vars.local.test']
352
- end
353
-
354
- def test_ranges
355
- @context.merge("test" => '5')
356
- assert_equal (1..5), @context['(1..5)']
357
- assert_equal (1..5), @context['(1..test)']
358
- assert_equal (5..5), @context['(test..test)']
359
- end
360
-
361
- def test_cents_through_drop_nestedly
362
- @context.merge("cents" => { "cents" => CentsDrop.new })
363
- assert_equal 100, @context['cents.cents.amount']
364
-
365
- @context.merge("cents" => { "cents" => { "cents" => CentsDrop.new } })
366
- assert_equal 100, @context['cents.cents.cents.amount']
367
- end
368
-
369
- def test_drop_with_variable_called_only_once
370
- @context['counter'] = CounterDrop.new
371
-
372
- assert_equal 1, @context['counter.count']
373
- assert_equal 2, @context['counter.count']
374
- assert_equal 3, @context['counter.count']
375
- end
376
-
377
- def test_drop_with_key_called_only_once
378
- @context['counter'] = CounterDrop.new
379
-
380
- assert_equal 1, @context['counter["count"]']
381
- assert_equal 2, @context['counter["count"]']
382
- assert_equal 3, @context['counter["count"]']
383
- end
384
-
385
- def test_proc_as_variable
386
- @context['dynamic'] = proc { 'Hello' }
387
-
388
- assert_equal 'Hello', @context['dynamic']
389
- end
390
-
391
- def test_lambda_as_variable
392
- @context['dynamic'] = proc { 'Hello' }
393
-
394
- assert_equal 'Hello', @context['dynamic']
395
- end
396
-
397
- def test_nested_lambda_as_variable
398
- @context['dynamic'] = { "lambda" => proc { 'Hello' } }
399
-
400
- assert_equal 'Hello', @context['dynamic.lambda']
401
- end
402
-
403
- def test_array_containing_lambda_as_variable
404
- @context['dynamic'] = [1, 2, proc { 'Hello' }, 4, 5]
405
-
406
- assert_equal 'Hello', @context['dynamic[2]']
407
- end
408
-
409
- def test_lambda_is_called_once
410
- @context['callcount'] = proc { @global ||= 0; @global += 1; @global.to_s }
411
-
412
- assert_equal '1', @context['callcount']
413
- assert_equal '1', @context['callcount']
414
- assert_equal '1', @context['callcount']
415
-
416
- @global = nil
417
- end
418
-
419
- def test_nested_lambda_is_called_once
420
- @context['callcount'] = { "lambda" => proc { @global ||= 0; @global += 1; @global.to_s } }
421
-
422
- assert_equal '1', @context['callcount.lambda']
423
- assert_equal '1', @context['callcount.lambda']
424
- assert_equal '1', @context['callcount.lambda']
425
-
426
- @global = nil
427
- end
428
-
429
- def test_lambda_in_array_is_called_once
430
- @context['callcount'] = [1, 2, proc { @global ||= 0; @global += 1; @global.to_s }, 4, 5]
431
-
432
- assert_equal '1', @context['callcount[2]']
433
- assert_equal '1', @context['callcount[2]']
434
- assert_equal '1', @context['callcount[2]']
435
-
436
- @global = nil
437
- end
438
-
439
- def test_access_to_context_from_proc
440
- @context.registers[:magic] = 345392
441
-
442
- @context['magic'] = proc { @context.registers[:magic] }
443
-
444
- assert_equal 345392, @context['magic']
445
- end
446
-
447
- def test_to_liquid_and_context_at_first_level
448
- @context['category'] = Category.new("foobar")
449
- assert_kind_of CategoryDrop, @context['category']
450
- assert_equal @context, @context['category'].context
451
- end
452
-
453
- def test_use_empty_instead_of_any_in_interrupt_handling_to_avoid_lots_of_unnecessary_object_allocations
454
- mock_any = Spy.on_instance_method(Array, :any?)
455
- mock_empty = Spy.on_instance_method(Array, :empty?)
456
-
457
- @context.interrupt?
458
-
459
- refute mock_any.has_been_called?
460
- assert mock_empty.has_been_called?
461
- end
462
-
463
- def test_context_initialization_with_a_proc_in_environment
464
- contx = Context.new([test: ->(c) { c['poutine'] }], { test: :foo })
465
-
466
- assert contx
467
- assert_nil contx['poutine']
468
- end
469
-
470
- def test_apply_global_filter
471
- global_filter_proc = ->(output) { "#{output} filtered" }
472
-
473
- context = Context.new
474
- context.global_filter = global_filter_proc
475
-
476
- assert_equal 'hi filtered', context.apply_global_filter('hi')
477
- end
478
-
479
- def test_apply_global_filter_when_no_global_filter_exist
480
- context = Context.new
481
- assert_equal 'hi', context.apply_global_filter('hi')
482
- end
483
- end # ContextTest