Skip to content

Commit 2d54b1a

Browse files
authored
Merge pull request #193 from jg-rp/experimental-snippet
Call the `snippet` tag experimental
2 parents 4b3d5ad + f5da3f9 commit 2d54b1a

File tree

13 files changed

+98
-92
lines changed

13 files changed

+98
-92
lines changed

CHANGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Version 2.2.0 (unreleased)
44

5-
- Added the `{% snippet %}` tag.
5+
- Added an **experimental** `{% snippet %}` tag. Shopify/liquid released then quickly removed `{% snippet %}`. We're calling it "experimental" and keeping it disabled by default pending more activity from Shopify/liquid.
66
- Improved static analysis of partial templates. Previously we would visit a partial template only once, regardless of how many times it is rendered with `{% render %}`. Now we visit partial templates once for each distinct set of arguments passed to `{% render %}`, potentially reporting "global" variables that we'd previously missed.
77

88
## Version 2.1.0

docs/experimental_tags.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
The tags described on this page are considered experimental and might change without warning and not follow semantic versioning.
2+
3+
## snippet
4+
5+
**_New in version 2.2.0_**
6+
7+
```plain
8+
{% snippet <identifier> %}
9+
<liquid markup>
10+
{% endsnippet %}
11+
```
12+
13+
A snippet is a reusable block of Liquid markup. Traditionally we'd save a snippet to a file and include it in a template with the `{% render %}` tag.
14+
15+
```liquid
16+
{% render "some_snippet" %}
17+
```
18+
19+
With the `{% snippet %}` tag we can define blocks for reuse inside a single template, potentially reducing the number of snippet files we need.
20+
21+
```liquid
22+
{% snippet div %}
23+
<div>
24+
{{ content }}
25+
</div>
26+
{% endsnippet %}
27+
```
28+
29+
Defining a snippet does not render it. We use `{% render snippet_name %}` to render a snippet, where `snippet_name` is the name of your snippet without quotes (file-based snippet names must be quoted).
30+
31+
```liquid
32+
{% snippet div %}
33+
<div>
34+
{{ content }}
35+
</div>
36+
{% endsnippet %}
37+
38+
{% render div, content: "Some content" %}
39+
{% render div, content: "Other content" %}
40+
```
41+
42+
```html title="output"
43+
<div>Some content</div>
44+
45+
<div>Other content</div>
46+
```
47+
48+
Inline snippets share the same namespace as variables defined with `{% assign %}` and `{% capture %}`, so be wary of accidentally overwriting snippets with non-snippet data.
49+
50+
```liquid
51+
{% snippet foo %}Hello{% endsnippet %}
52+
{% foo = 42 %}
53+
{% render foo %} {% # error %}
54+
```
55+
56+
Snippets can be nested and follow the same scoping rules as file-based snippets.
57+
58+
```liquid
59+
{% snippet a %}
60+
b
61+
{% snippet c %}
62+
d
63+
{% endsnippet %}
64+
{% render c %}
65+
{% endsnippet %}
66+
67+
{% render a %}
68+
{% render c %} {% # error, c is out of scope %}
69+
```
70+
71+
Snippet blocks are bound to their names late. You can conditionally define multiple snippets with the same name and pick one at render time.
72+
73+
```liquid
74+
{% if x %}
75+
{% snippet a %}b{% endsnippet %}
76+
{% else %}
77+
{% snippet a %}c{% endsnippet %}
78+
{% endif %}
79+
{% render a %}
80+
```

