liquid 5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b1c036e6dd6d55418e6364b008551f5d3ba91f6e7dbc1c0ac3be43b235bd957
4
- data.tar.gz: a6279802ed388bcffc8980c49bcb0034a0f98de7cd6730bf97f603c07bf13dcd
3
+ metadata.gz: 98bb40e18a2bb905a917743968edb79732f903b3beb1f51ab9551e1aaee3f91a
4
+ data.tar.gz: 264b8ccd158a79f2b43a0308a055d38b018b0f4132f316007f3589e778f5d9dd
5
5
  SHA512:
6
- metadata.gz: 0c5094a47d46c8de3ac8ac632dbec8b813c1e47af834c0037ed9b868f5a2dde4da8dfdd143ff34c41505c1425524f1879ca909525676028cadd9900cbd028e63
7
- data.tar.gz: 7195f154c81283e8b7d99a07b82a2d9976b41be761efc528945f79ac0d77c2ff9c7632b3455f871b6db0471979c35e633f87e1c33900e4f9898012f836fd1496
6
+ metadata.gz: 19b30524fc6b7828de10e3eecc4e28b5595436144eacedad06c36d6472b740d01e971d315f7aa911ebad80dac5c075b75649c0b506f588e50ff8c977f08ed365
7
+ data.tar.gz: 53726f629d8a76ebcc4e134bc12abe981df9526fb5baa4d9312b68bc967e691af329bfcabadad86af65b8149034bd94479a2f98a93a9056a090fd28ba2901597
data/History.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Liquid Change Log
2
2
 
