Fix string print (#18351)
This commit is contained in:
1 parent
8785c6e3af
commit
3e770b95a7
7 files changed
+193
-9
No files matched your search
@@ -0,0 +1,13 @@
|
||||
#### Fix string print when switching quotes (#18351 by @fisker)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
// Input
|
||||
console.log("A descriptor\\'s .kind must be \"method\" or \"field\".")
|
||||
|
||||
// Prettier stable
|
||||
console.log('A descriptor\\'s .kind must be "method" or "field".');
|
||||
|
||||
// Prettier main
|
||||
console.log('A descriptor\\\'s .kind must be "method" or "field".');
|
||||
```
|
||||
@@ -1,7 +1,8 @@
|
||||
/** @import {Quote} from "./get-preferred-quote.js" */
|
||||
|
||||
// Matches _any_ escape and unescaped quotes (both single and double).
|
||||
const REGEX = /\\?(?<quote>["'])/gu;
|
||||
// Matching `\` in first group, so we won't treat `\\"` as escaped quote.
|
||||
const REGEX = /\\(["'\\])|(["'])/gu;
|
||||
|
||||
/**
|
||||
* @param {string} rawText
|
||||
@@ -9,14 +10,25 @@ const REGEX = /\\?(?<quote>["'])/gu;
|
||||
* @returns {string}
|
||||
*/
|
||||
function makeString(rawText, enclosingQuote) {
|
||||
return (
|
||||
enclosingQuote +
|
||||
rawText.replaceAll(
|
||||
REGEX,
|
||||
(_, quote) => (quote === enclosingQuote ? "\\" : "") + quote,
|
||||
) +
|
||||
enclosingQuote
|
||||
);
|
||||
const otherQuote = enclosingQuote === '"' ? "'" : '"';
|
||||
|
||||
// Escape and unescape single and double quotes as needed to be able to
|
||||
// enclose `rawText` with `enclosingQuote`.
|
||||
const raw = rawText.replaceAll(REGEX, (match, escaped, unescaped) => {
|
||||
// If we matched an escape, and the escaped character is a quote of the
|
||||
// other type than we intend to enclose the string with, there's no need for
|
||||
// it to be escaped, so return it _without_ the backslash.
|
||||
if (escaped) {
|
||||
return escaped === otherQuote ? otherQuote : match;
|
||||
}
|
||||
|
||||
// If we matched an unescaped quote and it is of the _same_ type as we
|
||||
// intend to enclose the string with, it must be escaped, so return it with
|
||||
// a backslash.
|
||||
return unescaped === enclosingQuote ? "\\" + unescaped : unescaped;
|
||||
});
|
||||
|
||||
return enclosingQuote + raw + enclosingQuote;
|
||||
}
|
||||
|
||||
export default makeString;
|
||||
@@ -0,0 +1,53 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`switch-quote.js format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["babel", "typescript", "flow"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
console.log([
|
||||
// 18351
|
||||
"A descriptor\\\\'s .kind must be \\"method\\" or \\"field\\".",
|
||||
|
||||
// Will switch to single quote
|
||||
"0 backslash [ ' ] \\"\\"",
|
||||
"0 backslash [ \\' ] \\"\\"",
|
||||
"1 backslash [ \\\\' ] \\"\\"",
|
||||
"1 backslash [ \\\\\\' ] \\"\\"",
|
||||
|
||||
// Other charectors
|
||||
"\\\\'\\"\\" [ \\ ]",
|
||||
"\\\\'\\"\\" [ \\\\ ]",
|
||||
"\\\\'\\"\\" [ \\\\\\ ]",
|
||||
"\\\\'\\"\\" [ \\\\\\\\ ]",
|
||||
"\\\\'\\"\\" [ \\n ]",
|
||||
"\\\\'\\"\\" [ \\\\n ]",
|
||||
"\\\\'\\"\\" [ \\\\\\n ]",
|
||||
"\\\\'\\"\\" [ \\\\\\\\n ]",
|
||||
]);
|
||||
|
||||
=====================================output=====================================
|
||||
console.log([
|
||||
// 18351
|
||||
'A descriptor\\\\\\'s .kind must be "method" or "field".',
|
||||
|
||||
// Will switch to single quote
|
||||
'0 backslash [ \\' ] ""',
|
||||
'0 backslash [ \\' ] ""',
|
||||
'1 backslash [ \\\\\\' ] ""',
|
||||
'1 backslash [ \\\\\\' ] ""',
|
||||
|
||||
// Other charectors
|
||||
'\\\\\\'"" [ \\ ]',
|
||||
'\\\\\\'"" [ \\\\ ]',
|
||||
'\\\\\\'"" [ \\\\\\ ]',
|
||||
'\\\\\\'"" [ \\\\\\\\ ]',
|
||||
'\\\\\\'"" [ \\n ]',
|
||||
'\\\\\\'"" [ \\\\n ]',
|
||||
'\\\\\\'"" [ \\\\\\n ]',
|
||||
'\\\\\\'"" [ \\\\\\\\n ]',
|
||||
]);
|
||||
|
||||
================================================================================
|
||||
`;
|
||||
@@ -0,0 +1 @@
|
||||
runFormatTest(import.meta, ["babel", "typescript", "flow"]);
|
||||
@@ -0,0 +1,20 @@
|
||||
console.log([
|
||||
// 18351
|
||||
"A descriptor\\'s .kind must be \"method\" or \"field\".",
|
||||
|
||||
// Will switch to single quote
|
||||
"0 backslash [ ' ] \"\"",
|
||||
"0 backslash [ \' ] \"\"",
|
||||
"1 backslash [ \\' ] \"\"",
|
||||
"1 backslash [ \\\' ] \"\"",
|
||||
|
||||
// Other charectors
|
||||
"\\'\"\" [ \ ]",
|
||||
"\\'\"\" [ \\ ]",
|
||||
"\\'\"\" [ \\\ ]",
|
||||
"\\'\"\" [ \\\\ ]",
|
||||
"\\'\"\" [ \n ]",
|
||||
"\\'\"\" [ \\n ]",
|
||||
"\\'\"\" [ \\\n ]",
|
||||
"\\'\"\" [ \\\\n ]",
|
||||
]);
|
||||
@@ -225,6 +225,39 @@ test("sharedUtil.makeString", () => {
|
||||
expect(makeString(`a${DOUBLE_QUOTE}`, SINGLE_QUOTE)).toBe(
|
||||
`${SINGLE_QUOTE}a${DOUBLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
expect(makeString(`a${DOUBLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
|
||||
`${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(makeString(`a\\${DOUBLE_QUOTE}\\${SINGLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
|
||||
`${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(makeString(`a\\${DOUBLE_QUOTE}\\${SINGLE_QUOTE}`, SINGLE_QUOTE)).toBe(
|
||||
`${SINGLE_QUOTE}a${DOUBLE_QUOTE}\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
makeString(`a\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}`, DOUBLE_QUOTE),
|
||||
).toBe(
|
||||
`${DOUBLE_QUOTE}a\\\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(
|
||||
makeString(`a\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}`, SINGLE_QUOTE),
|
||||
).toBe(
|
||||
`${SINGLE_QUOTE}a\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
makeString(`a\\\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}`, DOUBLE_QUOTE),
|
||||
).toBe(
|
||||
`${DOUBLE_QUOTE}a\\\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(
|
||||
makeString(`a\\\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}`, SINGLE_QUOTE),
|
||||
).toBe(
|
||||
`${SINGLE_QUOTE}a\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
makeString(
|
||||
String.raw`\a`,
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import makeString from "../../src/utils/make-string.js";
|
||||
|
||||
const DOUBLE_QUOTE = '"';
|
||||
const SINGLE_QUOTE = "'";
|
||||
|
||||
test("makeString", () => {
|
||||
expect(makeString("a", DOUBLE_QUOTE)).toBe(`${DOUBLE_QUOTE}a${DOUBLE_QUOTE}`);
|
||||
expect(makeString("a", SINGLE_QUOTE)).toBe(`${SINGLE_QUOTE}a${SINGLE_QUOTE}`);
|
||||
expect(makeString(`a${DOUBLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
|
||||
`${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(makeString(`a${DOUBLE_QUOTE}`, SINGLE_QUOTE)).toBe(
|
||||
`${SINGLE_QUOTE}a${DOUBLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
expect(makeString(`a${DOUBLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
|
||||
`${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(makeString(`a\\${DOUBLE_QUOTE}\\${SINGLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
|
||||
`${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(makeString(`a\\${DOUBLE_QUOTE}\\${SINGLE_QUOTE}`, SINGLE_QUOTE)).toBe(
|
||||
`${SINGLE_QUOTE}a${DOUBLE_QUOTE}\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
makeString(`a\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}`, DOUBLE_QUOTE),
|
||||
).toBe(
|
||||
`${DOUBLE_QUOTE}a\\\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(
|
||||
makeString(`a\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}`, SINGLE_QUOTE),
|
||||
).toBe(
|
||||
`${SINGLE_QUOTE}a\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
makeString(`a\\\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}`, DOUBLE_QUOTE),
|
||||
).toBe(
|
||||
`${DOUBLE_QUOTE}a\\\\\\${DOUBLE_QUOTE}\\\\${SINGLE_QUOTE}${DOUBLE_QUOTE}`,
|
||||
);
|
||||
expect(
|
||||
makeString(`a\\\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}`, SINGLE_QUOTE),
|
||||
).toBe(
|
||||
`${SINGLE_QUOTE}a\\\\${DOUBLE_QUOTE}\\\\\\${SINGLE_QUOTE}${SINGLE_QUOTE}`,
|
||||
);
|
||||
|
||||
// Do not unescape `\a`
|
||||
expect(makeString(String.raw`\a`, SINGLE_QUOTE)).toBe(
|
||||
String.raw`${SINGLE_QUOTE}\a${SINGLE_QUOTE}`,
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user