Fix embedded template literal idempotency (#19725)
This commit is contained in:
1 parent
103c2e8118
commit
b923138612
13 files changed
+413
-21
No files matched your search
@@ -0,0 +1,38 @@
|
|||||||
|
#### Fix embedded template literal idempotency (#19725 by @fisker)
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```jsx
|
||||||
|
// Input
|
||||||
|
const foo = html`
|
||||||
|
<div>${getText({
|
||||||
|
value,
|
||||||
|
})}</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Prettier stable (first format)
|
||||||
|
const foo = html`
|
||||||
|
<div>
|
||||||
|
${getText({
|
||||||
|
value,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Prettier stable (second format)
|
||||||
|
const foo = html`
|
||||||
|
<div>
|
||||||
|
${getText({
|
||||||
|
value,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Prettier main
|
||||||
|
const foo = html`
|
||||||
|
<div>
|
||||||
|
${getText({
|
||||||
|
value,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
```
|
||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
softline,
|
softline,
|
||||||
} from "../../document/index.js";
|
} from "../../document/index.js";
|
||||||
import isNonEmptyArray from "../../utilities/is-non-empty-array.js";
|
import isNonEmptyArray from "../../utilities/is-non-empty-array.js";
|
||||||
import { printTemplateExpressions } from "../print/template-literal.js";
|
import { printEmbeddedTemplateExpressions } from "../print/template-literal.js";
|
||||||
import { isNodeMatches } from "../utilities/is-node-matches.js";
|
import { isNodeMatches } from "../utilities/is-node-matches.js";
|
||||||
import { isAngularComponentStyles } from "./utilities.js";
|
import { isAngularComponentStyles } from "./utilities.js";
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ async function printEmbedCss(textToDoc, print, path, options) {
|
|||||||
text += raw;
|
text += raw;
|
||||||
}
|
}
|
||||||
const quasisDoc = await textToDoc(text, { parser: "scss" });
|
const quasisDoc = await textToDoc(text, { parser: "scss" });
|
||||||
const expressionDocs = printTemplateExpressions(path, options, print);
|
const expressionDocs = printEmbeddedTemplateExpressions(path, options, print);
|
||||||
const newDoc = replacePlaceholders(quasisDoc, expressionDocs);
|
const newDoc = replacePlaceholders(quasisDoc, expressionDocs);
|
||||||
/* c8 ignore next 3 */
|
/* c8 ignore next 3 */
|
||||||
if (!newDoc) {
|
if (!newDoc) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { hardline, indent, join } from "../../document/index.js";
|
import { hardline, indent, join } from "../../document/index.js";
|
||||||
import {
|
import {
|
||||||
escapeTemplateCharacters,
|
escapeTemplateCharacters,
|
||||||
printTemplateExpressions,
|
printEmbeddedTemplateExpressions,
|
||||||
} from "../print/template-literal.js";
|
} from "../print/template-literal.js";
|
||||||
import { hasLanguageComment } from "./utilities.js";
|
import { hasLanguageComment } from "./utilities.js";
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ async function printEmbedGraphQL(textToDoc, print, path, options) {
|
|||||||
|
|
||||||
const numQuasis = node.quasis.length;
|
const numQuasis = node.quasis.length;
|
||||||
|
|
||||||
const expressionDocs = printTemplateExpressions(path, options, print);
|
const expressionDocs = printEmbeddedTemplateExpressions(path, options, print);
|
||||||
const parts = [];
|
const parts = [];
|
||||||
|
|
||||||
for (let i = 0; i < numQuasis; i++) {
|
for (let i = 0; i < numQuasis; i++) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
mapDoc,
|
mapDoc,
|
||||||
} from "../../document/index.js";
|
} from "../../document/index.js";
|
||||||
import {
|
import {
|
||||||
printTemplateExpressions,
|
printEmbeddedTemplateExpressions,
|
||||||
uncookTemplateElementValue,
|
uncookTemplateElementValue,
|
||||||
} from "../print/template-literal.js";
|
} from "../print/template-literal.js";
|
||||||
import { hasLanguageComment, isAngularComponentTemplate } from "./utilities.js";
|
import { hasLanguageComment, isAngularComponentTemplate } from "./utilities.js";
|
||||||
@@ -30,7 +30,7 @@ async function printEmbedHtmlLike(parser, textToDoc, print, path, options) {
|
|||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
const expressionDocs = printTemplateExpressions(path, options, print);
|
const expressionDocs = printEmbeddedTemplateExpressions(path, options, print);
|
||||||
|
|
||||||
const placeholderRegex = new RegExp(
|
const placeholderRegex = new RegExp(
|
||||||
composePlaceholder(String.raw`(\d+)`),
|
composePlaceholder(String.raw`(\d+)`),
|
||||||
|
|||||||
@@ -203,7 +203,12 @@ function getTemplateLiteralExpressionIndent(path, options) {
|
|||||||
- `TemplateLiteral`
|
- `TemplateLiteral`
|
||||||
- `TSTemplateLiteralType` (TypeScript)
|
- `TSTemplateLiteralType` (TypeScript)
|
||||||
*/
|
*/
|
||||||
function printTemplateExpression(path, options, print) {
|
function printTemplateExpression(
|
||||||
|
path,
|
||||||
|
options,
|
||||||
|
print,
|
||||||
|
shouldPreserveIndentation = true,
|
||||||
|
) {
|
||||||
const { node, index } = path;
|
const { node, index } = path;
|
||||||
let expressionDoc = print();
|
let expressionDoc = print();
|
||||||
|
|
||||||
@@ -249,6 +254,11 @@ function printTemplateExpression(path, options, print) {
|
|||||||
expressionDoc = [indent([softline, expressionDoc]), softline];
|
expressionDoc = [indent([softline, expressionDoc]), softline];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is no way to know how the quasis will be printed
|
||||||
|
if (!shouldPreserveIndentation) {
|
||||||
|
return group(["${", expressionDoc, lineSuffixBoundary, "}"]);
|
||||||
|
}
|
||||||
|
|
||||||
// For a template literal of the following form:
|
// For a template literal of the following form:
|
||||||
// `someQuery {
|
// `someQuery {
|
||||||
// ${call({
|
// ${call({
|
||||||
@@ -283,6 +293,19 @@ function printTemplateExpressions(path, options, print) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function printEmbeddedTemplateExpressions(path, options, print) {
|
||||||
|
return path.map(
|
||||||
|
() =>
|
||||||
|
printTemplateExpression(
|
||||||
|
path,
|
||||||
|
options,
|
||||||
|
print,
|
||||||
|
/* shouldPreserveIndentation */ false,
|
||||||
|
),
|
||||||
|
"expressions",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function escapeTemplateCharacters(doc, raw) {
|
function escapeTemplateCharacters(doc, raw) {
|
||||||
return mapDoc(doc, (currentDoc) => {
|
return mapDoc(doc, (currentDoc) => {
|
||||||
if (typeof currentDoc === "string") {
|
if (typeof currentDoc === "string") {
|
||||||
@@ -331,8 +354,8 @@ function isJestEachTemplateLiteral({ node, parent }) {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
escapeTemplateCharacters,
|
escapeTemplateCharacters,
|
||||||
|
printEmbeddedTemplateExpressions,
|
||||||
printTaggedTemplateExpression,
|
printTaggedTemplateExpression,
|
||||||
printTemplateExpressions,
|
|
||||||
printTemplateLiteral,
|
printTemplateLiteral,
|
||||||
uncookTemplateElementValue,
|
uncookTemplateElementValue,
|
||||||
};
|
};
|
||||||
@@ -25,8 +25,6 @@ const unstableTests = new Map(
|
|||||||
"typescript/satisfies-operators/comments-unstable.ts",
|
"typescript/satisfies-operators/comments-unstable.ts",
|
||||||
"jsx/comments/in-attributes.js",
|
"jsx/comments/in-attributes.js",
|
||||||
"typescript/import-type/long-module-name/long-module-name4.ts",
|
"typescript/import-type/long-module-name/long-module-name4.ts",
|
||||||
// Unstable due to lack of indent information
|
|
||||||
"js/multiparser-comments/comment-inside.js",
|
|
||||||
[
|
[
|
||||||
"typescript/method-chain/object/issue-17239.ts",
|
"typescript/method-chain/object/issue-17239.ts",
|
||||||
(options) => options.objectWrap !== "collapse",
|
(options) => options.objectWrap !== "collapse",
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
const t = html`
|
||||||
|
<ol>
|
||||||
|
${items.map(
|
||||||
|
(entry) => html`
|
||||||
|
<li>
|
||||||
|
${entry.children
|
||||||
|
? html`
|
||||||
|
<ol>
|
||||||
|
${entry.children.map(
|
||||||
|
(child) => html`<li>${child.title}</li>`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
`
|
||||||
|
: entry.title}
|
||||||
|
</li>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function foo() {
|
||||||
|
return html`
|
||||||
|
<div>
|
||||||
|
<pre>${JSON.stringify({
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
})}</pre>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = html`
|
||||||
|
${{
|
||||||
|
c: y,
|
||||||
|
}}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
|
exports[`19518.js format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["babel", "flow", "typescript"]
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
const t = html\`
|
||||||
|
<ol>
|
||||||
|
\${items.map(
|
||||||
|
(entry) => html\`
|
||||||
|
<li>
|
||||||
|
\${entry.children
|
||||||
|
? html\`
|
||||||
|
<ol>
|
||||||
|
\${entry.children.map(
|
||||||
|
(child) => html\`<li>\${child.title}</li>\`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
\`
|
||||||
|
: entry.title}
|
||||||
|
</li>
|
||||||
|
\`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
\`;
|
||||||
|
|
||||||
|
export function foo() {
|
||||||
|
return html\`
|
||||||
|
<div>
|
||||||
|
<pre>\${JSON.stringify({
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
})}</pre>
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = html\`
|
||||||
|
\${{
|
||||||
|
c: y,
|
||||||
|
}}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
const t = html\`
|
||||||
|
<ol>
|
||||||
|
\${items.map(
|
||||||
|
(entry) => html\`
|
||||||
|
<li>
|
||||||
|
\${
|
||||||
|
entry.children
|
||||||
|
? html\`
|
||||||
|
<ol>
|
||||||
|
\${entry.children.map(
|
||||||
|
(child) => html\`<li>\${child.title}</li>\`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
\`
|
||||||
|
: entry.title
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
\`,
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
\`;
|
||||||
|
|
||||||
|
export function foo() {
|
||||||
|
return html\`
|
||||||
|
<div>
|
||||||
|
<pre>
|
||||||
|
\${JSON.stringify({
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
})}</pre>
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = html\`
|
||||||
|
\${{
|
||||||
|
c: y,
|
||||||
|
}}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`indention.js format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["babel", "flow", "typescript"]
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
_ = \`
|
||||||
|
line
|
||||||
|
\${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
line
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = String.raw\`
|
||||||
|
line
|
||||||
|
\${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
line
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = css\`
|
||||||
|
a{
|
||||||
|
color:
|
||||||
|
\${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = html\`
|
||||||
|
<div>
|
||||||
|
\${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = gql\`
|
||||||
|
|
||||||
|
\${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
|
||||||
|
\`;
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
_ = \`
|
||||||
|
line
|
||||||
|
\${
|
||||||
|
a +
|
||||||
|
// comment
|
||||||
|
b
|
||||||
|
}
|
||||||
|
line
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = String.raw\`
|
||||||
|
line
|
||||||
|
\${
|
||||||
|
a +
|
||||||
|
// comment
|
||||||
|
b
|
||||||
|
}
|
||||||
|
line
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = css\`
|
||||||
|
a {
|
||||||
|
color: \${
|
||||||
|
a +
|
||||||
|
// comment
|
||||||
|
b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = html\`
|
||||||
|
<div>
|
||||||
|
\${
|
||||||
|
a +
|
||||||
|
// comment
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
|
||||||
|
_ = gql\`
|
||||||
|
\${
|
||||||
|
a +
|
||||||
|
// comment
|
||||||
|
b
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`indention-2.js format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["babel", "flow", "typescript"]
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
_ = html\`
|
||||||
|
<div>
|
||||||
|
\${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div><div><div><div>
|
||||||
|
\${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div></div></div></div>
|
||||||
|
\`
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
_ = html\`
|
||||||
|
<div>
|
||||||
|
\${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
\${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
runFormatTest(import.meta, ["babel", "flow", "typescript"]);
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
_ = html`
|
||||||
|
<div>
|
||||||
|
${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div><div><div><div>
|
||||||
|
${
|
||||||
|
a + //
|
||||||
|
b
|
||||||
|
}
|
||||||
|
</div></div></div></div>
|
||||||
|
`
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
_ = `
|
||||||
|
line
|
||||||
|
${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
line
|
||||||
|
`;
|
||||||
|
|
||||||
|
_ = String.raw`
|
||||||
|
line
|
||||||
|
${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
line
|
||||||
|
`;
|
||||||
|
|
||||||
|
_ = css`
|
||||||
|
a{
|
||||||
|
color:
|
||||||
|
${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
_ = html`
|
||||||
|
<div>
|
||||||
|
${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
_ = gql`
|
||||||
|
|
||||||
|
${
|
||||||
|
a
|
||||||
|
// comment
|
||||||
|
+ b}
|
||||||
|
|
||||||
|
`;
|
||||||
@@ -84,9 +84,9 @@ html\`\${
|
|||||||
}\`;
|
}\`;
|
||||||
html\`
|
html\`
|
||||||
\${
|
\${
|
||||||
foo
|
foo
|
||||||
/* comment */
|
/* comment */
|
||||||
}
|
}
|
||||||
\`;
|
\`;
|
||||||
|
|
||||||
graphql\`
|
graphql\`
|
||||||
@@ -97,9 +97,9 @@ graphql\`
|
|||||||
\`;
|
\`;
|
||||||
graphql\`
|
graphql\`
|
||||||
\${
|
\${
|
||||||
foo
|
foo
|
||||||
/* comment */
|
/* comment */
|
||||||
}
|
}
|
||||||
\`;
|
\`;
|
||||||
|
|
||||||
css\`
|
css\`
|
||||||
@@ -110,9 +110,9 @@ css\`
|
|||||||
\`;
|
\`;
|
||||||
css\`
|
css\`
|
||||||
\${
|
\${
|
||||||
foo
|
foo
|
||||||
/* comment */
|
/* comment */
|
||||||
}
|
}
|
||||||
\`;
|
\`;
|
||||||
|
|
||||||
markdown\`\${
|
markdown\`\${
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ parsers: ["babel", "typescript", "flow"]
|
|||||||
<style jsx>{\`
|
<style jsx>{\`
|
||||||
.class {
|
.class {
|
||||||
flex-direction: column\${
|
flex-direction: column\${
|
||||||
long_cond && long_cond && long_cond ? "-reverse" : ""
|
long_cond && long_cond && long_cond ? "-reverse" : ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
\`}</style>;
|
\`}</style>;
|
||||||
<style jsx>{\`
|
<style jsx>{\`
|
||||||
|
|||||||
Reference in new issue
Block a user