From 3a13ac7e6c47aad98b2cacc47784ab51a643ff0e Mon Sep 17 00:00:00 2001 From: Julia Boutin Date: Tue, 30 Sep 2025 16:29:40 -0600 Subject: [PATCH] Create SnippetDrop and set in scope --- lib/liquid.rb | 1 + lib/liquid/snippet_drop.rb | 16 ++ lib/liquid/tags/render.rb | 19 ++- lib/liquid/tags/snippet.rb | 14 +- test/integration/tags/snippet_test.rb | 203 ++++++++++++++++++-------- 5 files changed, 179 insertions(+), 74 deletions(-) create mode 100644 lib/liquid/snippet_drop.rb diff --git a/lib/liquid.rb b/lib/liquid.rb index 4d0a71a6..09cafe94 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -67,6 +67,7 @@ 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/snippet_drop.rb b/lib/liquid/snippet_drop.rb new file mode 100644 index 00000000..fb48d068 --- /dev/null +++ b/lib/liquid/snippet_drop.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Liquid + class SnippetDrop < Drop + attr_reader :body + + def initialize(body) + super() + @body = body + end + + def to_s + 'SnippetDrop' + end + end +end diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb index c142caca..03f231ea 100644 --- a/lib/liquid/tags/render.rb +++ b/lib/liquid/tags/render.rb @@ -42,6 +42,10 @@ module Liquid @is_for_loop end + def inherit_context? + @inherit_context + end + def render_to_output_buffer(context, output) render_tag(context, output) end @@ -51,14 +55,15 @@ module Liquid template_name = @template_name_expr raise ::ArgumentError unless template_name.is_a?(String) - # Inline snippets take precedence over external snippets - if (inline_snippet = context.registers[:inline_snippet][template_name]) + if context[template_name].is_a?(Liquid::SnippetDrop) + snippet_drop = context[template_name] inner_context = context.new_isolated_subcontext - snippet_body = inline_snippet[:body] - context.scopes.each do |scope| - scope.each do |key, value| - inner_context[key] = value + if inherit_context? + context.scopes.each do |scope| + scope.each do |key, value| + inner_context[key] = value + end end end @@ -66,7 +71,7 @@ module Liquid inner_context[key] = context.evaluate(value) end - return output << snippet_body.render(inner_context) + return output << snippet_drop.body.render(inner_context) end partial = PartialCache.load( diff --git a/lib/liquid/tags/snippet.rb b/lib/liquid/tags/snippet.rb index 7f907274..e1d978b6 100644 --- a/lib/liquid/tags/snippet.rb +++ b/lib/liquid/tags/snippet.rb @@ -25,12 +25,14 @@ module Liquid end end - def render(context) - context.registers[:inline_snippet] ||= {} - context.registers[:inline_snippet][@to] = { - body: @body, - } - '' + def render_to_output_buffer(context, output) + snippet_drop = SnippetDrop.new(@body) + context.scopes.last[@to] = snippet_drop + output + end + + def blank? + true end end end diff --git a/test/integration/tags/snippet_test.rb b/test/integration/tags/snippet_test.rb index 24586227..27e50ec6 100644 --- a/test/integration/tags/snippet_test.rb +++ b/test/integration/tags/snippet_test.rb @@ -229,21 +229,18 @@ class SnippetTest < Minitest::Test assert_template_result(expected, template) end - def test_render_parent_context_variable + def test_render_inline_snippet_without_outside_context template = <<~LIQUID.strip {% assign color_scheme = 'dark' %} {% snippet header %} - {% doc %} - @param {string} message - Message. - {% enddoc %} -
{{ message }}
{% endsnippet %} - {%- render "header", message: "Welcome to my site" -%} + + {% render "header", message: 'Welcome!' %} LIQUID expected = <<~OUTPUT @@ -251,49 +248,44 @@ class SnippetTest < Minitest::Test + +
+ Welcome! +
+ OUTPUT + + assert_template_result(expected, template) + end + + def test_render_inline_snippet_with_outside_context + template = <<~LIQUID.strip + {% assign color_scheme = 'dark' %} + + {% snippet header %} +
+ {{ message }} +
+ {% endsnippet %} + + + {% render "header", ..., message: 'Welcome!' %} + LIQUID + expected = <<~OUTPUT + + + + + +
- Welcome to my site + Welcome!
OUTPUT assert_template_result(expected, template) end - def test_deeply_nested_snippets - template = <<~LIQUID.strip - {% assign color_scheme = 'first-color' %} - {% snippet first %} - {% assign color_scheme = 'second-color' %} - {% snippet second %} - {% assign color_scheme = 'third-color' %} - {% snippet third %} -
- This is a header -
- {% endsnippet %} - {%- render "third" -%} - {% endsnippet %} - {%- render "second" -%} - {% endsnippet %} - - {%- render "first" -%} - LIQUID - expected = <<~OUTPUT - - - - - - -
- This is a header -
- OUTPUT - - assert_template_result(expected, template) - end - - def test_render_snippet_with_variables_in_both_scopes + def test_inline_snippet_local_scope_takes_precedence template = <<~LIQUID.strip {% assign color_scheme = 'dark' %} @@ -306,7 +298,9 @@ class SnippetTest < Minitest::Test {{ color_scheme }} - {%- render "header", message: 'Welcome to my site' -%} + {% render "header", ..., message: 'Welcome!' %} + + {{ color_scheme }} LIQUID expected = <<~OUTPUT @@ -315,39 +309,126 @@ class SnippetTest < Minitest::Test dark + +
- Welcome to my site + Welcome! +
+ + + dark + OUTPUT + + assert_template_result(expected, template) + end + + def test_render_captured_snippet + template = <<~LIQUID.strip + {% assign color_scheme = 'dark' %} + + {% 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_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_snippets_as_arguments + # def test_render_inline_snippet_inside_loop # template = <<~LIQUID.strip # {% assign color_scheme = 'dark' %} + # {% assign array = '1,2,3' | split: ',' %} - # {% snippet main_header %} - # {% assign color_scheme = 'auto' %} - - #
- # {%- render "header", message: 'Welcome to my site' -%} - #
- # {% endsnippet %} - + # {% for i in array %} # {% snippet header %} - #
- # {{ message }} - #
+ #
+ # {{ message }} {{ i }} + #
# {% endsnippet %} + # {% endfor %} - # {%- render "main_header", header: header -%} + # {% render "header", ..., message: '👉' %} # LIQUID # expected = <<~OUTPUT - #
- #
- # Welcome to my site - #
+ + #
+ # 👉 3 #
# OUTPUT