diff --git a/src/language-handlebars/embed.js b/src/language-handlebars/embed.js
index 4d46e2cab..84ff0a185 100644
--- a/src/language-handlebars/embed.js
+++ b/src/language-handlebars/embed.js
@@ -1,4 +1,8 @@
-import { isPlainTextStyleOrScriptElement } from "./utilities.js";
+import { indent, replaceEndOfLine, softline } from "../document/index.js";
+import { replacePlaceholders } from "../language-js/embed/css.js";
+import { locEnd, locStart } from "./loc.js";
+import { printStartingTag } from "./print/tag.js";
+import { isPlainTextElement } from "./utilities.js";
function getAttribute(node, name) {
return node.attributes.find(
@@ -29,16 +33,61 @@ function getScriptTextToDocOptions(node) {
}
}
-function getStyleTextToDocOptions(node) {
- const langAttribute = getAttribute(node, "lang");
- if (!langAttribute || getTextValue(langAttribute) === "css") {
- return { parser: "css" };
+function isEmbedCss(node) {
+ if (node.type !== "ElementNode" || node.tag !== "style") {
+ return false;
}
+
+ const langAttribute = getAttribute(node, "lang");
+ return !langAttribute || getTextValue(langAttribute) === "css";
+}
+
+async function printEmbedCss(textToDoc, print, path, options) {
+ const { node } = path;
+
+ let text = "";
+ const mustacheDocs = [];
+ for (const child of node.children) {
+ if (child.type === "TextNode") {
+ text += child.chars;
+ continue;
+ }
+
+ text += `@prettier-placeholder-${mustacheDocs.length}-id`;
+ mustacheDocs.push(
+ replaceEndOfLine(
+ options.originalText.slice(locStart(child), locEnd(child)),
+ ),
+ );
+ }
+
+ if (!text.trim()) {
+ return [printStartingTag(path, options, print), ""];
+ }
+
+ const doc = await textToDoc(text, { parser: "css" });
+ const contentDoc = replacePlaceholders(doc, mustacheDocs);
+
+ /* c8 ignore next 3 */
+ if (!contentDoc) {
+ throw new Error("Couldn't insert all the mustaches");
+ }
+
+ return [
+ printStartingTag(path, options, print),
+ indent([softline, contentDoc]),
+ softline,
+ "",
+ ];
}
function embed(path /* , options*/) {
const { node } = path;
+ if (isEmbedCss(node)) {
+ return printEmbedCss;
+ }
+
if (node.type !== "TextNode") {
return;
}
@@ -46,15 +95,14 @@ function embed(path /* , options*/) {
const { parent } = path;
if (!(
- isPlainTextStyleOrScriptElement(parent) && parent.children[0] === node
+ isPlainTextElement(parent) &&
+ parent.tag === "script" &&
+ parent.children[0] === node
)) {
return;
}
- const textToDocOptions =
- parent.tag === "style"
- ? getStyleTextToDocOptions(parent)
- : getScriptTextToDocOptions(parent);
+ const textToDocOptions = getScriptTextToDocOptions(parent);
if (!textToDocOptions) {
return;
diff --git a/src/language-handlebars/massage-ast/index.js b/src/language-handlebars/massage-ast/index.js
index 226439819..232ba46d1 100644
--- a/src/language-handlebars/massage-ast/index.js
+++ b/src/language-handlebars/massage-ast/index.js
@@ -1,5 +1,5 @@
import htmlWhitespace from "../../utilities/html-whitespace.js";
-import { isPlainTextStyleOrScriptElement } from "../utilities.js";
+import { isPlainTextElement } from "../utilities.js";
function massageAstNode(original, cloned, parent) {
// (Glimmer/HTML) ignore TextNode
@@ -11,8 +11,10 @@ function massageAstNode(original, cloned, parent) {
// CSS/JS will be formatted
if (
- isPlainTextStyleOrScriptElement(parent) &&
- parent.children[0] === original
+ (parent.type === "ElementNode" && parent.tag === "style") ||
+ (isPlainTextElement(parent) &&
+ parent.tag === "script" &&
+ parent.children[0] === original)
) {
cloned.chars = "";
} else {
diff --git a/src/language-handlebars/print/tag.js b/src/language-handlebars/print/tag.js
new file mode 100644
index 000000000..63d86929f
--- /dev/null
+++ b/src/language-handlebars/print/tag.js
@@ -0,0 +1,58 @@
+import {
+ group,
+ ifBreak,
+ indent,
+ line,
+ softline,
+} from "../../document/index.js";
+import isNonEmptyArray from "../../utilities/is-non-empty-array.js";
+import { locStart } from "../loc.js";
+import { isVoidElement } from "../utilities.js";
+
+/* ElementNode print helpers */
+
+function sortByLoc(a, b) {
+ return locStart(a) - locStart(b);
+}
+
+function printStartingTag(path, options, print) {
+ const { node } = path;
+
+ const types = ["attributes", "modifiers", "comments"].filter((property) =>
+ isNonEmptyArray(node[property]),
+ );
+ const attributes = types.flatMap((type) => node[type]).sort(sortByLoc);
+
+ for (const attributeType of types) {
+ path.each(({ node }) => {
+ const index = attributes.indexOf(node);
+ attributes[index] = [line, print()];
+ }, attributeType);
+ }
+
+ if (isNonEmptyArray(node.blockParams)) {
+ attributes.push(line, printBlockParams(node));
+ }
+
+ return [
+ options.htmlWhitespaceSensitivity === "ignore" &&
+ path.previous?.type === "ElementNode"
+ ? softline
+ : "",
+ group(["<", node.tag, indent(attributes), printStartingTagEndMarker(node)]),
+ ];
+}
+
+function printStartingTagEndMarker(node) {
+ if (isVoidElement(node)) {
+ return ifBreak([softline, "/>"], [" />", softline]);
+ }
+
+ return ifBreak([softline, ">"], ">");
+}
+
+function printBlockParams(node) {
+ return ["as |", node.blockParams.join(" "), "|"];
+}
+
+export { printBlockParams, printStartingTag };
diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js
index f771f50ab..10f76f202 100644
--- a/src/language-handlebars/printer-glimmer.js
+++ b/src/language-handlebars/printer-glimmer.js
@@ -3,7 +3,6 @@ import {
fill,
group,
hardline,
- ifBreak,
indent,
join,
line,
@@ -18,6 +17,7 @@ import embed from "./embed.js";
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { massageAstNode } from "./massage-ast/index.js";
+import { printBlockParams, printStartingTag } from "./print/tag.js";
import {
hasPrettierIgnore,
isPlainTextStyleOrScriptElement,
@@ -48,12 +48,7 @@ function print(path, options, print) {
const isWhitespaceSensitive =
options.htmlWhitespaceSensitivity !== "ignore";
- const startingTag = [
- !isWhitespaceSensitive && path.previous?.type === "ElementNode"
- ? softline
- : "",
- group([printStartingTag(path, print)]),
- ];
+ const startingTag = printStartingTag(path, options, print);
if (isVoidElement(node)) {
return [startingTag];
@@ -424,42 +419,6 @@ function print(path, options, print) {
}
}
-/* ElementNode print helpers */
-
-function sortByLoc(a, b) {
- return locStart(a) - locStart(b);
-}
-
-function printStartingTag(path, print) {
- const { node } = path;
-
- const types = ["attributes", "modifiers", "comments"].filter((property) =>
- isNonEmptyArray(node[property]),
- );
- const attributes = types.flatMap((type) => node[type]).sort(sortByLoc);
-
- for (const attributeType of types) {
- path.each(({ node }) => {
- const index = attributes.indexOf(node);
- attributes[index] = [line, print()];
- }, attributeType);
- }
-
- if (isNonEmptyArray(node.blockParams)) {
- attributes.push(line, printBlockParams(node));
- }
-
- return ["<", node.tag, indent(attributes), printStartingTagEndMarker(node)];
-}
-
-function printStartingTagEndMarker(node) {
- if (isVoidElement(node)) {
- return ifBreak([softline, "/>"], [" />", softline]);
- }
-
- return ifBreak([softline, ">"], ">");
-}
-
/* MustacheStatement print helpers */
function printOpeningMustache(node) {
@@ -801,10 +760,6 @@ function printParams(path, print) {
return join(line, parts);
}
-function printBlockParams(node) {
- return ["as |", node.blockParams.join(" "), "|"];
-}
-
// https://handlebarsjs.com/guide/expressions.html#literal-segments
const PATH_EXPRESSION_FORBIDDEN_CHARACTERS = new Set(
"!\"#%&'()*+,./;<=>@[\\]^`{|}~",
diff --git a/src/language-handlebars/utilities.js b/src/language-handlebars/utilities.js
index c1eea8eba..67dd098fa 100644
--- a/src/language-handlebars/utilities.js
+++ b/src/language-handlebars/utilities.js
@@ -69,6 +69,7 @@ function hasPrettierIgnore(path) {
export {
hasPrettierIgnore,
+ isPlainTextElement,
isPlainTextStyleOrScriptElement,
isVoidElement,
isWhitespaceNode,
diff --git a/src/language-js/embed/css.js b/src/language-js/embed/css.js
index baaa60b51..ad81fa55d 100644
--- a/src/language-js/embed/css.js
+++ b/src/language-js/embed/css.js
@@ -171,4 +171,4 @@ const isEmbedCss = (path /* , options*/) =>
isCssProp(path) ||
isAngularComponentStyles(path);
-export { isEmbedCss, printEmbedCss };
+export { isEmbedCss, printEmbedCss, replacePlaceholders };
diff --git a/tests/format/handlebars/style-tag/__snapshots__/format.test.js.snap b/tests/format/handlebars/style-tag/__snapshots__/format.test.js.snap
index c9ec2a8cb..35a33b5d2 100644
--- a/tests/format/handlebars/style-tag/__snapshots__/format.test.js.snap
+++ b/tests/format/handlebars/style-tag/__snapshots__/format.test.js.snap
@@ -218,19 +218,113 @@ parsers: ["glimmer"]
-=====================================output=====================================
+
+
+
+
+
+
+
+
+
+
+
+=====================================output=====================================
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
================================================================================
`;
diff --git a/tests/format/handlebars/style-tag/with-mustache.hbs b/tests/format/handlebars/style-tag/with-mustache.hbs
index c8b9b8506..0972ba21b 100644
--- a/tests/format/handlebars/style-tag/with-mustache.hbs
+++ b/tests/format/handlebars/style-tag/with-mustache.hbs
@@ -10,3 +10,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+