diff --git a/History.md b/History.md index 69d4bd3..9b09aec 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ ## 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] * 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] diff --git a/lib/liquid.rb b/lib/liquid.rb index 257efc6..423096b 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -24,13 +24,12 @@ module Liquid ArgumentSeparator = ',' FilterArgumentSeparator = ':' VariableAttributeSeparator = '.' - TagStart = /\{\%/ - TagEnd = /\%\}/ + TagStart = '{%' + TagEnd = '%}' VariableSignature = /\(?[\w\-\.\[\]]\)?/ VariableSegment = /[\w\-]/ - VariableStart = /\{\{/ - VariableEnd = /\}\}/ - VariableIncompleteEnd = /\}\}?/ + VariableStart = '{{' + VariableEnd = '}}' QuotedString = /"[^"]*"|'[^']*'/ QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/o StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s|:,]+/ @@ -40,7 +39,7 @@ module Liquid Expression = /(?:#{QuotedFragment}(?:#{SpacelessFilter})*)/o TagAttributes = /(\w+)\s*\:\s*(#{QuotedFragment})/o AnyStartingTag = /\{\{|\{\%/ - PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/om + PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableEnd}/om TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/om VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/o end diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index c53c5c5..3f2dcbb 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -3,7 +3,6 @@ module Liquid IsTag = /\A#{TagStart}/o IsVariable = /\A#{VariableStart}/o FullToken = /\A#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}\z/om - ContentOfVariable = /\A#{VariableStart}(.*)#{VariableEnd}\z/om def blank? @blank || false @@ -41,10 +40,14 @@ module Liquid unknown_tag($1, $2, tokens) end 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 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 @children << new_var @blank = false @@ -99,13 +102,6 @@ module Liquid @tag_name 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) render_all(@nodelist, context) end @@ -116,6 +112,11 @@ module Liquid raise SyntaxError.new(options[:locale].t("errors.syntax.tag_never_closed", :block_name => block_name)) 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) output = [] context.resource_limits[:render_length_current] = 0 diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index 09f0ad8..6a245c7 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -15,8 +15,8 @@ unknown_tag: "Unknown tag '%{tag}'" 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" - tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}" - variable_termination: "Variable '%{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 '%{tag_end}'" tag_never_closed: "'%{block_name}' tag was never closed" 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" diff --git a/test/liquid/variable_test.rb b/test/liquid/variable_test.rb index 00210df..3bd5c42 100644 --- a/test/liquid/variable_test.rb +++ b/test/liquid/variable_test.rb @@ -201,4 +201,8 @@ class VariableResolutionTest < Test::Unit::TestCase def test_multiline_variable assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked') end + + def test_quoted_single_curly_braces + assert_template_result "{user}", "{{ variable | prepend: '{' | append: '}' }}", 'variable' => 'user' + end end # VariableTest