mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-18 18:30:40 -07:00
Merge pull request #325 from Shopify/remove-variable-incomplete-end
Allow quoted single curly braces in variables.
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
## 3.0.0 / not yet released / branch "master"
|
## 3.0.0 / not yet released / branch "master"
|
||||||
|
|
||||||
* ...
|
* ...
|
||||||
|
* Make tag/variable termination error clearer, see #325 [Dylan Thacker-Smith, dylanahsmith]
|
||||||
|
* Allow quoted single curly braces in variables, see #325 [Dylan Thacker-Smith, dylanahsmith]
|
||||||
* Allow newlines in tags and variables, see #324 [Dylan Thacker-Smith, dylanahsmith]
|
* Allow newlines in tags and variables, see #324 [Dylan Thacker-Smith, dylanahsmith]
|
||||||
* Tag#parse is called after initialize, which now takes options instead of tokens as the 3rd argument. See #321 [Dylan Thacker-Smith, dylanahsmith]
|
* Tag#parse is called after initialize, which now takes options instead of tokens as the 3rd argument. See #321 [Dylan Thacker-Smith, dylanahsmith]
|
||||||
* Raise `Liquid::ArgumentError` instead of `::ArgumentError` when filter has wrong number of arguments #309 [Bogdan Gusiev, bogdan]
|
* Raise `Liquid::ArgumentError` instead of `::ArgumentError` when filter has wrong number of arguments #309 [Bogdan Gusiev, bogdan]
|
||||||
|
|||||||
+5
-6
@@ -24,13 +24,12 @@ module Liquid
|
|||||||
ArgumentSeparator = ','
|
ArgumentSeparator = ','
|
||||||
FilterArgumentSeparator = ':'
|
FilterArgumentSeparator = ':'
|
||||||
VariableAttributeSeparator = '.'
|
VariableAttributeSeparator = '.'
|
||||||
TagStart = /\{\%/
|
TagStart = '{%'
|
||||||
TagEnd = /\%\}/
|
TagEnd = '%}'
|
||||||
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
||||||
VariableSegment = /[\w\-]/
|
VariableSegment = /[\w\-]/
|
||||||
VariableStart = /\{\{/
|
VariableStart = '{{'
|
||||||
VariableEnd = /\}\}/
|
VariableEnd = '}}'
|
||||||
VariableIncompleteEnd = /\}\}?/
|
|
||||||
QuotedString = /"[^"]*"|'[^']*'/
|
QuotedString = /"[^"]*"|'[^']*'/
|
||||||
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
|
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o
|
||||||
StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/
|
StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/
|
||||||
@@ -40,7 +39,7 @@ module Liquid
|
|||||||
Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o
|
Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o
|
||||||
TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
|
TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o
|
||||||
AnyStartingTag = /\{\{|\{\%/
|
AnyStartingTag = /\{\{|\{\%/
|
||||||
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om
|
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableEnd}/om
|
||||||
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om
|
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om
|
||||||
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
|
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o
|
||||||
end
|
end
|
||||||
|
|||||||
+11
-10
@@ -3,7 +3,6 @@ module Liquid
|
|||||||
IsTag = /\A#{TagStart}/o
|
IsTag = /\A#{TagStart}/o
|
||||||
IsVariable = /\A#{VariableStart}/o
|
IsVariable = /\A#{VariableStart}/o
|
||||||
FullToken = /\A#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}\z/om
|
FullToken = /\A#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}\z/om
|
||||||
ContentOfVariable = /\A#{VariableStart}(.*)#{VariableEnd}\z/om
|
|
||||||
|
|
||||||
def blank?
|
def blank?
|
||||||
@blank || false
|
@blank || false
|
||||||
@@ -41,10 +40,14 @@ module Liquid
|
|||||||
unknown_tag($1, $2, tokens)
|
unknown_tag($1, $2, tokens)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.tag_termination", :token => token, :tag_end => TagEnd.inspect))
|
raise_tag_termination_error("errors.syntax.tag_termination", token + tokens.shift.to_s, TagEnd)
|
||||||
end
|
end
|
||||||
when IsVariable
|
when IsVariable
|
||||||
new_var = create_variable(token)
|
if token.size < 4
|
||||||
|
raise_tag_termination_error("errors.syntax.variable_termination", token + tokens.shift.to_s, VariableEnd)
|
||||||
|
end
|
||||||
|
markup = token[2...-2]
|
||||||
|
new_var = Variable.new(markup, @options)
|
||||||
@nodelist << new_var
|
@nodelist << new_var
|
||||||
@children << new_var
|
@children << new_var
|
||||||
@blank = false
|
@blank = false
|
||||||
@@ -99,13 +102,6 @@ module Liquid
|
|||||||
@tag_name
|
@tag_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_variable(token)
|
|
||||||
token.scan(ContentOfVariable) do |content|
|
|
||||||
return Variable.new(content.first, @options)
|
|
||||||
end
|
|
||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.variable_termination", :token => token, :tag_end => VariableEnd.inspect))
|
|
||||||
end
|
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
render_all(@nodelist, context)
|
render_all(@nodelist, context)
|
||||||
end
|
end
|
||||||
@@ -116,6 +112,11 @@ module Liquid
|
|||||||
raise SyntaxError.new(options[:locale].t("errors.syntax.tag_never_closed", :block_name => block_name))
|
raise SyntaxError.new(options[:locale].t("errors.syntax.tag_never_closed", :block_name => block_name))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def raise_tag_termination_error(error_name, token, tag_end)
|
||||||
|
token = token.size > 50 ? "'#{token[0...47]}'..." : "'#{token}'"
|
||||||
|
raise SyntaxError.new(options[:locale].t(error_name, :token => token, :tag_end => tag_end))
|
||||||
|
end
|
||||||
|
|
||||||
def render_all(list, context)
|
def render_all(list, context)
|
||||||
output = []
|
output = []
|
||||||
context.resource_limits[:render_length_current] = 0
|
context.resource_limits[:render_length_current] = 0
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
unknown_tag: "Unknown tag '%{tag}'"
|
unknown_tag: "Unknown tag '%{tag}'"
|
||||||
invalid_delimiter: "'end' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
|
invalid_delimiter: "'end' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
|
||||||
unexpected_else: "%{block_name} tag does not expect else tag"
|
unexpected_else: "%{block_name} tag does not expect else tag"
|
||||||
tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"
|
tag_termination: "Tag %{token} was not properly terminated with '%{tag_end}'"
|
||||||
variable_termination: "Variable '%{token}' was not properly terminated with regexp: %{tag_end}"
|
variable_termination: "Variable %{token} was not properly terminated with '%{tag_end}'"
|
||||||
tag_never_closed: "'%{block_name}' tag was never closed"
|
tag_never_closed: "'%{block_name}' tag was never closed"
|
||||||
meta_syntax_error: "Liquid syntax error: #{e.message}"
|
meta_syntax_error: "Liquid syntax error: #{e.message}"
|
||||||
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
|
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
|
||||||
|
|||||||
@@ -201,4 +201,8 @@ class VariableResolutionTest < Test::Unit::TestCase
|
|||||||
def test_multiline_variable
|
def test_multiline_variable
|
||||||
assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked')
|
assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_quoted_single_curly_braces
|
||||||
|
assert_template_result "{user}", "{{ variable | prepend: '{' | append: '}' }}", 'variable' => 'user'
|
||||||
|
end
|
||||||
end # VariableTest
|
end # VariableTest
|
||||||
|
|||||||
Reference in New Issue
Block a user