docs/tag_reference.md

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -540,85 +540,6 @@ Additional keyword arguments given to the `render` tag will be added to the rend
540540
{% render "partial_template" greeting: "Hello", num: 3, skip: 2 %}
541541
```
542542

543-
## snippet
544-
545-
**_New in version 2.2.0_**
546-
547-
```plain
548-
{% snippet <identifier> %}
549-
<liquid markup>
550-
{% endsnippet %}
551-
```
552-
553-
A snippet is a reusable block of Liquid markup. Traditionally we'd save a snippet to a file and include it in a template with the `{% render %}` tag.
554-
555-
```liquid
556-
{% render "some_snippet" %}
557-
```
558-
559-
With the `{% snippet %}` tag we can define blocks for reuse inside a single template, potentially reducing the number of snippet files we need.
560-
561-
```liquid
562-
{% snippet div %}
563-
<div>
564-
{{ content }}
565-
</div>
566-
{% endsnippet %}
567-
```
568-
569-
Defining a snippet does not render it. We use `{% render snippet_name %}` to render a snippet, where `snippet_name` is the name of your snippet without quotes (file-based snippet names must be quoted).
570-
571-
```liquid
572-
{% snippet div %}
573-
<div>
574-
{{ content }}
575-
</div>
576-
{% endsnippet %}
577-
578-
{% render div, content: "Some content" %}
579-
{% render div, content: "Other content" %}
580-
```
581-
582-
```html title="output"
583-
<div>Some content</div>
584-
585-
<div>Other content</div>
586-
```
587-
588-
Inline snippets share the same namespace as variables defined with `{% assign %}` and `{% capture %}`, so be wary of accidentally overwriting snippets with non-snippet data.
589-
590-
```liquid
591-
{% snippet foo %}Hello{% endsnippet %}
592-
{% foo = 42 %}
593-
{% render foo %} {% # error %}
594-
```
595-
596-
Snippets can be nested and follow the same scoping rules as file-based snippets.
597-
598-
```liquid
599-
{% snippet a %}
600-
b
601-
{% snippet c %}
602-
d
603-
{% endsnippet %}
604-
{% render c %}
605-
{% endsnippet %}
606-
607-
{% render a %}
608-
{% render c %} {% # error, c is out of scope %}
609-
```
610-
611-
Snippet blocks are bound to their names late. You can conditionally define multiple snippets with the same name and pick one at render time.
612-
613-
```liquid
614-
{% if x %}
615-
{% snippet a %}b{% endsnippet %}
616-
{% else %}
617-
{% snippet a %}c{% endsnippet %}
618-
{% endif %}
619-
{% render a %}
620-
```
621-
622543
## tablerow
623544

624545
```plain

liquid/builtin/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
from .tags import inline_comment_tag
9191
from .tags import liquid_tag
9292
from .tags import render_tag
93-
from .tags import snippet
9493
from .tags import tablerow_tag
9594
from .tags import unless_tag
9695

@@ -134,7 +133,6 @@ def register(env: Environment) -> None: # noqa: PLR0915
134133
env.add_tag(ifchanged_tag.IfChangedTag)
135134
env.add_tag(inline_comment_tag.InlineCommentTag)
136135
env.add_tag(doc_tag.DocTag)
137-
env.add_tag(snippet.SnippetTag)
138136

139137
env.add_filter("abs", abs_)
140138
env.add_filter("at_most", at_most)

liquid/builtin/tags/case_tag.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from liquid.ast import BlockNode
1212
from liquid.ast import Node
1313
from liquid.builtin.expressions import parse_primitive
14-
from liquid.builtin.expressions.logical import _eq
14+
from liquid.builtin.expressions.logical import _eq # type: ignore
1515
from liquid.exceptions import LiquidSyntaxError
1616
from liquid.expression import Expression
1717
from liquid.parser import get_parser
@@ -85,7 +85,7 @@ def render_to_output(self, context: RenderContext, buffer: TextIO) -> int:
8585
count += count_
8686
# Only render `else` blocks if all preceding `when` blocks are falsy.
8787
# Multiple `else` blocks are OK.
88-
elif isinstance(block, BlockNode) and default:
88+
elif default:
8989
count += block.render(context, buffer)
9090

9191
return count
@@ -106,7 +106,7 @@ async def render_to_output_async(
106106
count += count_
107107
# Only render `else` blocks if all preceding `when` blocks are falsy.
108108
# Multiple `else` blocks are OK.
109-
elif isinstance(block, BlockNode) and default:
109+
elif default:
110110
count += await block.render_async(context, buffer)
111111

112112
return count

liquid/builtin/tags/if_tag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def parse(self, stream: TokenStream) -> Node:
152152
condition = BooleanExpression.parse(self.env, tokens)
153153
parse_block = get_parser(self.env).parse_block
154154
consequence = parse_block(stream, ENDIFBLOCK)
155-
alternatives = []
155+
alternatives: list[ConditionalBlockNode] = []
156156

157157
while stream.current.is_tag(TAG_ELSIF):
158158
# If the expression can't be parsed, eat the "elsif" block and

liquid/extra/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .tags import CallTag
2222
from .tags import ExtendsTag
2323
from .tags import MacroTag
24+
from .tags import SnippetTag
2425
from .tags import TranslateTag
2526
from .tags import WithTag
2627

@@ -38,7 +39,6 @@
3839
"DateTime",
3940
"ExtendsTag",
4041
"GetText",
41-
"IfNotTag",
4242
"index",
4343
"JSON",
4444
"MacroTag",
@@ -49,6 +49,7 @@
4949
"script_tag",
5050
"sort_numeric",
5151
"stylesheet_tag",
52+
"SnippetTag",
5253
"Translate",
5354
"Unit",
5455
"WithTag",

liquid/extra/tags/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .extends_tag import ExtendsTag
44
from .macro_tag import CallTag
55
from .macro_tag import MacroTag
6+
from .snippet_tag import SnippetTag
67
from .translate_tag import TranslateTag
78

89
__all__ = (
@@ -11,5 +12,6 @@
1112
"ExtendsTag",
1213
"CallTag",
1314
"MacroTag",
15+
"SnippetTag",
1416
"TranslateTag",
1517
)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ nav:
5151
- Tag reference:
5252
- Default tags: "tag_reference.md"
5353
- Extra tags: "optional_tags.md"
54+
- Experimental tags: "experimental_tags.md"
5455
- Filter reference:
5556
- Default filters: "filter_reference.md"
5657
- Extra filters: "optional_filters.md"

0 commit comments

Comments
 (0)