mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-19 10:52:48 -07:00
Support ... inline snippet syntax
This commit is contained in:
committed by
Guilherme Carreiro
parent
c7ad1c90ca
commit
9bcfd32e65
@@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="liquid" style="font-size: 56px;">
|
<div class="liquid" style="font-size: 56px;">
|
||||||
|
{% assign foo = true %}
|
||||||
|
{% assign link = "variable" %}
|
||||||
|
|
||||||
{% snippet main %}
|
{% snippet main %}
|
||||||
{% assign foo = false %}
|
{% assign foo = false %}
|
||||||
@@ -17,15 +18,16 @@
|
|||||||
<p>This is an inline snippet</p>
|
<p>This is an inline snippet</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/wow-a-link">wow a link</a></li>
|
<li><a href="/wow-a-link">wow a {{ link }}</a></li>
|
||||||
<li>1 + 1 = {{ 1 | plus: 1 }}</li>
|
<li>1 + 1 = {{ 1 | plus: 1 }}</li>
|
||||||
<li>{% if true %}Yes!{% endif %}</li>
|
<li>{% if true %}Yes!{% endif %}</li>
|
||||||
<li>{% if foo %}NO{% endif %}</li>
|
<li>foo = {% if foo %}true{%else%}false{% endif %}</li>
|
||||||
<li>{{ missing_var | default: 'fallback' }}</li>
|
<li>{{ missing_var | default: 'fallback' }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endsnippet %}
|
{% endsnippet %}
|
||||||
|
|
||||||
{% render main, arg: 'lsf' %}
|
{% render main, arg: 'lsf', ... %}
|
||||||
|
{{ foo }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+8
-2
@@ -17,6 +17,7 @@ module Liquid
|
|||||||
DASH = [:dash, "-"].freeze
|
DASH = [:dash, "-"].freeze
|
||||||
DOT = [:dot, "."].freeze
|
DOT = [:dot, "."].freeze
|
||||||
DOTDOT = [:dotdot, ".."].freeze
|
DOTDOT = [:dotdot, ".."].freeze
|
||||||
|
DOTDOTDOT = [:dotdotdot, "..."].freeze
|
||||||
DOT_ORD = ".".ord
|
DOT_ORD = ".".ord
|
||||||
DOUBLE_STRING_LITERAL = /"[^\"]*"/
|
DOUBLE_STRING_LITERAL = /"[^\"]*"/
|
||||||
EOS = [:end_of_string].freeze
|
EOS = [:end_of_string].freeze
|
||||||
@@ -113,10 +114,15 @@ module Liquid
|
|||||||
|
|
||||||
if (special = SPECIAL_TABLE[peeked])
|
if (special = SPECIAL_TABLE[peeked])
|
||||||
ss.scan_byte
|
ss.scan_byte
|
||||||
# Special case for ".."
|
# Special case for ".." and "..."
|
||||||
if special == DOT && ss.peek_byte == DOT_ORD
|
if special == DOT && ss.peek_byte == DOT_ORD
|
||||||
ss.scan_byte
|
ss.scan_byte
|
||||||
output << DOTDOT
|
if ss.peek_byte == DOT_ORD
|
||||||
|
ss.scan_byte
|
||||||
|
output << DOTDOTDOT
|
||||||
|
else
|
||||||
|
output << DOTDOT
|
||||||
|
end
|
||||||
elsif special == DASH
|
elsif special == DASH
|
||||||
# Special case for negative numbers
|
# Special case for negative numbers
|
||||||
if (peeked_byte = ss.peek_byte) && NUMBER_TABLE[peeked_byte]
|
if (peeked_byte = ss.peek_byte) && NUMBER_TABLE[peeked_byte]
|
||||||
|
|||||||
@@ -62,7 +62,13 @@ module Liquid
|
|||||||
|
|
||||||
inner_context = context.new_isolated_subcontext
|
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|
|
context.scopes.each do |scope|
|
||||||
scope.each do |key, value|
|
scope.each do |key, value|
|
||||||
inner_context[key] = value
|
inner_context[key] = value
|
||||||
@@ -125,6 +131,14 @@ module Liquid
|
|||||||
|
|
||||||
p.consume?(:comma)
|
p.consume?(:comma)
|
||||||
|
|
||||||
|
@inherit_context = false
|
||||||
|
# ... inline snippets syntax
|
||||||
|
if p.consume?(:dotdotdot)
|
||||||
|
p.consume?(:comma)
|
||||||
|
|
||||||
|
@inherit_context = true
|
||||||
|
end
|
||||||
|
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
while p.look(:id)
|
while p.look(:id)
|
||||||
key = p.consume
|
key = p.consume
|
||||||
@@ -137,7 +151,12 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def rigid_template_name(p)
|
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
|
end
|
||||||
|
|
||||||
def strict_parse(markup)
|
def strict_parse(markup)
|
||||||
@@ -155,6 +174,7 @@ module Liquid
|
|||||||
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
||||||
@template_name_expr = parse_expression(template_name)
|
@template_name_expr = parse_expression(template_name)
|
||||||
@is_for_loop = (with_or_for == FOR)
|
@is_for_loop = (with_or_for == FOR)
|
||||||
|
@inherit_context = markup.include?('...')
|
||||||
|
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
markup.scan(TagAttributes) do |key, value|
|
markup.scan(TagAttributes) do |key, value|
|
||||||
|
|||||||
@@ -115,6 +115,23 @@ class SnippetTest < Minitest::Test
|
|||||||
assert_template_result(expected, template)
|
assert_template_result(expected, template)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_render_inline_snippet_with_evaluated_assign
|
||||||
|
template = <<~LIQUID.strip
|
||||||
|
{% snippet input %}
|
||||||
|
<h1>{{ greeting }}</h1>
|
||||||
|
{% endsnippet %}
|
||||||
|
|
||||||
|
{%- assign greeting = "hello" | upcase -%}
|
||||||
|
{%- render input, greeting: greeting -%}
|
||||||
|
LIQUID
|
||||||
|
expected = <<~OUTPUT
|
||||||
|
|
||||||
|
<h1>HELLO</h1>
|
||||||
|
OUTPUT
|
||||||
|
|
||||||
|
assert_template_result(expected, template)
|
||||||
|
end
|
||||||
|
|
||||||
def test_render_inline_snippet_with_multiple_arguments
|
def test_render_inline_snippet_with_multiple_arguments
|
||||||
template = <<~LIQUID.strip
|
template = <<~LIQUID.strip
|
||||||
{% snippet input %}
|
{% snippet input %}
|
||||||
@@ -301,8 +318,36 @@ class SnippetTest < Minitest::Test
|
|||||||
assert_template_result(expected, template)
|
assert_template_result(expected, template)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_render_inline_snippet_with_outside_context_rigid
|
||||||
|
template = <<~LIQUID.strip
|
||||||
|
{% assign color_scheme = 'dark' %}
|
||||||
|
|
||||||
|
{% snippet header %}
|
||||||
|
<div class="header header--{{ color_scheme }}">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endsnippet %}
|
||||||
|
|
||||||
|
|
||||||
|
{% render header, ..., message: 'Welcome!' %}
|
||||||
|
LIQUID
|
||||||
|
expected = <<~OUTPUT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="header header--dark">
|
||||||
|
Welcome!
|
||||||
|
</div>
|
||||||
|
OUTPUT
|
||||||
|
|
||||||
|
assert_template_result(expected, template, error_mode: :rigid)
|
||||||
|
end
|
||||||
|
|
||||||
def test_inline_snippet_local_scope_takes_precedence
|
def test_inline_snippet_local_scope_takes_precedence
|
||||||
template = <<~LIQUID.strip
|
template = <<~LIQUID
|
||||||
{% assign color_scheme = 'dark' %}
|
{% assign color_scheme = 'dark' %}
|
||||||
|
|
||||||
{% snippet header %}
|
{% snippet header %}
|
||||||
@@ -339,17 +384,17 @@ class SnippetTest < Minitest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_render_captured_snippet
|
def test_render_captured_snippet
|
||||||
template = <<~LIQUID.strip
|
template = <<~LIQUID
|
||||||
{% assign color_scheme = 'dark' %}
|
{% assign color_scheme = 'dark' %}
|
||||||
|
|
||||||
{% snippet header %}
|
{% snippet header %}
|
||||||
<div class="header header--{{ color_scheme }}">
|
<div class="header header--{{ color_scheme }}">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
</div>
|
</div>
|
||||||
{% endsnippet %}
|
{% endsnippet %}
|
||||||
|
|
||||||
{% capture up_header %}
|
{% capture up_header %}
|
||||||
{% render header, ..., message: 'Welcome!' %}
|
{%- render header, ..., message: 'Welcome!' -%}
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
{{ up_header | upcase }}
|
{{ up_header | upcase }}
|
||||||
@@ -366,11 +411,9 @@ class SnippetTest < Minitest::Test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<DIV CLASS="HEADER HEADER--DARK">
|
||||||
<DIV CLASS="HEADER HEADER--DARK">
|
WELCOME!
|
||||||
WELCOME!
|
</DIV>
|
||||||
</DIV>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SNIPPETDROP
|
SNIPPETDROP
|
||||||
@@ -395,7 +438,7 @@ class SnippetTest < Minitest::Test
|
|||||||
{% assign color_scheme = 'auto' %}
|
{% assign color_scheme = 'auto' %}
|
||||||
|
|
||||||
<div class="main main--{{ color_scheme }}">
|
<div class="main main--{{ color_scheme }}">
|
||||||
{% render header, ..., message: 'Welcome!' %}
|
{% render header, ..., message: 'Welcome!' %}
|
||||||
</div>
|
</div>
|
||||||
{% endsnippet %}
|
{% endsnippet %}
|
||||||
|
|
||||||
@@ -448,4 +491,59 @@ class SnippetTest < Minitest::Test
|
|||||||
|
|
||||||
# assert_template_result(expected, template)
|
# assert_template_result(expected, template)
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
# def test_render_inline_snippet_forloop
|
||||||
|
# template = <<~LIQUID.strip
|
||||||
|
# {% snippet item %}
|
||||||
|
# <li>{{ forloop.index }}: {{ item }}</li>
|
||||||
|
# {% endsnippet %}
|
||||||
|
|
||||||
|
# {% assign items = "A,B,C" | split: "," %}
|
||||||
|
# {%- render item for items -%}
|
||||||
|
# LIQUID
|
||||||
|
# expected = <<~OUTPUT
|
||||||
|
|
||||||
|
# <li>1: A</li>
|
||||||
|
|
||||||
|
# <li>2: B</li>
|
||||||
|
|
||||||
|
# <li>3: C</li>
|
||||||
|
# OUTPUT
|
||||||
|
|
||||||
|
# assert_template_result(expected, template)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# def test_render_inline_snippet_with
|
||||||
|
# template = <<~LIQUID.strip
|
||||||
|
# {% snippet header %}
|
||||||
|
# <div>{{ header }}</div>
|
||||||
|
# {% endsnippet %}
|
||||||
|
|
||||||
|
# {% assign product = "Apple" %}
|
||||||
|
# {%- render header with product -%}
|
||||||
|
# LIQUID
|
||||||
|
# expected = <<~OUTPUT
|
||||||
|
|
||||||
|
# <div>Apple</div>
|
||||||
|
# OUTPUT
|
||||||
|
|
||||||
|
# assert_template_result(expected, template)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# def test_render_inline_snippet_alias
|
||||||
|
# template = <<~LIQUID.strip
|
||||||
|
# {% snippet product_card %}
|
||||||
|
# <div class="product">{{ item }}</div>
|
||||||
|
# {% endsnippet %}
|
||||||
|
|
||||||
|
# {% assign featured = "Apple" %}
|
||||||
|
# {%- render product_card with featured as item -%}
|
||||||
|
# LIQUID
|
||||||
|
# expected = <<~OUTPUT
|
||||||
|
|
||||||
|
# <div class="product">Apple</div>
|
||||||
|
# OUTPUT
|
||||||
|
|
||||||
|
# assert_template_result(expected, template)
|
||||||
|
# end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user