Correct text identification in liquid syntax (#19489)

Co-authored-by: fisker <lionkay@gmail.com>
fix #19488: check corresponding closing token in liquid syntax
fix #19488
This commit is contained in:
Seiya authored and GitHub committed 2026-06-29 19:10:31 +08:00
1 parent 269eee3faa
commit bd9e11ab41
5 files changed
+265 -47

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
#### Fix unexpected removal of characters in liquid syntax (#19489 by @seiyab)
<!-- prettier-ignore -->
```md
// Input
<!-- Input -->
{{ page.title
}} text
<!-- Prettier stable -->
{{ page.title
text
<!-- Prettier main -->
{{ page.title
}} text
```
@@ -33,10 +33,10 @@ function liquidFromMarkdown() {
/** @type {Handle} */
function exit(token) {
const d = this.resume();
this.resume();
/** @type {any} */
const node = this.stack.at(-1);
node.value = d;
node.value = this.sliceSerialize(token);
this.exit(token);
}
}
@@ -55,6 +55,9 @@ function liquidSyntax() {
};
function tokenize(effects, ok, nok) {
/** @type {typeof codes.rightCurlyBrace | typeof codes.percentSign} */
let closingCode;
return start;
/** @type {State} */
@@ -66,6 +69,10 @@ function liquidSyntax() {
switch (code) {
case codes.percentSign:
case codes.leftCurlyBrace:
closingCode =
code === codes.percentSign
? codes.percentSign
: codes.rightCurlyBrace;
effects.consume(code);
return inside;
default:
@@ -77,9 +84,9 @@ function liquidSyntax() {
/** @type {State} */
function inside(code) {
switch (code) {
case codes.percentSign:
case codes.rightCurlyBrace:
return effects.check({ tokenize: tokenizeClose }, close, data)(code);
case closingCode:
effects.consume(code);
return mayClose;
case codes.eof:
return nok(code);
default:
@@ -91,53 +98,21 @@ function liquidSyntax() {
effects.enter(types.data);
return inside;
}
return data(code);
effects.consume(code);
return inside;
}
}
/** @type {State} */
function data(code) {
effects.consume(code);
return inside;
}
function tokenizeClose(effects, ok, nok) {
return startClose;
/** @type {State} */
function startClose(code) {
switch (code) {
case codes.percentSign:
case codes.rightCurlyBrace:
effects.consume(code);
return endClose;
default:
return nok(code);
}
}
/** @type {State} */
function endClose(code) {
if (code !== codes.rightCurlyBrace) {
return nok(code);
}
function mayClose(code) {
if (code === codes.rightCurlyBrace) {
effects.consume(code);
effects.exit(types.data);
effects.exit(nodeType);
return ok;
}
}
/** @type {State} */
function close(code) {
effects.consume(code);
return closeEnd;
}
/** @type {State} */
function closeEnd(code) {
effects.consume(code);
effects.exit(types.data);
effects.exit(nodeType);
return ok;
return inside;
}
}
}
@@ -1,5 +1,63 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`character-after-closing-tokens.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
proseWrap: "always"
printWidth: 80 (default) |
=====================================input======================================
{{ page.title
}} a
---
{%
if user
%} Hello, {{ user }}!
{% endif %}
=====================================output=====================================
{{ page.title
}} a
---
{%
if user
%} Hello, {{ user }}! {% endif %}
================================================================================
`;
exports[`character-after-closing-tokens.md format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80 (default) |
=====================================input======================================
{{ page.title
}} a
---
{%
if user
%} Hello, {{ user }}!
{% endif %}
=====================================output=====================================
{{ page.title
}} a
---
{%
if user
%} Hello, {{ user }}!
{% endif %}
================================================================================
`;
exports[`example-1.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -216,6 +274,138 @@ parsers: ["markdown"]
================================================================================
`;
exports[`issue-19488.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
proseWrap: "always"
printWidth: 80 (default) |
=====================================input======================================
{{% blocks/cover
title="Welcome"
%}}
This input uses Hugo shortcode. Prettier doesn't support this explicitly but it shouldn't break it either.
{{% /blocks/cover %}}
---
{{% blocks/cover
%}}
{{% blocks/cover
%%}}
{{% blocks/cover
}}}
{{{% blocks/cover
%}}
{% blocks/cover
%}}
{{ blocks/cover
%}}
=====================================output=====================================
{{% blocks/cover
title="Welcome"
%}}
This input uses Hugo shortcode. Prettier doesn't support this explicitly but it
shouldn't break it either.
{{% /blocks/cover %}}
---
{{% blocks/cover
%}}
{{% blocks/cover
%%}}
{{% blocks/cover
}}}
{{{% blocks/cover
%}}
{% blocks/cover
%}}
{{ blocks/cover
%}}
================================================================================
`;
exports[`issue-19488.md format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80 (default) |
=====================================input======================================
{{% blocks/cover
title="Welcome"
%}}
This input uses Hugo shortcode. Prettier doesn't support this explicitly but it shouldn't break it either.
{{% /blocks/cover %}}
---
{{% blocks/cover
%}}
{{% blocks/cover
%%}}
{{% blocks/cover
}}}
{{{% blocks/cover
%}}
{% blocks/cover
%}}
{{ blocks/cover
%}}
=====================================output=====================================
{{% blocks/cover
title="Welcome"
%}}
This input uses Hugo shortcode. Prettier doesn't support this explicitly but it shouldn't break it either.
{{% /blocks/cover %}}
---
{{% blocks/cover
%}}
{{% blocks/cover
%%}}
{{% blocks/cover
}}}
{{{% blocks/cover
%}}
{% blocks/cover
%}}
{{ blocks/cover
%}}
================================================================================
`;
exports[`unbalanced-mismatched-braces.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -226,8 +416,8 @@ proseWrap: "always"
Braces {% doesn't match so these words should not be considered as *liquid node* }}
=====================================output=====================================
Braces
{% doesn't match so these words should not be considered as *liquid node* }}
Braces {% doesn't match so these words should not be considered as _liquid node_
}}
================================================================================
`;
@@ -241,7 +431,7 @@ parsers: ["markdown"]
Braces {% doesn't match so these words should not be considered as *liquid node* }}
=====================================output=====================================
Braces {% doesn't match so these words should not be considered as *liquid node* }}
Braces {% doesn't match so these words should not be considered as _liquid node_ }}
================================================================================
`;
@@ -0,0 +1,9 @@
{{ page.title
}} a
---
{%
if user
%} Hello, {{ user }}!
{% endif %}
@@ -0,0 +1,27 @@
{{% blocks/cover
title="Welcome"
%}}
This input uses Hugo shortcode. Prettier doesn't support this explicitly but it shouldn't break it either.
{{% /blocks/cover %}}
---
{{% blocks/cover
%}}
{{% blocks/cover
%%}}
{{% blocks/cover
}}}
{{{% blocks/cover
%}}
{% blocks/cover
%}}
{{ blocks/cover
%}}