Change inline snippet identifier from string to variable

Currently, snippet files identified by strings. This
PR makes changes to render to allow for new inline
snippets to use variables as identifiers instead
This commit is contained in:
Julia Boutin
2025-10-30 12:00:44 +01:00
committed by Guilherme Carreiro
parent 12bbbc4537
commit c7ad1c90ca
3 changed files with 68 additions and 87 deletions
+22 -61
View File
@@ -1,71 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Code Editor</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/codemirror.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/theme/dracula.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/xml/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/htmlmixed/htmlmixed.min.js"></script>
<style>
.liquid, .CodeMirror {
position: fixed;
height: 100vh;
width: 50vw;
top: 0;
font-size: 24px;
}
.liquid {
left: 0;
}
.CodeMirror {
left: 50%;
}
.CodeMirror-hscrollbar {
overflow: hidden;
}
</style>
</head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inline Snippets</title>
<body>
<div class="liquid">
{% snippet "main" %}
<div class="liquid" style="font-size: 56px;">
{% # Snippet input %}
{% snippet "input" |type, name| %}
<div>
<label>{{ type | capitalize }}</label>
<input type={{ type }}>
</div>
{% endsnippet %}
{% snippet main %}
{% assign foo = false %}
<p>Hi {{ arg | upcase }}!!!</p>
{% snippet "league" %}
<h1>Welcome to the league of super evil</h1>
{% endsnippet %}
{% render "league" %}
{% render "input", type: "text" %}
{% render "input", type: "password" %}
<p>This is an inline snippet</p>
<ul>
<li><a href="/wow-a-link">wow a link</a></li>
<li>1 + 1 = {{ 1 | plus: 1 }}</li>
<li>{% if true %}Yes!{% endif %}</li>
<li>{% if foo %}NO{% endif %}</li>
<li>{{ missing_var | default: 'fallback' }}</li>
</ul>
{% endsnippet %}
{% render 'main' %}
{% render main, arg: 'lsf' %}
</div>
<textarea id="code">
{% capture html %}{% render 'main' %}{% endcapture %}
{{ html | escape }}
</textarea>
<script>
const editorElement = document.querySelector('#code')
const editor = CodeMirror.fromTextArea(editorElement, {
lineNumbers: true,
mode: "htmlmixed",
theme: "dracula"
});
</script>
</body>
</html>
+11 -5
View File
@@ -27,7 +27,7 @@ module Liquid
# @liquid_syntax_keyword filename The name of the snippet to render, without the `.liquid` extension.
class Render < Tag
FOR = 'for'
SYNTAX = /(#{QuotedString}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
SYNTAX = /(#{QuotedString}+|#{VariableSegment}+)(\s+(with|#{FOR})\s+(#{QuotedFragment}+))?(\s+(?:as)\s+(#{VariableSegment}+))?/o
disable_tags "include"
@@ -51,12 +51,15 @@ module Liquid
end
def render_tag(context, output)
# The expression should be a String literal, which parses to a String object
template_name = @template_name_expr
raise ::ArgumentError unless template_name.is_a?(String)
if context[template_name].is_a?(Liquid::SnippetDrop)
snippet_drop = context[template_name]
# For inline snippets, @template_name_expr is a VariableLookup
if template_name.is_a?(VariableLookup)
snippet_drop = context[template_name.name]
raise ::ArgumentError unless snippet_drop.is_a?(Liquid::SnippetDrop)
inner_context = context.new_isolated_subcontext
if inherit_context?
@@ -74,6 +77,9 @@ module Liquid
return output << snippet_drop.body.render(inner_context)
end
# Otherwise, the expression should be a String literal, which parses to a String object
raise ::ArgumentError unless template_name.is_a?(String)
partial = PartialCache.load(
template_name,
context: context,
+35 -21
View File
@@ -22,7 +22,7 @@ class SnippetTest < Minitest::Test
Hey
{% endsnippet %}
{%- render "hey" -%}
{%- render hey -%}
LIQUID
expected = <<~OUTPUT
@@ -32,6 +32,22 @@ class SnippetTest < Minitest::Test
assert_template_result(expected, template)
end
def test_render_inline_snippet_with_variable
template = <<~LIQUID.strip
{% snippet hey %}
<p>Today is {{ "hello" | capitalize }}</p>
{% endsnippet %}
{%- render hey -%}
LIQUID
expected = <<~OUTPUT
<p>Today is Hello</p>
OUTPUT
assert_template_result(expected, template)
end
def test_render_multiple_inline_snippets
template = <<~LIQUID.strip
{% snippet input %}
@@ -44,8 +60,8 @@ class SnippetTest < Minitest::Test
</marquee>
{% endsnippet %}
{%- render "input" -%}
{%- render "banner" -%}
{%- render input -%}
{%- render banner -%}
LIQUID
expected = <<~OUTPUT
@@ -67,7 +83,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" />
{% endsnippet %}
{%- render "input", type: "text" -%}
{%- render input, type: "text" -%}
LIQUID
expected = <<~OUTPUT
@@ -87,7 +103,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" />
{% endsnippet %}
{%- render "input", type: "text" -%}
{%- render input, type: "text" -%}
LIQUID
expected = <<~OUTPUT
@@ -110,7 +126,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" />
{% endsnippet %}
{%- render "input", type: "text", value: "Hello" -%}
{%- render input, type: "text", value: "Hello" -%}
LIQUID
expected = <<~OUTPUT
@@ -132,8 +148,8 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" />
{% endsnippet %}
{%- render "input", type: "text" -%}
{%- render "inputs", type: "password", value: "pass" -%}
{%- render input, type: "text" -%}
{%- render inputs, type: "password", value: "pass" -%}
LIQUID
expected = <<~OUTPUT
@@ -159,7 +175,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" />
{% endsnippet %}
{%- render "input", type: "text" -%}
{%- render input, type: "text" -%}
LIQUID
expected = <<~OUTPUT
@@ -182,7 +198,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" />
{% endsnippet %}
{%- render "input", type: "text", value: "Hello" -%}
{%- render input, type: "text", value: "Hello" -%}
{{ type }}
{{ value }}
@@ -212,8 +228,8 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" />
{% endsnippet %}
{%- render "input", type: "text" -%}
{%- render "no_leak" -%}
{%- render input, type: "text" -%}
{%- render no_leak -%}
LIQUID
expected = <<~OUTPUT
@@ -240,7 +256,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %}
{% render "header", message: 'Welcome!' %}
{% render header, message: 'Welcome!' %}
LIQUID
expected = <<~OUTPUT
@@ -268,7 +284,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %}
{% render "header", ..., message: 'Welcome!' %}
{% render header, ..., message: 'Welcome!' %}
LIQUID
expected = <<~OUTPUT
@@ -298,7 +314,7 @@ class SnippetTest < Minitest::Test
{{ color_scheme }}
{% render "header", ..., message: 'Welcome!' %}
{% render header, ..., message: 'Welcome!' %}
{{ color_scheme }}
LIQUID
@@ -333,7 +349,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %}
{% capture up_header %}
{% render "header", ..., message: 'Welcome!' %}
{% render header, ..., message: 'Welcome!' %}
{% endcapture %}
{{ up_header | upcase }}
@@ -351,7 +367,6 @@ class SnippetTest < Minitest::Test
<DIV CLASS="HEADER HEADER--DARK">
WELCOME!
</DIV>
@@ -380,11 +395,11 @@ class SnippetTest < Minitest::Test
{% assign color_scheme = 'auto' %}
<div class="main main--{{ color_scheme }}">
{% render "header", ..., message: 'Welcome!' %}
{% render header, ..., message: 'Welcome!' %}
</div>
{% endsnippet %}
{% render "main", header: header %}
{% render main, header: header %}
LIQUID
expected = <<~OUTPUT
@@ -397,7 +412,6 @@ class SnippetTest < Minitest::Test
<div class="main main--auto">
<div class="header header--auto">
@@ -423,7 +437,7 @@ class SnippetTest < Minitest::Test
# {% endsnippet %}
# {% endfor %}
# {% render "header", ..., message: '👉' %}
# {% render header, ..., message: '👉' %}
# LIQUID
# expected = <<~OUTPUT