From d29c8db8cfc6456e83cd5e64649f56f831ef7325 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Wed, 29 Oct 2025 15:53:57 +0100 Subject: [PATCH] Adds parent template tracking to snippet drops Enhances snippet drops to track their parent template name, enabling better error reporting and context awareness within rendered snippets. Updates the render tag to use parent template names for proper context variable naming and improves error handling flow. --- lib/liquid/snippet_drop.rb | 5 +++-- lib/liquid/tags/render.rb | 11 +++++----- lib/liquid/tags/snippet.rb | 2 +- test/integration/tags/snippet_test.rb | 31 +++++++++++++++++++++------ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/lib/liquid/snippet_drop.rb b/lib/liquid/snippet_drop.rb index 11648826..8856925a 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, :parent_name - def initialize(body, name) + def initialize(body, name, parent_name) super() @body = body @name = name + @parent_name = parent_name end def to_partial diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb index 6d432ec7..fcde2a47 100644 --- a/lib/liquid/tags/render.rb +++ b/lib/liquid/tags/render.rb @@ -51,19 +51,18 @@ module Liquid if template.respond_to?(:to_partial) partial = template.to_partial - template_name = template.name + template_name = template.parent_name + context_variable_name = @alias_name || template.name.split('/').last + elsif @template_name_expr.is_a?(String) partial = PartialCache.load(template, context: context, parse_context: parse_context) template_name = partial.name - elsif template.nil? - template_name = @template_name_expr.respond_to?(:name) ? @template_name_expr.name : @template_name_expr - raise FileSystemError, "No such template '#{template_name}'" + context_variable_name = @alias_name || template_name.split('/').last + else raise ::ArgumentError, parse_context.locale.t("errors.argument.render") 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/snippet_test.rb b/test/integration/tags/snippet_test.rb index c2ff9248..2aecc4a8 100644 --- a/test/integration/tags/snippet_test.rb +++ b/test/integration/tags/snippet_test.rb @@ -482,22 +482,39 @@ class SnippetTest < Minitest::Test end def test_render_with_non_existent_tag - template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true) + template = <<-LIQUID {% snippet foo %} - {% render non_existent %} - {% endsnippet %} + Hello, - {% render foo %} + {{ errors.standard_error }} will raise a standard error. + + Bla bla test. + + {{ errors.syntax_error }} will raise a syntax error. + + This is an argument error: {{ errors.argument_error }} + + Bla. + {% endsnippet %} + {%- render foo -%} LIQUID - expected = <<~TEXT + expected = <<-TEXT + Hello, + Liquid error (line 3): standard error will raise a standard error. + Bla bla test. - Liquid error (foo line 2): No such template 'non_existent' + Liquid syntax error (line 7): syntax error will raise a syntax error. + + This is an argument error: Liquid error (line 9): argument error + + Bla. TEXT - assert_equal(expected, template.render('errors' => ErrorDrop.new)) + output = Liquid::Template.parse(template, line_numbers: true).render('errors' => ErrorDrop.new) + assert_equal(expected, output) end end