mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-14 08:20:39 -07:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47fbff07fa | ||
|
|
3de1db3c3a | ||
|
|
03522caaf8 | ||
|
|
7acea2a9c9 | ||
|
|
d8ef698539 |
@@ -5,7 +5,7 @@
|
||||
|
||||
* [Contributing guidelines](CONTRIBUTING.md)
|
||||
* [Version history](History.md)
|
||||
* [Liquid documentation from Shopify](http://docs.shopify.com/themes/liquid-basics)
|
||||
* [Liquid documentation from Shopify](https://shopify.dev/api/liquid)
|
||||
* [Liquid Wiki at GitHub](https://github.com/Shopify/liquid/wiki)
|
||||
* [Website](http://liquidmarkup.org/)
|
||||
|
||||
@@ -56,7 +56,7 @@ For standard use you can just pass it the content of a file and call render with
|
||||
|
||||
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.
|
||||
it very hard to debug and can lead to unexpected behaviour.
|
||||
|
||||
Liquid also comes with a stricter parser that can be used when editing templates to give better error messages
|
||||
when templates are invalid. You can enable this new parser like this:
|
||||
|
||||
@@ -64,6 +64,7 @@ require 'liquid/strainer_template'
|
||||
require 'liquid/expression'
|
||||
require 'liquid/context'
|
||||
require 'liquid/parser_switching'
|
||||
require 'liquid/renderabledrop'
|
||||
require 'liquid/tag'
|
||||
require 'liquid/tag/disabler'
|
||||
require 'liquid/tag/disableable'
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
render: "Syntax error in tag 'render' - Template name must be a quoted string"
|
||||
argument:
|
||||
include: "Argument error in tag 'include' - Illegal template name"
|
||||
render: "Argument error in tag 'render' - Illegal template name"
|
||||
disabled:
|
||||
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
|
||||
@@ -2,19 +2,6 @@
|
||||
|
||||
module Liquid
|
||||
class Comment < Block
|
||||
# Potential fix
|
||||
FullTokenPossiblyInvalid = /\A(.*)#{TagStart}#{WhitespaceControl}?\s*(\w+)\s*(.*)?#{WhitespaceControl}?#{TagEnd}\z/om
|
||||
|
||||
def parse(tokens)
|
||||
while (token = tokens.shift)
|
||||
if token =~ FullTokenPossiblyInvalid && block_delimiter == Regexp.last_match(2)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
raise_tag_never_closed(block_name)
|
||||
end
|
||||
|
||||
def render_to_output_buffer(_context, output)
|
||||
output
|
||||
end
|
||||
|
||||
@@ -15,19 +15,15 @@ module Liquid
|
||||
attr_reader :variable
|
||||
|
||||
def initialize(tag_name, markup, parse_context)
|
||||
puts "Initializing Echo tag"
|
||||
super
|
||||
@variable = Variable.new(markup, parse_context)
|
||||
end
|
||||
|
||||
def render(context)
|
||||
puts "Render Echo tag"
|
||||
@variable.render_to_output_buffer(context, +'')
|
||||
end
|
||||
|
||||
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
||||
puts "ParseTreeVisitor Echo tag"
|
||||
|
||||
def children
|
||||
[@node.variable]
|
||||
end
|
||||
|
||||
@@ -3,7 +3,20 @@
|
||||
module Liquid
|
||||
class Render < Tag
|
||||
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"
|
||||
|
||||
@@ -14,13 +27,13 @@ module Liquid
|
||||
|
||||
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)
|
||||
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)
|
||||
@template_name_expr = parse_expression(@template_name)
|
||||
@for = (with_or_for == FOR)
|
||||
|
||||
@attributes = {}
|
||||
@@ -34,9 +47,21 @@ module Liquid
|
||||
end
|
||||
|
||||
def render_tag(context, output)
|
||||
# Though we evaluate this here we will only ever parse it as a string literal.
|
||||
template_name = context.evaluate(@template_name_expr)
|
||||
raise ArgumentError, options[:locale].t("errors.argument.include") unless template_name
|
||||
render_target = context.evaluate(@template_name_expr)
|
||||
raise ArgumentError, options[:locale].t("errors.argument.render") unless render_target
|
||||
|
||||
# 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(
|
||||
template_name,
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class CommentTagTest < Minitest::Test
|
||||
include Liquid
|
||||
|
||||
def test_single_line_comments_parse
|
||||
assert_template_result('Before comment', <<~LIQUID)
|
||||
Before comment
|
||||
{%- comment -%}
|
||||
Regular text comment
|
||||
Liquid in comment: {% echo 'Hi from comment' %}
|
||||
{%- endcomment -%}
|
||||
LIQUID
|
||||
end
|
||||
|
||||
def test_multi_line_comments_parse
|
||||
assert_template_result('Before comment', <<~LIQUID)
|
||||
Before comment
|
||||
{%- comment -%} Regular text comment {%- endcomment -%}
|
||||
{%- comment -%} Liquid in comment: {% echo 'Hi from comment' %} {%- endcomment -%}
|
||||
LIQUID
|
||||
end
|
||||
end # CommentTagTest
|
||||
@@ -75,9 +75,8 @@ class RenderTagTest < Minitest::Test
|
||||
def test_dynamically_choosen_templates_are_not_allowed
|
||||
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'should not be rendered')
|
||||
|
||||
assert_raises(Liquid::SyntaxError) do
|
||||
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}")
|
||||
end
|
||||
assert_equal("<!-- Syntax error in tag 'render' - Template name must be a quoted string -->",
|
||||
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}").render!)
|
||||
end
|
||||
|
||||
def test_include_tag_caches_second_read_of_same_partial
|
||||
|
||||
Reference in New Issue
Block a user