diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index 7a9fb71e..53421f4c 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -34,3 +34,5 @@ render: "Argument error in tag 'render' - Dynamically chosen templates are not allowed" disabled: tag: "usage is not allowed in this context" + file_system: + includes: "This liquid context does not allow includes" diff --git a/lib/liquid/snippet_drop.rb b/lib/liquid/snippet_drop.rb index 11648826..98686999 100644 --- a/lib/liquid/snippet_drop.rb +++ b/lib/liquid/snippet_drop.rb @@ -2,12 +2,13 @@ module Liquid class SnippetDrop < Drop - attr_reader :body, :name + attr_reader :body, :name, :filename - def initialize(body, name) + def initialize(body, name, filename) super() @body = body @name = name + @filename = filename end def to_partial diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb index cabbfe2e..7f967282 100644 --- a/lib/liquid/tags/render.rb +++ b/lib/liquid/tags/render.rb @@ -51,16 +51,16 @@ module Liquid if template.respond_to?(:to_partial) partial = template.to_partial - template_name = template.name + 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, parse_context.locale.t("errors.argument.render") + raise Liquid::ArgumentError, parse_context.locale.t("errors.file_system.includes") end - 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 diff --git a/lib/liquid/tags/snippet.rb b/lib/liquid/tags/snippet.rb index 7853adc4..87e2a0de 100644 --- a/lib/liquid/tags/snippet.rb +++ b/lib/liquid/tags/snippet.rb @@ -26,7 +26,7 @@ module Liquid end def render_to_output_buffer(context, output) - snippet_drop = SnippetDrop.new(@body, @to) + 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 diff --git a/test/integration/tags/render_tag_test.rb b/test/integration/tags/render_tag_test.rb index 4dedaaae..6fe19abb 100644 --- a/test/integration/tags/render_tag_test.rb +++ b/test/integration/tags/render_tag_test.rb @@ -101,13 +101,6 @@ class RenderTagTest < Minitest::Test end end - def test_dynamically_chosen_templates_are_not_allowed - error = assert_raises(::ArgumentError) do - Template.parse('{% assign name = "snippet" %}{% render name %}').render! - end - assert_equal("Argument error in tag 'render' - Dynamically chosen templates are not allowed", error.message) - end - def test_rigid_parsing_errors with_error_modes(:lax, :strict) do assert_template_result( diff --git a/test/integration/tags/snippet_test.rb b/test/integration/tags/snippet_test.rb index 37fa67ec..571890ba 100644 --- a/test/integration/tags/snippet_test.rb +++ b/test/integration/tags/snippet_test.rb @@ -480,6 +480,54 @@ class SnippetTest < Minitest::Test 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): This liquid context does not allow includes + 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): This liquid context does not allow includes 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 @@ -956,6 +1004,54 @@ class SnippetTest < Minitest::Test 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): This liquid context does not allow includes + 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): This liquid context does not allow includes 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 %}"