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.
This commit is contained in:
Marco Concetto Rudilosso 2025-10-29 15:53:57 +01:00
parent b02ece20e7
commit d29c8db8cf
4 changed files with 33 additions and 16 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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