3
+ ## 5.0.1 / 2021-03-24
4
+
5
+ ### Fixes
6
+ * Add ParseTreeVisitor to Echo tag (#1414) [CP Clermont]
7
+ * Test with ruby 3.0 as the latest ruby version (#1398) [Dylan Thacker-Smith]
8
+ * Handle carriage return in newlines_to_br (#1391) [Unending]
9
+
10
+ ### Performance Improvements
11
+ * Use split limit in truncatewords (#1361) [Dylan Thacker-Smith]
12
+
3
13
  ## 5.0.0 / 2021-01-06
4
14
 
5
15
  ### Features
@@ -99,7 +99,9 @@ module Liquid
99
99
  end
100
100
 
101
101
  private def parse_liquid_tag(markup, parse_context)
102
- liquid_tag_tokenizer = Tokenizer.new(markup, line_number: parse_context.line_number, for_liquid_tag: true)
102
+ liquid_tag_tokenizer = parse_context.new_tokenizer(
103
+ markup, start_line_number: parse_context.line_number, for_liquid_tag: true
104
+ )
103
105
  parse_for_liquid_tag(liquid_tag_tokenizer, parse_context) do |end_tag_name, _end_tag_markup|
104
106
  if end_tag_name
105
107
  BlockBody.unknown_tag_in_liquid_tag(end_tag_name, parse_context)
@@ -23,6 +23,10 @@ module Liquid
23
23
  Liquid::BlockBody.new
24
24
  end
25
25
 
26
+ def new_tokenizer(markup, start_line_number: nil, for_liquid_tag: false)
27
+ Tokenizer.new(markup, line_number: start_line_number, for_liquid_tag: for_liquid_tag)
28
+ end
29
+
26
30
  def parse_expression(markup)
27
31
  Expression.parse(markup)
28
32
  end
@@ -89,13 +89,15 @@ module Liquid
89
89
 
90
90
  def truncatewords(input, words = 15, truncate_string = "...")
91
91
  return if input.nil?
92
- wordlist = input.to_s.split
93
- words = Utils.to_integer(words)
92
+ input = input.to_s
93
+ words = Utils.to_integer(words)
94
+ words = 1 if words <= 0
94
95
 
95
- l = words - 1
96
- l = 0 if l < 0
96
+ wordlist = input.split(" ", words + 1)
97
+ return input if wordlist.length <= words
97
98
 
98
- wordlist.length > l ? wordlist[0..l].join(" ").concat(truncate_string.to_s) : input
99
+ wordlist.pop
100
+ wordlist.join(" ").concat(truncate_string.to_s)
99
101
  end
100
102
 
101
103
  # Split input string into an array of substrings separated by given pattern.
@@ -295,7 +297,7 @@ module Liquid
295
297
 
296
298
  # Add <br /> tags in front of all newlines in input string
297
299
  def newline_to_br(input)
298
- input.to_s.gsub(/\n/, "<br />\n")
300
+ input.to_s.gsub(/\r?\n/, "<br />\n")
299
301
  end
300
302
 
301
303
  # Reformat a date using Ruby's core Time#strftime( string ) -> string
@@ -12,6 +12,8 @@ module Liquid
12
12
  # {% echo user | link %}
13
13
  #
14
14
  class Echo < Tag
15
+ attr_reader :variable
16
+
15
17
  def initialize(tag_name, markup, parse_context)
16
18
  super
17
19
  @variable = Variable.new(markup, parse_context)
@@ -20,6 +22,12 @@ module Liquid
20
22
  def render(context)
21
23
  @variable.render_to_output_buffer(context, +'')
22
24
  end
25
+
26
+ class ParseTreeVisitor < Liquid::ParseTreeVisitor
27
+ def children
28
+ [@node.variable]
29
+ end
30
+ end
23
31
  end
24
32
 
25
33
  Template.register_tag('echo', Echo)
@@ -107,7 +107,8 @@ module Liquid
107
107
  # Returns self for easy chaining
108
108
  def parse(source, options = {})
109
109
  parse_context = configure_options(options)
110
- @root = Document.parse(tokenize(source), parse_context)
110
+ tokenizer = parse_context.new_tokenizer(source, start_line_number: @line_numbers && 1)
111
+ @root = Document.parse(tokenizer, parse_context)
111
112
  self
112
113
  end
113
114
 
@@ -223,10 +224,6 @@ module Liquid
223
224
  parse_context
224
225
  end
225
226
 
226
- def tokenize(source)
227
- Tokenizer.new(source, @line_numbers)
228
- end
229
-
230
227
  def apply_options_to_context(context, options)
231
228
  context.add_filters(options[:filters]) if options[:filters]
232
229
  context.global_filter = options[:global_filter] if options[:global_filter]
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Liquid
5
- VERSION = "5.0.0"
5
+ VERSION = "5.0.1"
6
6
  end
@@ -461,6 +461,7 @@ class ContextTest < Minitest::Test
461
461
  end
462
462
 
463
463
  def test_interrupt_avoids_object_allocations
464
+ @context.interrupt? # ruby 3.0.0 allocates on the first call
464
465
  assert_no_object_allocations do
465
466
  @context.interrupt?
466
467
  end
@@ -171,10 +171,13 @@ class StandardFiltersTest < Minitest::Test
171
171
  assert_equal('one two three', @filters.truncatewords('one two three'))
172
172
  assert_equal(
173
173
  'Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221;...',
174
- @filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
174
+ @filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
175
175
  )
176
176
  assert_equal("测试测试测试测试", @filters.truncatewords('测试测试测试测试', 5))
177
177
  assert_equal('one two1', @filters.truncatewords("one two three", 2, 1))
178
+ assert_equal('one two three...', @filters.truncatewords("one two\tthree\nfour", 3))
179
+ assert_equal('one two...', @filters.truncatewords("one two three four", 2))
180
+ assert_equal('one...', @filters.truncatewords("one two three four", 0))
178
181
  end
179
182
 
180
183
  def test_strip_html
@@ -539,6 +542,7 @@ class StandardFiltersTest < Minitest::Test
539
542
 
540
543
  def test_newlines_to_br
541
544
  assert_template_result("a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc")
545
+ assert_template_result("a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\r\nb\nc")
542
546
  end
543
547
 
544
548
  def test_plus
@@ -96,12 +96,12 @@ class IncludeTagTest < Minitest::Test
96
96
 
97
97
  def test_include_tag_with_alias
98
98
  assert_template_result("Product: Draft 151cm ",
99
- "{% include 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
99
+ "{% include 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
100
100
  end
101
101
 
102
102
  def test_include_tag_for_alias
103
103
  assert_template_result("Product: Draft 151cm Product: Element 155cm ",
104
- "{% include 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
104
+ "{% include 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
105
105
  end
106
106
 
107
107
  def test_include_tag_with_default_name
@@ -151,7 +151,7 @@ class RenderTagTest < Minitest::Test
151
151
  )
152
152
 
153
153
  assert_template_result("Product: Draft 151cm ",
154
- "{% render 'product' with products[0] %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
154
+ "{% render 'product' with products[0] %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
155
155
  end
156
156
 
157
157
  def test_render_tag_with_alias
@@ -161,7 +161,7 @@ class RenderTagTest < Minitest::Test
161
161
  )
162
162
 
163
163
  assert_template_result("Product: Draft 151cm ",
164
- "{% render 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
164
+ "{% render 'product_alias' with products[0] as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
165
165
  end
166
166
 
167
167
  def test_render_tag_for_alias
@@ -171,7 +171,7 @@ class RenderTagTest < Minitest::Test
171
171
  )
172
172
 
173
173
  assert_template_result("Product: Draft 151cm Product: Element 155cm ",
174
- "{% render 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
174
+ "{% render 'product_alias' for products as product %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
175
175
  end
176
176
 
177
177
  def test_render_tag_for
@@ -181,7 +181,7 @@ class RenderTagTest < Minitest::Test
181
181
  )
182
182
 
183
183
  assert_template_result("Product: Draft 151cm Product: Element 155cm ",
184
- "{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
184
+ "{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
185
185
  end
186
186
 
187
187
  def test_render_tag_forloop
@@ -190,7 +190,7 @@ class RenderTagTest < Minitest::Test
190
190
  )
191
191
 
192
192
  assert_template_result("Product: Draft 151cm first index:1 Product: Element 155cm last index:2 ",
193
- "{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
193
+ "{% render 'product' for products %}", "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }])
194
194
  end
195
195
 
196
196
  def test_render_tag_for_drop
@@ -199,7 +199,7 @@ class RenderTagTest < Minitest::Test
199
199
  )
200
200
 
201
201
  assert_template_result("123",
202
- "{% render 'loop' for loop as value %}", "loop" => TestEnumerable.new)
202
+ "{% render 'loop' for loop as value %}", "loop" => TestEnumerable.new)
203
203
  end
204
204
 
205
205
  def test_render_tag_with_drop
@@ -208,6 +208,6 @@ class RenderTagTest < Minitest::Test
208
208
  )
209
209
 
210
210
  assert_template_result("TestEnumerable",
211
- "{% render 'loop' with loop as value %}", "loop" => TestEnumerable.new)
211
+ "{% render 'loop' with loop as value %}", "loop" => TestEnumerable.new)
212
212
  end
213
213
  end
@@ -26,6 +26,13 @@ class ParseTreeVisitorTest < Minitest::Test
26
26
  )
27
27
  end
28
28
 
29
+ def test_echo
30
+ assert_equal(
31
+ ["test"],
32
+ visit(%({% echo test %}))
33
+ )
34
+ end
35
+
29
36
  def test_if_condition
30
37
  assert_equal(
31
38
  ["test"],
@@ -32,21 +32,26 @@ class TokenizerTest < Minitest::Test
32
32
 
33
33
  private
34
34
 
35
+ def new_tokenizer(source, parse_context: Liquid::ParseContext.new, start_line_number: nil)
36
+ parse_context.new_tokenizer(source, start_line_number: start_line_number)
37
+ end
38
+
35
39
  def tokenize(source)
36
- tokenizer = Liquid::Tokenizer.new(source)
40
+ tokenizer = new_tokenizer(source)
37
41
  tokens = []
38
- while (t = tokenizer.shift)
42
+ # shift is private in Liquid::C::Tokenizer, since it is only for unit testing
43
+ while (t = tokenizer.send(:shift))
39
44
  tokens << t
40
45
  end
41
46
  tokens
42
47
  end
43
48
 
44
49
  def tokenize_line_numbers(source)
45
- tokenizer = Liquid::Tokenizer.new(source, true)
50
+ tokenizer = new_tokenizer(source, start_line_number: 1)
46
51
  line_numbers = []
47
52
  loop do
48
53
  line_number = tokenizer.line_number
49
- if tokenizer.shift
54
+ if tokenizer.send(:shift)
50
55
  line_numbers << line_number
51
56
  else
52
57
  break
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: 5.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: 2021-01-06 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
@@ -192,60 +192,60 @@ signing_key:
192
192
  specification_version: 4
193
193
  summary: A secure, non-evaling end user template engine with aesthetic markup.
194
194
  test_files:
195
- - test/unit/lexer_unit_test.rb
195
+ - test/fixtures/en_locale.yml
196
196
  - test/unit/condition_unit_test.rb
197
- - test/unit/template_factory_unit_test.rb
198
- - test/unit/tag_unit_test.rb
199
- - test/unit/tokenizer_unit_test.rb
200
- - test/unit/regexp_unit_test.rb
201
- - test/unit/file_system_unit_test.rb
202
- - test/unit/block_unit_test.rb
203
- - test/unit/strainer_factory_unit_test.rb
204
- - test/unit/i18n_unit_test.rb
205
197
  - test/unit/variable_unit_test.rb
206
- - test/unit/static_registers_unit_test.rb
207
- - test/unit/strainer_template_unit_test.rb
208
198
  - test/unit/template_unit_test.rb
209
- - test/unit/partial_cache_unit_test.rb
210
- - test/unit/parse_tree_visitor_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
211
203
  - test/unit/tags/if_tag_unit_test.rb
212
204
  - test/unit/tags/case_tag_unit_test.rb
213
- - test/unit/tags/for_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
214
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
215
216
  - test/test_helper.rb
216
- - test/integration/expression_test.rb
217
+ - test/integration/blank_test.rb
218
+ - test/integration/standard_filter_test.rb
217
219
  - test/integration/parsing_quirks_test.rb
220
+ - test/integration/tag/disableable_test.rb
221
+ - test/integration/context_test.rb
222
+ - test/integration/error_handling_test.rb
218
223
  - test/integration/security_test.rb
219
- - test/integration/template_test.rb
220
- - test/integration/filter_test.rb
221
- - test/integration/drop_test.rb
222
- - test/integration/blank_test.rb
223
224
  - test/integration/capture_test.rb
224
- - test/integration/context_test.rb
225
- - test/integration/document_test.rb
226
- - test/integration/block_test.rb
227
- - test/integration/tag_test.rb
228
- - test/integration/tag/disableable_test.rb
229
- - test/integration/standard_filter_test.rb
230
- - test/integration/output_test.rb
231
225
  - test/integration/assign_test.rb
232
- - test/integration/profiler_test.rb
233
- - test/integration/trim_mode_test.rb
234
- - test/integration/error_handling_test.rb
235
- - test/integration/tags/echo_test.rb
236
- - test/integration/tags/raw_tag_test.rb
237
- - test/integration/tags/statements_test.rb
238
- - test/integration/tags/for_tag_test.rb
239
- - test/integration/tags/standard_tag_test.rb
240
- - test/integration/tags/render_tag_test.rb
241
- - test/integration/tags/table_row_test.rb
226
+ - test/integration/tags/increment_tag_test.rb
242
227
  - test/integration/tags/break_tag_test.rb
243
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
244
231
  - test/integration/tags/unless_else_tag_test.rb
245
- - test/integration/tags/continue_tag_test.rb
246
232
  - test/integration/tags/include_tag_test.rb
247
- - test/integration/tags/liquid_tag_test.rb
248
- - test/integration/tags/increment_tag_test.rb
249
- - test/integration/hash_ordering_test.rb
233
+ - test/integration/tags/echo_test.rb
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
238
+ - test/integration/tags/table_row_test.rb
239
+ - test/integration/tags/standard_tag_test.rb
250
240
  - test/integration/variable_test.rb
251
- - test/fixtures/en_locale.yml
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
248
+ - test/integration/trim_mode_test.rb
249
+ - test/integration/output_test.rb
250
+ - test/integration/hash_ordering_test.rb
251
+ - test/integration/tag_test.rb