diff --git a/lib/liquid.rb b/lib/liquid.rb
index 09cafe94..4d0a71a6 100644
--- a/lib/liquid.rb
+++ b/lib/liquid.rb
@@ -67,7 +67,6 @@ 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'
diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml
index 7a9fb71e..b99d490c 100644
--- a/lib/liquid/locales/en.yml
+++ b/lib/liquid/locales/en.yml
@@ -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) "
@@ -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"
@@ -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"
diff --git a/lib/liquid/snippet_drop.rb b/lib/liquid/snippet_drop.rb
deleted file mode 100644
index 98686999..00000000
--- a/lib/liquid/snippet_drop.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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
diff --git a/lib/liquid/tags.rb b/lib/liquid/tags.rb
index 3ec5e7cf..dff7553f 100644
--- a/lib/liquid/tags.rb
+++ b/lib/liquid/tags.rb
@@ -20,7 +20,6 @@ require_relative "tags/raw"
require_relative "tags/render"
require_relative "tags/cycle"
require_relative "tags/doc"
-require_relative "tags/snippet"
module Liquid
module Tags
@@ -45,7 +44,6 @@ module Liquid
'echo' => Echo,
'tablerow' => TableRow,
'doc' => Doc,
- 'snippet' => Snippet,
}.freeze
end
end
diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb
index dec725ed..4d29e420 100644
--- a/lib/liquid/tags/render.rb
+++ b/lib/liquid/tags/render.rb
@@ -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"
@@ -47,23 +47,21 @@ module Liquid
end
def render_tag(context, output)
- template = context.evaluate(@template_name_expr)
+ # 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)
- 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
+ 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
@@ -103,18 +101,14 @@ module Liquid
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)
+ p.consume(:string)
end
def strict_parse(markup)
diff --git a/lib/liquid/tags/snippet.rb b/lib/liquid/tags/snippet.rb
deleted file mode 100644
index 87e2a0de..00000000
--- a/lib/liquid/tags/snippet.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# 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
diff --git a/test/integration/tags/render_tag_test.rb b/test/integration/tags/render_tag_test.rb
index 6fe19abb..d6453fb5 100644
--- a/test/integration/tags/render_tag_test.rb
+++ b/test/integration/tags/render_tag_test.rb
@@ -101,6 +101,10 @@ 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(
@@ -290,13 +294,6 @@ 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',
diff --git a/test/integration/tags/snippet_test.rb b/test/integration/tags/snippet_test.rb
deleted file mode 100644
index 6d1cb35d..00000000
--- a/test/integration/tags/snippet_test.rb
+++ /dev/null
@@ -1,1087 +0,0 @@
-# frozen_string_literal: true
-
-require 'test_helper'
-
-class SnippetTest < Minitest::Test
- include Liquid
-
- class LaxMode < SnippetTest
- def test_valid_inline_snippet
- template = <<~LIQUID.strip
- {% snippet input %}
- Hey
- {% endsnippet %}
- LIQUID
- expected = ''
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet
- template = <<~LIQUID.strip
- {% snippet hey %}
- Hey
- {% endsnippet %}
-
- {%- render hey -%}
- LIQUID
- expected = <<~OUTPUT
-
- Hey
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with_variable
- template = <<~LIQUID.strip
- {% snippet hey %}
-
Today is {{ "hello" | capitalize }}
- {% endsnippet %}
-
- {%- render hey -%}
- LIQUID
- expected = <<~OUTPUT
-
- Today is Hello
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_multiple_inline_snippets
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {% snippet banner %}
-
- {% endsnippet %}
-
- {%- render input -%}
- {%- render banner -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with_argument
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with_doc_tag
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with_evaluated_assign
- template = <<~LIQUID.strip
- {% snippet input %}
- {{ greeting }}
- {% endsnippet %}
-
- {%- assign greeting = "hello" | upcase -%}
- {%- render input, greeting: greeting -%}
- LIQUID
- expected = <<~OUTPUT
-
- HELLO
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with_multiple_arguments
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text", value: "Hello" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippets_using_same_argument_name
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {% snippet inputs %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- {%- render inputs, type: "password", value: "pass" -%}
- LIQUID
-
- expected = <<~OUTPUT
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_empty_string_when_missing_argument
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_snippets_as_arguments
- template = <<~LIQUID.strip
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
-
- {% endsnippet %}
-
- {% snippet main %}
- {% assign color_scheme = 'auto' %}
-
-
- {% render header, message: 'Welcome!' %}
-
- {% endsnippet %}
-
- {% render main, header: header %}
- LIQUID
-
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_shouldnt_leak_context
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text", value: "Hello" -%}
-
- {{ type }}
- {{ value }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_multiple_inline_snippets_without_leaking_context
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {% snippet no_leak %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- {%- render no_leak -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_ignores_outside_context
- template = <<~LIQUID.strip
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
-
- {% endsnippet %}
-
-
- {% render header, message: 'Welcome!' %}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_captured_snippet
- template = <<~LIQUID
- {% snippet header %}
-
- {% endsnippet %}
-
- {% capture up_header %}
- {%- render header, message: 'Welcome!' -%}
- {% endcapture %}
-
- {{ up_header | upcase }}
-
- {{ header | upcase }}
-
- {{ header }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
- SNIPPETDROP
-
- SnippetDrop
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_inline_snippet_local_scope_takes_precedence
- template = <<~LIQUID
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
- {% assign color_scheme = 'light' %}
-
- {% endsnippet %}
-
- {{ color_scheme }}
-
- {% render header, message: 'Welcome!', color_scheme: color_scheme %}
-
- {{ color_scheme }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- dark
-
-
-
-
-
-
- dark
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_forloop
- template = <<~LIQUID.strip
- {% snippet item %}
- {{ forloop.index }}: {{ item }}
- {% endsnippet %}
-
- {% assign items = "A,B,C" | split: "," %}
- {%- render item for items -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- 1: A
-
- 2: B
-
- 3: C
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_with
- template = <<~LIQUID.strip
- {% snippet header %}
- {{ header }}
- {% endsnippet %}
-
- {% assign product = "Apple" %}
- {%- render header with product -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- Apple
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_render_inline_snippet_alias
- template = <<~LIQUID.strip
- {% snippet product_card %}
- {{ item }}
- {% endsnippet %}
-
- {% assign featured = "Apple" %}
- {%- render product_card with featured as item -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- Apple
- OUTPUT
-
- assert_template_result(expected, template)
- end
-
- def test_snippet_with_invalid_identifier
- template = <<~LIQUID
- {% snippet header foo bar %}
- Invalid
- {% endsnippet %}
- LIQUID
-
- exception = assert_raises(SyntaxError) { Liquid::Template.parse(template) }
-
- assert_match("Expected end_of_string but found id", exception.message)
- end
-
- def test_render_with_non_existent_tag
- template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true)
- {% snippet foo %}
- {% render non_existent %}
- {% endsnippet %}
-
- {% render foo %}
- LIQUID
-
- expected = <<~TEXT
-
-
-
- Liquid error (index line 2): internal
- TEXT
- template.name = "index"
-
- assert_equal(expected, template.render('errors' => ErrorDrop.new))
- end
-
- def test_render_handles_errors
- template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true)
- {% snippet foo %}
- {% render non_existent %} will raise an error.
-
- Bla bla test.
-
- This is an argument error: {{ 'test' | slice: 'not a number' }}
- {% endsnippet %}
-
- {% render foo %}
- LIQUID
-
- expected = <<~TEXT
-
-
-
- Liquid error (index line 2): internal will raise an error.
-
- Bla bla test.
-
- This is an argument error: Liquid error (index line 6): invalid integer
- TEXT
- template.name = "index"
-
- assert_equal(expected, template.render('errors' => ErrorDrop.new))
- end
- end
-
- class RigidMode < SnippetTest
- def test_valid_inline_snippet
- template = <<~LIQUID.strip
- {% snippet input %}
- Hey
- {% endsnippet %}
- LIQUID
- expected = ''
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet
- template = <<~LIQUID.strip
- {% snippet hey %}
- Hey
- {% endsnippet %}
-
- {%- render hey -%}
- LIQUID
- expected = <<~OUTPUT
-
- Hey
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with_variable
- template = <<~LIQUID.strip
- {% snippet hey %}
- Today is {{ "hello" | capitalize }}
- {% endsnippet %}
-
- {%- render hey -%}
- LIQUID
- expected = <<~OUTPUT
-
- Today is Hello
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_multiple_inline_snippets
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {% snippet banner %}
-
- {% endsnippet %}
-
- {%- render input -%}
- {%- render banner -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with_argument
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with_doc_tag
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with_evaluated_assign
- template = <<~LIQUID.strip
- {% snippet input %}
- {{ greeting }}
- {% endsnippet %}
-
- {%- assign greeting = "hello" | upcase -%}
- {%- render input, greeting: greeting -%}
- LIQUID
- expected = <<~OUTPUT
-
- HELLO
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with_multiple_arguments
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text", value: "Hello" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippets_using_same_argument_name
- template = <<~LIQUID.strip
- {% snippet input %}
-
- {% endsnippet %}
-
- {% snippet inputs %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- {%- render inputs, type: "password", value: "pass" -%}
- LIQUID
-
- expected = <<~OUTPUT
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_empty_string_when_missing_argument
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_snippets_as_arguments
- template = <<~LIQUID.strip
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
-
- {% endsnippet %}
-
- {% snippet main %}
- {% assign color_scheme = 'auto' %}
-
-
- {% render header, message: 'Welcome!' %}
-
- {% endsnippet %}
-
- {% render main, header: header %}
- LIQUID
-
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_shouldnt_leak_context
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- @param {string} value - Input value.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {%- render input, type: "text", value: "Hello" -%}
-
- {{ type }}
- {{ value }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_multiple_inline_snippets_without_leaking_context
- template = <<~LIQUID.strip
- {% snippet input %}
- {% doc %}
- @param {string} type - Input type.
- {% enddoc %}
-
-
- {% endsnippet %}
-
- {% snippet no_leak %}
-
- {% endsnippet %}
-
- {%- render input, type: "text" -%}
- {%- render no_leak -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_ignores_outside_context
- template = <<~LIQUID.strip
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
-
- {% endsnippet %}
-
-
- {% render header, message: 'Welcome!' %}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_inline_snippet_local_scope_takes_precedence
- template = <<~LIQUID
- {% assign color_scheme = 'dark' %}
-
- {% snippet header %}
- {% assign color_scheme = 'light' %}
-
- {% endsnippet %}
-
- {{ color_scheme }}
-
- {% render header, message: 'Welcome!', color_scheme: color_scheme %}
-
- {{ color_scheme }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
- dark
-
-
-
-
-
-
- dark
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_forloop
- template = <<~LIQUID.strip
- {% snippet item %}
- {{ forloop.index }}: {{ item }}
- {% endsnippet %}
-
- {% assign items = "A,B,C" | split: "," %}
- {%- render item for items -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- 1: A
-
- 2: B
-
- 3: C
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_with
- template = <<~LIQUID.strip
- {% snippet header %}
- {{ header }}
- {% endsnippet %}
-
- {% assign product = "Apple" %}
- {%- render header with product -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- Apple
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_inline_snippet_alias
- template = <<~LIQUID.strip
- {% snippet product_card %}
- {{ item }}
- {% endsnippet %}
-
- {% assign featured = "Apple" %}
- {%- render product_card with featured as item -%}
- LIQUID
- expected = <<~OUTPUT
-
-
-
- Apple
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_captured_snippet
- template = <<~LIQUID
- {% snippet header %}
-
- {% endsnippet %}
-
- {% capture up_header %}
- {%- render header, message: 'Welcome!' -%}
- {% endcapture %}
-
- {{ up_header | upcase }}
-
- {{ header | upcase }}
-
- {{ header }}
- LIQUID
- expected = <<~OUTPUT
-
-
-
-
-
-
-
-
- SNIPPETDROP
-
- SnippetDrop
- OUTPUT
-
- assert_template_result(expected, template, error_mode: :rigid)
- end
-
- def test_render_with_invalid_identifier
- template = "{% render 123 %}"
-
- exception = assert_raises(SyntaxError) do
- Liquid::Template.parse(template, error_mode: :rigid)
- end
-
- assert_match("Expected a string or identifier, found 123", exception.message)
- end
-
- def test_render_with_non_existent_tag
- template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true, error_mode: :rigid)
- {% snippet foo %}
- {% render non_existent %}
- {% endsnippet %}
-
- {% render foo %}
- LIQUID
-
- expected = <<~TEXT
-
-
-
- Liquid error (index line 2): internal
- TEXT
- template.name = "index"
-
- assert_equal(expected, template.render('errors' => ErrorDrop.new))
- end
-
- def test_render_handles_errors
- template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true, error_mode: :rigid)
- {% snippet foo %}
- {% render non_existent %} will raise an error.
-
- Bla bla test.
-
- This is an argument error: {{ 'test' | slice: 'not a number' }}
- {% endsnippet %}
-
- {% render foo %}
- LIQUID
-
- expected = <<~TEXT
-
-
-
- Liquid error (index line 2): internal will raise an error.
-
- Bla bla test.
-
- This is an argument error: Liquid error (index line 6): invalid integer
- TEXT
- template.name = "index"
-
- assert_equal(expected, template.render('errors' => ErrorDrop.new))
- end
-
- def test_render_with_no_identifier
- template = "{% render %}"
-
- exception = assert_raises(SyntaxError) do
- Liquid::Template.parse(template, error_mode: :rigid)
- end
-
- assert_match("Expected a string or identifier, found nothing", exception.message)
- end
-
- def test_snippet_with_invalid_identifier
- template = <<~LIQUID
- {% snippet header foo bar %}
- Invalid
- {% endsnippet %}
- LIQUID
-
- exception = assert_raises(SyntaxError) do
- Liquid::Template.parse(template, error_mode: :rigid)
- end
-
- assert_match("Expected end_of_string but found id", exception.message)
- end
- end
-
- class ResourceLimits < SnippetTest
- def test_increment_assign_score_by_bytes_not_characters
- t = Template.parse("{% snippet foo %}すごい{% endsnippet %}")
- t.render!
- assert_equal(9, t.resource_limits.assign_score)
- end
- end
-end