diff --git a/src/language-html/clean.js b/src/language-html/clean.js
index c095b4290..c12531dde 100644
--- a/src/language-html/clean.js
+++ b/src/language-html/clean.js
@@ -38,8 +38,8 @@ function clean(ast, newNode) {
delete newNode.value;
}
- if (ast.type === "block") {
- for (const parameter of newNode.parameters) {
+ if (ast.type === "angularControlFlowBlock" && newNode.parameters?.children) {
+ for (const parameter of newNode.parameters.children) {
if (embeddedAngularControlFlowBlocks.has(ast.name)) {
delete parameter.expression;
} else {
diff --git a/src/language-html/embed.js b/src/language-html/embed.js
index 42e5d1947..8118aae2f 100644
--- a/src/language-html/embed.js
+++ b/src/language-html/embed.js
@@ -145,12 +145,8 @@ function embed(path, options) {
case "front-matter":
return (textToDoc) => printFrontMatter(node, textToDoc);
- // TODO: This should work on `blockParameter`, but currently we don't have a parser for it.
- case "block":
- if (
- !embeddedAngularControlFlowBlocks.has(node.name) ||
- node.parameters.length === 0
- ) {
+ case "angularControlFlowBlockParameters":
+ if (!embeddedAngularControlFlowBlocks.has(path.parent.name)) {
return;
}
diff --git a/src/language-html/embed/angular-control-flow-block-parameters.js b/src/language-html/embed/angular-control-flow-block-parameters.js
index 821944648..46750cd5d 100644
--- a/src/language-html/embed/angular-control-flow-block-parameters.js
+++ b/src/language-html/embed/angular-control-flow-block-parameters.js
@@ -1,16 +1,25 @@
import { formatAttributeValue, shouldHugJsExpression } from "./utils.js";
-async function printAngularControlFlowBlockParameters(
+function printAngularControlFlowBlockParameters(
textToDoc,
print,
path,
- /* options,*/
+ options,
) {
const { node } = path;
- const code = node.parameters.map(({ expression }) => expression).join("; ");
- const doc = await formatAttributeValue(
- code,
+ const content = options.originalText.slice(
+ node.sourceSpan.start.offset,
+ node.sourceSpan.end.offset,
+ );
+ const isEmpty = /^\s*$/.test(content);
+
+ if (isEmpty) {
+ return "";
+ }
+
+ return formatAttributeValue(
+ content,
textToDoc,
{
parser: "__ng_directive",
@@ -19,9 +28,6 @@ async function printAngularControlFlowBlockParameters(
},
shouldHugJsExpression,
);
-
- // We have to put the doc on the node, since `node.parameters` is not a valid "node"
- node.__embed_parameters_doc = doc;
}
export default printAngularControlFlowBlockParameters;
diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js
index fdfb0214d..96e75556a 100644
--- a/src/language-html/parser-html.js
+++ b/src/language-html/parser-html.js
@@ -11,6 +11,7 @@ import {
import parseFrontMatter from "../utils/front-matter/parse.js";
import inferParser from "../utils/infer-parser.js";
import createError from "../common/parser-create-error.js";
+import isNonEmptyArray from "../utils/is-non-empty-array.js";
import HTML_TAGS from "./utils/html-tag-names.evaluate.js";
import HTML_ELEMENT_ATTRIBUTES from "./utils/html-elements-attributes.evaluate.js";
import isUnknownNamespace from "./utils/is-unknown-namespace.js";
@@ -39,10 +40,31 @@ import { locStart, locEnd } from "./loc.js";
*/
// `@else if`
-function normalizeAngularControlFlowBlockName(node) {
- if (node.type === "block") {
- node.name = node.name.toLowerCase().replaceAll(/\s+/g, " ").trim();
+function normalizeAngularControlFlowBlock(node) {
+ if (node.type !== "block") {
+ return;
}
+
+ node.name = node.name.toLowerCase().replaceAll(/\s+/g, " ").trim();
+ node.type = "angularControlFlowBlock";
+
+ if (!isNonEmptyArray(node.parameters)) {
+ delete node.parameters;
+ return;
+ }
+
+ for (const parameter of node.parameters) {
+ parameter.type = "angularControlFlowBlockParameter";
+ }
+
+ node.parameters = {
+ type: "angularControlFlowBlockParameters",
+ children: node.parameters,
+ sourceSpan: new ParseSourceSpan(
+ node.parameters[0].sourceSpan.start,
+ node.parameters.at(-1).sourceSpan.end,
+ ),
+ };
}
/**
@@ -244,7 +266,6 @@ function ngHtmlParser(input, parseOptions, options) {
addTagDefinition(node);
normalizeName(node);
fixSourceSpan(node);
- normalizeAngularControlFlowBlockName(node);
}
})(),
rootNodes,
@@ -351,6 +372,8 @@ function parse(
node.parent.replaceChild(node, ieConditionalComment);
}
}
+
+ normalizeAngularControlFlowBlock(node);
});
return ast;
diff --git a/src/language-html/print/angular-control-flow-block.js b/src/language-html/print/angular-control-flow-block.js
index 61729603f..69257c714 100644
--- a/src/language-html/print/angular-control-flow-block.js
+++ b/src/language-html/print/angular-control-flow-block.js
@@ -29,15 +29,8 @@ function printAngularControlFlowBlock(path, options, print) {
docs.push("@", node.name);
- if (node.parameters.length > 0) {
- const parametersDoc = group(
- node.__embed_parameters_doc ?? [
- indent([softline, join([";", line], path.map(print, "parameters"))]),
- softline,
- ],
- );
-
- docs.push(" (", parametersDoc, ")");
+ if (node.parameters) {
+ docs.push(" (", group(print("parameters")), ")");
}
docs.push(" {");
@@ -67,7 +60,7 @@ function printAngularControlFlowBlock(path, options, print) {
function shouldCloseBlock(node, names) {
return !(
names.size > 0 &&
- node.next?.type === "block" &&
+ node.next?.type === "angularControlFlowBlock" &&
names.has(node.next.name)
);
}
@@ -78,10 +71,17 @@ function findPreviousBlock(path) {
for (let i = index - 1; i >= 0; i--) {
const sibling = siblings[i];
- if (sibling.type === "block") {
+ if (sibling.type === "angularControlFlowBlock") {
return sibling;
}
}
}
-export { printAngularControlFlowBlock };
+function printAngularControlFlowBlockParameters(path, options, print) {
+ return [
+ indent([softline, join([";", line], path.map(print, "children"))]),
+ softline,
+ ];
+}
+
+export { printAngularControlFlowBlock, printAngularControlFlowBlockParameters };
diff --git a/src/language-html/print/tag.js b/src/language-html/print/tag.js
index 86f5a53c8..db77aaedf 100644
--- a/src/language-html/print/tag.js
+++ b/src/language-html/print/tag.js
@@ -128,7 +128,7 @@ function needsToBorrowPrevClosingTagEndMarker(node) {
return (
node.prev &&
node.prev.type !== "docType" &&
- node.type !== "block" &&
+ node.type !== "angularControlFlowBlock" &&
!isTextLikeNode(node.prev) &&
node.isLeadingSpaceSensitive &&
!node.hasLeadingSpaces
diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js
index ee2f5c8a1..1adabfdc0 100644
--- a/src/language-html/printer-html.js
+++ b/src/language-html/printer-html.js
@@ -21,7 +21,10 @@ import {
} from "./print/tag.js";
import { printElement } from "./print/element.js";
import { printChildren } from "./print/children.js";
-import { printAngularControlFlowBlock } from "./print/angular-control-flow-block.js";
+import {
+ printAngularControlFlowBlock,
+ printAngularControlFlowBlockParameters,
+} from "./print/angular-control-flow-block.js";
import getVisitorKeys from "./get-visitor-keys.js";
function genericPrint(path, options, print) {
@@ -39,9 +42,11 @@ function genericPrint(path, options, print) {
case "ieConditionalComment":
return printElement(path, options, print);
- case "block":
+ case "angularControlFlowBlock":
return printAngularControlFlowBlock(path, options, print);
- case "blockParameter":
+ case "angularControlFlowBlockParameters":
+ return printAngularControlFlowBlockParameters(path, options, print);
+ case "angularControlFlowBlockParameter":
return htmlWhitespaceUtils.trim(node.expression);
case "ieConditionalStartComment":
diff --git a/src/language-html/visitor-keys.js b/src/language-html/visitor-keys.js
index 9fef1bb20..1952fcf5e 100644
--- a/src/language-html/visitor-keys.js
+++ b/src/language-html/visitor-keys.js
@@ -11,8 +11,9 @@ const visitorKeys = {
comment: [],
attribute: [],
cdata: [],
- block: ["children", "parameters"],
- blockParameter: [],
+ angularControlFlowBlock: ["children", "parameters"],
+ angularControlFlowBlockParameters: ["children"],
+ angularControlFlowBlockParameter: [],
};
export default visitorKeys;
diff --git a/tests/unit/__snapshots__/visitor-keys.js.snap b/tests/unit/__snapshots__/visitor-keys.js.snap
index ea17e7219..5b759cf2f 100644
--- a/tests/unit/__snapshots__/visitor-keys.js.snap
+++ b/tests/unit/__snapshots__/visitor-keys.js.snap
@@ -1389,12 +1389,15 @@ exports[`visitor keys graphql 1`] = `
exports[`visitor keys html 1`] = `
{
- "attribute": [],
- "block": [
+ "angularControlFlowBlock": [
"children",
"parameters",
],
- "blockParameter": [],
+ "angularControlFlowBlockParameter": [],
+ "angularControlFlowBlockParameters": [
+ "children",
+ ],
+ "attribute": [],
"cdata": [],
"comment": [],
"docType": [],