mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-29 15:15:19 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fed0c1f94 | ||
|
|
eb89f22d93 | ||
|
|
98e146ebf7 | ||
|
|
7611463f02 | ||
|
|
f1846d63a3 | ||
|
|
af3f8612bf | ||
|
|
6f8722a6d3 | ||
|
|
81f44e36be | ||
|
|
c9ec8f4635 | ||
|
|
3fb467f069 | ||
|
|
992e15a173 | ||
|
|
0bb6539dce | ||
|
|
1fdc577246 |
@@ -1,2 +0,0 @@
|
||||
enabled:
|
||||
- cla
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Contributor License Agreement (CLA)
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
cla:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event.issue.pull_request
|
||||
&& !github.event.issue.pull_request.merged_at
|
||||
&& contains(github.event.comment.body, 'signed')
|
||||
)
|
||||
|| (github.event.pull_request && !github.event.pull_request.merged)
|
||||
steps:
|
||||
- uses: Shopify/shopify-cla-action@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
cla-token: ${{ secrets.CLA_TOKEN }}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
# Liquid Change Log
|
||||
|
||||
## 5.4.0 (unreleased)
|
||||
## 5.4.0 2022-07-29
|
||||
|
||||
### Breaking Changes
|
||||
* Drop support for end-of-life Ruby versions (2.5 and 2.6) (#1578) [Andy Waite]
|
||||
@@ -11,6 +11,7 @@
|
||||
### Fixes
|
||||
* `PartialCache` now shares snippet cache with subcontexts by default (#1553) [Chris AtLee]
|
||||
* Hash registers no longer leak into subcontexts as static registers (#1564) [Chris AtLee]
|
||||
* Fix `ParseTreeVisitor` for `with` variable expressions in `Render` tag (#1596) [CP Clermont]
|
||||
|
||||
### Changed
|
||||
* Liquid::Context#registers now always returns a Liquid::Registers object, though supports the most used Hash functions for compatibility (#1553)
|
||||
|
||||
+2
-3
@@ -18,6 +18,7 @@ module Liquid
|
||||
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
|
||||
SINGLE_STRING_LITERAL = /'[^\']*'/
|
||||
DOUBLE_STRING_LITERAL = /"[^\"]*"/
|
||||
STRING_LITERAL = Regexp.union(SINGLE_STRING_LITERAL, DOUBLE_STRING_LITERAL)
|
||||
NUMBER_LITERAL = /-?\d+(\.\d+)?/
|
||||
DOTDOT = /\.\./
|
||||
COMPARISON_OPERATOR = /==|!=|<>|<=?|>=?|contains(?=\s)/
|
||||
@@ -35,9 +36,7 @@ module Liquid
|
||||
break if @ss.eos?
|
||||
tok = if (t = @ss.scan(COMPARISON_OPERATOR))
|
||||
[:comparison, t]
|
||||
elsif (t = @ss.scan(SINGLE_STRING_LITERAL))
|
||||
[:string, t]
|
||||
elsif (t = @ss.scan(DOUBLE_STRING_LITERAL))
|
||||
elsif (t = @ss.scan(STRING_LITERAL))
|
||||
[:string, t]
|
||||
elsif (t = @ss.scan(NUMBER_LITERAL))
|
||||
[:number, t]
|
||||
|
||||
@@ -8,7 +8,17 @@ module Liquid
|
||||
if start_obj.respond_to?(:evaluate) || end_obj.respond_to?(:evaluate)
|
||||
new(start_obj, end_obj)
|
||||
else
|
||||
start_obj.to_i..end_obj.to_i
|
||||
begin
|
||||
start_obj.to_i..end_obj.to_i
|
||||
rescue NoMethodError
|
||||
invalid_expr = start_markup unless start_obj.respond_to?(:to_i)
|
||||
invalid_expr ||= end_markup unless end_obj.respond_to?(:to_i)
|
||||
if invalid_expr
|
||||
raise Liquid::SyntaxError, "Invalid expression type '#{invalid_expr}' in range expression"
|
||||
end
|
||||
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -813,9 +813,10 @@ module Liquid
|
||||
# @liquid_syntax number | at_least
|
||||
# @liquid_return [number]
|
||||
def at_least(input, n)
|
||||
min_value = Utils.to_number(n)
|
||||
|
||||
result = Utils.to_number(input)
|
||||
min_value = Utils.to_number(n)
|
||||
min_value, result = result.coerce(min_value) if result.respond_to?(:coerce)
|
||||
|
||||
result = min_value if min_value > result
|
||||
result.is_a?(BigDecimal) ? result.to_f : result
|
||||
end
|
||||
@@ -828,9 +829,10 @@ module Liquid
|
||||
# @liquid_syntax number | at_most
|
||||
# @liquid_return [number]
|
||||
def at_most(input, n)
|
||||
max_value = Utils.to_number(n)
|
||||
|
||||
result = Utils.to_number(input)
|
||||
max_value = Utils.to_number(n)
|
||||
max_value, result = result.coerce(max_value) if result.respond_to?(:coerce)
|
||||
|
||||
result = max_value if max_value < result
|
||||
result.is_a?(BigDecimal) ? result.to_f : result
|
||||
end
|
||||
|
||||
@@ -14,6 +14,10 @@ module Liquid
|
||||
strainer_from_cache(filters).new(context)
|
||||
end
|
||||
|
||||
def global_filter_names
|
||||
GlobalCache.filter_method_names
|
||||
end
|
||||
|
||||
GlobalCache = Class.new(StrainerTemplate)
|
||||
|
||||
private
|
||||
|
||||
@@ -36,6 +36,10 @@ module Liquid
|
||||
subclass.instance_variable_set(:@filter_methods, @filter_methods.dup)
|
||||
end
|
||||
|
||||
def filter_method_names
|
||||
filter_methods.map(&:to_s).to_a
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filter_methods
|
||||
|
||||
@@ -31,7 +31,7 @@ module Liquid
|
||||
|
||||
disable_tags "include"
|
||||
|
||||
attr_reader :template_name_expr, :attributes
|
||||
attr_reader :template_name_expr, :variable_name_expr, :attributes
|
||||
|
||||
def initialize(tag_name, markup, options)
|
||||
super
|
||||
@@ -99,6 +99,7 @@ module Liquid
|
||||
def children
|
||||
[
|
||||
@node.template_name_expr,
|
||||
@node.variable_name_expr,
|
||||
] + @node.attributes.values
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Liquid
|
||||
VERSION = "5.4.0.alpha"
|
||||
VERSION = "5.4.0"
|
||||
end
|
||||
|
||||
@@ -29,6 +29,11 @@ class ExpressionTest < Minitest::Test
|
||||
def test_range
|
||||
assert_equal(1..2, parse_and_eval("(1..2)"))
|
||||
assert_equal(3..4, parse_and_eval(" ( 3 .. 4 ) "))
|
||||
|
||||
exc = assert_raises(Liquid::SyntaxError) { Liquid::Expression.parse("(false..true)") }
|
||||
assert_equal("Liquid syntax error: Invalid expression type 'false' in range expression", exc.message)
|
||||
exc = assert_raises(Liquid::SyntaxError) { Liquid::Expression.parse("((1..2)..3)") }
|
||||
assert_equal("Liquid syntax error: Invalid expression type '(1..2)' in range expression", exc.message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -64,6 +64,42 @@ class NumberLikeThing < Liquid::Drop
|
||||
end
|
||||
end
|
||||
|
||||
class MeasurementDrop < Liquid::Drop
|
||||
include Comparable
|
||||
|
||||
attr_reader :amount, :unit
|
||||
|
||||
def initialize(amount, unit = nil)
|
||||
@amount = amount
|
||||
@unit = unit
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
amount <=> other.amount
|
||||
end
|
||||
|
||||
def to_number
|
||||
self
|
||||
end
|
||||
|
||||
def coerce(other)
|
||||
coerced_other =
|
||||
case other
|
||||
when MeasurementDrop then other if other.unit == unit
|
||||
when Numeric then self.class.new(other, unit)
|
||||
end
|
||||
|
||||
raise Liquid::ArgumentError, "Can't coerce #{other} into MeasurementDrop" if coerced_other.nil?
|
||||
|
||||
[coerced_other, self]
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{@amount}#{@unit}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class StandardFiltersTest < Minitest::Test
|
||||
Filters = Class.new(Liquid::StrainerTemplate)
|
||||
Filters.add_filter(Liquid::StandardFilters)
|
||||
@@ -723,6 +759,8 @@ class StandardFiltersTest < Minitest::Test
|
||||
assert_template_result("5", "{{ width | at_most:5 }}", 'width' => NumberLikeThing.new(6))
|
||||
assert_template_result("4", "{{ width | at_most:5 }}", 'width' => NumberLikeThing.new(4))
|
||||
assert_template_result("4", "{{ 5 | at_most: width }}", 'width' => NumberLikeThing.new(4))
|
||||
assert_template_result("4mm", "{{ width | at_most: 5 }}", 'width' => MeasurementDrop.new(4, "mm"))
|
||||
assert_template_result("5mm", "{{ width | at_most: 5 }}", 'width' => MeasurementDrop.new(6, "mm"))
|
||||
end
|
||||
|
||||
def test_at_least
|
||||
@@ -730,10 +768,12 @@ class StandardFiltersTest < Minitest::Test
|
||||
assert_template_result("5", "{{ 5 | at_least:5 }}")
|
||||
assert_template_result("6", "{{ 5 | at_least:6 }}")
|
||||
|
||||
assert_template_result("5", "{{ 4.5 | at_least:5 }}")
|
||||
assert_template_result("5.0", "{{ 4.5 | at_least:5 }}")
|
||||
assert_template_result("6", "{{ width | at_least:5 }}", 'width' => NumberLikeThing.new(6))
|
||||
assert_template_result("5", "{{ width | at_least:5 }}", 'width' => NumberLikeThing.new(4))
|
||||
assert_template_result("6", "{{ 5 | at_least: width }}", 'width' => NumberLikeThing.new(6))
|
||||
assert_template_result("5mm", "{{ width | at_least: 5 }}", 'width' => MeasurementDrop.new(4, "mm"))
|
||||
assert_template_result("6mm", "{{ width | at_least: 5 }}", 'width' => MeasurementDrop.new(6, "mm"))
|
||||
end
|
||||
|
||||
def test_append
|
||||
|
||||
@@ -236,6 +236,20 @@ class ParseTreeVisitorTest < Minitest::Test
|
||||
)
|
||||
end
|
||||
|
||||
def test_render_with
|
||||
assert_equal(
|
||||
["test"],
|
||||
visit(%({% render "hai" with test %}))
|
||||
)
|
||||
end
|
||||
|
||||
def test_render_for
|
||||
assert_equal(
|
||||
["test"],
|
||||
visit(%({% render "hai" for test %}))
|
||||
)
|
||||
end
|
||||
|
||||
def test_preserve_tree_structure
|
||||
assert_equal(
|
||||
[[nil, [
|
||||
|
||||
Reference in New Issue
Block a user