Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# Liquid Change Log

## 5.11.0
* Revert the Inline Snippets tag (#2001), treat its inclusion in the latest Liquid release as a bug, and allow for feedback on RFC#1916 to better support Liquid developers [Guilherme Carreiro]
* Rename the `:rigid` error mode to `:strict2` and display a warning when users attempt to use the `:rigid` mode [Guilherme Carreiro]

## 5.10.0
* Introduce support for Inline Snippets [Julia Boutin]
```
{%- snippet snowdevil -%}
Snowdevil
{%- endsnippet -%}
{% render snowdevil %}
```

## 5.9.0
* Introduce `:rigid` error mode for stricter, safer parsing of all tags [CP Clermont, Guilherme Carreiro]
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ Liquid also comes with different parsers that can be used when editing templates
when templates are invalid. You can enable this new parser like this:

```ruby
Liquid::Environment.default.error_mode = :rigid # 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.
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`:
Expand Down
16 changes: 8 additions & 8 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ task :rubocop do
end
end

desc('runs test suite with lax, strict, and rigid parsers')
desc('runs test suite with lax, strict, and strict2 parsers')
task :test do
ENV['LIQUID_PARSER_MODE'] = 'lax'
Rake::Task['base_test'].invoke
Expand All @@ -42,7 +42,7 @@ task :test do
Rake::Task['base_test'].reenable
Rake::Task['base_test'].invoke

ENV['LIQUID_PARSER_MODE'] = 'rigid'
ENV['LIQUID_PARSER_MODE'] = 'strict2'
Rake::Task['base_test'].reenable
Rake::Task['base_test'].invoke

Expand All @@ -55,7 +55,7 @@ task :test do
Rake::Task['integration_test'].reenable
Rake::Task['integration_test'].invoke

ENV['LIQUID_PARSER_MODE'] = 'rigid'
ENV['LIQUID_PARSER_MODE'] = 'strict2'
Rake::Task['integration_test'].reenable
Rake::Task['integration_test'].invoke
end
Expand Down Expand Up @@ -88,13 +88,13 @@ namespace :benchmark do
ruby "./performance/benchmark.rb strict"
end

desc "Run the liquid benchmark with rigid parsing"
task :rigid do
ruby "./performance/benchmark.rb rigid"
desc "Run the liquid benchmark with strict2 parsing"
task :strict2 do
ruby "./performance/benchmark.rb strict2"
end

desc "Run the liquid benchmark with lax, strict, and rigid parsing"
task run: [:lax, :strict, :rigid]
desc "Run the liquid benchmark with lax, strict, and strict2 parsing"
task run: [:lax, :strict, :strict2]

desc "Run unit benchmarks"
namespace :unit do
Expand Down
2 changes: 1 addition & 1 deletion bin/render
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ def assigns
end

puts Liquid::Template
.parse(source, error_mode: :rigid)
.parse(source, error_mode: :strict2)
.tap { |t| t.registers[:file_system] = VirtualFileSystem.new }
.render(assigns)
1 change: 0 additions & 1 deletion lib/liquid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ module Liquid
require 'liquid/drop'
require 'liquid/tablerowloop_drop'
require 'liquid/forloop_drop'
require 'liquid/snippet_drop'
require 'liquid/extensions'
require 'liquid/errors'
require 'liquid/interrupts'
Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class << self
# @param file_system The default file system that is used
# to load templates from.
# @param error_mode [Symbol] The default error mode for all templates
# (either :rigid, :strict, :warn, or :lax).
# (either :strict2, :strict, :warn, or :lax).
# @param exception_renderer [Proc] The exception renderer that is used to
# render exceptions.
# @yieldparam environment [Environment] The environment instance that is being built.
Expand Down
3 changes: 0 additions & 3 deletions lib/liquid/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
block_tag_unexpected_args: "Syntax Error in '%{tag}' - Valid syntax: {% %{tag} %}{% end%{tag} %}"
assign: "Syntax Error in 'assign' - Valid syntax: assign [var] = [source]"
capture: "Syntax Error in 'capture' - Valid syntax: capture [var]"
snippet: "Syntax Error in 'snippet' - Valid syntax: snippet [var]"
case: "Syntax Error in 'case' - Valid syntax: case [condition]"
case_invalid_when: "Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %}"
case_invalid_else: "Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) "
Expand All @@ -20,7 +19,6 @@
invalid_delimiter: "'%{tag}' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
invalid_template_encoding: "Invalid template encoding"
render: "Syntax error in tag 'render' - Template name must be a quoted string"
render_invalid_template_name: "Syntax error in tag 'render' - Expected a string or identifier, found %{found}"
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
table_row_invalid_attribute: "Invalid attribute '%{attribute}' in tablerow loop. Valid attributes are cols, limit, offset, and range"
tag_never_closed: "'%{block_name}' tag was never closed"
Expand All @@ -31,6 +29,5 @@
variable_termination: "Variable '%{token}' was not properly terminated with regexp: %{tag_end}"
argument:
include: "Argument error in tag 'include' - Illegal template name"
render: "Argument error in tag 'render' - Dynamically chosen templates are not allowed"
disabled:
tag: "usage is not allowed in this context"
8 changes: 4 additions & 4 deletions lib/liquid/parse_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ def safe_parse_expression(parser)
end

def parse_expression(markup, safe: false)
if !safe && @error_mode == :rigid
if !safe && @error_mode == :strict2
# parse_expression is a widely used API. To maintain backward
# compatibility while raising awareness about rigid parser standards,
# compatibility while raising awareness about strict2 parser standards,
# the safe flag supports API users make a deliberate decision.
#
# In rigid mode, markup MUST come from a string returned by the parser
# In strict2 mode, markup MUST come from a string returned by the parser
# (e.g., parser.expression). We're not calling the parser here to
# prevent redundant parser overhead.
raise Liquid::InternalError, "unsafe parse_expression cannot be used in rigid mode"
raise Liquid::InternalError, "unsafe parse_expression cannot be used in strict2 mode"
end

Expression.parse(markup, @string_scanner, @expression_cache)
Expand Down
28 changes: 18 additions & 10 deletions lib/liquid/parser_switching.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ module ParserSwitching
# 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 rigid mode where it uses the rigid parser.
# 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 rigid_parse_with_error_context(markup) if rigid_mode?
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
Expand All @@ -28,27 +31,32 @@ def strict_parse_with_error_mode_fallback(markup)

def parse_with_selected_parser(markup)
case parse_context.error_mode
when :rigid then rigid_parse_with_error_context(markup)
when :strict then strict_parse_with_error_context(markup)
when :lax then lax_parse(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
rigid_parse_with_error_context(markup)
strict2_parse_with_error_context(markup)
rescue SyntaxError => e
parse_context.warnings << e
lax_parse(markup)
end
end
end

def rigid_mode?
parse_context.error_mode == :rigid
def strict2_mode?
parse_context.error_mode == :strict2 || parse_context.error_mode == :rigid
end

private

def rigid_parse_with_error_context(markup)
rigid_parse(markup)
def rigid_warn
Deprecations.warn(':rigid', ':strict2')
end

def strict2_parse_with_error_context(markup)
strict2_parse(markup)
rescue SyntaxError => e
e.line_number = line_number
e.markup_context = markup_context(markup)
Expand Down
22 changes: 0 additions & 22 deletions lib/liquid/snippet_drop.rb

This file was deleted.

2 changes: 0 additions & 2 deletions lib/liquid/tags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
require_relative "tags/render"
require_relative "tags/cycle"
require_relative "tags/doc"
require_relative "tags/snippet"

module Liquid
module Tags
Expand All @@ -45,7 +44,6 @@ module Tags
'echo' => Echo,
'tablerow' => TableRow,
'doc' => Doc,
'snippet' => Snippet,
}.freeze
end
end
8 changes: 4 additions & 4 deletions lib/liquid/tags/case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def render_to_output_buffer(context, output)

private

def rigid_parse(markup)
def strict2_parse(markup)
parser = @parse_context.new_parser(markup)
@left = safe_parse_expression(parser)
parser.consume(:end_of_string)
Expand All @@ -107,14 +107,14 @@ def lax_parse(markup)
def record_when_condition(markup)
body = new_body

if rigid_mode?
parse_rigid_when(markup, body)
if strict2_mode?
parse_strict2_when(markup, body)
else
parse_lax_when(markup, body)
end
end

def parse_rigid_when(markup, body)
def parse_strict2_when(markup, body)
parser = @parse_context.new_parser(markup)

loop do
Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/tags/cycle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def render_to_output_buffer(context, output)
private

# cycle [name:] expression(, expression)*
def rigid_parse(markup)
def strict2_parse(markup)
p = @parse_context.new_parser(markup)

@variables = []
Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/tags/for.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def strict_parse(markup)

private

def rigid_parse(markup)
def strict2_parse(markup)
strict_parse(markup)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/tags/if.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def render_to_output_buffer(context, output)

private

def rigid_parse(markup)
def strict2_parse(markup)
strict_parse(markup)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/tags/include.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def render_to_output_buffer(context, output)
alias_method :parse_context, :options
private :parse_context

def rigid_parse(markup)
def strict2_parse(markup)
p = @parse_context.new_parser(markup)

@template_name_expr = safe_parse_expression(p)
Expand Down
42 changes: 18 additions & 24 deletions lib/liquid/tags/render.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module Liquid
# @liquid_syntax_keyword filename The name of the snippet to render, without the `.liquid` extension.
class Render < Tag
FOR = 'for'
SYNTAX = /(#{QuotedString}+|#{VariableSegment}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
SYNTAX = /(#{QuotedString}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o

disable_tags "include"

Expand All @@ -47,23 +47,21 @@ def render_to_output_buffer(context, output)
end

def render_tag(context, output)
template = context.evaluate(@template_name_expr)

if template.respond_to?(:to_partial)
partial = template.to_partial
template_name = template.filename
context_variable_name = @alias_name || template.name
elsif @template_name_expr.is_a?(String)
partial = PartialCache.load(template, context: context, parse_context: parse_context)
template_name = partial.name
context_variable_name = @alias_name || template_name.split('/').last
else
raise ::ArgumentError
end
# The expression should be a String literal, which parses to a String object
template_name = @template_name_expr
raise ::ArgumentError unless template_name.is_a?(String)

partial = PartialCache.load(
template_name,
context: context,
parse_context: parse_context,
)

context_variable_name = @alias_name || template_name.split('/').last

render_partial_func = ->(var, forloop) {
inner_context = context.new_isolated_subcontext
inner_context.template_name = template_name
inner_context.template_name = partial.name
inner_context.partial = true
inner_context['forloop'] = forloop if forloop

Expand All @@ -87,10 +85,10 @@ def render_tag(context, output)
end

# render (string) (with|for expression)? (as id)? (key: value)*
def rigid_parse(markup)
def strict2_parse(markup)
p = @parse_context.new_parser(markup)

@template_name_expr = parse_expression(rigid_template_name(p), safe: true)
@template_name_expr = parse_expression(strict2_template_name(p), safe: true)
with_or_for = p.id?("for") || p.id?("with")
@variable_name_expr = safe_parse_expression(p) if with_or_for
@alias_name = p.consume(:id) if p.id?("as")
Expand All @@ -103,18 +101,14 @@ def rigid_parse(markup)
key = p.consume
p.consume(:colon)
@attributes[key] = safe_parse_expression(p)
p.consume?(:comma) # optional comma
p.consume?(:comma)
end

p.consume(:end_of_string)
end

def rigid_template_name(p)
return p.consume(:string) if p.look(:string)
return p.consume(:id) if p.look(:id)

found = p.consume || "nothing"
raise SyntaxError, options[:locale].t("errors.syntax.render_invalid_template_name", found: found)
def strict2_template_name(p)
p.consume(:string)
end

def strict_parse(markup)
Expand Down
Loading