diff --git a/example/server/templates/index.liquid b/example/server/templates/index.liquid index d4ea6afc..0862f216 100644 --- a/example/server/templates/index.liquid +++ b/example/server/templates/index.liquid @@ -8,7 +8,8 @@
- + {% assign foo = true %} + {% assign link = "variable" %} {% snippet main %} {% assign foo = false %} @@ -17,15 +18,16 @@

This is an inline snippet

{% endsnippet %} - {% render main, arg: 'lsf' %} + {% render main, arg: 'lsf', ... %} + {{ foo }}
diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index f1740dba..94a3d9fa 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -17,6 +17,7 @@ module Liquid DASH = [:dash, "-"].freeze DOT = [:dot, "."].freeze DOTDOT = [:dotdot, ".."].freeze + DOTDOTDOT = [:dotdotdot, "..."].freeze DOT_ORD = ".".ord DOUBLE_STRING_LITERAL = /"[^\"]*"/ EOS = [:end_of_string].freeze @@ -113,10 +114,15 @@ module Liquid if (special = SPECIAL_TABLE[peeked]) ss.scan_byte - # Special case for ".." + # Special case for ".." and "..." if special == DOT && ss.peek_byte == DOT_ORD ss.scan_byte - output << DOTDOT + if ss.peek_byte == DOT_ORD + ss.scan_byte + output << DOTDOTDOT + else + output << DOTDOT + end elsif special == DASH # Special case for negative numbers if (peeked_byte = ss.peek_byte) && NUMBER_TABLE[peeked_byte] diff --git a/lib/liquid/tags/render.rb b/lib/liquid/tags/render.rb index 288e226d..e84397b0 100644 --- a/lib/liquid/tags/render.rb +++ b/lib/liquid/tags/render.rb @@ -62,7 +62,13 @@ module Liquid inner_context = context.new_isolated_subcontext - if inherit_context? + if is_file + inner_context.template_name = partial.name + inner_context.partial = true + end + + if is_inline && inherit_context? + context.scopes.each do |scope| scope.each do |key, value| inner_context[key] = value @@ -125,6 +131,14 @@ module Liquid p.consume?(:comma) + @inherit_context = false + # ... inline snippets syntax + if p.consume?(:dotdotdot) + p.consume?(:comma) + + @inherit_context = true + end + @attributes = {} while p.look(:id) key = p.consume @@ -137,7 +151,12 @@ module Liquid end def rigid_template_name(p) - p.consume(:string) + if p.look(:string) + p.consume(:string) + # inline snippets use variable identifiers + elsif p.look(:id) + p.consume(:id) + end end def strict_parse(markup) @@ -155,6 +174,7 @@ module Liquid @variable_name_expr = variable_name ? parse_expression(variable_name) : nil @template_name_expr = parse_expression(template_name) @is_for_loop = (with_or_for == FOR) + @inherit_context = markup.include?('...') @attributes = {} markup.scan(TagAttributes) do |key, value| diff --git a/test/integration/tags/snippet_test.rb b/test/integration/tags/snippet_test.rb index 5dcd5465..9824a16e 100644 --- a/test/integration/tags/snippet_test.rb +++ b/test/integration/tags/snippet_test.rb @@ -115,6 +115,23 @@ class SnippetTest < Minitest::Test assert_template_result(expected, template) end + def test_render_inline_snippet_with_evaluated_assign + template = <<~LIQUID.strip + {% snippet input %} +

{{ greeting }}

+ {% endsnippet %} + + {%- assign greeting = "hello" | upcase -%} + {%- render input, greeting: greeting -%} + LIQUID + expected = <<~OUTPUT + +

HELLO

+ OUTPUT + + assert_template_result(expected, template) + end + def test_render_inline_snippet_with_multiple_arguments template = <<~LIQUID.strip {% snippet input %} @@ -301,8 +318,36 @@ class SnippetTest < Minitest::Test assert_template_result(expected, template) end + def test_render_inline_snippet_with_outside_context_rigid + template = <<~LIQUID.strip + {% assign color_scheme = 'dark' %} + + {% snippet header %} +
+ {{ message }} +
+ {% endsnippet %} + + + {% render header, ..., message: 'Welcome!' %} + LIQUID + expected = <<~OUTPUT + + + + + + +
+ Welcome! +
+ OUTPUT + + assert_template_result(expected, template, error_mode: :rigid) + end + def test_inline_snippet_local_scope_takes_precedence - template = <<~LIQUID.strip + template = <<~LIQUID {% assign color_scheme = 'dark' %} {% snippet header %} @@ -339,17 +384,17 @@ class SnippetTest < Minitest::Test end def test_render_captured_snippet - template = <<~LIQUID.strip + template = <<~LIQUID {% assign color_scheme = 'dark' %} {% snippet header %} -
- {{ message }} -
+
+ {{ message }} +
{% endsnippet %} {% capture up_header %} - {% render header, ..., message: 'Welcome!' %} + {%- render header, ..., message: 'Welcome!' -%} {% endcapture %} {{ up_header | upcase }} @@ -366,11 +411,9 @@ class SnippetTest < Minitest::Test - -
- WELCOME! -
- +
+ WELCOME! +
SNIPPETDROP @@ -395,7 +438,7 @@ class SnippetTest < Minitest::Test {% assign color_scheme = 'auto' %}
- {% render header, ..., message: 'Welcome!' %} + {% render header, ..., message: 'Welcome!' %}
{% endsnippet %} @@ -448,4 +491,59 @@ class SnippetTest < Minitest::Test # assert_template_result(expected, template) # end + + # def test_render_inline_snippet_forloop + # template = <<~LIQUID.strip + # {% snippet item %} + #
  • {{ forloop.index }}: {{ item }}
  • + # {% endsnippet %} + + # {% assign items = "A,B,C" | split: "," %} + # {%- render item for items -%} + # LIQUID + # expected = <<~OUTPUT + + #
  • 1: A
  • + + #
  • 2: B
  • + + #
  • 3: C
  • + # OUTPUT + + # assert_template_result(expected, template) + # end + + # def test_render_inline_snippet_with + # template = <<~LIQUID.strip + # {% snippet header %} + #
    {{ header }}
    + # {% endsnippet %} + + # {% assign product = "Apple" %} + # {%- render header with product -%} + # LIQUID + # expected = <<~OUTPUT + + #
    Apple
    + # OUTPUT + + # assert_template_result(expected, template) + # end + + # def test_render_inline_snippet_alias + # template = <<~LIQUID.strip + # {% snippet product_card %} + #
    {{ item }}
    + # {% endsnippet %} + + # {% assign featured = "Apple" %} + # {%- render product_card with featured as item -%} + # LIQUID + # expected = <<~OUTPUT + + #
    Apple
    + # OUTPUT + + # assert_template_result(expected, template) + # end end