Merge pull request #325 from Shopify/remove-variable-incomplete-end

Allow quoted single curly braces in variables.
This commit is contained in:
Dylan Thacker-Smith
2014-03-21 13:48:47 -04:00
5 changed files with 24 additions and 18 deletions
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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"
+4
View File
@@ -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