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-27 10:11:22 -06:00
parent 3a13ac7e6c
commit db474d5b57
3 changed files with 68 additions and 87 deletions
+22 -61
View File
@@ -1,71 +1,32 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Code Editor</title> <title>Inline Snippets</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>
<body> <body>
<div class="liquid"> <div class="liquid" style="font-size: 56px;">
{% snippet "main" %}
{% # Snippet input %}
{% snippet "input" |type, name| %} {% snippet main %}
<div> {% assign foo = false %}
<label>{{ type | capitalize }}</label> <p>Hi {{ arg | upcase }}!!!</p>
<input type={{ type }}>
</div>
{% endsnippet %}
{% snippet "league" %} <p>This is an inline snippet</p>
<h1>Welcome to the league of super evil</h1>
{% endsnippet %}
{% render "league" %}
{% render "input", type: "text" %}
{% render "input", type: "password" %}
<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 %} {% endsnippet %}
{% render 'main' %}
{% render main, arg: 'lsf' %}
</div> </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> </body>
</html> </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. # @liquid_syntax_keyword filename The name of the snippet to render, without the `.liquid` extension.
class Render < Tag class Render < Tag
FOR = 'for' 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" disable_tags "include"
@@ -51,12 +51,15 @@ module Liquid
end end
def render_tag(context, output) def render_tag(context, output)
# The expression should be a String literal, which parses to a String object
template_name = @template_name_expr template_name = @template_name_expr
raise ::ArgumentError unless template_name.is_a?(String)
if context[template_name].is_a?(Liquid::SnippetDrop) # For inline snippets, @template_name_expr is a VariableLookup
snippet_drop = context[template_name] 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 inner_context = context.new_isolated_subcontext
if inherit_context? if inherit_context?
@@ -74,6 +77,9 @@ module Liquid
return output << snippet_drop.body.render(inner_context) return output << snippet_drop.body.render(inner_context)
end 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( partial = PartialCache.load(
template_name, template_name,
context: context, context: context,
+35 -21
View File
@@ -22,7 +22,7 @@ class SnippetTest < Minitest::Test
Hey Hey
{% endsnippet %} {% endsnippet %}
{%- render "hey" -%} {%- render hey -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -32,6 +32,22 @@ class SnippetTest < Minitest::Test
assert_template_result(expected, template) assert_template_result(expected, template)
end 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 def test_render_multiple_inline_snippets
template = <<~LIQUID.strip template = <<~LIQUID.strip
{% snippet input %} {% snippet input %}
@@ -44,8 +60,8 @@ class SnippetTest < Minitest::Test
</marquee> </marquee>
{% endsnippet %} {% endsnippet %}
{%- render "input" -%} {%- render input -%}
{%- render "banner" -%} {%- render banner -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -67,7 +83,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" /> <input type="{{ type }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text" -%} {%- render input, type: "text" -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -87,7 +103,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" /> <input type="{{ type }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text" -%} {%- render input, type: "text" -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -110,7 +126,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" /> <input type="{{ type }}" value="{{ value }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text", value: "Hello" -%} {%- render input, type: "text", value: "Hello" -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -132,8 +148,8 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" /> <input type="{{ type }}" value="{{ value }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text" -%} {%- render input, type: "text" -%}
{%- render "inputs", type: "password", value: "pass" -%} {%- render inputs, type: "password", value: "pass" -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -159,7 +175,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" /> <input type="{{ type }}" value="{{ value }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text" -%} {%- render input, type: "text" -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -182,7 +198,7 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" value="{{ value }}" /> <input type="{{ type }}" value="{{ value }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text", value: "Hello" -%} {%- render input, type: "text", value: "Hello" -%}
{{ type }} {{ type }}
{{ value }} {{ value }}
@@ -212,8 +228,8 @@ class SnippetTest < Minitest::Test
<input type="{{ type }}" /> <input type="{{ type }}" />
{% endsnippet %} {% endsnippet %}
{%- render "input", type: "text" -%} {%- render input, type: "text" -%}
{%- render "no_leak" -%} {%- render no_leak -%}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -240,7 +256,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %} {% endsnippet %}
{% render "header", message: 'Welcome!' %} {% render header, message: 'Welcome!' %}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -268,7 +284,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %} {% endsnippet %}
{% render "header", ..., message: 'Welcome!' %} {% render header, ..., message: 'Welcome!' %}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -298,7 +314,7 @@ class SnippetTest < Minitest::Test
{{ color_scheme }} {{ color_scheme }}
{% render "header", ..., message: 'Welcome!' %} {% render header, ..., message: 'Welcome!' %}
{{ color_scheme }} {{ color_scheme }}
LIQUID LIQUID
@@ -333,7 +349,7 @@ class SnippetTest < Minitest::Test
{% endsnippet %} {% endsnippet %}
{% capture up_header %} {% capture up_header %}
{% render "header", ..., message: 'Welcome!' %} {% render header, ..., message: 'Welcome!' %}
{% endcapture %} {% endcapture %}
{{ up_header | upcase }} {{ up_header | upcase }}
@@ -351,7 +367,6 @@ class SnippetTest < Minitest::Test
<DIV CLASS="HEADER HEADER--DARK"> <DIV CLASS="HEADER HEADER--DARK">
WELCOME! WELCOME!
</DIV> </DIV>
@@ -380,11 +395,11 @@ 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 %}
{% render "main", header: header %} {% render main, header: header %}
LIQUID LIQUID
expected = <<~OUTPUT expected = <<~OUTPUT
@@ -397,7 +412,6 @@ class SnippetTest < Minitest::Test
<div class="main main--auto"> <div class="main main--auto">
<div class="header header--auto"> <div class="header header--auto">
@@ -423,7 +437,7 @@ class SnippetTest < Minitest::Test
# {% endsnippet %} # {% endsnippet %}
# {% endfor %} # {% endfor %}
# {% render "header", ..., message: '👉' %} # {% render header, ..., message: '👉' %}
# LIQUID # LIQUID
# expected = <<~OUTPUT # expected = <<~OUTPUT