liquid 2.6.1 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.md +194 -29
- data/{MIT-LICENSE → LICENSE} +0 -0
- data/README.md +60 -2
- data/lib/liquid.rb +25 -14
- data/lib/liquid/block.rb +47 -96
- data/lib/liquid/block_body.rb +143 -0
- data/lib/liquid/condition.rb +70 -39
- data/lib/liquid/context.rb +116 -157
- data/lib/liquid/document.rb +19 -9
- data/lib/liquid/drop.rb +31 -14
- data/lib/liquid/errors.rb +54 -10
- data/lib/liquid/expression.rb +49 -0
- data/lib/liquid/extensions.rb +19 -7
- data/lib/liquid/file_system.rb +25 -14
- data/lib/liquid/forloop_drop.rb +42 -0
- data/lib/liquid/i18n.rb +39 -0
- data/lib/liquid/interrupts.rb +2 -3
- data/lib/liquid/lexer.rb +55 -0
- data/lib/liquid/locales/en.yml +26 -0
- data/lib/liquid/parse_context.rb +38 -0
- data/lib/liquid/parse_tree_visitor.rb +42 -0
- data/lib/liquid/parser.rb +90 -0
- data/lib/liquid/parser_switching.rb +31 -0
- data/lib/liquid/profiler.rb +158 -0
- data/lib/liquid/profiler/hooks.rb +23 -0
- data/lib/liquid/range_lookup.rb +37 -0
- data/lib/liquid/resource_limits.rb +23 -0
- data/lib/liquid/standardfilters.rb +311 -77
- data/lib/liquid/strainer.rb +39 -26
- data/lib/liquid/tablerowloop_drop.rb +62 -0
- data/lib/liquid/tag.rb +28 -11
- data/lib/liquid/tags/assign.rb +34 -10
- data/lib/liquid/tags/break.rb +1 -4
- data/lib/liquid/tags/capture.rb +11 -9
- data/lib/liquid/tags/case.rb +37 -22
- data/lib/liquid/tags/comment.rb +10 -3
- data/lib/liquid/tags/continue.rb +1 -4
- data/lib/liquid/tags/cycle.rb +20 -14
- data/lib/liquid/tags/decrement.rb +4 -8
- data/lib/liquid/tags/for.rb +121 -60
- data/lib/liquid/tags/if.rb +73 -30
- data/lib/liquid/tags/ifchanged.rb +3 -5
- data/lib/liquid/tags/include.rb +77 -46
- data/lib/liquid/tags/increment.rb +4 -8
- data/lib/liquid/tags/raw.rb +35 -10
- data/lib/liquid/tags/table_row.rb +62 -0
- data/lib/liquid/tags/unless.rb +6 -9
- data/lib/liquid/template.rb +130 -32
- data/lib/liquid/tokenizer.rb +31 -0
- data/lib/liquid/truffle.rb +5 -0
- data/lib/liquid/utils.rb +57 -4
- data/lib/liquid/variable.rb +121 -30
- data/lib/liquid/variable_lookup.rb +88 -0
- data/lib/liquid/version.rb +2 -1
- data/test/fixtures/en_locale.yml +9 -0
- data/test/integration/assign_test.rb +48 -0
- data/test/integration/blank_test.rb +106 -0
- data/test/integration/block_test.rb +12 -0
- data/test/{liquid → integration}/capture_test.rb +13 -3
- data/test/integration/context_test.rb +32 -0
- data/test/integration/document_test.rb +19 -0
- data/test/integration/drop_test.rb +273 -0
- data/test/integration/error_handling_test.rb +260 -0
- data/test/integration/filter_test.rb +178 -0
- data/test/integration/hash_ordering_test.rb +23 -0
- data/test/integration/output_test.rb +123 -0
- data/test/integration/parse_tree_visitor_test.rb +247 -0
- data/test/integration/parsing_quirks_test.rb +122 -0
- data/test/integration/render_profiling_test.rb +154 -0
- data/test/integration/security_test.rb +80 -0
- data/test/integration/standard_filter_test.rb +776 -0
- data/test/{liquid → integration}/tags/break_tag_test.rb +2 -3
- data/test/{liquid → integration}/tags/continue_tag_test.rb +1 -2
- data/test/integration/tags/for_tag_test.rb +410 -0
- data/test/integration/tags/if_else_tag_test.rb +188 -0
- data/test/integration/tags/include_tag_test.rb +253 -0
- data/test/integration/tags/increment_tag_test.rb +23 -0
- data/test/{liquid → integration}/tags/raw_tag_test.rb +9 -2
- data/test/integration/tags/standard_tag_test.rb +296 -0
- data/test/integration/tags/statements_test.rb +111 -0
- data/test/{liquid/tags/html_tag_test.rb → integration/tags/table_row_test.rb} +25 -24
- data/test/integration/tags/unless_else_tag_test.rb +26 -0
- data/test/integration/template_test.rb +332 -0
- data/test/integration/trim_mode_test.rb +529 -0
- data/test/integration/variable_test.rb +96 -0
- data/test/test_helper.rb +106 -19
- data/test/truffle/truffle_test.rb +9 -0
- data/test/{liquid/block_test.rb → unit/block_unit_test.rb} +9 -9
- data/test/unit/condition_unit_test.rb +166 -0
- data/test/{liquid/context_test.rb → unit/context_unit_test.rb} +85 -74
- data/test/unit/file_system_unit_test.rb +35 -0
- data/test/unit/i18n_unit_test.rb +37 -0
- data/test/unit/lexer_unit_test.rb +51 -0
- data/test/unit/parser_unit_test.rb +82 -0
- data/test/{liquid/regexp_test.rb → unit/regexp_unit_test.rb} +4 -4
- data/test/unit/strainer_unit_test.rb +164 -0
- data/test/unit/tag_unit_test.rb +21 -0
- data/test/unit/tags/case_tag_unit_test.rb +10 -0
- data/test/unit/tags/for_tag_unit_test.rb +13 -0
- data/test/unit/tags/if_tag_unit_test.rb +8 -0
- data/test/unit/template_unit_test.rb +78 -0
- data/test/unit/tokenizer_unit_test.rb +55 -0
- data/test/unit/variable_unit_test.rb +162 -0
- metadata +157 -77
- data/lib/extras/liquid_view.rb +0 -51
- data/lib/liquid/htmltags.rb +0 -74
- data/lib/liquid/module_ex.rb +0 -62
- data/test/liquid/assign_test.rb +0 -21
- data/test/liquid/condition_test.rb +0 -127
- data/test/liquid/drop_test.rb +0 -180
- data/test/liquid/error_handling_test.rb +0 -81
- data/test/liquid/file_system_test.rb +0 -29
- data/test/liquid/filter_test.rb +0 -125
- data/test/liquid/hash_ordering_test.rb +0 -25
- data/test/liquid/module_ex_test.rb +0 -87
- data/test/liquid/output_test.rb +0 -116
- data/test/liquid/parsing_quirks_test.rb +0 -52
- data/test/liquid/security_test.rb +0 -64
- data/test/liquid/standard_filter_test.rb +0 -251
- data/test/liquid/strainer_test.rb +0 -52
- data/test/liquid/tags/for_tag_test.rb +0 -297
- data/test/liquid/tags/if_else_tag_test.rb +0 -166
- data/test/liquid/tags/include_tag_test.rb +0 -166
- data/test/liquid/tags/increment_tag_test.rb +0 -24
- data/test/liquid/tags/standard_tag_test.rb +0 -295
- data/test/liquid/tags/statements_test.rb +0 -134
- data/test/liquid/tags/unless_else_tag_test.rb +0 -26
- data/test/liquid/template_test.rb +0 -146
- data/test/liquid/variable_test.rb +0 -186
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e41c3a6ffee8037dec34a186cf023e2ccb09ac4f94d0c9a812ea02fd50559bf7
|
4
|
+
data.tar.gz: ff088908363f5a54e5833c64d32b441fb679503340b5f7511de99eb257fd4289
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b726a02e92f8d9fac005e07034aeee32dd2eae3a2b342fb4e9e648dc79da4c086de92e1e1a24bf52054a4a2b0a74af17f89fdd6c3cbbb2982e4b5b5971a23c2
|
7
|
+
data.tar.gz: e875f98a0b30f914ec1703781bfb443e737ea11675829c3e98fca96524dfe30a72fb9adf59c7855f85eda8014c2e6a9850d911b22cb96a63d2eac52e91273a42
|
data/History.md
CHANGED
@@ -1,43 +1,208 @@
|
|
1
|
-
# Liquid
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
# Liquid Change Log
|
2
|
+
|
3
|
+
## 4.0.3 / 2019-03-12
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
* Fix break and continue tags inside included templates in loops (#1072) [Justin Li]
|
7
|
+
|
8
|
+
## 4.0.2 / 2019-03-08
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
* Add `where` filter (#1026) [Samuel Doiron]
|
12
|
+
* Add `ParseTreeVisitor` to iterate the Liquid AST (#1025) [Stephen Paul Weber]
|
13
|
+
* Improve `strip_html` performance (#1032) [printercu]
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
* Add error checking for invalid combinations of inputs to sort, sort_natural, where, uniq, map, compact filters (#1059) [Garland Zhang]
|
17
|
+
* Validate the character encoding in url_decode (#1070) [Clayton Smith]
|
18
|
+
|
19
|
+
## 4.0.1 / 2018-10-09
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
* Add benchmark group in Gemfile (#855) [Jerry Liu]
|
23
|
+
* Allow benchmarks to benchmark render by itself (#851) [Jerry Liu]
|
24
|
+
* Avoid calling `line_number` on String node when rescuing a render error. (#860) [Dylan Thacker-Smith]
|
25
|
+
* Avoid duck typing to detect whether to call render on a node. [Dylan Thacker-Smith]
|
26
|
+
* Clarify spelling of `reversed` on `for` block tag (#843) [Mark Crossfield]
|
27
|
+
* Replace recursion with loop to avoid potential stack overflow from malicious input (#891, #892) [Dylan Thacker-Smith]
|
28
|
+
* Limit block tag nesting to 100 (#894) [Dylan Thacker-Smith]
|
29
|
+
* Replace `assert_equal nil` with `assert_nil` (#895) [Dylan Thacker-Smith]
|
30
|
+
* Remove Spy Gem (#896) [Dylan Thacker-Smith]
|
31
|
+
* Add `collection_name` and `variable_name` reader to `For` block (#909)
|
32
|
+
* Symbols render as strings (#920) [Justin Li]
|
33
|
+
* Remove default value from Hash objects (#932) [Maxime Bedard]
|
34
|
+
* Remove one level of nesting (#944) [Dylan Thacker-Smith]
|
35
|
+
* Update Rubocop version (#952) [Justin Li]
|
36
|
+
* Add `at_least` and `at_most` filters (#954, #958) [Nithin Bekal]
|
37
|
+
* Add a regression test for a liquid-c trim mode bug (#972) [Dylan Thacker-Smith]
|
38
|
+
* Use https rather than git protocol to fetch liquid-c [Dylan Thacker-Smith]
|
39
|
+
* Add tests against Ruby 2.4 (#963) and 2.5 (#981)
|
40
|
+
* Replace RegExp literals with constants (#988) [Ashwin Maroli]
|
41
|
+
* Replace unnecessary `#each_with_index` with `#each` (#992) [Ashwin Maroli]
|
42
|
+
* Improve the unexpected end delimiter message for block tags. (#1003) [Dylan Thacker-Smith]
|
43
|
+
* Refactor and optimize rendering (#1005) [Christopher Aue]
|
44
|
+
* Add installation instruction (#1006) [Ben Gift]
|
45
|
+
* Remove Circle CI (#1010)
|
46
|
+
* Rename deprecated `BigDecimal.new` to `BigDecimal` (#1024) [Koichi ITO]
|
47
|
+
* Rename deprecated Rubocop name (#1027) [Justin Li]
|
48
|
+
|
49
|
+
### Fixed
|
50
|
+
* Handle `join` filter on non String joiners (#857) [Richard Monette]
|
51
|
+
* Fix duplicate inclusion condition logic error of `Liquid::Strainer.add_filter` method (#861)
|
52
|
+
* Fix `escape`, `url_encode`, `url_decode` not handling non-string values (#898) [Thierry Joyal]
|
53
|
+
* Fix raise when variable is defined but nil when using `strict_variables` [Pascal Betz]
|
54
|
+
* Fix `sort` and `sort_natural` to handle arrays with nils (#930) [Eric Chan]
|
55
|
+
|
56
|
+
## 4.0.0 / 2016-12-14 / branch "4-0-stable"
|
57
|
+
|
58
|
+
### Changed
|
59
|
+
* Render an opaque internal error by default for non-Liquid::Error (#835) [Dylan Thacker-Smith]
|
60
|
+
* Ruby 2.0 support dropped (#832) [Dylan Thacker-Smith]
|
61
|
+
* Add to_number Drop method to allow custom drops to work with number filters (#731)
|
62
|
+
* Add strict_variables and strict_filters options to detect undefined references (#691)
|
63
|
+
* Improve loop performance (#681) [Florian Weingarten]
|
64
|
+
* Rename Drop method `before_method` to `liquid_method_missing` (#661) [Thierry Joyal]
|
65
|
+
* Add url_decode filter to invert url_encode (#645) [Larry Archer]
|
66
|
+
* Add global_filter to apply a filter to all output (#610) [Loren Hale]
|
67
|
+
* Add compact filter (#600) [Carson Reinke]
|
68
|
+
* Rename deprecated "has_key?" and "has_interrupt?" methods (#593) [Florian Weingarten]
|
69
|
+
* Include template name with line numbers in render errors (574) [Dylan Thacker-Smith]
|
70
|
+
* Add sort_natural filter (#554) [Martin Hanzel]
|
71
|
+
* Add forloop.parentloop as a reference to the parent loop (#520) [Justin Li]
|
72
|
+
* Block parsing moved to BlockBody class (#458) [Dylan Thacker-Smith]
|
73
|
+
* Add concat filter to concatenate arrays (#429) [Diogo Beato]
|
74
|
+
* Ruby 1.9 support dropped (#491) [Justin Li]
|
75
|
+
* Liquid::Template.file_system's read_template_file method is no longer passed the context. (#441) [James Reid-Smith]
|
76
|
+
* Remove `liquid_methods` (See https://github.com/Shopify/liquid/pull/568 for replacement)
|
77
|
+
* Liquid::Template.register_filter raises when the module overrides registered public methods as private or protected (#705) [Gaurav Chande]
|
78
|
+
|
79
|
+
### Fixed
|
80
|
+
|
81
|
+
* Fix variable names being detected as an operator when starting with contains (#788) [Michael Angell]
|
82
|
+
* Fix include tag used with strict_variables (#828) [QuickPay]
|
83
|
+
* Fix map filter when value is a Proc (#672) [Guillaume Malette]
|
84
|
+
* Fix truncate filter when value is not a string (#672) [Guillaume Malette]
|
85
|
+
* Fix behaviour of escape filter when input is nil (#665) [Tanel Jakobsoo]
|
86
|
+
* Fix sort filter behaviour with empty array input (#652) [Marcel Cary]
|
87
|
+
* Fix test failure under certain timezones (#631) [Dylan Thacker-Smith]
|
88
|
+
* Fix bug in uniq filter (#595) [Florian Weingarten]
|
89
|
+
* Fix bug when "blank" and "empty" are used as variable names (#592) [Florian Weingarten]
|
90
|
+
* Fix condition parse order in strict mode (#569) [Justin Li]
|
91
|
+
* Fix naming of the "context variable" when dynamically including a template (#559) [Justin Li]
|
92
|
+
* Gracefully accept empty strings in the date filter (#555) [Loren Hale]
|
93
|
+
* Fix capturing into variables with a hyphen in the name (#505) [Florian Weingarten]
|
94
|
+
* Fix case sensitivity regression in date standard filter (#499) [Kelley Reynolds]
|
95
|
+
* Disallow filters with no variable in strict mode (#475) [Justin Li]
|
96
|
+
* Disallow variable names in the strict parser that are not valid in the lax parser (#463) [Justin Li]
|
97
|
+
* Fix BlockBody#warnings taking exponential time to compute (#486) [Justin Li]
|
98
|
+
|
99
|
+
## 3.0.5 / 2015-07-23 / branch "3-0-stable"
|
100
|
+
|
101
|
+
* Fix test failure under certain timezones [Dylan Thacker-Smith]
|
102
|
+
|
103
|
+
## 3.0.4 / 2015-07-17
|
104
|
+
|
105
|
+
* Fix chained access to multi-dimensional hashes [Florian Weingarten]
|
106
|
+
|
107
|
+
## 3.0.3 / 2015-05-28
|
108
|
+
|
109
|
+
* Fix condition parse order in strict mode (#569) [Justin Li]
|
110
|
+
|
111
|
+
## 3.0.2 / 2015-04-24
|
112
|
+
|
113
|
+
* Expose VariableLookup private members (#551) [Justin Li]
|
114
|
+
* Documentation fixes
|
115
|
+
|
116
|
+
## 3.0.1 / 2015-01-23
|
117
|
+
|
118
|
+
* Remove duplicate `index0` key in TableRow tag (#502) [Alfred Xing]
|
119
|
+
|
120
|
+
## 3.0.0 / 2014-11-12
|
121
|
+
|
122
|
+
* Removed Block#end_tag. Instead, override parse with `super` followed by your code. See #446 [Dylan Thacker-Smith]
|
123
|
+
* Fixed condition with wrong data types (#423) [Bogdan Gusiev]
|
124
|
+
* Add url_encode to standard filters (#421) [Derrick Reimer]
|
125
|
+
* Add uniq to standard filters [Florian Weingarten]
|
126
|
+
* Add exception_handler feature (#397) and #254 [Bogdan Gusiev, Florian Weingarten]
|
127
|
+
* Optimize variable parsing to avoid repeated regex evaluation during template rendering #383 [Jason Hiltz-Laforge]
|
128
|
+
* Optimize checking for block interrupts to reduce object allocation #380 [Jason Hiltz-Laforge]
|
129
|
+
* Properly set context rethrow_errors on render! #349 [Thierry Joyal]
|
130
|
+
* Fix broken rendering of variables which are equal to false (#345) [Florian Weingarten]
|
131
|
+
* Remove ActionView template handler [Dylan Thacker-Smith]
|
132
|
+
* Freeze lots of string literals for new Ruby 2.1 optimization (#297) [Florian Weingarten]
|
133
|
+
* Allow newlines in tags and variables (#324) [Dylan Thacker-Smith]
|
134
|
+
* Tag#parse is called after initialize, which now takes options instead of tokens as the 3rd argument. See #321 [Dylan Thacker-Smith]
|
135
|
+
* Raise `Liquid::ArgumentError` instead of `::ArgumentError` when filter has wrong number of arguments #309 [Bogdan Gusiev]
|
136
|
+
* Add a to_s default for liquid drops (#306) [Adam Doeler]
|
137
|
+
* Add strip, lstrip, and rstrip to standard filters [Florian Weingarten]
|
138
|
+
* Make if, for & case tags return complete and consistent nodelists (#250) [Nick Jones]
|
139
|
+
* Prevent arbitrary method invocation on condition objects (#274) [Dylan Thacker-Smith]
|
140
|
+
* Don't call to_sym when creating conditions for security reasons (#273) [Bouke van der Bijl]
|
141
|
+
* Fix resource counting bug with respond_to?(:length) (#263) [Florian Weingarten]
|
142
|
+
* Allow specifying custom patterns for template filenames (#284) [Andrei Gladkyi]
|
143
|
+
* Allow drops to optimize loading a slice of elements (#282) [Tom Burns]
|
144
|
+
* Support for passing variables to snippets in subdirs (#271) [Joost Hietbrink]
|
145
|
+
* Add a class cache to avoid runtime extend calls (#249) [James Tucker]
|
146
|
+
* Remove some legacy Ruby 1.8 compatibility code (#276) [Florian Weingarten]
|
147
|
+
* Add default filter to standard filters (#267) [Derrick Reimer]
|
148
|
+
* Add optional strict parsing and warn parsing (#235) [Tristan Hume]
|
149
|
+
* Add I18n syntax error translation (#241) [Simon Hørup Eskildsen, Sirupsen]
|
150
|
+
* Make sort filter work on enumerable drops (#239) [Florian Weingarten]
|
151
|
+
* Fix clashing method names in enumerable drops (#238) [Florian Weingarten]
|
152
|
+
* Make map filter work on enumerable drops (#233) [Florian Weingarten]
|
153
|
+
* Improved whitespace stripping for blank blocks, related to #216 [Florian Weingarten]
|
154
|
+
|
155
|
+
## 2.6.3 / 2015-07-23 / branch "2-6-stable"
|
156
|
+
|
157
|
+
* Fix test failure under certain timezones [Dylan Thacker-Smith]
|
158
|
+
|
159
|
+
## 2.6.2 / 2015-01-23
|
160
|
+
|
161
|
+
* Remove duplicate hash key [Parker Moore]
|
162
|
+
|
163
|
+
## 2.6.1 / 2014-01-10
|
7
164
|
|
8
165
|
Security fix, cherry-picked from master (4e14a65):
|
9
|
-
* Don't call to_sym when creating conditions for security reasons
|
10
|
-
* Prevent arbitrary method invocation on condition objects
|
166
|
+
* Don't call to_sym when creating conditions for security reasons (#273) [Bouke van der Bijl]
|
167
|
+
* Prevent arbitrary method invocation on condition objects (#274) [Dylan Thacker-Smith]
|
11
168
|
|
12
169
|
## 2.6.0 / 2013-11-25
|
13
170
|
|
14
|
-
|
171
|
+
IMPORTANT: Liquid 2.6 is going to be the last version of Liquid which maintains explicit Ruby 1.8 compatability.
|
172
|
+
The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are likely to break on Ruby 1.8.
|
173
|
+
|
15
174
|
* Bugfix for #106: fix example servlet [gnowoel]
|
16
|
-
* Bugfix for #97: strip_html filter supports multi-line tags [Jo Liss
|
17
|
-
* Bugfix for #114: strip_html filter supports style tags [James Allardice
|
18
|
-
* Bugfix for #117: 'now' support for date filter in Ruby 1.9 [Notre Dame Webgroup
|
19
|
-
* Bugfix for #166: truncate filter on UTF-8 strings with Ruby 1.8 [Florian Weingarten
|
20
|
-
* Bugfix for #204: 'raw' parsing bug [Florian Weingarten
|
21
|
-
* Bugfix for #150: 'for' parsing bug [Peter Schröder
|
22
|
-
* Bugfix for #126: Strip CRLF in strip_newline [Peter Schröder
|
23
|
-
* Bugfix for #174, "can't convert Fixnum into String" for "replace" [
|
24
|
-
* Allow a Liquid::Drop to be passed into Template#render [Daniel Huckstep
|
25
|
-
* Resource limits [Florian Weingarten
|
26
|
-
* Add reverse filter [Jay Strybis
|
175
|
+
* Bugfix for #97: strip_html filter supports multi-line tags [Jo Liss]
|
176
|
+
* Bugfix for #114: strip_html filter supports style tags [James Allardice]
|
177
|
+
* Bugfix for #117: 'now' support for date filter in Ruby 1.9 [Notre Dame Webgroup]
|
178
|
+
* Bugfix for #166: truncate filter on UTF-8 strings with Ruby 1.8 [Florian Weingarten]
|
179
|
+
* Bugfix for #204: 'raw' parsing bug [Florian Weingarten]
|
180
|
+
* Bugfix for #150: 'for' parsing bug [Peter Schröder]
|
181
|
+
* Bugfix for #126: Strip CRLF in strip_newline [Peter Schröder]
|
182
|
+
* Bugfix for #174, "can't convert Fixnum into String" for "replace" [jsw0528]
|
183
|
+
* Allow a Liquid::Drop to be passed into Template#render [Daniel Huckstep]
|
184
|
+
* Resource limits [Florian Weingarten]
|
185
|
+
* Add reverse filter [Jay Strybis]
|
27
186
|
* Add utf-8 support
|
28
|
-
* Use array instead of Hash to keep the registered filters [Tasos Stathopoulos
|
29
|
-
* Cache tokenized partial templates [Tom Burns
|
30
|
-
* Avoid warnings in Ruby 1.9.3 [Marcus Stollsteimer
|
31
|
-
* Better documentation for 'include' tag (closes #163) [Peter Schröder
|
32
|
-
* Use of BigDecimal on filters to have better precision (closes #155) [Arthur Nogueira Neves
|
187
|
+
* Use array instead of Hash to keep the registered filters [Tasos Stathopoulos]
|
188
|
+
* Cache tokenized partial templates [Tom Burns]
|
189
|
+
* Avoid warnings in Ruby 1.9.3 [Marcus Stollsteimer]
|
190
|
+
* Better documentation for 'include' tag (closes #163) [Peter Schröder]
|
191
|
+
* Use of BigDecimal on filters to have better precision (closes #155) [Arthur Nogueira Neves]
|
192
|
+
|
193
|
+
## 2.5.5 / 2014-01-10 / branch "2-5-stable"
|
194
|
+
|
195
|
+
Security fix, cherry-picked from master (4e14a65):
|
196
|
+
* Don't call to_sym when creating conditions for security reasons (#273) [Bouke van der Bijl]
|
197
|
+
* Prevent arbitrary method invocation on condition objects (#274) [Dylan Thacker-Smith]
|
33
198
|
|
34
|
-
## 2.5.4 / 2013-11-11
|
199
|
+
## 2.5.4 / 2013-11-11
|
35
200
|
|
36
|
-
* Fix "can't convert Fixnum into String" for "replace"
|
201
|
+
* Fix "can't convert Fixnum into String" for "replace" (#173), [jsw0528]
|
37
202
|
|
38
203
|
## 2.5.3 / 2013-10-09
|
39
204
|
|
40
|
-
* #232, #234, #237: Fix map filter bugs [Florian Weingarten
|
205
|
+
* #232, #234, #237: Fix map filter bugs [Florian Weingarten]
|
41
206
|
|
42
207
|
## 2.5.2 / 2013-09-03 / deleted
|
43
208
|
|
@@ -45,7 +210,7 @@ Yanked from rubygems, as it contained too many changes that broke compatibility.
|
|
45
210
|
|
46
211
|
## 2.5.1 / 2013-07-24
|
47
212
|
|
48
|
-
* #230: Fix security issue with map filter, Use invoke_drop in map filter [Florian Weingarten
|
213
|
+
* #230: Fix security issue with map filter, Use invoke_drop in map filter [Florian Weingarten]
|
49
214
|
|
50
215
|
## 2.5.0 / 2013-03-06
|
51
216
|
|
data/{MIT-LICENSE → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
[![Build Status](https://api.travis-ci.org/Shopify/liquid.svg?branch=master)](http://travis-ci.org/Shopify/liquid)
|
2
|
+
[![Inline docs](http://inch-ci.org/github/Shopify/liquid.svg?branch=master)](http://inch-ci.org/github/Shopify/liquid)
|
3
|
+
|
1
4
|
# Liquid template engine
|
2
5
|
|
3
6
|
* [Contributing guidelines](CONTRIBUTING.md)
|
4
7
|
* [Version history](History.md)
|
5
8
|
* [Liquid documentation from Shopify](http://docs.shopify.com/themes/liquid-basics)
|
6
|
-
* [Liquid Wiki
|
9
|
+
* [Liquid Wiki at GitHub](https://github.com/Shopify/liquid/wiki)
|
7
10
|
* [Website](http://liquidmarkup.org/)
|
8
11
|
|
9
12
|
## Introduction
|
@@ -39,6 +42,8 @@ Liquid is a template engine which was written with very specific requirements:
|
|
39
42
|
|
40
43
|
## How to use Liquid
|
41
44
|
|
45
|
+
Install Liquid by adding `gem 'liquid'` to your gemfile.
|
46
|
+
|
42
47
|
Liquid supports a very simple API based around the Liquid::Template class.
|
43
48
|
For standard use you can just pass it the content of a file and call render with a parameters hash.
|
44
49
|
|
@@ -47,4 +52,57 @@ For standard use you can just pass it the content of a file and call render with
|
|
47
52
|
@template.render('name' => 'tobi') # => "hi tobi"
|
48
53
|
```
|
49
54
|
|
50
|
-
|
55
|
+
### Error Modes
|
56
|
+
|
57
|
+
Setting the error mode of Liquid lets you specify how strictly you want your templates to be interpreted.
|
58
|
+
Normally the parser is very lax and will accept almost anything without error. Unfortunately this can make
|
59
|
+
it very hard to debug and can lead to unexpected behaviour.
|
60
|
+
|
61
|
+
Liquid also comes with a stricter parser that can be used when editing templates to give better error messages
|
62
|
+
when templates are invalid. You can enable this new parser like this:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
Liquid::Template.error_mode = :strict # Raises a SyntaxError when invalid syntax is used
|
66
|
+
Liquid::Template.error_mode = :warn # Adds errors to template.errors but continues as normal
|
67
|
+
Liquid::Template.error_mode = :lax # The default mode, accepts almost anything.
|
68
|
+
```
|
69
|
+
|
70
|
+
If you want to set the error mode only on specific templates you can pass `:error_mode` as an option to `parse`:
|
71
|
+
```ruby
|
72
|
+
Liquid::Template.parse(source, :error_mode => :strict)
|
73
|
+
```
|
74
|
+
This is useful for doing things like enabling strict mode only in the theme editor.
|
75
|
+
|
76
|
+
It is recommended that you enable `:strict` or `:warn` mode on new apps to stop invalid templates from being created.
|
77
|
+
It is also recommended that you use it in the template editors of existing apps to give editors better error messages.
|
78
|
+
|
79
|
+
### Undefined variables and filters
|
80
|
+
|
81
|
+
By default, the renderer doesn't raise or in any other way notify you if some variables or filters are missing, i.e. not passed to the `render` method.
|
82
|
+
You can improve this situation by passing `strict_variables: true` and/or `strict_filters: true` options to the `render` method.
|
83
|
+
When one of these options is set to true, all errors about undefined variables and undefined filters will be stored in `errors` array of a `Liquid::Template` instance.
|
84
|
+
Here are some examples:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
template = Liquid::Template.parse("{{x}} {{y}} {{z.a}} {{z.b}}")
|
88
|
+
template.render({ 'x' => 1, 'z' => { 'a' => 2 } }, { strict_variables: true })
|
89
|
+
#=> '1 2 ' # when a variable is undefined, it's rendered as nil
|
90
|
+
template.errors
|
91
|
+
#=> [#<Liquid::UndefinedVariable: Liquid error: undefined variable y>, #<Liquid::UndefinedVariable: Liquid error: undefined variable b>]
|
92
|
+
```
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
template = Liquid::Template.parse("{{x | filter1 | upcase}}")
|
96
|
+
template.render({ 'x' => 'foo' }, { strict_filters: true })
|
97
|
+
#=> '' # when at least one filter in the filter chain is undefined, a whole expression is rendered as nil
|
98
|
+
template.errors
|
99
|
+
#=> [#<Liquid::UndefinedFilter: Liquid error: undefined filter filter1>]
|
100
|
+
```
|
101
|
+
|
102
|
+
If you want to raise on a first exception instead of pushing all of them in `errors`, you can use `render!` method:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
template = Liquid::Template.parse("{{x}} {{y}}")
|
106
|
+
template.render!({ 'x' => 1}, { strict_variables: true })
|
107
|
+
#=> Liquid::UndefinedVariable: Liquid error: undefined variable y
|
108
|
+
```
|
data/lib/liquid.rb
CHANGED
@@ -21,9 +21,10 @@
|
|
21
21
|
|
22
22
|
module Liquid
|
23
23
|
FilterSeparator = /\|/
|
24
|
-
ArgumentSeparator = ','
|
25
|
-
FilterArgumentSeparator = ':'
|
26
|
-
VariableAttributeSeparator = '.'
|
24
|
+
ArgumentSeparator = ','.freeze
|
25
|
+
FilterArgumentSeparator = ':'.freeze
|
26
|
+
VariableAttributeSeparator = '.'.freeze
|
27
|
+
WhitespaceControl = '-'.freeze
|
27
28
|
TagStart = /\{\%/
|
28
29
|
TagEnd = /\%\}/
|
29
30
|
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
@@ -33,37 +34,47 @@ module Liquid
|
|
33
34
|
VariableIncompleteEnd = /\}\}?/
|
34
35
|
QuotedString = /"[^"]*"|'[^']*'/
|
35
36
|
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
|
36
|
-
StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/
|
37
|
-
FirstFilterArgument = /#{FilterArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
38
|
-
OtherFilterArgument = /#{ArgumentSeparator}(?:#{StrictQuotedFragment})/o
|
39
|
-
SpacelessFilter = /^(?:'[^']+'|"[^"]+"|[^'"])*#{FilterSeparator}(?:#{StrictQuotedFragment})(?:#{FirstFilterArgument}(?:#{OtherFilterArgument})*)?/o
|
40
|
-
Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o
|
41
37
|
TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
|
42
|
-
AnyStartingTag =
|
43
|
-
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/
|
44
|
-
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/
|
38
|
+
AnyStartingTag = /#{TagStart}|#{VariableStart}/o
|
39
|
+
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om
|
40
|
+
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om
|
45
41
|
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
|
42
|
+
|
43
|
+
singleton_class.send(:attr_accessor, :cache_classes)
|
44
|
+
self.cache_classes = true
|
46
45
|
end
|
47
46
|
|
48
47
|
require "liquid/version"
|
48
|
+
require 'liquid/parse_tree_visitor'
|
49
|
+
require 'liquid/lexer'
|
50
|
+
require 'liquid/parser'
|
51
|
+
require 'liquid/i18n'
|
49
52
|
require 'liquid/drop'
|
53
|
+
require 'liquid/tablerowloop_drop'
|
54
|
+
require 'liquid/forloop_drop'
|
50
55
|
require 'liquid/extensions'
|
51
56
|
require 'liquid/errors'
|
52
57
|
require 'liquid/interrupts'
|
53
58
|
require 'liquid/strainer'
|
59
|
+
require 'liquid/expression'
|
54
60
|
require 'liquid/context'
|
61
|
+
require 'liquid/parser_switching'
|
55
62
|
require 'liquid/tag'
|
56
63
|
require 'liquid/block'
|
64
|
+
require 'liquid/block_body'
|
57
65
|
require 'liquid/document'
|
58
66
|
require 'liquid/variable'
|
67
|
+
require 'liquid/variable_lookup'
|
68
|
+
require 'liquid/range_lookup'
|
59
69
|
require 'liquid/file_system'
|
70
|
+
require 'liquid/resource_limits'
|
60
71
|
require 'liquid/template'
|
61
|
-
require 'liquid/htmltags'
|
62
72
|
require 'liquid/standardfilters'
|
63
73
|
require 'liquid/condition'
|
64
|
-
require 'liquid/module_ex'
|
65
74
|
require 'liquid/utils'
|
75
|
+
require 'liquid/tokenizer'
|
76
|
+
require 'liquid/parse_context'
|
66
77
|
|
67
78
|
# Load all the tags of the standard library
|
68
79
|
#
|
69
|
-
Dir[
|
80
|
+
Dir["#{__dir__}/liquid/tags/*.rb"].each { |f| require f }
|
data/lib/liquid/block.rb
CHANGED
@@ -1,126 +1,77 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
3
2
|
class Block < Tag
|
4
|
-
|
5
|
-
IsVariable = /^#{VariableStart}/o
|
6
|
-
FullToken = /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/o
|
7
|
-
ContentOfVariable = /^#{VariableStart}(.*)#{VariableEnd}$/o
|
8
|
-
|
9
|
-
def parse(tokens)
|
10
|
-
@nodelist ||= []
|
11
|
-
@nodelist.clear
|
12
|
-
|
13
|
-
while token = tokens.shift
|
3
|
+
MAX_DEPTH = 100
|
14
4
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# if we found the proper block delimiter just end parsing here and let the outer block
|
20
|
-
# proceed
|
21
|
-
if block_delimiter == $1
|
22
|
-
end_tag
|
23
|
-
return
|
24
|
-
end
|
5
|
+
def initialize(tag_name, markup, options)
|
6
|
+
super
|
7
|
+
@blank = true
|
8
|
+
end
|
25
9
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
# this tag is not registered with the system
|
31
|
-
# pass it to the current block for special handling or error reporting
|
32
|
-
unknown_tag($1, $2, tokens)
|
33
|
-
end
|
34
|
-
else
|
35
|
-
raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
|
36
|
-
end
|
37
|
-
when IsVariable
|
38
|
-
@nodelist << create_variable(token)
|
39
|
-
when ''
|
40
|
-
# pass
|
41
|
-
else
|
42
|
-
@nodelist << token
|
43
|
-
end
|
10
|
+
def parse(tokens)
|
11
|
+
@body = BlockBody.new
|
12
|
+
while parse_body(@body, tokens)
|
44
13
|
end
|
14
|
+
end
|
45
15
|
|
46
|
-
|
47
|
-
|
48
|
-
# of type Document
|
49
|
-
assert_missing_delimitation!
|
16
|
+
def render(context)
|
17
|
+
@body.render(context)
|
50
18
|
end
|
51
19
|
|
52
|
-
def
|
20
|
+
def blank?
|
21
|
+
@blank
|
53
22
|
end
|
54
23
|
|
55
|
-
def
|
56
|
-
|
57
|
-
when 'else'
|
58
|
-
raise SyntaxError, "#{block_name} tag does not expect else tag"
|
59
|
-
when 'end'
|
60
|
-
raise SyntaxError, "'end' is not a valid delimiter for #{block_name} tags. use #{block_delimiter}"
|
61
|
-
else
|
62
|
-
raise SyntaxError, "Unknown tag '#{tag}'"
|
63
|
-
end
|
24
|
+
def nodelist
|
25
|
+
@body.nodelist
|
64
26
|
end
|
65
27
|
|
66
|
-
def
|
67
|
-
|
28
|
+
def unknown_tag(tag, _params, _tokens)
|
29
|
+
if tag == 'else'.freeze
|
30
|
+
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unexpected_else".freeze,
|
31
|
+
block_name: block_name))
|
32
|
+
elsif tag.start_with?('end'.freeze)
|
33
|
+
raise SyntaxError.new(parse_context.locale.t("errors.syntax.invalid_delimiter".freeze,
|
34
|
+
tag: tag,
|
35
|
+
block_name: block_name,
|
36
|
+
block_delimiter: block_delimiter))
|
37
|
+
else
|
38
|
+
raise SyntaxError.new(parse_context.locale.t("errors.syntax.unknown_tag".freeze, tag: tag))
|
39
|
+
end
|
68
40
|
end
|
69
41
|
|
70
42
|
def block_name
|
71
43
|
@tag_name
|
72
44
|
end
|
73
45
|
|
74
|
-
def
|
75
|
-
|
76
|
-
return Variable.new(content.first)
|
77
|
-
end
|
78
|
-
raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ")
|
79
|
-
end
|
80
|
-
|
81
|
-
def render(context)
|
82
|
-
render_all(@nodelist, context)
|
46
|
+
def block_delimiter
|
47
|
+
@block_delimiter ||= "end#{block_name}"
|
83
48
|
end
|
84
49
|
|
85
50
|
protected
|
86
51
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
begin
|
101
|
-
# If we get an Interrupt that means the block must stop processing. An
|
102
|
-
# Interrupt is any command that stops block execution such as {% break %}
|
103
|
-
# or {% continue %}
|
104
|
-
if token.is_a? Continue or token.is_a? Break
|
105
|
-
context.push_interrupt(token.interrupt)
|
106
|
-
break
|
52
|
+
def parse_body(body, tokens)
|
53
|
+
if parse_context.depth >= MAX_DEPTH
|
54
|
+
raise StackLevelError, "Nesting too deep".freeze
|
55
|
+
end
|
56
|
+
parse_context.depth += 1
|
57
|
+
begin
|
58
|
+
body.parse(tokens, parse_context) do |end_tag_name, end_tag_params|
|
59
|
+
@blank &&= body.blank?
|
60
|
+
|
61
|
+
return false if end_tag_name == block_delimiter
|
62
|
+
unless end_tag_name
|
63
|
+
raise SyntaxError.new(parse_context.locale.t("errors.syntax.tag_never_closed".freeze, block_name: block_name))
|
107
64
|
end
|
108
65
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
context.resource_limits[:reached] = true
|
113
|
-
raise MemoryError.new("Memory limits exceeded")
|
114
|
-
end
|
115
|
-
output << token_output
|
116
|
-
rescue MemoryError => e
|
117
|
-
raise e
|
118
|
-
rescue ::StandardError => e
|
119
|
-
output << (context.handle_error(e))
|
66
|
+
# this tag is not registered with the system
|
67
|
+
# pass it to the current block for special handling or error reporting
|
68
|
+
unknown_tag(end_tag_name, end_tag_params, tokens)
|
120
69
|
end
|
70
|
+
ensure
|
71
|
+
parse_context.depth -= 1
|
121
72
|
end
|
122
73
|
|
123
|
-
|
74
|
+
true
|
124
75
|
end
|
125
76
|
end
|
126
77
|
end
|