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 %} - - Welcome to my store! - - {% endsnippet %} - - {%- render input -%} - {%- render banner -%} - LIQUID - expected = <<~OUTPUT - - - - - - - Welcome to my store! - - 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 %} -
- {{ message }} -
- {% endsnippet %} - - {% snippet main %} - {% assign color_scheme = 'auto' %} - -
- {% render header, message: 'Welcome!' %} -
- {% endsnippet %} - - {% render main, header: header %} - LIQUID - - expected = <<~OUTPUT - - - - - - - - - -
- -
- Welcome! -
- -
- 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 %} -
- {{ message }} -
- {% endsnippet %} - - - {% render header, message: 'Welcome!' %} - LIQUID - expected = <<~OUTPUT - - - - - - -
- Welcome! -
- OUTPUT - - assert_template_result(expected, template) - end - - def test_render_captured_snippet - template = <<~LIQUID - {% snippet header %} -
- {{ message }} -
- {% endsnippet %} - - {% capture up_header %} - {%- render header, message: 'Welcome!' -%} - {% endcapture %} - - {{ up_header | upcase }} - - {{ header | upcase }} - - {{ header }} - LIQUID - expected = <<~OUTPUT - - - - - -
- WELCOME! -
- - - 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' %} -
- {{ message }} -
- {% endsnippet %} - - {{ color_scheme }} - - {% render header, message: 'Welcome!', color_scheme: color_scheme %} - - {{ color_scheme }} - LIQUID - expected = <<~OUTPUT - - - - - dark - - - -
- Welcome! -
- - - 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 %} - - Welcome to my store! - - {% endsnippet %} - - {%- render input -%} - {%- render banner -%} - LIQUID - expected = <<~OUTPUT - - - - - - - Welcome to my store! - - 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 %} -
    - {{ message }} -
    - {% endsnippet %} - - {% snippet main %} - {% assign color_scheme = 'auto' %} - -
    - {% render header, message: 'Welcome!' %} -
    - {% endsnippet %} - - {% render main, header: header %} - LIQUID - - expected = <<~OUTPUT - - - - - - - - - -
    - -
    - Welcome! -
    - -
    - 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 %} -
    - {{ message }} -
    - {% endsnippet %} - - - {% render header, message: 'Welcome!' %} - LIQUID - expected = <<~OUTPUT - - - - - - -
    - Welcome! -
    - 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' %} -
    - {{ message }} -
    - {% endsnippet %} - - {{ color_scheme }} - - {% render header, message: 'Welcome!', color_scheme: color_scheme %} - - {{ color_scheme }} - LIQUID - expected = <<~OUTPUT - - - - - dark - - - -
    - Welcome! -
    - - - 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 %} -
    - {{ message }} -
    - {% endsnippet %} - - {% capture up_header %} - {%- render header, message: 'Welcome!' -%} - {% endcapture %} - - {{ up_header | upcase }} - - {{ header | upcase }} - - {{ header }} - LIQUID - expected = <<~OUTPUT - - - - - -
    - WELCOME! -
    - - - 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