mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-20 19:30:47 -07:00
Remove :lax, :strict and :warn error modes
This commit is contained in:
@@ -93,31 +93,6 @@ LIQUID
|
|||||||
|
|
||||||
By using Environments, you ensure that custom tags and filters are only available in the contexts where they are needed, making your Liquid templates more robust and easier to manage. For smaller projects, a global environment is available via `Liquid::Environment.default`.
|
By using Environments, you ensure that custom tags and filters are only available in the contexts where they are needed, making your Liquid templates more robust and easier to manage. For smaller projects, a global environment is available via `Liquid::Environment.default`.
|
||||||
|
|
||||||
### Error Modes
|
|
||||||
|
|
||||||
Setting the error mode of Liquid lets you specify how strictly you want your templates to be interpreted.
|
|
||||||
Normally the parser is very lax and will accept almost anything without error. Unfortunately this can make
|
|
||||||
it very hard to debug and can lead to unexpected behaviour.
|
|
||||||
|
|
||||||
Liquid also comes with different parsers that can be used when editing templates to give better error messages
|
|
||||||
when templates are invalid. You can enable this new parser like this:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
Liquid::Environment.default.error_mode = :strict2 # Raises a SyntaxError when invalid syntax is used in all tags
|
|
||||||
Liquid::Environment.default.error_mode = :strict # Raises a SyntaxError when invalid syntax is used in some tags
|
|
||||||
Liquid::Environment.default.error_mode = :warn # Adds strict errors to template.errors but continues as normal
|
|
||||||
Liquid::Environment.default.error_mode = :lax # The default mode, accepts almost anything.
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to set the error mode only on specific templates you can pass `:error_mode` as an option to `parse`:
|
|
||||||
```ruby
|
|
||||||
Liquid::Template.parse(source, error_mode: :strict)
|
|
||||||
```
|
|
||||||
This is useful for doing things like enabling strict mode only in the theme editor.
|
|
||||||
|
|
||||||
It is recommended that you enable `:strict` or `:warn` mode on new apps to stop invalid templates from being created.
|
|
||||||
It is also recommended that you use it in the template editors of existing apps to give editors better error messages.
|
|
||||||
|
|
||||||
### Undefined variables and filters
|
### Undefined variables and filters
|
||||||
|
|
||||||
By default, the renderer doesn't raise or in any other way notify you if some variables or filters are missing, i.e. not passed to the `render` method.
|
By default, the renderer doesn't raise or in any other way notify you if some variables or filters are missing, i.e. not passed to the `render` method.
|
||||||
|
|||||||
@@ -33,28 +33,13 @@ task :rubocop do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc('runs test suite with lax, strict, and strict2 parsers')
|
desc('runs test suite with strict2 parser')
|
||||||
task :test do
|
task :test do
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'lax'
|
|
||||||
Rake::Task['base_test'].invoke
|
|
||||||
|
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'strict'
|
|
||||||
Rake::Task['base_test'].reenable
|
|
||||||
Rake::Task['base_test'].invoke
|
|
||||||
|
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'strict2'
|
ENV['LIQUID_PARSER_MODE'] = 'strict2'
|
||||||
Rake::Task['base_test'].reenable
|
Rake::Task['base_test'].reenable
|
||||||
Rake::Task['base_test'].invoke
|
Rake::Task['base_test'].invoke
|
||||||
|
|
||||||
if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'truffleruby'
|
if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'truffleruby'
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'lax'
|
|
||||||
Rake::Task['integration_test'].reenable
|
|
||||||
Rake::Task['integration_test'].invoke
|
|
||||||
|
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'strict'
|
|
||||||
Rake::Task['integration_test'].reenable
|
|
||||||
Rake::Task['integration_test'].invoke
|
|
||||||
|
|
||||||
ENV['LIQUID_PARSER_MODE'] = 'strict2'
|
ENV['LIQUID_PARSER_MODE'] = 'strict2'
|
||||||
Rake::Task['integration_test'].reenable
|
Rake::Task['integration_test'].reenable
|
||||||
Rake::Task['integration_test'].invoke
|
Rake::Task['integration_test'].invoke
|
||||||
@@ -78,23 +63,13 @@ task release: :build do
|
|||||||
end
|
end
|
||||||
|
|
||||||
namespace :benchmark do
|
namespace :benchmark do
|
||||||
desc "Run the liquid benchmark with lax parsing"
|
|
||||||
task :lax do
|
|
||||||
ruby "./performance/benchmark.rb lax"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run the liquid benchmark with strict parsing"
|
|
||||||
task :strict do
|
|
||||||
ruby "./performance/benchmark.rb strict"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run the liquid benchmark with strict2 parsing"
|
desc "Run the liquid benchmark with strict2 parsing"
|
||||||
task :strict2 do
|
task :strict2 do
|
||||||
ruby "./performance/benchmark.rb strict2"
|
ruby "./performance/benchmark.rb strict2"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Run the liquid benchmark with lax, strict, and strict2 parsing"
|
desc "Run the liquid benchmark"
|
||||||
task run: [:lax, :strict, :strict2]
|
task run: [:strict2]
|
||||||
|
|
||||||
desc "Run unit benchmarks"
|
desc "Run unit benchmarks"
|
||||||
namespace :unit do
|
namespace :unit do
|
||||||
@@ -127,9 +102,9 @@ namespace :profile do
|
|||||||
ruby "./performance/profile.rb"
|
ruby "./performance/profile.rb"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Run the liquid profile/performance coverage with strict parsing"
|
desc "Run the liquid profile/performance coverage with strict2 parsing"
|
||||||
task :strict do
|
task :strict2 do
|
||||||
ruby "./performance/profile.rb strict"
|
ruby "./performance/profile.rb strict2"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ module Liquid
|
|||||||
# @param file_system The default file system that is used
|
# @param file_system The default file system that is used
|
||||||
# to load templates from.
|
# to load templates from.
|
||||||
# @param error_mode [Symbol] The default error mode for all templates
|
# @param error_mode [Symbol] The default error mode for all templates
|
||||||
# (either :strict2, :strict, :warn, or :lax).
|
# (:strict2).
|
||||||
# @param exception_renderer [Proc] The exception renderer that is used to
|
# @param exception_renderer [Proc] The exception renderer that is used to
|
||||||
# render exceptions.
|
# render exceptions.
|
||||||
# @yieldparam environment [Environment] The environment instance that is being built.
|
# @yieldparam environment [Environment] The environment instance that is being built.
|
||||||
@@ -75,7 +75,7 @@ module Liquid
|
|||||||
# @api private
|
# @api private
|
||||||
def initialize
|
def initialize
|
||||||
@tags = Tags::STANDARD_TAGS.dup
|
@tags = Tags::STANDARD_TAGS.dup
|
||||||
@error_mode = :lax
|
@error_mode = :strict2
|
||||||
@strainer_template = Class.new(StrainerTemplate).tap do |klass|
|
@strainer_template = Class.new(StrainerTemplate).tap do |klass|
|
||||||
klass.add_filter(StandardFilters)
|
klass.add_filter(StandardFilters)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ module Liquid
|
|||||||
'false' => false,
|
'false' => false,
|
||||||
'blank' => '',
|
'blank' => '',
|
||||||
'empty' => '',
|
'empty' => '',
|
||||||
# in lax mode, minus sign can be a VariableLookup
|
|
||||||
# For simplicity and performace, we treat it like a literal
|
|
||||||
'-' => VariableLookup.parse("-", nil).freeze,
|
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
DOT = ".".ord
|
DOT = ".".ord
|
||||||
|
|||||||
@@ -2,59 +2,12 @@
|
|||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
module ParserSwitching
|
module ParserSwitching
|
||||||
# Do not use this.
|
|
||||||
#
|
|
||||||
# It's basically doing the same thing the {#parse_with_selected_parser},
|
|
||||||
# except this will try the strict parser regardless of the error mode,
|
|
||||||
# and fall back to the lax parser if the error mode is lax or warn,
|
|
||||||
# except when in strict2 mode where it uses the strict2 parser.
|
|
||||||
#
|
|
||||||
# @deprecated Use {#parse_with_selected_parser} instead.
|
|
||||||
def strict_parse_with_error_mode_fallback(markup)
|
|
||||||
return strict2_parse_with_error_context(markup) if strict2_mode?
|
|
||||||
|
|
||||||
strict_parse_with_error_context(markup)
|
|
||||||
rescue SyntaxError => e
|
|
||||||
case parse_context.error_mode
|
|
||||||
when :rigid
|
|
||||||
rigid_warn
|
|
||||||
raise
|
|
||||||
when :strict2
|
|
||||||
raise
|
|
||||||
when :strict
|
|
||||||
raise
|
|
||||||
when :warn
|
|
||||||
parse_context.warnings << e
|
|
||||||
end
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_with_selected_parser(markup)
|
def parse_with_selected_parser(markup)
|
||||||
case parse_context.error_mode
|
strict2_parse_with_error_context(markup)
|
||||||
when :rigid then rigid_warn && strict2_parse_with_error_context(markup)
|
|
||||||
when :strict2 then strict2_parse_with_error_context(markup)
|
|
||||||
when :strict then strict_parse_with_error_context(markup)
|
|
||||||
when :lax then lax_parse(markup)
|
|
||||||
when :warn
|
|
||||||
begin
|
|
||||||
strict2_parse_with_error_context(markup)
|
|
||||||
rescue SyntaxError => e
|
|
||||||
parse_context.warnings << e
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict2_mode?
|
|
||||||
parse_context.error_mode == :strict2 || parse_context.error_mode == :rigid
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def rigid_warn
|
|
||||||
Deprecations.warn(':rigid', ':strict2')
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict2_parse_with_error_context(markup)
|
def strict2_parse_with_error_context(markup)
|
||||||
strict2_parse(markup)
|
strict2_parse(markup)
|
||||||
rescue SyntaxError => e
|
rescue SyntaxError => e
|
||||||
@@ -63,14 +16,6 @@ module Liquid
|
|||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse_with_error_context(markup)
|
|
||||||
strict_parse(markup)
|
|
||||||
rescue SyntaxError => e
|
|
||||||
e.line_number = line_number
|
|
||||||
e.markup_context = markup_context(markup)
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
|
|
||||||
def markup_context(markup)
|
def markup_context(markup)
|
||||||
"in \"#{markup.strip}\""
|
"in \"#{markup.strip}\""
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ module Liquid
|
|||||||
# @liquid_syntax_keyword second_expression An expression to be rendered when the variable's value matches `second_value`.
|
# @liquid_syntax_keyword second_expression An expression to be rendered when the variable's value matches `second_value`.
|
||||||
# @liquid_syntax_keyword third_expression An expression to be rendered when the variable's value has no match.
|
# @liquid_syntax_keyword third_expression An expression to be rendered when the variable's value has no match.
|
||||||
class Case < Block
|
class Case < Block
|
||||||
Syntax = /(#{QuotedFragment})/o
|
|
||||||
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/om
|
|
||||||
|
|
||||||
attr_reader :blocks, :left
|
attr_reader :blocks, :left
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
@@ -92,18 +89,6 @@ module Liquid
|
|||||||
parser.consume(:end_of_string)
|
parser.consume(:end_of_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
if markup =~ Syntax
|
|
||||||
@left = parse_expression(Regexp.last_match(1))
|
|
||||||
else
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.case")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def record_when_condition(markup)
|
def record_when_condition(markup)
|
||||||
body = new_body
|
body = new_body
|
||||||
|
|
||||||
@@ -129,20 +114,6 @@ module Liquid
|
|||||||
parser.consume(:end_of_string)
|
parser.consume(:end_of_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_lax_when(markup, body)
|
|
||||||
while markup
|
|
||||||
unless markup =~ WhenSyntax
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_when")
|
|
||||||
end
|
|
||||||
|
|
||||||
markup = Regexp.last_match(2)
|
|
||||||
|
|
||||||
block = Condition.new(@left, '==', Condition.parse_expression(parse_context, Regexp.last_match(1)))
|
|
||||||
block.attach(body)
|
|
||||||
@blocks << block
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def record_else_condition(markup)
|
def record_else_condition(markup)
|
||||||
unless markup.strip.empty?
|
unless markup.strip.empty?
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_else")
|
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_else")
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ module Liquid
|
|||||||
# @liquid_syntax
|
# @liquid_syntax
|
||||||
# {% cycle string, string, ... %}
|
# {% cycle string, string, ... %}
|
||||||
class Cycle < Tag
|
class Cycle < Tag
|
||||||
SimpleSyntax = /\A#{QuotedFragment}+/o
|
|
||||||
NamedSyntax = /\A(#{QuotedFragment})\s*\:\s*(.*)/om
|
|
||||||
UNNAMED_CYCLE_PATTERN = /\w+:0x\h{8}/
|
UNNAMED_CYCLE_PATTERN = /\w+:0x\h{8}/
|
||||||
|
|
||||||
attr_reader :variables
|
attr_reader :variables
|
||||||
@@ -91,35 +89,6 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
case markup
|
|
||||||
when NamedSyntax
|
|
||||||
@variables = variables_from_string(Regexp.last_match(2))
|
|
||||||
@name = parse_expression(Regexp.last_match(1))
|
|
||||||
@is_named = true
|
|
||||||
when SimpleSyntax
|
|
||||||
@variables = variables_from_string(markup)
|
|
||||||
@name = @variables.to_s
|
|
||||||
@is_named = !@name.match?(UNNAMED_CYCLE_PATTERN)
|
|
||||||
else
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.cycle")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def variables_from_string(markup)
|
|
||||||
markup.split(',').collect do |var|
|
|
||||||
var =~ /\s*(#{QuotedFragment})\s*/o
|
|
||||||
next unless Regexp.last_match(1)
|
|
||||||
|
|
||||||
var = parse_expression(Regexp.last_match(1))
|
|
||||||
maybe_dup_lookup(var)
|
|
||||||
end.compact
|
|
||||||
end
|
|
||||||
|
|
||||||
# For backwards compatibility, whenever a lookup is used in an unnamed cycle,
|
# For backwards compatibility, whenever a lookup is used in an unnamed cycle,
|
||||||
# we make it so that the @variables.to_s produces different strings for cycles
|
# we make it so that the @variables.to_s produces different strings for cycles
|
||||||
# called with the same arguments (since @variables.to_s is used as the cycle counter key)
|
# called with the same arguments (since @variables.to_s is used as the cycle counter key)
|
||||||
|
|||||||
+1
-22
@@ -25,8 +25,6 @@ module Liquid
|
|||||||
# @liquid_optional_param range [untyped] A custom numeric range to iterate over.
|
# @liquid_optional_param range [untyped] A custom numeric range to iterate over.
|
||||||
# @liquid_optional_param reversed [untyped] Iterate in reverse order.
|
# @liquid_optional_param reversed [untyped] Iterate in reverse order.
|
||||||
class For < Block
|
class For < Block
|
||||||
Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
|
|
||||||
|
|
||||||
attr_reader :collection_name, :variable_name, :limit, :from
|
attr_reader :collection_name, :variable_name, :limit, :from
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
@@ -72,22 +70,7 @@ module Liquid
|
|||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def lax_parse(markup)
|
def strict2_parse(markup)
|
||||||
if markup =~ Syntax
|
|
||||||
@variable_name = Regexp.last_match(1)
|
|
||||||
collection_name = Regexp.last_match(2)
|
|
||||||
@reversed = !!Regexp.last_match(3)
|
|
||||||
@name = "#{@variable_name}-#{collection_name}"
|
|
||||||
@collection_name = parse_expression(collection_name)
|
|
||||||
markup.scan(TagAttributes) do |key, value|
|
|
||||||
set_attribute(key, value)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.for")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
p = @parse_context.new_parser(markup)
|
p = @parse_context.new_parser(markup)
|
||||||
@variable_name = p.consume(:id)
|
@variable_name = p.consume(:id)
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
|
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
|
||||||
@@ -111,10 +94,6 @@ module Liquid
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def strict2_parse(markup)
|
|
||||||
strict_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def collection_segment(context)
|
def collection_segment(context)
|
||||||
offsets = context.registers[:for] ||= {}
|
offsets = context.registers[:for] ||= {}
|
||||||
|
|
||||||
|
|||||||
+1
-29
@@ -14,10 +14,6 @@ module Liquid
|
|||||||
# @liquid_syntax_keyword condition The condition to evaluate.
|
# @liquid_syntax_keyword condition The condition to evaluate.
|
||||||
# @liquid_syntax_keyword expression The expression to render if the condition is met.
|
# @liquid_syntax_keyword expression The expression to render if the condition is met.
|
||||||
class If < Block
|
class If < Block
|
||||||
Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
|
|
||||||
ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
|
|
||||||
BOOLEAN_OPERATORS = %w(and or).freeze
|
|
||||||
|
|
||||||
attr_reader :blocks
|
attr_reader :blocks
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
@@ -66,10 +62,6 @@ module Liquid
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def strict2_parse(markup)
|
|
||||||
strict_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def push_block(tag, markup)
|
def push_block(tag, markup)
|
||||||
block = if tag == 'else'
|
block = if tag == 'else'
|
||||||
ElseCondition.new
|
ElseCondition.new
|
||||||
@@ -85,27 +77,7 @@ module Liquid
|
|||||||
Condition.parse_expression(parse_context, markup, safe: safe)
|
Condition.parse_expression(parse_context, markup, safe: safe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def lax_parse(markup)
|
def strict2_parse(markup)
|
||||||
expressions = markup.scan(ExpressionsAndOperators)
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax
|
|
||||||
|
|
||||||
condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))
|
|
||||||
|
|
||||||
until expressions.empty?
|
|
||||||
operator = expressions.pop.to_s.strip
|
|
||||||
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax
|
|
||||||
|
|
||||||
new_condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.if") unless BOOLEAN_OPERATORS.include?(operator)
|
|
||||||
new_condition.send(operator, condition)
|
|
||||||
condition = new_condition
|
|
||||||
end
|
|
||||||
|
|
||||||
condition
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
p = @parse_context.new_parser(markup)
|
p = @parse_context.new_parser(markup)
|
||||||
condition = parse_binary_comparisons(p)
|
condition = parse_binary_comparisons(p)
|
||||||
p.consume(:end_of_string)
|
p.consume(:end_of_string)
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ module Liquid
|
|||||||
class Include < Tag
|
class Include < Tag
|
||||||
prepend Tag::Disableable
|
prepend Tag::Disableable
|
||||||
|
|
||||||
SYNTAX = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
|
|
||||||
Syntax = SYNTAX
|
|
||||||
|
|
||||||
attr_reader :template_name_expr, :variable_name_expr, :attributes
|
attr_reader :template_name_expr, :variable_name_expr, :attributes
|
||||||
|
|
||||||
def initialize(tag_name, markup, options)
|
def initialize(tag_name, markup, options)
|
||||||
@@ -104,29 +101,6 @@ module Liquid
|
|||||||
p.consume(:end_of_string)
|
p.consume(:end_of_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
if markup =~ SYNTAX
|
|
||||||
template_name = Regexp.last_match(1)
|
|
||||||
variable_name = Regexp.last_match(3)
|
|
||||||
|
|
||||||
@alias_name = Regexp.last_match(5)
|
|
||||||
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
|
||||||
@template_name_expr = parse_expression(template_name)
|
|
||||||
@attributes = {}
|
|
||||||
|
|
||||||
markup.scan(TagAttributes) do |key, value|
|
|
||||||
@attributes[key] = parse_expression(value)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.include")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
||||||
def children
|
def children
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ module Liquid
|
|||||||
# @liquid_syntax_keyword filename The name of the snippet to render, without the `.liquid` extension.
|
# @liquid_syntax_keyword filename The name of the snippet to render, without the `.liquid` extension.
|
||||||
class Render < Tag
|
class Render < Tag
|
||||||
FOR = 'for'
|
FOR = 'for'
|
||||||
SYNTAX = /(#{QuotedString}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
|
|
||||||
|
|
||||||
disable_tags "include"
|
disable_tags "include"
|
||||||
|
|
||||||
@@ -111,28 +110,6 @@ module Liquid
|
|||||||
p.consume(:string)
|
p.consume(:string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
|
|
||||||
|
|
||||||
template_name = Regexp.last_match(1)
|
|
||||||
with_or_for = Regexp.last_match(3)
|
|
||||||
variable_name = Regexp.last_match(4)
|
|
||||||
|
|
||||||
@alias_name = Regexp.last_match(6)
|
|
||||||
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
|
||||||
@template_name_expr = parse_expression(template_name)
|
|
||||||
@is_for_loop = (with_or_for == FOR)
|
|
||||||
|
|
||||||
@attributes = {}
|
|
||||||
markup.scan(TagAttributes) do |key, value|
|
|
||||||
@attributes[key] = parse_expression(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
||||||
def children
|
def children
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ module Liquid
|
|||||||
# @liquid_optional_param offset: [number] The 1-based index to start iterating at.
|
# @liquid_optional_param offset: [number] The 1-based index to start iterating at.
|
||||||
# @liquid_optional_param range [untyped] A custom numeric range to iterate over.
|
# @liquid_optional_param range [untyped] A custom numeric range to iterate over.
|
||||||
class TableRow < Block
|
class TableRow < Block
|
||||||
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
|
|
||||||
ALLOWED_ATTRIBUTES = ['cols', 'limit', 'offset', 'range'].freeze
|
ALLOWED_ATTRIBUTES = ['cols', 'limit', 'offset', 'range'].freeze
|
||||||
|
|
||||||
attr_reader :variable_name, :collection_name, :attributes
|
attr_reader :variable_name, :collection_name, :attributes
|
||||||
@@ -62,23 +61,6 @@ module Liquid
|
|||||||
p.consume(:end_of_string)
|
p.consume(:end_of_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
lax_parse(markup)
|
|
||||||
end
|
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
if markup =~ Syntax
|
|
||||||
@variable_name = Regexp.last_match(1)
|
|
||||||
@collection_name = parse_expression(Regexp.last_match(2))
|
|
||||||
@attributes = {}
|
|
||||||
markup.scan(TagAttributes) do |key, value|
|
|
||||||
@attributes[key] = parse_expression(value)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.table_row")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_to_output_buffer(context, output)
|
def render_to_output_buffer(context, output)
|
||||||
(collection = context.evaluate(@collection_name)) || (return '')
|
(collection = context.evaluate(@collection_name)) || (return '')
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ module Liquid
|
|||||||
|
|
||||||
class << self
|
class << self
|
||||||
# Sets how strict the parser should be.
|
# 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 enforces correct syntax for most tags
|
|
||||||
# :strict2 enforces correct syntax for all tags
|
# :strict2 enforces correct syntax for all tags
|
||||||
def error_mode=(mode)
|
def error_mode=(mode)
|
||||||
Deprecations.warn("Template.error_mode=", "Environment#error_mode=")
|
Deprecations.warn("Template.error_mode=", "Environment#error_mode=")
|
||||||
|
|||||||
+1
-58
@@ -30,7 +30,7 @@ module Liquid
|
|||||||
@parse_context = parse_context
|
@parse_context = parse_context
|
||||||
@line_number = parse_context.line_number
|
@line_number = parse_context.line_number
|
||||||
|
|
||||||
strict_parse_with_error_mode_fallback(markup)
|
parse_with_selected_parser(markup)
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw
|
def raw
|
||||||
@@ -41,39 +41,6 @@ module Liquid
|
|||||||
"in \"{{#{markup}}}\""
|
"in \"{{#{markup}}}\""
|
||||||
end
|
end
|
||||||
|
|
||||||
def lax_parse(markup)
|
|
||||||
@filters = []
|
|
||||||
return unless markup =~ MarkupWithQuotedFragment
|
|
||||||
|
|
||||||
name_markup = Regexp.last_match(1)
|
|
||||||
filter_markup = Regexp.last_match(2)
|
|
||||||
@name = parse_context.parse_expression(name_markup)
|
|
||||||
if filter_markup =~ FilterMarkupRegex
|
|
||||||
filters = Regexp.last_match(1).scan(FilterParser)
|
|
||||||
filters.each do |f|
|
|
||||||
next unless f =~ /\w+/
|
|
||||||
filtername = Regexp.last_match(0)
|
|
||||||
filterargs = f.scan(FilterArgsRegex).flatten
|
|
||||||
@filters << lax_parse_filter_expressions(filtername, filterargs)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict_parse(markup)
|
|
||||||
@filters = []
|
|
||||||
p = @parse_context.new_parser(markup)
|
|
||||||
|
|
||||||
return if p.look(:end_of_string)
|
|
||||||
|
|
||||||
@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 << lax_parse_filter_expressions(filtername, filterargs)
|
|
||||||
end
|
|
||||||
p.consume(:end_of_string)
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict2_parse(markup)
|
def strict2_parse(markup)
|
||||||
@filters = []
|
@filters = []
|
||||||
p = @parse_context.new_parser(markup)
|
p = @parse_context.new_parser(markup)
|
||||||
@@ -85,14 +52,6 @@ module Liquid
|
|||||||
p.consume(:end_of_string)
|
p.consume(:end_of_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_filterargs(p)
|
|
||||||
# first argument
|
|
||||||
filterargs = [p.argument]
|
|
||||||
# followed by comma separated others
|
|
||||||
filterargs << p.argument while p.consume?(:comma)
|
|
||||||
filterargs
|
|
||||||
end
|
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
obj = context.evaluate(@name)
|
obj = context.evaluate(@name)
|
||||||
|
|
||||||
@@ -133,22 +92,6 @@ module Liquid
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def lax_parse_filter_expressions(filter_name, unparsed_args)
|
|
||||||
filter_args = []
|
|
||||||
keyword_args = nil
|
|
||||||
unparsed_args.each do |a|
|
|
||||||
if (matches = a.match(JustTagAttributes))
|
|
||||||
keyword_args ||= {}
|
|
||||||
keyword_args[matches[1]] = parse_context.parse_expression(matches[2])
|
|
||||||
else
|
|
||||||
filter_args << parse_context.parse_expression(a)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
result = [filter_name, filter_args]
|
|
||||||
result << keyword_args if keyword_args
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
# Surprisingly, positional and keyword arguments can be mixed.
|
# Surprisingly, positional and keyword arguments can be mixed.
|
||||||
#
|
#
|
||||||
# filter = filtername [":" filterargs?]
|
# filter = filtername [":" filterargs?]
|
||||||
|
|||||||
@@ -41,11 +41,10 @@ class AssignTest < Minitest::Test
|
|||||||
|
|
||||||
def test_assign_uses_error_mode
|
def test_assign_uses_error_mode
|
||||||
assert_match_syntax_error(
|
assert_match_syntax_error(
|
||||||
"Expected dotdot but found pipe in ",
|
"Expected dotdot but found pipe",
|
||||||
"{% assign foo = ('X' | downcase) %}",
|
"{% assign foo = ('X' | downcase) %}",
|
||||||
error_mode: :strict,
|
error_mode: :rigid,
|
||||||
)
|
)
|
||||||
assert_template_result("", "{% assign foo = ('X' | downcase) %}", error_mode: :lax)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_expression_with_whitespace_in_square_brackets
|
def test_expression_with_whitespace_in_square_brackets
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ class ContextTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_has_key_will_not_add_an_error_for_missing_keys
|
def test_has_key_will_not_add_an_error_for_missing_keys
|
||||||
with_error_modes(:strict) do
|
with_error_modes(:rigid) do
|
||||||
context = Context.new
|
context = Context.new
|
||||||
context.key?('unknown')
|
context.key?('unknown')
|
||||||
assert_empty(context.errors)
|
assert_empty(context.errors)
|
||||||
|
|||||||
@@ -67,20 +67,13 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_unrecognized_operator
|
def test_unrecognized_operator
|
||||||
with_error_modes(:strict) do
|
with_error_modes(:rigid) do
|
||||||
assert_raises(SyntaxError) do
|
assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_lax_unrecognized_operator
|
|
||||||
template = Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', error_mode: :lax)
|
|
||||||
assert_equal(' Liquid error: Unknown operator =! ', template.render)
|
|
||||||
assert_equal(1, template.errors.size)
|
|
||||||
assert_equal(Liquid::ArgumentError, template.errors.first.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_with_line_numbers_adds_numbers_to_parser_errors
|
def test_with_line_numbers_adds_numbers_to_parser_errors
|
||||||
source = <<~LIQUID
|
source = <<~LIQUID
|
||||||
foobar
|
foobar
|
||||||
@@ -104,25 +97,6 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
assert_match_syntax_error(/Liquid syntax error \(line 3\)/, source)
|
assert_match_syntax_error(/Liquid syntax error \(line 3\)/, source)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_parsing_warn_with_line_numbers_adds_numbers_to_lexer_errors
|
|
||||||
template = Liquid::Template.parse(
|
|
||||||
'
|
|
||||||
foobar
|
|
||||||
|
|
||||||
{% if 1 =! 2 %}ok{% endif %}
|
|
||||||
|
|
||||||
bla
|
|
||||||
',
|
|
||||||
error_mode: :warn,
|
|
||||||
line_numbers: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert_equal(
|
|
||||||
['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'],
|
|
||||||
template.warnings.map(&:message),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_parsing_strict_with_line_numbers_adds_numbers_to_lexer_errors
|
def test_parsing_strict_with_line_numbers_adds_numbers_to_lexer_errors
|
||||||
err = assert_raises(SyntaxError) do
|
err = assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse(
|
Liquid::Template.parse(
|
||||||
@@ -133,7 +107,7 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
|
|
||||||
bla
|
bla
|
||||||
',
|
',
|
||||||
error_mode: :strict,
|
error_mode: :rigid,
|
||||||
line_numbers: true,
|
line_numbers: true,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -157,34 +131,16 @@ class ErrorHandlingTest < Minitest::Test
|
|||||||
|
|
||||||
def test_strict_error_messages
|
def test_strict_error_messages
|
||||||
err = assert_raises(SyntaxError) do
|
err = assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', error_mode: :strict)
|
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', error_mode: :rigid)
|
||||||
end
|
end
|
||||||
assert_equal('Liquid syntax error: Unexpected character = in "1 =! 2"', err.message)
|
assert_equal('Liquid syntax error: Unexpected character = in "1 =! 2"', err.message)
|
||||||
|
|
||||||
err = assert_raises(SyntaxError) do
|
err = assert_raises(SyntaxError) do
|
||||||
Liquid::Template.parse('{{%%%}}', error_mode: :strict)
|
Liquid::Template.parse('{{%%%}}', error_mode: :rigid)
|
||||||
end
|
end
|
||||||
assert_equal('Liquid syntax error: Unexpected character % in "{{%%%}}"', err.message)
|
assert_equal('Liquid syntax error: Unexpected character % in "{{%%%}}"', err.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_warnings
|
|
||||||
template = Liquid::Template.parse('{% if ~~~ %}{{%%%}}{% else %}{{ hello. }}{% endif %}', error_mode: :warn)
|
|
||||||
assert_equal(3, template.warnings.size)
|
|
||||||
assert_equal('Unexpected character ~ in "~~~"', template.warnings[0].to_s(false))
|
|
||||||
assert_equal('Unexpected character % in "{{%%%}}"', template.warnings[1].to_s(false))
|
|
||||||
assert_equal('Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].to_s(false))
|
|
||||||
assert_equal('', template.render)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_warning_line_numbers
|
|
||||||
template = Liquid::Template.parse("{% if ~~~ %}\n{{%%%}}{% else %}\n{{ hello. }}{% endif %}", error_mode: :warn, line_numbers: true)
|
|
||||||
assert_equal('Liquid syntax error (line 1): Unexpected character ~ in "~~~"', template.warnings[0].message)
|
|
||||||
assert_equal('Liquid syntax error (line 2): Unexpected character % in "{{%%%}}"', template.warnings[1].message)
|
|
||||||
assert_equal('Liquid syntax error (line 3): Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].message)
|
|
||||||
assert_equal(3, template.warnings.size)
|
|
||||||
assert_equal([1, 2, 3], template.warnings.map(&:line_number))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError
|
# Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError
|
||||||
def test_exceptions_propagate
|
def test_exceptions_propagate
|
||||||
assert_raises(Exception) do
|
assert_raises(Exception) do
|
||||||
|
|||||||
@@ -27,11 +27,6 @@ class ExpressionTest < Minitest::Test
|
|||||||
assert_template_result("-17.42", "{{ -17.42 }}")
|
assert_template_result("-17.42", "{{ -17.42 }}")
|
||||||
assert_template_result("2.5", "{{ 2.5 }}")
|
assert_template_result("2.5", "{{ 2.5 }}")
|
||||||
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_expression_result(0.0, "0.....5")
|
|
||||||
assert_expression_result(0.0, "-0..1")
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_expression_result(1.5, "1.5")
|
assert_expression_result(1.5, "1.5")
|
||||||
|
|
||||||
# this is a unfortunate quirky behavior of Liquid
|
# this is a unfortunate quirky behavior of Liquid
|
||||||
@@ -56,19 +51,6 @@ class ExpressionTest < Minitest::Test
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_quirky_negative_sign_expression_markup
|
|
||||||
result = Expression.parse("-", nil)
|
|
||||||
assert(result.is_a?(VariableLookup))
|
|
||||||
assert_equal("-", result.name)
|
|
||||||
|
|
||||||
# for this template, the expression markup is "-"
|
|
||||||
assert_template_result(
|
|
||||||
"",
|
|
||||||
"{{ - 'theme.css' - }}",
|
|
||||||
error_mode: :lax,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_expression_cache
|
def test_expression_cache
|
||||||
skip("Liquid-C does not support Expression caching") if defined?(Liquid::C) && Liquid::C.enabled
|
skip("Liquid-C does not support Expression caching") if defined?(Liquid::C) && Liquid::C.enabled
|
||||||
|
|
||||||
|
|||||||
@@ -31,18 +31,14 @@ class ParsingQuirksTest < Minitest::Test
|
|||||||
def test_error_on_empty_filter
|
def test_error_on_empty_filter
|
||||||
assert(Template.parse("{{test}}"))
|
assert(Template.parse("{{test}}"))
|
||||||
|
|
||||||
with_error_modes(:lax) do
|
with_error_modes(:rigid) do
|
||||||
assert(Template.parse("{{|test}}"))
|
assert_raises(Liquid::SyntaxError) { Template.parse("{{|test}}") }
|
||||||
end
|
assert_raises(Liquid::SyntaxError) { Template.parse("{{test |a|b|}}") }
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
assert_raises(SyntaxError) { Template.parse("{{|test}}") }
|
|
||||||
assert_raises(SyntaxError) { Template.parse("{{test |a|b|}}") }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_meaningless_parens_error
|
def test_meaningless_parens_error
|
||||||
with_error_modes(:strict) do
|
with_error_modes(:rigid) do
|
||||||
assert_raises(SyntaxError) do
|
assert_raises(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 %}")
|
||||||
@@ -51,7 +47,7 @@ class ParsingQuirksTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_unexpected_characters_syntax_error
|
def test_unexpected_characters_syntax_error
|
||||||
with_error_modes(:strict) do
|
with_error_modes(:rigid) do
|
||||||
assert_raises(SyntaxError) do
|
assert_raises(SyntaxError) do
|
||||||
markup = "true && false"
|
markup = "true && false"
|
||||||
Template.parse("{% if #{markup} %} YES {% endif %}")
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
||||||
@@ -63,61 +59,12 @@ class ParsingQuirksTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_no_error_on_lax_empty_filter
|
|
||||||
assert(Template.parse("{{test |a|b|}}", error_mode: :lax))
|
|
||||||
assert(Template.parse("{{test}}", error_mode: :lax))
|
|
||||||
assert(Template.parse("{{|test|}}", error_mode: :lax))
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_meaningless_parens_lax
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assigns = { 'b' => 'bar', 'c' => 'baz' }
|
|
||||||
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
|
||||||
assert_template_result(' YES ', "{% if #{markup} %} YES {% endif %}", assigns)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_unexpected_characters_silently_eat_logic_lax
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
markup = "true && false"
|
|
||||||
assert_template_result(' YES ', "{% if #{markup} %} YES {% endif %}")
|
|
||||||
markup = "false || true"
|
|
||||||
assert_template_result('', "{% if #{markup} %} YES {% endif %}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_raise_on_invalid_tag_delimiter
|
def test_raise_on_invalid_tag_delimiter
|
||||||
assert_raises(Liquid::SyntaxError) do
|
assert_raises(Liquid::SyntaxError) do
|
||||||
Template.new.parse('{% end %}')
|
Template.new.parse('{% end %}')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_unanchored_filter_arguments
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_template_result('hi', "{{ 'hi there' | split$$$:' ' | first }}")
|
|
||||||
|
|
||||||
assert_template_result('x', "{{ 'X' | downcase) }}")
|
|
||||||
|
|
||||||
# After the messed up quotes a filter without parameters (reverse) should work
|
|
||||||
# but one with parameters (remove) shouldn't be detected.
|
|
||||||
assert_template_result('here', "{{ 'hi there' | split:\"t\"\" | reverse | first}}")
|
|
||||||
assert_template_result('hi ', "{{ 'hi there' | split:\"t\"\" | remove:\"i\" | first}}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_invalid_variables_work
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_template_result('bar', "{% assign 123foo = 'bar' %}{{ 123foo }}")
|
|
||||||
assert_template_result('123', "{% assign 123 = 'bar' %}{{ 123 }}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_extra_dots_in_ranges
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_template_result('12345', "{% for i in (1...5) %}{{ i }}{% endfor %}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_blank_variable_markup
|
def test_blank_variable_markup
|
||||||
assert_template_result('', "{{}}")
|
assert_template_result('', "{{}}")
|
||||||
end
|
end
|
||||||
@@ -131,24 +78,4 @@ class ParsingQuirksTest < Minitest::Test
|
|||||||
def test_contains_in_id
|
def test_contains_in_id
|
||||||
assert_template_result(' YES ', '{% if containsallshipments == true %} YES {% endif %}', { 'containsallshipments' => true })
|
assert_template_result(' YES ', '{% if containsallshipments == true %} YES {% endif %}', { 'containsallshipments' => true })
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_incomplete_expression
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_template_result("false", "{{ false - }}")
|
|
||||||
assert_template_result("false", "{{ false > }}")
|
|
||||||
assert_template_result("false", "{{ false < }}")
|
|
||||||
assert_template_result("false", "{{ false = }}")
|
|
||||||
assert_template_result("false", "{{ false ! }}")
|
|
||||||
assert_template_result("false", "{{ false 1 }}")
|
|
||||||
assert_template_result("false", "{{ false a }}")
|
|
||||||
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false -\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false >\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false <\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false =\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false !\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false 1\n%}{{ foo }}")
|
|
||||||
assert_template_result("false", "{% liquid assign foo = false a\n%}{{ foo }}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end # ParsingQuirksTest
|
end # ParsingQuirksTest
|
||||||
|
|||||||
@@ -96,11 +96,6 @@ class CycleTagTest < Minitest::Test
|
|||||||
template1 = "{% assign 5 = 'b' %}{% cycle .5, .4 %}"
|
template1 = "{% assign 5 = 'b' %}{% cycle .5, .4 %}"
|
||||||
template2 = "{% cycle .5: 'a', 'b' %}"
|
template2 = "{% cycle .5: 'a', 'b' %}"
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("b", template1)
|
|
||||||
assert_template_result("a", template2)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error1 = assert_raises(Liquid::SyntaxError) { Template.parse(template1) }
|
error1 = assert_raises(Liquid::SyntaxError) { Template.parse(template1) }
|
||||||
error2 = assert_raises(Liquid::SyntaxError) { Template.parse(template2) }
|
error2 = assert_raises(Liquid::SyntaxError) { Template.parse(template2) }
|
||||||
@@ -121,14 +116,6 @@ class CycleTagTest < Minitest::Test
|
|||||||
template4 = "#{assignments}{% cycle n e: 'a', 'b', 'c' %}"
|
template4 = "#{assignments}{% cycle n e: 'a', 'b', 'c' %}"
|
||||||
template5 = "#{assignments}{% cycle n e 'a', 'b', 'c' %}"
|
template5 = "#{assignments}{% cycle n e 'a', 'b', 'c' %}"
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("a", template1)
|
|
||||||
assert_template_result("a", template2)
|
|
||||||
assert_template_result("a", template3)
|
|
||||||
assert_template_result("N", template4)
|
|
||||||
assert_template_result("N", template5)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error1 = assert_raises(Liquid::SyntaxError) { Template.parse(template1) }
|
error1 = assert_raises(Liquid::SyntaxError) { Template.parse(template1) }
|
||||||
error2 = assert_raises(Liquid::SyntaxError) { Template.parse(template2) }
|
error2 = assert_raises(Liquid::SyntaxError) { Template.parse(template2) }
|
||||||
@@ -153,10 +140,6 @@ class CycleTagTest < Minitest::Test
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
@@ -170,10 +153,6 @@ class CycleTagTest < Minitest::Test
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
|
|||||||
@@ -205,14 +205,6 @@ class IncludeTagTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_strict2_parsing_errors
|
def test_strict2_parsing_errors
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result(
|
|
||||||
'hello value1 value2',
|
|
||||||
'{% include "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
|
||||||
partials: { 'snippet' => 'hello {{ arg1 }} {{ arg2 }}' },
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_syntax_error(
|
assert_syntax_error(
|
||||||
'{% include "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
'{% include "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
||||||
@@ -301,16 +293,10 @@ class IncludeTagTest < Minitest::Test
|
|||||||
env = Liquid::Environment.build(file_system: TestFileSystem.new)
|
env = Liquid::Environment.build(file_system: TestFileSystem.new)
|
||||||
|
|
||||||
assert_raises(Liquid::SyntaxError) do
|
assert_raises(Liquid::SyntaxError) do
|
||||||
Template.parse("{% include template %}", error_mode: :strict, environment: env).render!("template" => '{{ "X" || downcase }}')
|
Template.parse("{% include template %}", error_mode: :rigid, environment: env).render!("template" => '{{ "X" || downcase }}')
|
||||||
end
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true, environment: env).render!("template" => '{{ "X" || downcase }}'))
|
|
||||||
end
|
end
|
||||||
assert_raises(Liquid::SyntaxError) do
|
assert_raises(Liquid::SyntaxError) do
|
||||||
Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale], environment: env).render!("template" => '{{ "X" || downcase }}')
|
Template.parse("{% include template %}", error_mode: :rigid, include_options_blacklist: [:locale], environment: env).render!("template" => '{{ "X" || downcase }}')
|
||||||
end
|
|
||||||
with_error_modes(:lax) do
|
|
||||||
assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode], environment: env).render!("template" => '{{ "X" || downcase }}'))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -404,10 +390,6 @@ class IncludeTagTest < Minitest::Test
|
|||||||
def test_include_template_with_invalid_expression
|
def test_include_template_with_invalid_expression
|
||||||
template = "{% include foo=>bar %}"
|
template = "{% include foo=>bar %}"
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
@@ -417,10 +399,6 @@ class IncludeTagTest < Minitest::Test
|
|||||||
def test_include_with_invalid_expression
|
def test_include_with_invalid_expression
|
||||||
template = '{% include "snippet" with foo=>bar %}'
|
template = '{% include "snippet" with foo=>bar %}'
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
@@ -430,10 +408,6 @@ class IncludeTagTest < Minitest::Test
|
|||||||
def test_include_attribute_with_invalid_expression
|
def test_include_attribute_with_invalid_expression
|
||||||
template = '{% include "snippet", key: foo=>bar %}'
|
template = '{% include "snippet", key: foo=>bar %}'
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
|
|||||||
@@ -106,14 +106,6 @@ class RenderTagTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_strict2_parsing_errors
|
def test_strict2_parsing_errors
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result(
|
|
||||||
'hello value1 value2',
|
|
||||||
'{% render "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
|
||||||
partials: { 'snippet' => 'hello {{ arg1 }} {{ arg2 }}' },
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_syntax_error(
|
assert_syntax_error(
|
||||||
'{% render "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
'{% render "snippet" !!! arg1: "value1" ~~~ arg2: "value2" %}',
|
||||||
@@ -318,10 +310,6 @@ class RenderTagTest < Minitest::Test
|
|||||||
def test_render_with_invalid_expression
|
def test_render_with_invalid_expression
|
||||||
template = '{% render "snippet" with foo=>bar %}'
|
template = '{% render "snippet" with foo=>bar %}'
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
@@ -331,10 +319,6 @@ class RenderTagTest < Minitest::Test
|
|||||||
def test_render_attribute_with_invalid_expression
|
def test_render_attribute_with_invalid_expression
|
||||||
template = '{% render "snippet", key: foo=>bar %}'
|
template = '{% render "snippet", key: foo=>bar %}'
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
refute_nil(Template.parse(template))
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
|
|||||||
@@ -188,29 +188,6 @@ class TableRowTest < Minitest::Test
|
|||||||
assert_template_result(expected_output, template)
|
assert_template_result(expected_output, template)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_table_row_renders_correct_error_message_for_invalid_parameters
|
|
||||||
assert_template_result(
|
|
||||||
"Liquid error (line 1): invalid integer",
|
|
||||||
'{% tablerow n in (1...10) limit:true %} {{n}} {% endtablerow %}',
|
|
||||||
error_mode: :warn,
|
|
||||||
render_errors: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert_template_result(
|
|
||||||
"Liquid error (line 1): invalid integer",
|
|
||||||
'{% tablerow n in (1...10) offset:true %} {{n}} {% endtablerow %}',
|
|
||||||
error_mode: :warn,
|
|
||||||
render_errors: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert_template_result(
|
|
||||||
"Liquid error (line 1): invalid integer",
|
|
||||||
'{% tablerow n in (1...10) cols:true %} {{n}} {% endtablerow %}',
|
|
||||||
render_errors: true,
|
|
||||||
error_mode: :warn,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_table_row_handles_interrupts
|
def test_table_row_handles_interrupts
|
||||||
assert_template_result(
|
assert_template_result(
|
||||||
"<tr class=\"row1\">\n<td class=\"col1\"> 1 </td></tr>\n",
|
"<tr class=\"row1\">\n<td class=\"col1\"> 1 </td></tr>\n",
|
||||||
@@ -439,10 +416,6 @@ class TableRowTest < Minitest::Test
|
|||||||
<td class="col1">1</td><td class="col2">2</td><td class="col3">3</td><td class="col4">4</td><td class="col5">5</td></tr>
|
<td class="col1">1</td><td class="col2">2</td><td class="col3">3</td><td class="col4">4</td><td class="col5">5</td></tr>
|
||||||
OUTPUT
|
OUTPUT
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result(expected, template)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(SyntaxError) { Template.parse(template) }
|
error = assert_raises(SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Invalid attribute 'invalid_attr'/, error.message)
|
assert_match(/Invalid attribute 'invalid_attr'/, error.message)
|
||||||
@@ -452,14 +425,6 @@ class TableRowTest < Minitest::Test
|
|||||||
def test_tablerow_with_invalid_expression_strict_vs_strict2
|
def test_tablerow_with_invalid_expression_strict_vs_strict2
|
||||||
template = '{% tablerow i in (1..5) limit: foo=>bar %}{{ i }}{% endtablerow %}'
|
template = '{% tablerow i in (1..5) limit: foo=>bar %}{{ i }}{% endtablerow %}'
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
expected = <<~OUTPUT
|
|
||||||
<tr class="row1">
|
|
||||||
</tr>
|
|
||||||
OUTPUT
|
|
||||||
assert_template_result(expected, template)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(SyntaxError) { Template.parse(template) }
|
error = assert_raises(SyntaxError) { Template.parse(template) }
|
||||||
assert_match(/Unexpected character =/, error.message)
|
assert_match(/Unexpected character =/, error.message)
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ class TemplateTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_nil_value_does_not_raise
|
def test_nil_value_does_not_raise
|
||||||
t = Template.parse("some{{x}}thing", error_mode: :strict)
|
t = Template.parse("some{{x}}thing", error_mode: :rigid)
|
||||||
result = t.render!({ 'x' => nil }, strict_variables: true)
|
result = t.render!({ 'x' => nil }, strict_variables: true)
|
||||||
|
|
||||||
assert_equal(0, t.errors.count)
|
assert_equal(0, t.errors.count)
|
||||||
|
|||||||
@@ -176,48 +176,9 @@ class VariableTest < Minitest::Test
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_variable_lookup_should_not_hang_with_invalid_syntax
|
|
||||||
Timeout.timeout(1) do
|
|
||||||
assert_template_result(
|
|
||||||
'bar',
|
|
||||||
"{{['foo'}}",
|
|
||||||
{
|
|
||||||
'foo' => 'bar',
|
|
||||||
},
|
|
||||||
error_mode: :lax,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
very_long_key = "1234567890" * 100
|
|
||||||
|
|
||||||
template_list = [
|
|
||||||
"{{['#{very_long_key}']}}", # valid
|
|
||||||
"{{['#{very_long_key}'}}", # missing closing bracket
|
|
||||||
"{{[['#{very_long_key}']}}", # extra open bracket
|
|
||||||
]
|
|
||||||
|
|
||||||
template_list.each do |template|
|
|
||||||
Timeout.timeout(1) do
|
|
||||||
assert_template_result(
|
|
||||||
'bar',
|
|
||||||
template,
|
|
||||||
{
|
|
||||||
very_long_key => 'bar',
|
|
||||||
},
|
|
||||||
error_mode: :lax,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_filter_with_single_trailing_comma
|
def test_filter_with_single_trailing_comma
|
||||||
template = '{{ "hello" | append: "world", }}'
|
template = '{{ "hello" | append: "world", }}'
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
|
||||||
assert_match(/is not a valid expression/, error.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result('helloworld', template)
|
assert_template_result('helloworld', template)
|
||||||
end
|
end
|
||||||
@@ -226,11 +187,6 @@ class VariableTest < Minitest::Test
|
|||||||
def test_multiple_filters_with_trailing_commas
|
def test_multiple_filters_with_trailing_commas
|
||||||
template = '{{ "hello" | append: "1", | append: "2", }}'
|
template = '{{ "hello" | append: "1", | append: "2", }}'
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
|
||||||
assert_match(/is not a valid expression/, error.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result('hello12', template)
|
assert_template_result('hello12', template)
|
||||||
end
|
end
|
||||||
@@ -239,11 +195,6 @@ class VariableTest < Minitest::Test
|
|||||||
def test_filter_with_colon_but_no_arguments
|
def test_filter_with_colon_but_no_arguments
|
||||||
template = '{{ "test" | upcase: }}'
|
template = '{{ "test" | upcase: }}'
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
|
||||||
assert_match(/is not a valid expression/, error.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result('TEST', template)
|
assert_template_result('TEST', template)
|
||||||
end
|
end
|
||||||
@@ -252,11 +203,6 @@ class VariableTest < Minitest::Test
|
|||||||
def test_filter_chain_with_colon_no_args
|
def test_filter_chain_with_colon_no_args
|
||||||
template = '{{ "test" | append: "x" | upcase: }}'
|
template = '{{ "test" | append: "x" | upcase: }}'
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
|
||||||
assert_match(/is not a valid expression/, error.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result('TESTX', template)
|
assert_template_result('TESTX', template)
|
||||||
end
|
end
|
||||||
@@ -265,11 +211,6 @@ class VariableTest < Minitest::Test
|
|||||||
def test_combining_trailing_comma_and_empty_args
|
def test_combining_trailing_comma_and_empty_args
|
||||||
template = '{{ "test" | append: "x", | upcase: }}'
|
template = '{{ "test" | append: "x", | upcase: }}'
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
|
||||||
assert_match(/is not a valid expression/, error.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result('TESTX', template)
|
assert_template_result('TESTX', template)
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ $LOAD_PATH.unshift(File.join(File.expand_path(__dir__), '..', 'lib'))
|
|||||||
require 'liquid.rb'
|
require 'liquid.rb'
|
||||||
require 'liquid/profiler'
|
require 'liquid/profiler'
|
||||||
|
|
||||||
mode = :strict
|
mode = :rigid
|
||||||
if (env_mode = ENV['LIQUID_PARSER_MODE'])
|
if (env_mode = ENV['LIQUID_PARSER_MODE'])
|
||||||
puts "-- #{env_mode.upcase} ERROR MODE"
|
puts "-- #{env_mode.upcase} ERROR MODE"
|
||||||
mode = env_mode.to_sym
|
mode = env_mode.to_sym
|
||||||
|
|||||||
@@ -167,9 +167,9 @@ class ConditionUnitTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_expression_in_strict_mode
|
def test_parse_expression_in_strict_mode
|
||||||
environment = Environment.build(error_mode: :strict)
|
environment = Environment.build(error_mode: :rigid)
|
||||||
parse_context = ParseContext.new(environment: environment)
|
parse_context = ParseContext.new(environment: environment)
|
||||||
result = Condition.parse_expression(parse_context, 'product.title')
|
result = Condition.parse_expression(parse_context, 'product.title', safe: true)
|
||||||
|
|
||||||
assert_instance_of(VariableLookup, result)
|
assert_instance_of(VariableLookup, result)
|
||||||
assert_equal('product', result.name)
|
assert_equal('product', result.name)
|
||||||
|
|||||||
@@ -38,12 +38,6 @@ class ParseContextUnitTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_expression_with_variable_lookup
|
def test_parse_expression_with_variable_lookup
|
||||||
result_strict = strict_parse_context.parse_expression('product.title')
|
|
||||||
|
|
||||||
assert_instance_of(VariableLookup, result_strict)
|
|
||||||
assert_equal('product', result_strict.name)
|
|
||||||
assert_equal(['title'], result_strict.lookups)
|
|
||||||
|
|
||||||
error = assert_raises(Liquid::InternalError) do
|
error = assert_raises(Liquid::InternalError) do
|
||||||
strict2_parse_context.parse_expression('product.title')
|
strict2_parse_context.parse_expression('product.title')
|
||||||
end
|
end
|
||||||
@@ -66,9 +60,6 @@ class ParseContextUnitTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_expression_with_empty_string
|
def test_parse_expression_with_empty_string
|
||||||
result_strict = strict_parse_context.parse_expression('')
|
|
||||||
assert_nil(result_strict)
|
|
||||||
|
|
||||||
error = assert_raises(Liquid::InternalError) do
|
error = assert_raises(Liquid::InternalError) do
|
||||||
strict2_parse_context.parse_expression('')
|
strict2_parse_context.parse_expression('')
|
||||||
end
|
end
|
||||||
@@ -77,9 +68,6 @@ class ParseContextUnitTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_expression_with_empty_string_and_safe_true
|
def test_parse_expression_with_empty_string_and_safe_true
|
||||||
result_strict = strict_parse_context.parse_expression('', safe: true)
|
|
||||||
assert_nil(result_strict)
|
|
||||||
|
|
||||||
result_strict2 = strict2_parse_context.parse_expression('', safe: true)
|
result_strict2 = strict2_parse_context.parse_expression('', safe: true)
|
||||||
assert_nil(result_strict2)
|
assert_nil(result_strict2)
|
||||||
end
|
end
|
||||||
@@ -109,12 +97,6 @@ class ParseContextUnitTest < Minitest::Test
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def strict_parse_context
|
|
||||||
@strict_parse_context ||= ParseContext.new(
|
|
||||||
environment: Environment.build(error_mode: :strict),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def strict2_parse_context
|
def strict2_parse_context
|
||||||
@strict2_parse_context ||= ParseContext.new(
|
@strict2_parse_context ||= ParseContext.new(
|
||||||
environment: Environment.build(error_mode: :strict2),
|
environment: Environment.build(error_mode: :strict2),
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ class PartialCacheUnitTest < Minitest::Test
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
[:lax, :warn, :strict, :strict2].each do |error_mode|
|
[:strict2].each do |error_mode|
|
||||||
Liquid::PartialCache.load(
|
Liquid::PartialCache.load(
|
||||||
'my_partial',
|
'my_partial',
|
||||||
context: context,
|
context: context,
|
||||||
@@ -193,7 +193,7 @@ class PartialCacheUnitTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
assert_equal(
|
assert_equal(
|
||||||
["my_partial:lax", "my_partial:warn", "my_partial:strict", "my_partial:strict2"],
|
["my_partial:strict2"],
|
||||||
context.registers[:cached_partials].keys,
|
context.registers[:cached_partials].keys,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
{%- endcase -%}
|
{%- endcase -%}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("one", template)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
|
|
||||||
@@ -41,10 +37,6 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
{%- endcase -%}
|
{%- endcase -%}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("one", template)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
|
|
||||||
@@ -62,7 +54,7 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
{%- endcase -%}
|
{%- endcase -%}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict, :strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result("one", template)
|
assert_template_result("one", template)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -77,7 +69,7 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
{%- endcase -%}
|
{%- endcase -%}
|
||||||
LIQUID
|
LIQUID
|
||||||
|
|
||||||
with_error_modes(:lax, :strict, :strict2) do
|
with_error_modes(:strict2) do
|
||||||
assert_template_result("one", template)
|
assert_template_result("one", template)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -113,10 +105,6 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
LIQUID
|
LIQUID
|
||||||
assigns = { 'foo' => { 'bar' => 'baz' } }
|
assigns = { 'foo' => { 'bar' => 'baz' } }
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("one", template, assigns)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
|
|
||||||
@@ -135,10 +123,6 @@ class CaseTagUnitTest < Minitest::Test
|
|||||||
LIQUID
|
LIQUID
|
||||||
assigns = { 'foo' => { 'bar' => 'baz' } }
|
assigns = { 'foo' => { 'bar' => 'baz' } }
|
||||||
|
|
||||||
with_error_modes(:lax, :strict) do
|
|
||||||
assert_template_result("one", template, assigns)
|
|
||||||
end
|
|
||||||
|
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
|
||||||
|
|
||||||
|
|||||||
@@ -72,12 +72,6 @@ class VariableUnitTest < Minitest::Test
|
|||||||
assert_equal([['replace', ['foo', 'bar']], ['textileze', []]], var.filters)
|
assert_equal([['replace', ['foo', 'bar']], ['textileze', []]], var.filters)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_symbol
|
|
||||||
var = create_variable("http://disney.com/logo.gif | image: 'med' ", error_mode: :lax)
|
|
||||||
assert_equal(VariableLookup.new('http://disney.com/logo.gif'), var.name)
|
|
||||||
assert_equal([['image', ['med']]], var.filters)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_string_to_filter
|
def test_string_to_filter
|
||||||
var = create_variable("'http://disney.com/logo.gif' | image: 'med' ")
|
var = create_variable("'http://disney.com/logo.gif' | image: 'med' ")
|
||||||
assert_equal('http://disney.com/logo.gif', var.name)
|
assert_equal('http://disney.com/logo.gif', var.name)
|
||||||
@@ -108,7 +102,7 @@ class VariableUnitTest < Minitest::Test
|
|||||||
assert_equal(VariableLookup.new('foo-bar'), create_variable('foo-bar').name)
|
assert_equal(VariableLookup.new('foo-bar'), create_variable('foo-bar').name)
|
||||||
assert_equal(VariableLookup.new('foo-bar-2'), create_variable('foo-bar-2').name)
|
assert_equal(VariableLookup.new('foo-bar-2'), create_variable('foo-bar-2').name)
|
||||||
|
|
||||||
with_error_modes(:strict) do
|
with_error_modes(:strict2) do
|
||||||
assert_raises(Liquid::SyntaxError) { create_variable('foo - bar') }
|
assert_raises(Liquid::SyntaxError) { create_variable('foo - bar') }
|
||||||
assert_raises(Liquid::SyntaxError) { create_variable('-foo') }
|
assert_raises(Liquid::SyntaxError) { create_variable('-foo') }
|
||||||
assert_raises(Liquid::SyntaxError) { create_variable('2foo') }
|
assert_raises(Liquid::SyntaxError) { create_variable('2foo') }
|
||||||
@@ -131,36 +125,6 @@ class VariableUnitTest < Minitest::Test
|
|||||||
assert_equal([['things', [], { 'greeting' => 'world', 'farewell' => 'goodbye' }]], var.filters)
|
assert_equal([['things', [], { 'greeting' => 'world', 'farewell' => 'goodbye' }]], var.filters)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_lax_filter_argument_parsing
|
|
||||||
var = create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ), error_mode: :lax)
|
|
||||||
assert_equal(VariableLookup.new('number_of_comments'), var.name)
|
|
||||||
assert_equal([['pluralize', ['comment', 'comments']]], var.filters)
|
|
||||||
|
|
||||||
# missing does not throws error
|
|
||||||
create_variable(%(n | f1: ,), error_mode: :lax)
|
|
||||||
create_variable(%(n | f1: ,| f2), error_mode: :lax)
|
|
||||||
|
|
||||||
# arg does not require colon, but ignores args :O, also ignores first kwarg since it splits on ':'
|
|
||||||
var = create_variable(%(n | f1 1 | f2 k1: v1), error_mode: :lax)
|
|
||||||
assert_equal([['f1', []], ['f2', [VariableLookup.new('v1')]]], var.filters)
|
|
||||||
|
|
||||||
# positional and kwargs parsing
|
|
||||||
var = create_variable(%(n | filter: 1, 2, 3 | filter2: k1: 1, k2: 2), error_mode: :lax)
|
|
||||||
assert_equal([['filter', [1, 2, 3]], ['filter2', [], { "k1" => 1, "k2" => 2 }]], var.filters)
|
|
||||||
|
|
||||||
# positional and kwargs intermixed (pos1, key1: val1, pos2)
|
|
||||||
var = create_variable(%(n | link_to: class: "black", "https://example.com", title: "title"), error_mode: :lax)
|
|
||||||
assert_equal([['link_to', ["https://example.com"], { "class" => "black", "title" => "title" }]], var.filters)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_strict_filter_argument_parsing
|
|
||||||
with_error_modes(:strict) do
|
|
||||||
assert_raises(SyntaxError) do
|
|
||||||
create_variable(%( number_of_comments | pluralize: 'comment': 'comments' ))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_strict2_filter_argument_parsing
|
def test_strict2_filter_argument_parsing
|
||||||
with_error_modes(:strict2) do
|
with_error_modes(:strict2) do
|
||||||
# optional colon
|
# optional colon
|
||||||
|
|||||||
Reference in New Issue
Block a user