From adcbc8bedb5ac32880d270c5fd8799da162e20f9 Mon Sep 17 00:00:00 2001 From: Prince Yadav Date: Tue, 11 Jun 2024 07:38:12 +0530 Subject: [PATCH] Fix handlebars path expressions starts with `@` (#16358) Co-authored-by: prince.yadav Co-authored-by: fisker --- changelog_unreleased/handlebars/16358.md | 13 ++++++++ src/language-handlebars/clean.js | 4 +++ src/language-handlebars/printer-glimmer.js | 32 +++++++++---------- .../visitor-keys.evaluate.js | 12 +------ .../__snapshots__/format.test.js.snap | 8 +++++ .../path-expressions/literal-expressions.hbs | 4 +++ tests/unit/__snapshots__/visitor-keys.js.snap | 7 +--- 7 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 changelog_unreleased/handlebars/16358.md diff --git a/changelog_unreleased/handlebars/16358.md b/changelog_unreleased/handlebars/16358.md new file mode 100644 index 000000000..39f91fd2c --- /dev/null +++ b/changelog_unreleased/handlebars/16358.md @@ -0,0 +1,13 @@ +#### Fix handlebars path expressions starts with `@` (#16358 by @Princeyadav05) + + +```hbs +{{! Input }} +
{{@x.y.z}}
+ +{{! Prettier stable }} +
{{@x}}
+ +{{! Prettier main }} +
{{@x.y.z}}
+``` diff --git a/src/language-handlebars/clean.js b/src/language-handlebars/clean.js index 04ac8aa60..cbf58e77f 100644 --- a/src/language-handlebars/clean.js +++ b/src/language-handlebars/clean.js @@ -32,6 +32,10 @@ function clean(original, cloned /*, parent*/) { if (original.type === "AttrNode" && original.name.toLowerCase() === "class") { delete cloned.value; } + + if (original.type === "PathExpression") { + cloned.head = original.head.original; + } } clean.ignoredProperties = new Set(["loc", "selfClosing"]); diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js index ff1fdb2eb..53a4f2b99 100644 --- a/src/language-handlebars/printer-glimmer.js +++ b/src/language-handlebars/printer-glimmer.js @@ -366,10 +366,7 @@ function print(path, options, print) { ]; } case "PathExpression": - return printPathExpression(node, print); - - case "AtHead": - return node.name; + return printPathExpression(node); case "BooleanLiteral": return String(node.value); @@ -389,6 +386,7 @@ function print(path, options, print) { case "NullLiteral": return "null"; + case "AtHead": // Handled in `printPathExpression` case "VarHead": // Handled in `printPathExpression` case "ThisHead": // Handled in `printPathExpression` default: @@ -784,21 +782,23 @@ const PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART = new Set([ "null", "undefined", ]); -const isPathExpressionPartNeedBrackets = (part, index) => - (index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) || - /\s/.test(part) || - /^\d/.test(part) || - Array.prototype.some.call(part, (character) => - PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character), - ); -function printPathExpression(node, print) { - if (node.head.type === "AtHead") { - return print("head"); +const isPathExpressionPartNeedBrackets = (part, index) => { + if (index === 0 && part.startsWith("@")) { + return false; } + return ( + (index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) || + /\s/.test(part) || + /^\d/.test(part) || + Array.prototype.some.call(part, (character) => + PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character), + ) + ); +}; +function printPathExpression(node) { + // check if node is a legacy path expression and leave it alone if (node.tail.length === 0 && node.original.includes("/")) { - // check if node has data, or - // check if node is a legacy path expression (and leave it alone) return node.original; } diff --git a/src/language-handlebars/visitor-keys.evaluate.js b/src/language-handlebars/visitor-keys.evaluate.js index 4d2df7bf0..0c86c8e91 100644 --- a/src/language-handlebars/visitor-keys.evaluate.js +++ b/src/language-handlebars/visitor-keys.evaluate.js @@ -1,11 +1 @@ -import { visitorKeys as glimmerVisitorKeys } from "@glimmer/syntax"; - -const visitorKeys = { - VarHead: [], - ThisHead: [], - AtHead: [], - ...glimmerVisitorKeys, - PathExpression: [...glimmerVisitorKeys.PathExpression, "head"], -}; - -export default visitorKeys; +export { visitorKeys as default } from "@glimmer/syntax"; diff --git a/tests/format/handlebars/path-expressions/__snapshots__/format.test.js.snap b/tests/format/handlebars/path-expressions/__snapshots__/format.test.js.snap index 1e2af028a..0efe291d4 100644 --- a/tests/format/handlebars/path-expressions/__snapshots__/format.test.js.snap +++ b/tests/format/handlebars/path-expressions/__snapshots__/format.test.js.snap @@ -42,6 +42,10 @@ printWidth: 80 {{array.2.[@#].[1]}} {{array.2.[a b]}} {{this.test}} + {{@x.y.z}} + {{@array.[true]}} + {{@array.2.[@#].[1]}} + {{@array.2.[a b]}} {{#if @foo}} {{/if}} @@ -54,6 +58,10 @@ printWidth: 80 {{array.[2].[@#].[1]}} {{array.[2].[a b]}} {{this.test}} + {{@x.y.z}} + {{@array.[true]}} + {{@array.[2].[@#].[1]}} + {{@array.[2].[a b]}} {{#if @foo}}{{/if}} {{foo/bar/baz ab=cd}} diff --git a/tests/format/handlebars/path-expressions/literal-expressions.hbs b/tests/format/handlebars/path-expressions/literal-expressions.hbs index ea2b3caec..9b665d207 100644 --- a/tests/format/handlebars/path-expressions/literal-expressions.hbs +++ b/tests/format/handlebars/path-expressions/literal-expressions.hbs @@ -3,6 +3,10 @@ {{array.2.[@#].[1]}} {{array.2.[a b]}} {{this.test}} + {{@x.y.z}} + {{@array.[true]}} + {{@array.2.[@#].[1]}} + {{@array.2.[a b]}} {{#if @foo}} {{/if}} diff --git a/tests/unit/__snapshots__/visitor-keys.js.snap b/tests/unit/__snapshots__/visitor-keys.js.snap index 5727c1a17..d783e8526 100644 --- a/tests/unit/__snapshots__/visitor-keys.js.snap +++ b/tests/unit/__snapshots__/visitor-keys.js.snap @@ -1165,7 +1165,6 @@ exports[`visitor keys estree-json 1`] = ` exports[`visitor keys glimmer 1`] = ` { - "AtHead": [], "AttrNode": [ "value", ], @@ -1209,9 +1208,7 @@ exports[`visitor keys glimmer 1`] = ` ], "NullLiteral": [], "NumberLiteral": [], - "PathExpression": [ - "head", - ], + "PathExpression": [], "StringLiteral": [], "SubExpression": [ "path", @@ -1222,9 +1219,7 @@ exports[`visitor keys glimmer 1`] = ` "body", ], "TextNode": [], - "ThisHead": [], "UndefinedLiteral": [], - "VarHead": [], } `;