mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
Add error mode switching
This commit is contained in:
@@ -30,6 +30,10 @@ namespace :benchmark do
|
|||||||
ruby "./performance/benchmark.rb"
|
ruby "./performance/benchmark.rb"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "Run the liquid benchmark with lax parsing"
|
||||||
|
task :lax do
|
||||||
|
ruby "./performance/benchmark.rb lax"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+18
-2
@@ -29,6 +29,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
|
context.errors += @warnings if @warnings
|
||||||
context.stack do
|
context.stack do
|
||||||
@blocks.each do |block|
|
@blocks.each do |block|
|
||||||
if block.evaluate(context)
|
if block.evaluate(context)
|
||||||
@@ -52,7 +53,22 @@ module Liquid
|
|||||||
@nodelist = block.attach(Array.new)
|
@nodelist = block.attach(Array.new)
|
||||||
end
|
end
|
||||||
|
|
||||||
def old_parse(markup)
|
def parse_condition(markup)
|
||||||
|
case Template.error_mode
|
||||||
|
when :strict then strict_parse(markup)
|
||||||
|
when :lax then lax_parse(markup)
|
||||||
|
when :warn
|
||||||
|
begin
|
||||||
|
return strict_parse(markup)
|
||||||
|
rescue SyntaxError => e
|
||||||
|
@warnings ||= []
|
||||||
|
@warnings << e
|
||||||
|
return lax_parse(markup)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def lax_parse(markup)
|
||||||
expressions = markup.scan(ExpressionsAndOperators).reverse
|
expressions = markup.scan(ExpressionsAndOperators).reverse
|
||||||
raise(SyntaxError, SyntaxHelp) unless expressions.shift =~ Syntax
|
raise(SyntaxError, SyntaxHelp) unless expressions.shift =~ Syntax
|
||||||
|
|
||||||
@@ -71,7 +87,7 @@ module Liquid
|
|||||||
condition
|
condition
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_condition(markup)
|
def strict_parse(markup)
|
||||||
p = Parser.new(markup)
|
p = Parser.new(markup)
|
||||||
|
|
||||||
condition = parse_comparison(p)
|
condition = parse_comparison(p)
|
||||||
|
|||||||
@@ -34,6 +34,18 @@ module Liquid
|
|||||||
@tags ||= {}
|
@tags ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets how strict the parser should be.
|
||||||
|
# :lax acts like liquid 2.5 and silently ignores malformed tags in most cases.
|
||||||
|
# :warn is the default and will give deprecation warnings when invalid syntax is used.
|
||||||
|
# :strict will enforce correct syntax.
|
||||||
|
def error_mode=(mode)
|
||||||
|
@error_mode = mode
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_mode
|
||||||
|
@error_mode || :warn
|
||||||
|
end
|
||||||
|
|
||||||
# Pass a module with filter methods which should be available
|
# Pass a module with filter methods which should be available
|
||||||
# to all liquid views. Good for registering the standard library
|
# to all liquid views. Good for registering the standard library
|
||||||
def register_filter(mod)
|
def register_filter(mod)
|
||||||
|
|||||||
+19
-4
@@ -17,11 +17,24 @@ module Liquid
|
|||||||
def initialize(markup)
|
def initialize(markup)
|
||||||
@markup = markup
|
@markup = markup
|
||||||
@name = nil
|
@name = nil
|
||||||
@filters = []
|
@warning = nil
|
||||||
parse(markup)
|
|
||||||
|
|
||||||
|
case Template.error_mode
|
||||||
|
when :strict then strict_parse(markup)
|
||||||
|
when :lax then lax_parse(markup)
|
||||||
|
when :warn
|
||||||
|
begin
|
||||||
|
strict_parse(markup)
|
||||||
|
rescue SyntaxError => e
|
||||||
|
@warning = e
|
||||||
|
lax_parse(markup)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def old_parse(markup)
|
def lax_parse(markup)
|
||||||
|
@filters = []
|
||||||
if match = markup.match(/\s*(#{QuotedFragment})(.*)/o)
|
if match = markup.match(/\s*(#{QuotedFragment})(.*)/o)
|
||||||
@name = match[1]
|
@name = match[1]
|
||||||
if match[2].match(/#{FilterSeparator}\s*(.*)/o)
|
if match[2].match(/#{FilterSeparator}\s*(.*)/o)
|
||||||
@@ -37,7 +50,8 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse(markup)
|
def strict_parse(markup)
|
||||||
|
@filters = []
|
||||||
p = Parser.new(markup)
|
p = Parser.new(markup)
|
||||||
# Could be just filters with no input
|
# Could be just filters with no input
|
||||||
@name = p.look(:pipe) ? '' : p.expression
|
@name = p.look(:pipe) ? '' : p.expression
|
||||||
@@ -61,6 +75,7 @@ module Liquid
|
|||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
return '' if @name.nil?
|
return '' if @name.nil?
|
||||||
|
context.errors << @warning if @warning
|
||||||
@filters.inject(context[@name]) do |output, filter|
|
@filters.inject(context[@name]) do |output, filter|
|
||||||
filterargs = []
|
filterargs = []
|
||||||
keyword_args = {}
|
keyword_args = {}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ require 'rubygems'
|
|||||||
require 'benchmark'
|
require 'benchmark'
|
||||||
require File.dirname(__FILE__) + '/theme_runner'
|
require File.dirname(__FILE__) + '/theme_runner'
|
||||||
|
|
||||||
|
Liquid::Template.error_mode = ARGV.first.to_sym if ARGV.first
|
||||||
profiler = ThemeRunner.new
|
profiler = ThemeRunner.new
|
||||||
|
|
||||||
Benchmark.bmbm do |x|
|
Benchmark.bmbm do |x|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_unrecognized_operator
|
def test_unrecognized_operator
|
||||||
|
Template.error_mode = :strict
|
||||||
assert_raise(SyntaxError) do
|
assert_raise(SyntaxError) do
|
||||||
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_error_on_empty_filter
|
def test_error_on_empty_filter
|
||||||
|
Template.error_mode = :strict
|
||||||
assert_nothing_raised do
|
assert_nothing_raised do
|
||||||
Template.parse("{{test}}")
|
Template.parse("{{test}}")
|
||||||
Template.parse("{{|test}}")
|
Template.parse("{{|test}}")
|
||||||
@@ -40,6 +41,7 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_meaningless_parens
|
def test_meaningless_parens
|
||||||
|
Template.error_mode = :strict
|
||||||
assert_raise(SyntaxError) do
|
assert_raise(SyntaxError) do
|
||||||
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
||||||
Template.parse("{% if #{markup} %} YES {% endif %}")
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
||||||
@@ -47,6 +49,7 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_unexpected_characters_silently_eat_logic
|
def test_unexpected_characters_silently_eat_logic
|
||||||
|
Template.error_mode = :strict
|
||||||
assert_raise(SyntaxError) do
|
assert_raise(SyntaxError) do
|
||||||
markup = "true && false"
|
markup = "true && false"
|
||||||
Template.parse("{% if #{markup} %} YES {% endif %}")
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
||||||
|
|||||||
Reference in New Issue
Block a user