Charles-P. Clermont and Guilherme Carreiro
94bbf6ca32
Make it possible to safe_parse subsets of expressions
...
e.g. sometimes you want to only accept strings | lookups.
{% render snippetName %} for example. snippetName is a string right now.
We don't want safe_parse_expression because this would allow snippetName
to be a number, a boolean, etc. But we still want to strict parse this.
So what we'll do is use parse_expression(string, safe: true), this is
an optional opt-in to say "I know what I'm doing". Usually that's
because you're using the output of Parser#something as the input of
parse_expression.
It is true that Parser#expression is subset of Expression.parse, it is
not true of the opposite (e.g. Expression.parse doesn't care about .5
and happily parses that as a global lookup of the variable named "5",
Parser#expression throws for that.)
diff --git a/lib/liquid/condition.rb b/lib/liquid/condition.rb
index e5c321dc..9ab350f0 100644
--- a/lib/liquid/condition.rb
+++ b/lib/liquid/condition.rb
@@ -48,8 +48,8 @@ module Liquid
@@operators
end
- def self.parse_expression(parse_context, markup)
- @@method_literals[markup] || parse_context.parse_expression(markup)
+ def self.parse_expression(parse_context, markup, safe: false)
+ @@method_literals[markup] || parse_context.parse_expression(markup, safe: safe)
end
attr_reader :attachment, :child_condition
diff --git a/lib/liquid/parse_context.rb b/lib/liquid/parse_context.rb
index 1c59fe4a..82cf5768 100644
--- a/lib/liquid/parse_context.rb
+++ b/lib/liquid/parse_context.rb
@@ -51,13 +51,13 @@ module Liquid
end
def safe_parse_expression(parser)
- Expression.safe_parse(parser)
+ Expression.safe_parse(parser, @string_scanner, @expression_cache)
end
- def parse_expression(markup)
+ def parse_expression(markup, safe: false)
# todo(guilherme): remove this once rigid mode is fully using safe_parse_expression
- # raise Liquid::InternalError, "parse_expression is not supported in rigid mode" if @error_mode == :rigid
- puts("🚨 parse_expression used in rigid mode") if @error_mode == :rigid
+ # raise Liquid::InternalError, "parse_expression is not supported in rigid mode" if !safe && @error_mode == :rigid
+ puts("🚨 parse_expression used in rigid mode") if !safe && @error_mode == :rigid
Expression.parse(markup, @string_scanner, @expression_cache)
end
diff --git a/lib/liquid/tag.rb b/lib/liquid/tag.rb
index 656d2e47..374ee511 100644
--- a/lib/liquid/tag.rb
+++ b/lib/liquid/tag.rb
@@ -72,8 +72,8 @@ module Liquid
parse_context.safe_parse_expression(parser)
end
- def parse_expression(markup)
- parse_context.parse_expression(markup)
+ def parse_expression(markup, safe: false)
+ parse_context.parse_expression(markup, safe: safe)
end
end
end
diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb
index c2be5db1..3182983b 100644
--- a/lib/liquid/tags/for.rb
+++ b/lib/liquid/tags/for.rb
@@ -93,7 +93,7 @@ module Liquid
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
collection_name = p.expression
- @collection_name = parse_expression(collection_name)
+ @collection_name = parse_expression(collection_name, safe: true)
@name = "#{@variable_name}-#{collection_name}"
@reversed = p.id?('reversed')
diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb
index 342374f1..e25d6250 100644
--- a/lib/liquid/tags/if.rb
+++ b/lib/liquid/tags/if.rb
@@ -81,8 +81,8 @@ module Liquid
block.attach(new_body)
end
- def parse_expression(markup)
- Condition.parse_expression(parse_context, markup)
+ def parse_expression(markup, safe: false)
+ Condition.parse_expression(parse_context, markup, safe: safe)
end
def lax_parse(markup)
@@ -124,9 +124,9 @@ module Liquid
end
def parse_comparison(p)
- a = parse_expression(p.expression)
+ a = parse_expression(p.expression, safe: true)
if (op = p.consume?(:comparison))
- b = parse_expression(p.expression)
+ b = parse_expression(p.expression, safe: true)
Condition.new(a, op, b)
else
Condition.new(a)
diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb
index 6cdbfd6f..b72a235b 100644
--- a/lib/liquid/tags/include.rb
+++ b/lib/liquid/tags/include.rb
@@ -87,10 +87,11 @@ module Liquid
def rigid_parse(markup)
p = @parse_context.new_parser(markup)
- template_name = p.expression
+ @template_name_expr = safe_parse_expression(p)
with_or_for = p.id?("for") || p.id?("with") || nil
+ @variable_name_expr = nil
if with_or_for
- variable_name = p.expression
+ @variable_name_expr = parse_expression(p.consume(:id), safe: true)
end
alias_name = nil
@@ -98,8 +99,6 @@ module Liquid
alias_name = p.consume(:id)
end
- @template_name_expr = parse_expression(template_name)
- @variable_name_expr = variable_name ? parse_expression(variable_name) : nil
@alias_name = alias_name
# optional comma
@@ -109,7 +108,7 @@ module Liquid
while p.look(:id)
key = p.consume
p.consume(:colon)
- @attributes[key] = parse_expression(p.expression)
+ @attributes[key] = safe_parse_expression(p)
p.consume?(:comma) # optional comma
end
end
diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb
index 89c11063..4f716b24 100644
--- a/lib/liquid/tags/render.rb
+++ b/lib/liquid/tags/render.rb
@@ -88,10 +88,11 @@ module Liquid
def rigid_parse(markup)
p = @parse_context.new_parser(markup)
- template_name = rigid_template_name(p)
+ @template_name_expr = parse_expression(rigid_template_name(p), safe: true)
+ @variable_name_expr = nil
with_or_for = p.id?("for") || p.id?("with") || nil
if with_or_for
- variable_name = p.expression
+ @variable_name_expr = safe_parse_expression(p)
end
alias_name = nil
@@ -99,8 +100,6 @@ module Liquid
alias_name = p.consume(:id)
end
- @template_name_expr = parse_expression(template_name)
- @variable_name_expr = variable_name ? parse_expression(variable_name) : nil
@alias_name = alias_name
@is_for_loop = (with_or_for == FOR)
@@ -111,7 +110,7 @@ module Liquid
while p.look(:id)
key = p.consume
p.consume(:colon)
- @attributes[key] = parse_expression(p.expression)
+ @attributes[key] = safe_parse_expression(p)
p.consume?(:comma) # optional comma
end
end
diff --git a/lib/liquid/variable.rb b/lib/liquid/variable.rb
index 20957065..a3623bc5 100644
--- a/lib/liquid/variable.rb
+++ b/lib/liquid/variable.rb
@@ -65,11 +65,11 @@ module Liquid
return if p.look(:end_of_string)
- @name = parse_context.parse_expression(p.expression)
+ @name = parse_context.safe_parse_expression(p)
while p.consume?(:pipe)
filtername = p.consume(:id)
filterargs = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
- @filters << parse_filter_expressions(filtername, filterargs)
+ @filters << parse_filter_expressions(filtername, filterargs, safe: true)
end
p.consume(:end_of_string)
end
@@ -122,15 +122,15 @@ module Liquid
private
- def parse_filter_expressions(filter_name, unparsed_args)
+ def parse_filter_expressions(filter_name, unparsed_args, safe: false)
filter_args = []
keyword_args = nil
unparsed_args.each do |a|
- if (matches = a.match(JustTagAttributes))
+ if (matches = a.match(JustTagAttributes)) # we'll need to fix this
keyword_args ||= {}
- keyword_args[matches[1]] = parse_context.parse_expression(matches[2])
+ keyword_args[matches[1]] = parse_context.parse_expression(matches[2], safe: false)
else
- filter_args << parse_context.parse_expression(a)
+ filter_args << parse_context.parse_expression(a, safe: safe)
end
end
result = [filter_name, filter_args]
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
4f7dafbcac
Use safe_parse_expression instead of parse_expression
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
d77662cd0e
Remove unnecessary skips
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
65a1c167b3
Add rigid_parse to case/when
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
e2a15334f0
Fail with trailing elements in the cycle tag
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
327790cdce
Fix an int the cycle tag, add extra unit tests, and updated parser switcher:
...
- Fixed NoMethod error with .peek (using look instead)
- Add friendlier error message when {% cycle %}
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
75c95d0791
Fix cycle tag
...
- `respond_to?` was returning `false` in the parser switcher
because `rigid_parse` was private
It was working before because `parse_context` was doing
the double-parsing thing, but when we removed that, this
test fairly started breaking
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
e413104e78
Remove ExpressionParser in favor of ParseContext#safe_parse
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
d56e3c50f9
Use ExpressionParser in the ParseContext when parsing in :rigid mode
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
1bff382ebc
Add ExpressionParser and ExpressionConsumer
2025-10-27 16:33:31 +01:00
Charles-P. Clermont and Guilherme Carreiro
6a9e46dd19
Add rigid_parse method to include
2025-10-27 16:33:31 +01:00
Charles-P. Clermont and Guilherme Carreiro
e58ac0e75b
Add rigid_parse to render
2025-10-27 16:33:31 +01:00
Charles-P. Clermont and Guilherme Carreiro
c78bf20010
Add a rigid_parse method to cycle
2025-10-27 16:33:31 +01:00
Charles-P. Clermont and Guilherme Carreiro
6d585a24f1
Add rigid_parse_with_error_context and clarifications
2025-10-27 16:33:31 +01:00
Guilherme Carreiro and Guilherme Carreiro
edf06c2882
Introduce :rigid parsing mode
2025-10-27 16:33:31 +01:00
Michael Go and GitHub
1c1e711906
Merge pull request #1995 from Shopify/avoid-regex-allocation
...
avoid new regex allocation in util functions
2025-10-15 10:43:52 -03:00
Michael Go
b5b36665e6
avoid new regex allocation in util functions
2025-10-15 10:08:13 -03:00
Alok Swamy and GitHub
9942592ea8
Merge pull request #1984 from Shopify/update-loop-named-params
...
Update liquid docs for loop's named params
2025-09-08 06:24:06 -04:00
Alok Swamy
786381c762
Update liquid docs for loop's named params
2025-09-05 16:43:48 -04:00
Gray Gilmore and GitHub
8ad91b5e36
Merge pull request #1952 from Shopify/jus/template.rb-typo-docs
...
template.rb: Correct typo in docs
2025-09-03 09:03:54 -07:00
iain and GitHub
9bb7fbf123
Merge pull request #1968 from Shopify/shopify-dev-docs-formatting
...
Inline some information that previously lived at category level
2025-07-03 10:59:58 -04:00
Iain Campbell
8555fd8a20
inline warning previuosly at category level
2025-06-27 16:57:00 -04:00
James Meng and GitHub
9bd408f5d0
Merge pull request #1965 from Shopify/jm/bump_liquid
...
Bump Liquid to 5.8.7
v5.8.7
2025-06-09 12:42:27 -07:00
James Meng
79b831d96c
Bump Liquid to 5.8.7
2025-06-09 12:38:04 -07:00
James Meng and GitHub
aebd75e5e8
Merge pull request #1954 from Shopify/jm/doc_body
...
Expose tag body in the Doc tag
2025-06-09 12:25:19 -07:00
James Meng
7f2f8a226b
Add tests for new public methods
2025-06-09 12:24:59 -07:00
James Meng
7b2b25fda1
Fix Doc tag blank? method to check body content
...
Previously the blank? method always returned true. Now it properly checks
if the body is empty, making the tag behavior consistent with other tags.
Also updated test to use whitespace control for cleaner assertions.
2025-06-09 11:36:18 -07:00
James Meng
8548b96a97
Remove body attr_reader and initiliaze @body instance variable in parse method
2025-06-06 13:08:06 -07:00
upgrade-umpire[bot] and GitHub
fc96e66e14
Merge pull request #1953 from Shopify/actions-commit
...
Applying Merge
2025-06-05 20:15:14 +00:00
James Meng
79a771d724
Add test for doc tag capturing token before enddoc
2025-06-04 19:30:47 -07:00
James Meng
65b1dedac5
Expose tag body in the Doc tag
2025-06-04 12:04:41 -07:00
Ian Ker-Seymer and GitHub
f375d7b3aa
Add unit test for custom Liquid tag registration ( #1960 )
...
Adds EnvironmentTest to verify custom tag registration and rendering.
2025-05-22 11:38:10 -04:00
James Meng and GitHub
c6f05eaf83
Merge pull request #1955 from Shopify/jm/trim_doc_tag_desc
...
Remove {{ foo }} and {{ bar }} from `doc` tag description
2025-05-06 15:29:29 -07:00
James Meng
eabbd5cb6f
Remove {{ foo }} and {{ bar }} from doc tag description
2025-05-06 15:20:35 -07:00
Brian Chen
6b3f6c6fb4
update github actions to commits
2025-04-29 14:04:22 -04:00
Justin D. Harris and GitHub
aefd48e341
template.rb: Correct typo in docs
2025-04-22 09:50:47 -04:00
Marco Concetto Rudilosso and GitHub
ea864f1177
Merge pull request #1951 from Shopify/actual-revert
...
Fully revert calling to_s on filter array
v5.8.6
2025-04-14 17:49:47 +02:00
Marco Concetto Rudilosso
c34dd812c5
Fully revert calling to_s on filter array
2025-04-14 17:36:45 +02:00
Marco Concetto Rudilosso and GitHub
cc04892e54
Merge pull request #1943 from Shopify/revert-to-s
...
Revert `Utils.to_s` on all array filters
v5.8.5
2025-04-14 17:22:10 +02:00
Marco Concetto Rudilosso
f676e699a4
rollback changes to tests
2025-04-14 11:24:01 +02:00
Marco Concetto Rudilosso
fc0f7f44c1
use Utils.to_s on property error
2025-04-14 11:17:59 +02:00
Marco Concetto Rudilosso
b459eb656f
remove test
2025-04-14 11:17:46 +02:00
Marco Concetto Rudilosso
c6dcf3e714
add test
2025-04-14 11:17:46 +02:00
Marco Concetto Rudilosso
4dae678c63
Revert "Stringify properties before filtering ( #1929 )"
...
This reverts commit f5d6a36574 .
2025-04-14 11:17:46 +02:00
Marco Concetto Rudilosso
4c07ff920b
Revert "Always stringify properties in all array filters ( #1936 )"
...
This reverts commit aa1640035f .
2025-04-14 11:17:46 +02:00
Ian Ker-Seymer and GitHub
dbe709c3bf
Use to_liquid_value in uniq filter ( #1948 )
...
* Use to_liquid_value in uniq filter
* Bump version to 5.8.4
v5.8.4
2025-04-09 15:00:01 -04:00
2b75bfaff4
Fix regression when using empty/nil properties with array filters ( #1944 )
...
* Make all array filters that use `filter_array` util process empty string and nil correctly
* up version
* fix ordering of checks
* also do it for map
* Do not raise property error
* Gracefully empty property in map filter
---------
Co-authored-by: Marco Concetto Rudilosso <[email protected] >
v5.8.3
2025-04-04 11:27:29 -04:00
James Meng and GitHub
87bc6e7cfa
Merge pull request #1940 from Shopify/jm/update_snippet_url_links
...
Update snippet URLs in documentation links to point to newly created snippet page
2025-04-01 10:58:54 -07:00
James Meng
7f122aeed2
Fix snippet URLs in documentation links
2025-03-31 17:08:31 -07:00
aa1640035f
Always stringify properties in all array filters ( #1936 )
...
* Always stringify sum property.
* Add test
* always stringify properties in all array filters
* fix syntax error
* up version
---------
Co-authored-by: Dominic Petrick <[email protected] >
v5.8.2
2025-03-19 13:50:01 -04:00