diff --git a/lib/liquid/partial_cache.rb b/lib/liquid/partial_cache.rb index 1ef527887..09b4442ab 100644 --- a/lib/liquid/partial_cache.rb +++ b/lib/liquid/partial_cache.rb @@ -15,8 +15,13 @@ def self.load(template_name, context:, parse_context:) template_factory = context.registers[:template_factory] template = template_factory.for(template_name) - partial = template.parse(source, parse_context) - partial.name ||= template_name + begin + partial = template.parse(source, parse_context) + partial.name ||= template_name + rescue Liquid::Error => e + e.template_name = template&.name || template_name + raise e + end cached_partials[template_name] = partial ensure diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index e20ec1e0f..30742dd6f 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -189,6 +189,8 @@ def render(*args) @profiler = context.profiler = Liquid::Profiler.new end + context.template_name ||= name + begin # render the nodelist. @root.render_to_output_buffer(context, output || +'') diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index 4affac236..64b410d4f 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -263,4 +263,81 @@ def test_bug_compatible_silencing_of_errors_in_blank_nodes output = Liquid::Template.parse("{% assign x = 0 %}{% if 1 < '2' %}{% assign x = 3 %}{% endif %}{{ x }}").render assert_equal("0", output) end + + def test_syntax_error_is_raised_with_template_name + file_system = StubFileSystem.new("snippet" => "1\n2\n{{ 1") + + context = Liquid::Context.build( + registers: { file_system: file_system }, + ) + + template = Template.parse( + '{% render "snippet" %}', + line_numbers: true, + ) + template.name = "template/index" + + assert_equal( + "Liquid syntax error (snippet line 3): Variable '{{' was not properly terminated with regexp: /\\}\\}/", + template.render(context), + ) + end + + def test_syntax_error_is_raised_with_actual_filenmae + file_system = StubFileSystem.new("snippet" => "1\n2\n{{ 1") + + context = Liquid::Context.build( + registers: { + file_system: file_system, + template_factory: StubTemplateFactory.new, + }, + ) + + template = Template.parse( + '{% render "snippet" %}', + line_numbers: true, + ) + template.name = "template/index" + + assert_equal( + "Liquid syntax error (some/path/snippet line 3): Variable '{{' was not properly terminated with regexp: /\\}\\}/", + template.render(context), + ) + end + + def test_stack_level_error_is_raised_with_actual_filenmae + depth = Liquid::Block::MAX_DEPTH + 1 + code = "{% if true %}" * depth + "rendered" + "{% endif %}" * depth + + template = Template.parse("{% render 'snippet' %}", line_numbers: true) + + context = Liquid::Context.build( + registers: { + file_system: StubFileSystem.new("snippet" => code), + template_factory: StubTemplateFactory.new, + }, + ) + + assert_equal("Liquid error (some/path/snippet line 1): Nesting too deep", template.render(context)) + end + + def test_internal_error_is_raised_with_template_name + template = Template.new + template.parse( + "{% render 'snippet' %}", + line_numbers: true, + ) + template.name = "template/index" + + context = Liquid::Context.build( + registers: { + file_system: StubFileSystem.new({}), + }, + ) + + assert_equal( + "Liquid error (template/index line 1): internal", + template.render(context), + ) + end end