mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-15 00:40:40 -07:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4a6987a30 | ||
|
|
eab457f8ca | ||
|
|
99b0b38806 | ||
|
|
d109bc9242 | ||
|
|
47288ccca0 | ||
|
|
de23ed82d5 | ||
|
|
1069b944a0 | ||
|
|
c6c342ab32 | ||
|
|
3556c3371e | ||
|
|
96a44927b5 | ||
|
|
fb6cf17099 | ||
|
|
9409dd8f4a | ||
|
|
b5ecd4d0f8 | ||
|
|
ba5aa0abf6 | ||
|
|
a384e229d8 | ||
|
|
db474d5b57 | ||
|
|
3a13ac7e6c | ||
|
|
4d13f030f8 | ||
|
|
8c6149782d |
@@ -67,6 +67,7 @@ require 'liquid/i18n'
|
||||
require 'liquid/drop'
|
||||
require 'liquid/tablerowloop_drop'
|
||||
require 'liquid/forloop_drop'
|
||||
require 'liquid/snippet_drop'
|
||||
require 'liquid/extensions'
|
||||
require 'liquid/errors'
|
||||
require 'liquid/interrupts'
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
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) "
|
||||
@@ -19,6 +20,7 @@
|
||||
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"
|
||||
@@ -29,5 +31,6 @@
|
||||
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"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Liquid
|
||||
class SnippetDrop < Drop
|
||||
attr_reader :body, :name, :filename
|
||||
|
||||
def initialize(body, name, filename)
|
||||
super()
|
||||
@body = body
|
||||
@name = name
|
||||
@filename = filename
|
||||
end
|
||||
|
||||
def to_partial
|
||||
@body
|
||||
end
|
||||
|
||||
def to_s
|
||||
'SnippetDrop'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,6 +20,7 @@ require_relative "tags/raw"
|
||||
require_relative "tags/render"
|
||||
require_relative "tags/cycle"
|
||||
require_relative "tags/doc"
|
||||
require_relative "tags/snippet"
|
||||
|
||||
module Liquid
|
||||
module Tags
|
||||
@@ -44,6 +45,7 @@ module Liquid
|
||||
'echo' => Echo,
|
||||
'tablerow' => TableRow,
|
||||
'doc' => Doc,
|
||||
'snippet' => Snippet,
|
||||
}.freeze
|
||||
end
|
||||
end
|
||||
|
||||
+20
-14
@@ -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}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
|
||||
SYNTAX = /(#{QuotedString}+|#{VariableSegment}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
|
||||
|
||||
disable_tags "include"
|
||||
|
||||
@@ -47,21 +47,23 @@ module Liquid
|
||||
end
|
||||
|
||||
def render_tag(context, output)
|
||||
# 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)
|
||||
template = context.evaluate(@template_name_expr)
|
||||
|
||||
partial = PartialCache.load(
|
||||
template_name,
|
||||
context: context,
|
||||
parse_context: parse_context,
|
||||
)
|
||||
|
||||
context_variable_name = @alias_name || template_name.split('/').last
|
||||
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
|
||||
|
||||
render_partial_func = ->(var, forloop) {
|
||||
inner_context = context.new_isolated_subcontext
|
||||
inner_context.template_name = partial.name
|
||||
inner_context.template_name = template_name
|
||||
inner_context.partial = true
|
||||
inner_context['forloop'] = forloop if forloop
|
||||
|
||||
@@ -101,14 +103,18 @@ module Liquid
|
||||
key = p.consume
|
||||
p.consume(:colon)
|
||||
@attributes[key] = safe_parse_expression(p)
|
||||
p.consume?(:comma)
|
||||
p.consume?(:comma) # optional comma
|
||||
end
|
||||
|
||||
p.consume(:end_of_string)
|
||||
end
|
||||
|
||||
def rigid_template_name(p)
|
||||
p.consume(:string)
|
||||
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)
|
||||
end
|
||||
|
||||
def strict_parse(markup)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Liquid
|
||||
# @liquid_public_docs
|
||||
# @liquid_type tag
|
||||
# @liquid_category variable
|
||||
# @liquid_name snippet
|
||||
# @liquid_summary
|
||||
# Creates a new inline snippet.
|
||||
# @liquid_description
|
||||
# You can create inline snippets to make your Liquid code more modular.
|
||||
# @liquid_syntax
|
||||
# {% snippet snippet_name %}
|
||||
# value
|
||||
# {% endsnippet %}
|
||||
class Snippet < Block
|
||||
def initialize(tag_name, markup, options)
|
||||
super
|
||||
p = @parse_context.new_parser(markup)
|
||||
if p.look(:id)
|
||||
@to = p.consume(:id)
|
||||
p.consume(:end_of_string)
|
||||
else
|
||||
raise SyntaxError, options[:locale].t("errors.syntax.snippet")
|
||||
end
|
||||
end
|
||||
|
||||
def render_to_output_buffer(context, output)
|
||||
snippet_drop = SnippetDrop.new(@body, @to, context.template_name)
|
||||
context.scopes.last[@to] = snippet_drop
|
||||
context.resource_limits.increment_assign_score(assign_score_of(snippet_drop))
|
||||
output
|
||||
end
|
||||
|
||||
def blank?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assign_score_of(snippet_drop)
|
||||
snippet_drop.body.nodelist.sum { |node| node.to_s.bytesize }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -101,10 +101,6 @@ class RenderTagTest < Minitest::Test
|
||||
end
|
||||
end
|
||||
|
||||
def test_dynamically_choosen_templates_are_not_allowed
|
||||
assert_syntax_error("{% assign name = 'snippet' %}{% render name %}")
|
||||
end
|
||||
|
||||
def test_rigid_parsing_errors
|
||||
with_error_modes(:lax, :strict) do
|
||||
assert_template_result(
|
||||
@@ -294,6 +290,13 @@ class RenderTagTest < Minitest::Test
|
||||
)
|
||||
end
|
||||
|
||||
def test_render_tag_with_snippet_drop
|
||||
assert_template_result(
|
||||
"Hello from snippet",
|
||||
"{% snippet my_snippet %}Hello from snippet{% endsnippet %}{% render my_snippet %}",
|
||||
)
|
||||
end
|
||||
|
||||
def test_render_tag_renders_error_with_template_name
|
||||
assert_template_result(
|
||||
'Liquid error (foo line 1): standard error',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user