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
- - wow a link
+ - wow a {{ link }}
- 1 + 1 = {{ 1 | plus: 1 }}
- {% if true %}Yes!{% endif %}
- - {% if foo %}NO{% endif %}
+ - foo = {% if foo %}true{%else%}false{% endif %}
- {{ missing_var | default: 'fallback' }}
{% 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 %}
+
+ {% endsnippet %}
+
+
+ {% render header, ..., message: 'Welcome!' %}
+ LIQUID
+ expected = <<~OUTPUT
+
+
+
+
+
+
+
+ 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 %}
-
+
{% endsnippet %}
{% capture up_header %}
- {% render header, ..., message: 'Welcome!' %}
+ {%- render header, ..., message: 'Welcome!' -%}
{% endcapture %}
{{ up_header | upcase }}
@@ -366,11 +411,9 @@ class SnippetTest < Minitest::Test
-
-
-
+
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