mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-20 03:10:39 -07:00
WIP - Support {% render obj %}
This commit is contained in:
@@ -64,6 +64,7 @@ require 'liquid/strainer_template'
|
|||||||
require 'liquid/expression'
|
require 'liquid/expression'
|
||||||
require 'liquid/context'
|
require 'liquid/context'
|
||||||
require 'liquid/parser_switching'
|
require 'liquid/parser_switching'
|
||||||
|
require 'liquid/renderabledrop'
|
||||||
require 'liquid/tag'
|
require 'liquid/tag'
|
||||||
require 'liquid/tag/disabler'
|
require 'liquid/tag/disabler'
|
||||||
require 'liquid/tag/disableable'
|
require 'liquid/tag/disableable'
|
||||||
|
|||||||
@@ -24,5 +24,6 @@
|
|||||||
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
||||||
argument:
|
argument:
|
||||||
include: "Argument error in tag 'include' - Illegal template name"
|
include: "Argument error in tag 'include' - Illegal template name"
|
||||||
|
render: "Argument error in tag 'render' - Illegal template name"
|
||||||
disabled:
|
disabled:
|
||||||
tag: "usage is not allowed in this context"
|
tag: "usage is not allowed in this context"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Liquid
|
||||||
|
class RenderableDrop < Drop
|
||||||
|
def render(_context, _output)
|
||||||
|
raise NotImplementedError, "render must be implemented for #{self.class.name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -3,7 +3,20 @@
|
|||||||
module Liquid
|
module Liquid
|
||||||
class Render < Tag
|
class Render < Tag
|
||||||
FOR = 'for'
|
FOR = 'for'
|
||||||
SYNTAX = /(#{QuotedString}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
|
SYNTAX = %r{
|
||||||
|
(
|
||||||
|
## for {% render "snippet" %}
|
||||||
|
#{Liquid::QuotedString}+ |
|
||||||
|
## for {% render block %}
|
||||||
|
\A#{Liquid::VariableSegment}+
|
||||||
|
)
|
||||||
|
## for {% render "snippet" with product as p %}
|
||||||
|
## or {% render "snippet" for products p %}
|
||||||
|
(\s+(with|#{Liquid::Render::FOR})\s+(#{Liquid::QuotedFragment}+))?
|
||||||
|
(\s+(?:as)\s+(#{Liquid::VariableSegment}+))?
|
||||||
|
## variables passed into the tag (e.g. {% render "snippet", var1: value1, var2: value2 %}
|
||||||
|
## are not matched by this regex and are handled by .initialize
|
||||||
|
}xo
|
||||||
|
|
||||||
disable_tags "include"
|
disable_tags "include"
|
||||||
|
|
||||||
@@ -14,13 +27,13 @@ module Liquid
|
|||||||
|
|
||||||
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
|
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
|
||||||
|
|
||||||
template_name = Regexp.last_match(1)
|
@template_name = Regexp.last_match(1)
|
||||||
with_or_for = Regexp.last_match(3)
|
with_or_for = Regexp.last_match(3)
|
||||||
variable_name = Regexp.last_match(4)
|
variable_name = Regexp.last_match(4)
|
||||||
|
|
||||||
@alias_name = Regexp.last_match(6)
|
@alias_name = Regexp.last_match(6)
|
||||||
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
||||||
@template_name_expr = parse_expression(template_name)
|
@template_name_expr = parse_expression(@template_name)
|
||||||
@for = (with_or_for == FOR)
|
@for = (with_or_for == FOR)
|
||||||
|
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
@@ -34,9 +47,21 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_tag(context, output)
|
def render_tag(context, output)
|
||||||
# Though we evaluate this here we will only ever parse it as a string literal.
|
render_target = context.evaluate(@template_name_expr)
|
||||||
template_name = context.evaluate(@template_name_expr)
|
raise ArgumentError, options[:locale].t("errors.argument.render") unless render_target
|
||||||
raise ArgumentError, options[:locale].t("errors.argument.include") unless template_name
|
|
||||||
|
# Check to see if this is a renderable drop
|
||||||
|
if render_target.is_a?(Liquid::RenderableDrop)
|
||||||
|
return render_target.render(context, output)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Otherwise it must be a quoted string
|
||||||
|
unless /#{Liquid::QuotedString}+/.match?(@template_name)
|
||||||
|
output << "<!-- #{options[:locale].t('errors.syntax.render')} -->"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
template_name = render_target
|
||||||
|
|
||||||
partial = PartialCache.load(
|
partial = PartialCache.load(
|
||||||
template_name,
|
template_name,
|
||||||
|
|||||||
@@ -75,9 +75,8 @@ class RenderTagTest < Minitest::Test
|
|||||||
def test_dynamically_choosen_templates_are_not_allowed
|
def test_dynamically_choosen_templates_are_not_allowed
|
||||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'should not be rendered')
|
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'should not be rendered')
|
||||||
|
|
||||||
assert_raises(Liquid::SyntaxError) do
|
assert_equal("<!-- Syntax error in tag 'render' - Template name must be a quoted string -->",
|
||||||
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}")
|
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}").render!)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_include_tag_caches_second_read_of_same_partial
|
def test_include_tag_caches_second_read_of_same_partial
|
||||||
|
|||||||
Reference in New Issue
Block a user