Fix Angular ngNonBindable interpolation formatting (#20044)

Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
Максим Ивановandfisker authored and GitHub committed 2026-09-13 03:15:54 +08:00
1 parent c41be0bf9c
commit 0631073e47
11 files changed
+135 -1

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
#### Preserve interpolations inside elements with `ngNonBindable` directive (#20044 by @splincode)
<!-- prettier-ignore -->
```html
<!-- Input -->
<span ngNonBindable>{{foo+bar}}</span>
<!-- Prettier stable -->
<span ngNonBindable>{{ foo + bar }}</span>
<!-- Prettier main -->
<span ngNonBindable>{{foo+bar}}</span>
```
+5 -1
View File
@@ -23,6 +23,7 @@ import {
isScriptLikeTag,
isVueNonHtmlBlock,
} from "./utilities/index.js";
import { isInNgNonBindable } from "./utilities/is-in-ng-non-bindable.js";
import isVueSfcWithTypescriptScript from "./utilities/is-vue-sfc-with-typescript-script.js";
const embeddedAngularControlFlowBlocks = new Set([
@@ -109,7 +110,10 @@ function embed(path, options) {
];
};
}
} else if (node.parent.kind === "interpolation") {
} else if (
node.parent.kind === "interpolation" &&
!isInNgNonBindable(path, options)
) {
return async (textToDoc) => {
const textToDocOptions = {
__isInHtmlInterpolation: true, // to avoid unexpected `}}`
@@ -0,0 +1,29 @@
import { getOrInsertComputed } from "../../utilities/get-or-insert.js";
const angularNonBindableCache = new WeakMap();
function hasOrInNgNonBindable(node) {
return getOrInsertComputed(angularNonBindableCache, node, (node) => {
if (
node.kind === "element" &&
Object.hasOwn(node.attrMap, "ngNonBindable")
) {
return true;
}
if (!node.parent) {
return false;
}
return hasOrInNgNonBindable(node.parent);
});
}
function isInNgNonBindable(path, options) {
if (options.parser !== "angular") {
return false;
}
return hasOrInNgNonBindable(path.node.parent);
}
export { isInNgNonBindable };
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`ng-non-bindable.html format 1`] = `
====================================options=====================================
parsers: ["angular"]
printWidth: 80 (default) |
=====================================input======================================
<span ngNonBindable>{{foo +bar}}</span>
<div ngNonBindable>
{{foo +bar}}
<span>{{baz +qux}}</span>
</div>
<span>{{foo +bar}}</span>
<span ngNonBindable>
@if (A) {
<span>{{foo +bar}}</span>
}
</span>
=====================================output=====================================
<span ngNonBindable>{{foo +bar}}</span>
<div ngNonBindable>
{{foo +bar}}
<span>{{baz +qux}}</span>
</div>
<span>{{ foo + bar }}</span>
<span ngNonBindable>
@if (A) {
<span>{{foo +bar}}</span>
}
</span>
================================================================================
`;
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`ng-non-bindable.html - {"embeddedLanguageFormatting":"off"} format 1`] = `
====================================options=====================================
embeddedLanguageFormatting: "off"
parsers: ["angular"]
printWidth: 80 (default) |
=====================================input======================================
<span ngNonBindable>{{foo +bar}}</span>
=====================================output=====================================
<span ngNonBindable>{{foo +bar}}</span>
================================================================================
`;
@@ -0,0 +1 @@
runFormatTest(import.meta, ["angular"], { embeddedLanguageFormatting: "off" });
@@ -0,0 +1 @@
<span ngNonBindable>{{foo +bar}}</span>
@@ -0,0 +1 @@
runFormatTest(import.meta, ["angular"]);
@@ -0,0 +1,14 @@
<span ngNonBindable>{{foo +bar}}</span>
<div ngNonBindable>
{{foo +bar}}
<span>{{baz +qux}}</span>
</div>
<span>{{foo +bar}}</span>
<span ngNonBindable>
@if (A) {
<span>{{foo +bar}}</span>
}
</span>
@@ -75,6 +75,21 @@ parsers: ["vue"]
================================================================================
`;
exports[`ng-non-bindable.vue format 1`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80 (default) |
=====================================input======================================
<template><span ngNonBindable>{{foo +bar}}</span></template>
=====================================output=====================================
<template>
<span ngNonBindable>{{ foo + bar }}</span>
</template>
================================================================================
`;
exports[`parenthesized.vue format 1`] = `
====================================options=====================================
parsers: ["vue"]
@@ -0,0 +1 @@
<template><span ngNonBindable>{{foo +bar}}</span></template>