liquid 4.0.0 → 5.10.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.
- checksums.yaml +5 -5
- data/History.md +235 -2
- data/README.md +58 -8
- data/lib/liquid/block.rb +51 -20
- data/lib/liquid/block_body.rb +216 -82
- data/lib/liquid/condition.rb +83 -32
- data/lib/liquid/const.rb +8 -0
- data/lib/liquid/context.rb +130 -59
- data/lib/liquid/deprecations.rb +22 -0
- data/lib/liquid/document.rb +47 -9
- data/lib/liquid/drop.rb +8 -2
- data/lib/liquid/environment.rb +159 -0
- data/lib/liquid/errors.rb +23 -20
- data/lib/liquid/expression.rb +114 -31
- data/lib/liquid/extensions.rb +8 -0
- data/lib/liquid/file_system.rb +6 -4
- data/lib/liquid/forloop_drop.rb +51 -4
- data/lib/liquid/i18n.rb +5 -3
- data/lib/liquid/interrupts.rb +3 -1
- data/lib/liquid/lexer.rb +165 -39
- data/lib/liquid/locales/en.yml +16 -6
- data/lib/liquid/parse_context.rb +62 -7
- data/lib/liquid/parse_tree_visitor.rb +42 -0
- data/lib/liquid/parser.rb +31 -19
- data/lib/liquid/parser_switching.rb +42 -3
- data/lib/liquid/partial_cache.rb +33 -0
- data/lib/liquid/profiler/hooks.rb +26 -14
- data/lib/liquid/profiler.rb +67 -86
- data/lib/liquid/range_lookup.rb +26 -6
- data/lib/liquid/registers.rb +51 -0
- data/lib/liquid/resource_limits.rb +47 -8
- data/lib/liquid/snippet_drop.rb +22 -0
- data/lib/liquid/standardfilters.rb +813 -137
- data/lib/liquid/strainer_template.rb +62 -0
- data/lib/liquid/tablerowloop_drop.rb +64 -5
- data/lib/liquid/tag/disableable.rb +22 -0
- data/lib/liquid/tag/disabler.rb +13 -0
- data/lib/liquid/tag.rb +42 -6
- data/lib/liquid/tags/assign.rb +46 -18
- data/lib/liquid/tags/break.rb +15 -4
- data/lib/liquid/tags/capture.rb +26 -18
- data/lib/liquid/tags/case.rb +108 -32
- data/lib/liquid/tags/comment.rb +76 -4
- data/lib/liquid/tags/continue.rb +15 -13
- data/lib/liquid/tags/cycle.rb +117 -34
- data/lib/liquid/tags/decrement.rb +30 -23
- data/lib/liquid/tags/doc.rb +81 -0
- data/lib/liquid/tags/echo.rb +39 -0
- data/lib/liquid/tags/for.rb +109 -96
- data/lib/liquid/tags/if.rb +72 -41
- data/lib/liquid/tags/ifchanged.rb +10 -11
- data/lib/liquid/tags/include.rb +89 -63
- data/lib/liquid/tags/increment.rb +31 -20
- data/lib/liquid/tags/inline_comment.rb +28 -0
- data/lib/liquid/tags/raw.rb +25 -13
- data/lib/liquid/tags/render.rb +151 -0
- data/lib/liquid/tags/snippet.rb +45 -0
- data/lib/liquid/tags/table_row.rb +104 -21
- data/lib/liquid/tags/unless.rb +37 -20
- data/lib/liquid/tags.rb +51 -0
- data/lib/liquid/template.rb +90 -106
- data/lib/liquid/template_factory.rb +9 -0
- data/lib/liquid/tokenizer.rb +143 -13
- data/lib/liquid/usage.rb +8 -0
- data/lib/liquid/utils.rb +114 -5
- data/lib/liquid/variable.rb +119 -45
- data/lib/liquid/variable_lookup.rb +35 -13
- data/lib/liquid/version.rb +3 -1
- data/lib/liquid.rb +31 -18
- metadata +56 -107
- data/lib/liquid/strainer.rb +0 -66
- data/test/fixtures/en_locale.yml +0 -9
- data/test/integration/assign_test.rb +0 -48
- data/test/integration/blank_test.rb +0 -106
- data/test/integration/capture_test.rb +0 -50
- data/test/integration/context_test.rb +0 -32
- data/test/integration/document_test.rb +0 -19
- data/test/integration/drop_test.rb +0 -273
- data/test/integration/error_handling_test.rb +0 -260
- data/test/integration/filter_test.rb +0 -178
- data/test/integration/hash_ordering_test.rb +0 -23
- data/test/integration/output_test.rb +0 -123
- data/test/integration/parsing_quirks_test.rb +0 -118
- data/test/integration/render_profiling_test.rb +0 -154
- data/test/integration/security_test.rb +0 -66
- data/test/integration/standard_filter_test.rb +0 -535
- data/test/integration/tags/break_tag_test.rb +0 -15
- data/test/integration/tags/continue_tag_test.rb +0 -15
- data/test/integration/tags/for_tag_test.rb +0 -410
- data/test/integration/tags/if_else_tag_test.rb +0 -188
- data/test/integration/tags/include_tag_test.rb +0 -238
- data/test/integration/tags/increment_tag_test.rb +0 -23
- data/test/integration/tags/raw_tag_test.rb +0 -31
- data/test/integration/tags/standard_tag_test.rb +0 -296
- data/test/integration/tags/statements_test.rb +0 -111
- data/test/integration/tags/table_row_test.rb +0 -64
- data/test/integration/tags/unless_else_tag_test.rb +0 -26
- data/test/integration/template_test.rb +0 -323
- data/test/integration/trim_mode_test.rb +0 -525
- data/test/integration/variable_test.rb +0 -92
- data/test/test_helper.rb +0 -117
- data/test/unit/block_unit_test.rb +0 -58
- data/test/unit/condition_unit_test.rb +0 -158
- data/test/unit/context_unit_test.rb +0 -483
- data/test/unit/file_system_unit_test.rb +0 -35
- data/test/unit/i18n_unit_test.rb +0 -37
- data/test/unit/lexer_unit_test.rb +0 -51
- data/test/unit/parser_unit_test.rb +0 -82
- data/test/unit/regexp_unit_test.rb +0 -44
- data/test/unit/strainer_unit_test.rb +0 -148
- data/test/unit/tag_unit_test.rb +0 -21
- data/test/unit/tags/case_tag_unit_test.rb +0 -10
- data/test/unit/tags/for_tag_unit_test.rb +0 -13
- data/test/unit/tags/if_tag_unit_test.rb +0 -8
- data/test/unit/template_unit_test.rb +0 -78
- data/test/unit/tokenizer_unit_test.rb +0 -55
- data/test/unit/variable_unit_test.rb +0 -162
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1b12ad70375f0ed9e3a2bab4a0a53ea565f3082af8d5bc06f4dea13a0a4ac574
|
|
4
|
+
data.tar.gz: 04c2f7494b1ab0f97a2a33ad9d39c9c573a33b42bd109df8d42bb5e26d245f01
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc94bd83ae20e716eabf8ab2ce9f1fe9f8ff45dee6e0acac91f9095c32557c94d08e5a3c1b473c268c5a6a6d63a4d4ca10170406f062545545f63c1980a4d392
|
|
7
|
+
data.tar.gz: 0f19c1d79039fda7a6e485cf794cde252817dc43bd292351b7bc53d1adabd12919e18cc0870fcf3db3c0018e22ef91a1507ded76b27719fb30b79414e04d3d2f
|
data/History.md
CHANGED
|
@@ -1,6 +1,236 @@
|
|
|
1
1
|
# Liquid Change Log
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 5.10.0
|
|
4
|
+
* Introduce support for Inline Snippets [Julia Boutin]
|
|
5
|
+
```
|
|
6
|
+
{%- snippet snowdevil -%}
|
|
7
|
+
Snowdevil
|
|
8
|
+
{%- endsnippet -%}
|
|
9
|
+
{% render snowdevil %}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 5.9.0
|
|
13
|
+
* Introduce `:rigid` error mode for stricter, safer parsing of all tags [CP Clermont, Guilherme Carreiro]
|
|
14
|
+
|
|
15
|
+
## 5.8.7
|
|
16
|
+
* Expose body content in the `Doc` tag [James Meng]
|
|
17
|
+
|
|
18
|
+
## 5.8.1
|
|
19
|
+
|
|
20
|
+
* Fix `{% doc %}` tag to be visitable [Guilherme Carreiro]
|
|
21
|
+
|
|
22
|
+
## 5.8.0
|
|
23
|
+
|
|
24
|
+
* Introduce the new `{% doc %}` tag [Guilherme Carreiro]
|
|
25
|
+
|
|
26
|
+
## 5.7.3
|
|
27
|
+
|
|
28
|
+
* Raise Liquid::SyntaxError when parsing invalidly encoded strings [Chris AtLee]
|
|
29
|
+
|
|
30
|
+
## 5.7.2 2025-01-31
|
|
31
|
+
|
|
32
|
+
* Fix array filters to not support nested properties [Guilherme Carreiro]
|
|
33
|
+
|
|
34
|
+
## 5.7.1 2025-01-24
|
|
35
|
+
|
|
36
|
+
* Fix the `find` and `find_index`filters to return `nil` when filtering empty arrays [Guilherme Carreiro]
|
|
37
|
+
* Fix the `has` filter to return `false` when filtering empty arrays [Guilherme Carreiro]
|
|
38
|
+
|
|
39
|
+
## 5.7.0 2025-01-16
|
|
40
|
+
|
|
41
|
+
### Features
|
|
42
|
+
|
|
43
|
+
* Add `find`, `find_index`, `has`, and `reject` filters to arrays [Guilherme Carreiro]
|
|
44
|
+
* Compatibility with Ruby 3.4 [Ian Ker-Seymer]
|
|
45
|
+
|
|
46
|
+
## 5.6.4 2025-01-14
|
|
47
|
+
|
|
48
|
+
### Fixes
|
|
49
|
+
* Add a default `string_scanner` to avoid errors with `Liquid::VariableLookup.parse("foo.bar")` [Ian Ker-Seymer]
|
|
50
|
+
|
|
51
|
+
## 5.6.3 2025-01-13
|
|
52
|
+
* Remove `lru_redux` dependency [Michael Go]
|
|
53
|
+
|
|
54
|
+
## 5.6.2 2025-01-13
|
|
55
|
+
|
|
56
|
+
### Fixes
|
|
57
|
+
* Preserve the old behavior of requiring floats to start with a digit [Michael Go]
|
|
58
|
+
|
|
59
|
+
## 5.6.1 2025-01-13
|
|
60
|
+
|
|
61
|
+
### Performance improvements
|
|
62
|
+
* Faster Expression parser / Tokenizer with StringScanner [Michael Go]
|
|
63
|
+
|
|
64
|
+
## 5.6.0 2024-12-19
|
|
65
|
+
|
|
66
|
+
### Architectural changes
|
|
67
|
+
* Added new `Environment` class to manage configuration and state that was previously stored in `Template` [Ian Ker-Seymer]
|
|
68
|
+
* Moved tag registration from `Template` to `Environment` [Ian Ker-Seymer]
|
|
69
|
+
* Removed `StrainerFactory` in favor of `Environment`-based strainer creation [Ian Ker-Seymer]
|
|
70
|
+
* Consolidated standard tags into a new `Tags` module with `STANDARD_TAGS` constant [Ian Ker-Seymer]
|
|
71
|
+
|
|
72
|
+
### Performance improvements
|
|
73
|
+
* Optimized `Lexer` with a new `Lexer2` implementation using jump tables for faster tokenization, requires Ruby 3.4 [Ian Ker-Seymer]
|
|
74
|
+
* Improved variable rendering with specialized handling for different types [Michael Go]
|
|
75
|
+
* Reduced array allocations by using frozen empty constants [Michael Go]
|
|
76
|
+
|
|
77
|
+
### API changes
|
|
78
|
+
* Deprecated several `Template` class methods in favor of `Environment` methods [Ian Ker-Seymer]
|
|
79
|
+
* Added deprecation warnings system [Ian Ker-Seymer]
|
|
80
|
+
* Changed how filters and tags are registered to use Environment [Ian Ker-Seymer]
|
|
81
|
+
|
|
82
|
+
### Fixes
|
|
83
|
+
* Fixed table row handling of break interrupts [Alex Coco]
|
|
84
|
+
* Improved variable output handling for arrays [Ian Ker-Seymer]
|
|
85
|
+
* Fix Tokenizer to handle null source value (#1873) [Bahar Pourazar]
|
|
86
|
+
|
|
87
|
+
## 5.5.0 2024-03-21
|
|
88
|
+
|
|
89
|
+
Please reference the GitHub release for more information.
|
|
90
|
+
|
|
91
|
+
## 5.4.0 2022-07-29
|
|
92
|
+
|
|
93
|
+
### Breaking Changes
|
|
94
|
+
* Drop support for end-of-life Ruby versions (2.5 and 2.6) (#1578) [Andy Waite]
|
|
95
|
+
|
|
96
|
+
### Features
|
|
97
|
+
* Allow `#` to be used as an inline comment tag (#1498) [CP Clermont]
|
|
98
|
+
|
|
99
|
+
### Fixes
|
|
100
|
+
* `PartialCache` now shares snippet cache with subcontexts by default (#1553) [Chris AtLee]
|
|
101
|
+
* Hash registers no longer leak into subcontexts as static registers (#1564) [Chris AtLee]
|
|
102
|
+
* Fix `ParseTreeVisitor` for `with` variable expressions in `Render` tag (#1596) [CP Clermont]
|
|
103
|
+
|
|
104
|
+
### Changed
|
|
105
|
+
* Liquid::Context#registers now always returns a Liquid::Registers object, though supports the most used Hash functions for compatibility (#1553)
|
|
106
|
+
|
|
107
|
+
## 5.3.0 2022-03-22
|
|
108
|
+
|
|
109
|
+
### Fixes
|
|
110
|
+
* StandardFilter: Fix missing @context on iterations (#1525) [Thierry Joyal]
|
|
111
|
+
* Fix warning about block and default value in `static_registers.rb` (#1531) [Peter Zhu]
|
|
112
|
+
|
|
113
|
+
### Deprecation
|
|
114
|
+
* Condition#evaluate to require mandatory context argument in Liquid 6.0.0 (#1527) [Thierry Joyal]
|
|
115
|
+
|
|
116
|
+
## 5.2.0 2022-03-01
|
|
117
|
+
|
|
118
|
+
### Features
|
|
119
|
+
* Add `remove_last`, and `replace_last` filters (#1422) [Anders Hagbard]
|
|
120
|
+
* Eagerly cache global filters (#1524) [Jean Boussier]
|
|
121
|
+
|
|
122
|
+
### Fixes
|
|
123
|
+
* Fix some internal errors in filters from invalid input (#1476) [Dylan Thacker-Smith]
|
|
124
|
+
* Allow dash in filter kwarg name for consistency with Liquid::C (#1518) [CP Clermont]
|
|
125
|
+
|
|
126
|
+
## 5.1.0 / 2021-09-09
|
|
127
|
+
|
|
128
|
+
### Features
|
|
129
|
+
* Add `base64_encode`, `base64_decode`, `base64_url_safe_encode`, and `base64_url_safe_decode` filters (#1450) [Daniel Insley]
|
|
130
|
+
* Introduce `to_liquid_value` in `Liquid::Drop` (#1441) [Michael Go]
|
|
131
|
+
|
|
132
|
+
### Fixes
|
|
133
|
+
* Fix support for using a String subclass for the liquid source (#1421) [Dylan Thacker-Smith]
|
|
134
|
+
* Add `ParseTreeVisitor` to `RangeLookup` (#1470) [CP Clermont]
|
|
135
|
+
* Translate `RangeError` to `Liquid::Error` for `truncatewords` with large int (#1431) [Dylan Thacker-Smith]
|
|
136
|
+
|
|
137
|
+
## 5.0.1 / 2021-03-24
|
|
138
|
+
|
|
139
|
+
### Fixes
|
|
140
|
+
* Add ParseTreeVisitor to Echo tag (#1414) [CP Clermont]
|
|
141
|
+
* Test with ruby 3.0 as the latest ruby version (#1398) [Dylan Thacker-Smith]
|
|
142
|
+
* Handle carriage return in newlines_to_br (#1391) [Unending]
|
|
143
|
+
|
|
144
|
+
### Performance Improvements
|
|
145
|
+
* Use split limit in truncatewords (#1361) [Dylan Thacker-Smith]
|
|
146
|
+
|
|
147
|
+
## 5.0.0 / 2021-01-06
|
|
148
|
+
|
|
149
|
+
### Features
|
|
150
|
+
* Add new `{% render %}` tag (#1122) [Samuel Doiron]
|
|
151
|
+
* Add support for `as` in `{% render %}` and `{% include %}` (#1181) [Mike Angell]
|
|
152
|
+
* Add `{% liquid %}` and `{% echo %}` tags (#1086) [Justin Li]
|
|
153
|
+
* Add [usage tracking](README.md#usage-tracking) [Mike Angell]
|
|
154
|
+
* Add `Tag.disable_tags` for disabling tags that prepend `Tag::Disableable` at render time (#1162, #1274, #1275) [Mike Angell]
|
|
155
|
+
* Support using a profiler for multiple renders (#1365, #1366) [Dylan Thacker-Smith]
|
|
156
|
+
|
|
157
|
+
### Fixes
|
|
158
|
+
* Fix catastrophic backtracking in `RANGES_REGEX` regular expression (#1357) [Dylan Thacker-Smith]
|
|
159
|
+
* Make sure the for tag's limit and offset are integers (#1094) [David Cornu]
|
|
160
|
+
* Invokable methods for enumerable reject include (#1151) [Thierry Joyal]
|
|
161
|
+
* Allow `default` filter to handle `false` as value (#1144) [Mike Angell]
|
|
162
|
+
* Fix render length resource limit so it doesn't multiply nested output (#1285) [Dylan Thacker-Smith]
|
|
163
|
+
* Fix duplication of text in raw tags (#1304) [Peter Zhu]
|
|
164
|
+
* Fix strict parsing of find variable with a name expression (#1317) [Dylan Thacker-Smith]
|
|
165
|
+
* Use monotonic time to measure durations in Liquid::Profiler (#1362) [Dylan Thacker-Smith]
|
|
166
|
+
|
|
167
|
+
### Breaking Changes
|
|
168
|
+
* Require Ruby >= 2.5 (#1131, #1310) [Mike Angell, Dylan Thacker-Smith]
|
|
169
|
+
* Remove support for taint checking (#1268) [Dylan Thacker-Smith]
|
|
170
|
+
* Split Strainer class into StrainerFactory and StrainerTemplate (#1208) [Thierry Joyal]
|
|
171
|
+
* Remove handling of a nil context in the Strainer class (#1218) [Thierry Joyal]
|
|
172
|
+
* Handle `BlockBody#blank?` at parse time (#1287) [Dylan Thacker-Smith]
|
|
173
|
+
* Pass the tag markup and tokenizer to `Document#unknown_tag` (#1290) [Dylan Thacker-Smith]
|
|
174
|
+
* And several internal changes
|
|
175
|
+
|
|
176
|
+
### Performance Improvements
|
|
177
|
+
* Reduce allocations (#1073, #1091, #1115, #1099, #1117, #1141, #1322, #1341) [Richard Monette, Florian Weingarten, Ashwin Maroli]
|
|
178
|
+
* Improve resources limits performance (#1093, #1323) [Florian Weingarten, Dylan Thacker-Smith]
|
|
179
|
+
|
|
180
|
+
## 4.0.3 / 2019-03-12
|
|
181
|
+
|
|
182
|
+
### Fixed
|
|
183
|
+
* Fix break and continue tags inside included templates in loops (#1072) [Justin Li]
|
|
184
|
+
|
|
185
|
+
## 4.0.2 / 2019-03-08
|
|
186
|
+
|
|
187
|
+
### Changed
|
|
188
|
+
* Add `where` filter (#1026) [Samuel Doiron]
|
|
189
|
+
* Add `ParseTreeVisitor` to iterate the Liquid AST (#1025) [Stephen Paul Weber]
|
|
190
|
+
* Improve `strip_html` performance (#1032) [printercu]
|
|
191
|
+
|
|
192
|
+
### Fixed
|
|
193
|
+
* Add error checking for invalid combinations of inputs to sort, sort_natural, where, uniq, map, compact filters (#1059) [Garland Zhang]
|
|
194
|
+
* Validate the character encoding in url_decode (#1070) [Clayton Smith]
|
|
195
|
+
|
|
196
|
+
## 4.0.1 / 2018-10-09
|
|
197
|
+
|
|
198
|
+
### Changed
|
|
199
|
+
* Add benchmark group in Gemfile (#855) [Jerry Liu]
|
|
200
|
+
* Allow benchmarks to benchmark render by itself (#851) [Jerry Liu]
|
|
201
|
+
* Avoid calling `line_number` on String node when rescuing a render error. (#860) [Dylan Thacker-Smith]
|
|
202
|
+
* Avoid duck typing to detect whether to call render on a node. [Dylan Thacker-Smith]
|
|
203
|
+
* Clarify spelling of `reversed` on `for` block tag (#843) [Mark Crossfield]
|
|
204
|
+
* Replace recursion with loop to avoid potential stack overflow from malicious input (#891, #892) [Dylan Thacker-Smith]
|
|
205
|
+
* Limit block tag nesting to 100 (#894) [Dylan Thacker-Smith]
|
|
206
|
+
* Replace `assert_equal nil` with `assert_nil` (#895) [Dylan Thacker-Smith]
|
|
207
|
+
* Remove Spy Gem (#896) [Dylan Thacker-Smith]
|
|
208
|
+
* Add `collection_name` and `variable_name` reader to `For` block (#909)
|
|
209
|
+
* Symbols render as strings (#920) [Justin Li]
|
|
210
|
+
* Remove default value from Hash objects (#932) [Maxime Bedard]
|
|
211
|
+
* Remove one level of nesting (#944) [Dylan Thacker-Smith]
|
|
212
|
+
* Update Rubocop version (#952) [Justin Li]
|
|
213
|
+
* Add `at_least` and `at_most` filters (#954, #958) [Nithin Bekal]
|
|
214
|
+
* Add a regression test for a liquid-c trim mode bug (#972) [Dylan Thacker-Smith]
|
|
215
|
+
* Use https rather than git protocol to fetch liquid-c [Dylan Thacker-Smith]
|
|
216
|
+
* Add tests against Ruby 2.4 (#963) and 2.5 (#981)
|
|
217
|
+
* Replace RegExp literals with constants (#988) [Ashwin Maroli]
|
|
218
|
+
* Replace unnecessary `#each_with_index` with `#each` (#992) [Ashwin Maroli]
|
|
219
|
+
* Improve the unexpected end delimiter message for block tags. (#1003) [Dylan Thacker-Smith]
|
|
220
|
+
* Refactor and optimize rendering (#1005) [Christopher Aue]
|
|
221
|
+
* Add installation instruction (#1006) [Ben Gift]
|
|
222
|
+
* Remove Circle CI (#1010)
|
|
223
|
+
* Rename deprecated `BigDecimal.new` to `BigDecimal` (#1024) [Koichi ITO]
|
|
224
|
+
* Rename deprecated Rubocop name (#1027) [Justin Li]
|
|
225
|
+
|
|
226
|
+
### Fixed
|
|
227
|
+
* Handle `join` filter on non String joiners (#857) [Richard Monette]
|
|
228
|
+
* Fix duplicate inclusion condition logic error of `Liquid::Strainer.add_filter` method (#861)
|
|
229
|
+
* Fix `escape`, `url_encode`, `url_decode` not handling non-string values (#898) [Thierry Joyal]
|
|
230
|
+
* Fix raise when variable is defined but nil when using `strict_variables` [Pascal Betz]
|
|
231
|
+
* Fix `sort` and `sort_natural` to handle arrays with nils (#930) [Eric Chan]
|
|
232
|
+
|
|
233
|
+
## 4.0.0 / 2016-12-14 / branch "4-0-stable"
|
|
4
234
|
|
|
5
235
|
### Changed
|
|
6
236
|
* Render an opaque internal error by default for non-Liquid::Error (#835) [Dylan Thacker-Smith]
|
|
@@ -20,10 +250,13 @@
|
|
|
20
250
|
* Add concat filter to concatenate arrays (#429) [Diogo Beato]
|
|
21
251
|
* Ruby 1.9 support dropped (#491) [Justin Li]
|
|
22
252
|
* Liquid::Template.file_system's read_template_file method is no longer passed the context. (#441) [James Reid-Smith]
|
|
23
|
-
* Remove
|
|
253
|
+
* Remove `liquid_methods` (See https://github.com/Shopify/liquid/pull/568 for replacement)
|
|
24
254
|
* Liquid::Template.register_filter raises when the module overrides registered public methods as private or protected (#705) [Gaurav Chande]
|
|
25
255
|
|
|
26
256
|
### Fixed
|
|
257
|
+
|
|
258
|
+
* Fix variable names being detected as an operator when starting with contains (#788) [Michael Angell]
|
|
259
|
+
* Fix include tag used with strict_variables (#828) [QuickPay]
|
|
27
260
|
* Fix map filter when value is a Proc (#672) [Guillaume Malette]
|
|
28
261
|
* Fix truncate filter when value is not a string (#672) [Guillaume Malette]
|
|
29
262
|
* Fix behaviour of escape filter when input is nil (#665) [Tanel Jakobsoo]
|
data/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
[](https://github.com/Shopify/liquid/actions/workflows/liquid.yml)
|
|
2
2
|
[](http://inch-ci.org/github/Shopify/liquid)
|
|
3
3
|
|
|
4
4
|
# Liquid template engine
|
|
5
5
|
|
|
6
6
|
* [Contributing guidelines](CONTRIBUTING.md)
|
|
7
7
|
* [Version history](History.md)
|
|
8
|
-
* [Liquid documentation from Shopify](
|
|
8
|
+
* [Liquid documentation from Shopify](https://shopify.dev/docs/api/liquid)
|
|
9
9
|
* [Liquid Wiki at GitHub](https://github.com/Shopify/liquid/wiki)
|
|
10
10
|
* [Website](http://liquidmarkup.org/)
|
|
11
11
|
|
|
@@ -42,6 +42,8 @@ Liquid is a template engine which was written with very specific requirements:
|
|
|
42
42
|
|
|
43
43
|
## How to use Liquid
|
|
44
44
|
|
|
45
|
+
Install Liquid by adding `gem 'liquid'` to your gemfile.
|
|
46
|
+
|
|
45
47
|
Liquid supports a very simple API based around the Liquid::Template class.
|
|
46
48
|
For standard use you can just pass it the content of a file and call render with a parameters hash.
|
|
47
49
|
|
|
@@ -50,24 +52,66 @@ For standard use you can just pass it the content of a file and call render with
|
|
|
50
52
|
@template.render('name' => 'tobi') # => "hi tobi"
|
|
51
53
|
```
|
|
52
54
|
|
|
55
|
+
### Concept of Environments
|
|
56
|
+
|
|
57
|
+
In Liquid, a "Environment" is a scoped environment that encapsulates custom tags, filters, and other configurations. This allows you to define and isolate different sets of functionality for different contexts, avoiding global overrides that can lead to conflicts and unexpected behavior.
|
|
58
|
+
|
|
59
|
+
By using environments, you can:
|
|
60
|
+
|
|
61
|
+
1. **Encapsulate Logic**: Keep the logic for different parts of your application separate.
|
|
62
|
+
2. **Avoid Conflicts**: Prevent custom tags and filters from clashing with each other.
|
|
63
|
+
3. **Improve Maintainability**: Make it easier to manage and understand the scope of customizations.
|
|
64
|
+
4. **Enhance Security**: Limit the availability of certain tags and filters to specific contexts.
|
|
65
|
+
|
|
66
|
+
We encourage the use of Environments over globally overriding things because it promotes better software design principles such as modularity, encapsulation, and separation of concerns.
|
|
67
|
+
|
|
68
|
+
Here's an example of how you can define and use Environments in Liquid:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
user_environment = Liquid::Environment.build do |environment|
|
|
72
|
+
environment.register_tag("renderobj", RenderObjTag)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
Liquid::Template.parse(<<~LIQUID, environment: user_environment)
|
|
76
|
+
{% renderobj src: "path/to/model.obj" %}
|
|
77
|
+
LIQUID
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
In this example, `RenderObjTag` is a custom tag that is only available within the `user_environment`.
|
|
81
|
+
|
|
82
|
+
Similarly, you can define another environment for a different context, such as email templates:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
email_environment = Liquid::Environment.build do |environment|
|
|
86
|
+
environment.register_tag("unsubscribe_footer", UnsubscribeFooter)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Liquid::Template.parse(<<~LIQUID, environment: email_environment)
|
|
90
|
+
{% unsubscribe_footer %}
|
|
91
|
+
LIQUID
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
By using Environments, you ensure that custom tags and filters are only available in the contexts where they are needed, making your Liquid templates more robust and easier to manage. For smaller projects, a global environment is available via `Liquid::Environment.default`.
|
|
95
|
+
|
|
53
96
|
### Error Modes
|
|
54
97
|
|
|
55
98
|
Setting the error mode of Liquid lets you specify how strictly you want your templates to be interpreted.
|
|
56
99
|
Normally the parser is very lax and will accept almost anything without error. Unfortunately this can make
|
|
57
|
-
it very hard to debug and can lead to unexpected behaviour.
|
|
100
|
+
it very hard to debug and can lead to unexpected behaviour.
|
|
58
101
|
|
|
59
|
-
Liquid also comes with
|
|
102
|
+
Liquid also comes with different parsers that can be used when editing templates to give better error messages
|
|
60
103
|
when templates are invalid. You can enable this new parser like this:
|
|
61
104
|
|
|
62
105
|
```ruby
|
|
63
|
-
Liquid::
|
|
64
|
-
Liquid::
|
|
65
|
-
Liquid::
|
|
106
|
+
Liquid::Environment.default.error_mode = :rigid # Raises a SyntaxError when invalid syntax is used in all tags
|
|
107
|
+
Liquid::Environment.default.error_mode = :strict # Raises a SyntaxError when invalid syntax is used in some tags
|
|
108
|
+
Liquid::Environment.default.error_mode = :warn # Adds strict errors to template.errors but continues as normal
|
|
109
|
+
Liquid::Environment.default.error_mode = :lax # The default mode, accepts almost anything.
|
|
66
110
|
```
|
|
67
111
|
|
|
68
112
|
If you want to set the error mode only on specific templates you can pass `:error_mode` as an option to `parse`:
|
|
69
113
|
```ruby
|
|
70
|
-
Liquid::Template.parse(source, :
|
|
114
|
+
Liquid::Template.parse(source, error_mode: :strict)
|
|
71
115
|
```
|
|
72
116
|
This is useful for doing things like enabling strict mode only in the theme editor.
|
|
73
117
|
|
|
@@ -104,3 +148,9 @@ template = Liquid::Template.parse("{{x}} {{y}}")
|
|
|
104
148
|
template.render!({ 'x' => 1}, { strict_variables: true })
|
|
105
149
|
#=> Liquid::UndefinedVariable: Liquid error: undefined variable y
|
|
106
150
|
```
|
|
151
|
+
|
|
152
|
+
### Usage tracking
|
|
153
|
+
|
|
154
|
+
To help track usages of a feature or code path in production, we have released opt-in usage tracking. To enable this, we provide an empty `Liquid:: Usage.increment` method which you can customize to your needs. The feature is well suited to https://github.com/Shopify/statsd-instrument. However, the choice of implementation is up to you.
|
|
155
|
+
|
|
156
|
+
Once you have enabled usage tracking, we recommend reporting any events through Github Issues that your system may be logging. It is highly likely this event has been added to consider deprecating or improving code specific to this event, so please raise any concerns.
|
data/lib/liquid/block.rb
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Liquid
|
|
2
4
|
class Block < Tag
|
|
5
|
+
MAX_DEPTH = 100
|
|
6
|
+
|
|
3
7
|
def initialize(tag_name, markup, options)
|
|
4
8
|
super
|
|
5
9
|
@blank = true
|
|
6
10
|
end
|
|
7
11
|
|
|
8
12
|
def parse(tokens)
|
|
9
|
-
@body =
|
|
13
|
+
@body = new_body
|
|
10
14
|
while parse_body(@body, tokens)
|
|
11
15
|
end
|
|
16
|
+
@body.freeze
|
|
12
17
|
end
|
|
13
18
|
|
|
19
|
+
# For backwards compatibility
|
|
14
20
|
def render(context)
|
|
15
21
|
@body.render(context)
|
|
16
22
|
end
|
|
@@ -23,20 +29,33 @@ module Liquid
|
|
|
23
29
|
@body.nodelist
|
|
24
30
|
end
|
|
25
31
|
|
|
26
|
-
def unknown_tag(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
def unknown_tag(tag_name, _markup, _tokenizer)
|
|
33
|
+
Block.raise_unknown_tag(tag_name, block_name, block_delimiter, parse_context)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @api private
|
|
37
|
+
def self.raise_unknown_tag(tag, block_name, block_delimiter, parse_context)
|
|
38
|
+
if tag == 'else'
|
|
39
|
+
raise SyntaxError, parse_context.locale.t(
|
|
40
|
+
"errors.syntax.unexpected_else",
|
|
41
|
+
block_name: block_name,
|
|
42
|
+
)
|
|
43
|
+
elsif tag.start_with?('end')
|
|
44
|
+
raise SyntaxError, parse_context.locale.t(
|
|
45
|
+
"errors.syntax.invalid_delimiter",
|
|
46
|
+
tag: tag,
|
|
33
47
|
block_name: block_name,
|
|
34
|
-
block_delimiter: block_delimiter
|
|
48
|
+
block_delimiter: block_delimiter,
|
|
49
|
+
)
|
|
35
50
|
else
|
|
36
|
-
raise SyntaxError
|
|
51
|
+
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
|
|
37
52
|
end
|
|
38
53
|
end
|
|
39
54
|
|
|
55
|
+
def raise_tag_never_closed(block_name)
|
|
56
|
+
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_never_closed", block_name: block_name)
|
|
57
|
+
end
|
|
58
|
+
|
|
40
59
|
def block_name
|
|
41
60
|
@tag_name
|
|
42
61
|
end
|
|
@@ -45,20 +64,32 @@ module Liquid
|
|
|
45
64
|
@block_delimiter ||= "end#{block_name}"
|
|
46
65
|
end
|
|
47
66
|
|
|
48
|
-
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# @api public
|
|
70
|
+
def new_body
|
|
71
|
+
parse_context.new_block_body
|
|
72
|
+
end
|
|
49
73
|
|
|
74
|
+
# @api public
|
|
50
75
|
def parse_body(body, tokens)
|
|
51
|
-
|
|
52
|
-
|
|
76
|
+
if parse_context.depth >= MAX_DEPTH
|
|
77
|
+
raise StackLevelError, "Nesting too deep"
|
|
78
|
+
end
|
|
79
|
+
parse_context.depth += 1
|
|
80
|
+
begin
|
|
81
|
+
body.parse(tokens, parse_context) do |end_tag_name, end_tag_params|
|
|
82
|
+
@blank &&= body.blank?
|
|
53
83
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name))
|
|
57
|
-
end
|
|
84
|
+
return false if end_tag_name == block_delimiter
|
|
85
|
+
raise_tag_never_closed(block_name) unless end_tag_name
|
|
58
86
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
87
|
+
# this tag is not registered with the system
|
|
88
|
+
# pass it to the current block for special handling or error reporting
|
|
89
|
+
unknown_tag(end_tag_name, end_tag_params, tokens)
|
|
90
|
+
end
|
|
91
|
+
ensure
|
|
92
|
+
parse_context.depth -= 1
|
|
62
93
|
end
|
|
63
94
|
|
|
64
95
|
true
|