Preserve Angular control flow syntax in ngNonBindable directive (#20066)
Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
1 parent
1a15312010
commit
0292df6bf3
6 files changed
+240
-2
No files matched your search
@@ -0,0 +1,20 @@
|
|||||||
|
#### Preserve Angular syntax inside elements with `ngNonBindable` directive (#20066 by @splincode)
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```html
|
||||||
|
<!-- Input -->
|
||||||
|
<span ngNonBindable>@if(foo){bar}</span>
|
||||||
|
<span ngNonBindable>@let foo=bar+baz;</span>
|
||||||
|
|
||||||
|
<!-- Prettier stable -->
|
||||||
|
<span ngNonBindable>
|
||||||
|
@if (foo) {
|
||||||
|
bar
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
<span ngNonBindable>@let foo = bar + baz;</span>
|
||||||
|
|
||||||
|
<!-- Prettier main -->
|
||||||
|
<span ngNonBindable>@if(foo){bar}</span>
|
||||||
|
<span ngNonBindable>@let foo=bar+baz;</span>
|
||||||
|
```
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
} from "./utilities/index.js";
|
} from "./utilities/index.js";
|
||||||
|
|
||||||
const PREPROCESS_PIPELINE = [
|
const PREPROCESS_PIPELINE = [
|
||||||
|
convertAngularNonBindableNodesToText,
|
||||||
removeIgnorableFirstLf,
|
removeIgnorableFirstLf,
|
||||||
mergeIfConditionalStartEndCommentIntoElementOpeningTag,
|
mergeIfConditionalStartEndCommentIntoElementOpeningTag,
|
||||||
mergeCdataIntoText,
|
mergeCdataIntoText,
|
||||||
@@ -97,6 +98,88 @@ function mergeIfConditionalStartEndCommentIntoElementOpeningTag(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertAngularNonBindableNodesToText(ast, options) {
|
||||||
|
if (
|
||||||
|
options.parser !== "angular" ||
|
||||||
|
!options.originalText.includes("ngNonBindable")
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast.walk((node) => {
|
||||||
|
if (
|
||||||
|
node.kind === "element" &&
|
||||||
|
Object.hasOwn(node.attrMap, "ngNonBindable")
|
||||||
|
) {
|
||||||
|
convertAngularNonBindableChildren(node, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Avoid recursive call
|
||||||
|
function convertAngularNonBindableChildren(node, options) {
|
||||||
|
const { children } = node;
|
||||||
|
if (!children) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
const child = children[i];
|
||||||
|
|
||||||
|
if (child.kind === "angularControlFlowBlock") {
|
||||||
|
convertAngularNonBindableChildren(child, options);
|
||||||
|
|
||||||
|
const replacements = [];
|
||||||
|
let { start } = child.sourceSpan;
|
||||||
|
for (const blockChild of child.children) {
|
||||||
|
if (start.offset < blockChild.sourceSpan.start.offset) {
|
||||||
|
const sourceSpan = new ParseSourceSpan(
|
||||||
|
start,
|
||||||
|
blockChild.sourceSpan.start,
|
||||||
|
);
|
||||||
|
replacements.push(createOriginalTextNode(sourceSpan, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
replacements.push(blockChild);
|
||||||
|
start = blockChild.sourceSpan.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start.offset < child.sourceSpan.end.offset) {
|
||||||
|
const sourceSpan = new ParseSourceSpan(start, child.sourceSpan.end);
|
||||||
|
replacements.push(createOriginalTextNode(sourceSpan, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
children.splice(
|
||||||
|
i,
|
||||||
|
1,
|
||||||
|
...replacements.map((replacement) => node.createChild(replacement)),
|
||||||
|
);
|
||||||
|
i += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.kind === "angularLetDeclaration") {
|
||||||
|
children[i] = node.createChild(
|
||||||
|
createOriginalTextNode(child.sourceSpan, options),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertAngularNonBindableChildren(child, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createOriginalTextNode(sourceSpan, options) {
|
||||||
|
return {
|
||||||
|
kind: "text",
|
||||||
|
value: options.originalText.slice(
|
||||||
|
sourceSpan.start.offset,
|
||||||
|
sourceSpan.end.offset,
|
||||||
|
),
|
||||||
|
sourceSpan,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function mergeNodeIntoText(ast, shouldMerge, getValue) {
|
function mergeNodeIntoText(ast, shouldMerge, getValue) {
|
||||||
ast.walk((node) => {
|
ast.walk((node) => {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
|
|||||||
@@ -1,6 +1,62 @@
|
|||||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
exports[`ng-non-bindable.html format 1`] = `
|
exports[`control-flow.html format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["angular"]
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
<div ngNonBindable> @if ( foo ){ bar } </div>
|
||||||
|
<div ngNonBindable> _if ( foo )[ bar ] </div>
|
||||||
|
<span ngNonBindable> @if ( foo ){ bar } </span>
|
||||||
|
<span ngNonBindable> _if ( foo )[ bar ] </span>
|
||||||
|
<pre ngNonBindable> @if ( foo ){ bar } </pre>
|
||||||
|
<pre ngNonBindable> _if ( foo )[ bar ] </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> text @if ( foo ){ bar } text </div>
|
||||||
|
<span ngNonBindable> text @if ( foo ){ bar } text </span>
|
||||||
|
<pre ngNonBindable> text @if ( foo ){ bar } text </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> @if ( foo ){ <span>
|
||||||
|
<IMG
|
||||||
|
src="./foo.png" style=" color: red
|
||||||
|
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</span> } </div>
|
||||||
|
|
||||||
|
<div ngNonBindable> @if (foo ){<span>text
|
||||||
|
</span>} </div>
|
||||||
|
|
||||||
|
<div ngNonBindable> <div> @if ( foo ){ bar } </div></div>
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
<div ngNonBindable>@if ( foo ){ bar }</div>
|
||||||
|
<div ngNonBindable>_if ( foo )[ bar ]</div>
|
||||||
|
<span ngNonBindable> @if ( foo ){ bar } </span>
|
||||||
|
<span ngNonBindable> _if ( foo )[ bar ] </span>
|
||||||
|
<pre ngNonBindable> @if ( foo ){ bar } </pre>
|
||||||
|
<pre ngNonBindable> _if ( foo )[ bar ] </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable>text @if ( foo ){ bar } text</div>
|
||||||
|
<span ngNonBindable> text @if ( foo ){ bar } text </span>
|
||||||
|
<pre ngNonBindable> text @if ( foo ){ bar } text </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable>
|
||||||
|
@if ( foo ){
|
||||||
|
<span>
|
||||||
|
<IMG src="./foo.png" style="color: red" />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ngNonBindable>@if (foo ){<span>text </span>}</div>
|
||||||
|
|
||||||
|
<div ngNonBindable><div>@if ( foo ){ bar }</div></div>
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`interpolation.html format 1`] = `
|
||||||
====================================options=====================================
|
====================================options=====================================
|
||||||
parsers: ["angular"]
|
parsers: ["angular"]
|
||||||
printWidth: 80 (default) |
|
printWidth: 80 (default) |
|
||||||
@@ -20,6 +76,8 @@ parsers: ["angular"]
|
|||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<pre ngNonBindable>{{foo +bar}}</pre>
|
||||||
|
|
||||||
=====================================output=====================================
|
=====================================output=====================================
|
||||||
<span ngNonBindable>{{foo +bar}}</span>
|
<span ngNonBindable>{{foo +bar}}</span>
|
||||||
|
|
||||||
@@ -32,9 +90,48 @@ parsers: ["angular"]
|
|||||||
|
|
||||||
<span ngNonBindable>
|
<span ngNonBindable>
|
||||||
@if (A) {
|
@if (A) {
|
||||||
<span>{{foo +bar}}</span>
|
<span>{{foo +bar}}</span>
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<pre ngNonBindable>{{foo +bar}}</pre>
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`let-declaration.html format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["angular"]
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
<div ngNonBindable> @let foo = bar+baz; </div>
|
||||||
|
<div ngNonBindable> _let foo = bar+baz; </div>
|
||||||
|
<span ngNonBindable> @let foo = bar+baz; </span>
|
||||||
|
<span ngNonBindable> _let foo = bar+baz; </span>
|
||||||
|
<pre ngNonBindable> @let foo = bar+baz; </pre>
|
||||||
|
<pre ngNonBindable> _let foo = bar+baz; </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> text @let foo = bar+baz; text </div>
|
||||||
|
<span ngNonBindable> text @let foo = bar+baz; text </span>
|
||||||
|
<pre ngNonBindable> text @let foo = bar+baz; text </pre>
|
||||||
|
|
||||||
|
<span ngNonBindable>@if(foo){bar}</span>
|
||||||
|
<div ngNonBindable> <div> @let foo = bar+baz; </div></div>
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
<div ngNonBindable>@let foo = bar+baz;</div>
|
||||||
|
<div ngNonBindable>_let foo = bar+baz;</div>
|
||||||
|
<span ngNonBindable> @let foo = bar+baz; </span>
|
||||||
|
<span ngNonBindable> _let foo = bar+baz; </span>
|
||||||
|
<pre ngNonBindable> @let foo = bar+baz; </pre>
|
||||||
|
<pre ngNonBindable> _let foo = bar+baz; </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable>text @let foo = bar+baz; text</div>
|
||||||
|
<span ngNonBindable> text @let foo = bar+baz; text </span>
|
||||||
|
<pre ngNonBindable> text @let foo = bar+baz; text </pre>
|
||||||
|
|
||||||
|
<span ngNonBindable>@if(foo){bar}</span>
|
||||||
|
<div ngNonBindable><div>@let foo = bar+baz;</div></div>
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
`;
|
`;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<div ngNonBindable> @if ( foo ){ bar } </div>
|
||||||
|
<div ngNonBindable> _if ( foo )[ bar ] </div>
|
||||||
|
<span ngNonBindable> @if ( foo ){ bar } </span>
|
||||||
|
<span ngNonBindable> _if ( foo )[ bar ] </span>
|
||||||
|
<pre ngNonBindable> @if ( foo ){ bar } </pre>
|
||||||
|
<pre ngNonBindable> _if ( foo )[ bar ] </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> text @if ( foo ){ bar } text </div>
|
||||||
|
<span ngNonBindable> text @if ( foo ){ bar } text </span>
|
||||||
|
<pre ngNonBindable> text @if ( foo ){ bar } text </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> @if ( foo ){ <span>
|
||||||
|
<IMG
|
||||||
|
src="./foo.png" style=" color: red
|
||||||
|
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</span> } </div>
|
||||||
|
|
||||||
|
<div ngNonBindable> @if (foo ){<span>text
|
||||||
|
</span>} </div>
|
||||||
|
|
||||||
|
<div ngNonBindable> <div> @if ( foo ){ bar } </div></div>
|
||||||
+2
@@ -12,3 +12,5 @@
|
|||||||
<span>{{foo +bar}}</span>
|
<span>{{foo +bar}}</span>
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<pre ngNonBindable>{{foo +bar}}</pre>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<div ngNonBindable> @let foo = bar+baz; </div>
|
||||||
|
<div ngNonBindable> _let foo = bar+baz; </div>
|
||||||
|
<span ngNonBindable> @let foo = bar+baz; </span>
|
||||||
|
<span ngNonBindable> _let foo = bar+baz; </span>
|
||||||
|
<pre ngNonBindable> @let foo = bar+baz; </pre>
|
||||||
|
<pre ngNonBindable> _let foo = bar+baz; </pre>
|
||||||
|
|
||||||
|
<div ngNonBindable> text @let foo = bar+baz; text </div>
|
||||||
|
<span ngNonBindable> text @let foo = bar+baz; text </span>
|
||||||
|
<pre ngNonBindable> text @let foo = bar+baz; text </pre>
|
||||||
|
|
||||||
|
<span ngNonBindable>@if(foo){bar}</span>
|
||||||
|
<div ngNonBindable> <div> @let foo = bar+baz; </div></div>
|
||||||
Reference in new issue
Block a user