fix(markdown): preserve newline around Chinese/Japanese characters not around Korean letters in all proseWrap settings (#20143)
Internal ESLint Plugin Test / Test (push) Canceled after 0s
Lint / Lint (push) Canceled after 0s
Build / Build (push) Canceled after 0s
Prod / Lint (push) Canceled after 0s
Prod / Node.js 14 on MacOS (push) Canceled after 0s
Prod / Node.js 14 on Linux (push) Canceled after 0s
Prod / Node.js 14 on Windows (push) Canceled after 0s
Prod / Node.js 16 on Linux (push) Canceled after 0s
Prod / Node.js 18 on Linux (push) Canceled after 0s
Prod / Node.js 20 on Linux (push) Canceled after 0s
Prod / Node.js 22 on Linux (push) Canceled after 0s
Prod / Node.js 24 on Linux (push) Canceled after 0s
Prod / Node.js 26 on MacOS (push) Canceled after 0s
Prod / Node.js 26 on Windows (push) Canceled after 0s
Prod / [Full Test] Node.js 26 on Linux (push) Canceled after 0s
Prod / Browser(firefox) on Linux (push) Canceled after 0s
Prod / Browser(firefox) on Windows (push) Canceled after 0s
Prod / [Full Test] Browser(chrome) on Linux (push) Canceled after 0s
Prod / CLI (push) Canceled after 0s
Prod / Preview release (push) Canceled after 0s
Release Script Test / Test (push) Canceled after 0s
Dev / Node.js 22 on MacOS (push) Canceled after 0s
Dev / Node.js 22 on Linux (push) Canceled after 0s
Dev / Node.js 22 on Windows (push) Canceled after 0s
Dev / Node.js 26 on MacOS (push) Canceled after 0s
Dev / Node.js 26 on Windows (push) Canceled after 0s
Dev / [Full Test] Node.js 26 on Linux (push) Canceled after 0s
Prod / Build (push) Canceled after 0s
Internal ESLint Plugin Test / Test (push) Canceled after 0s
Lint / Lint (push) Canceled after 0s
Build / Build (push) Canceled after 0s
Prod / Lint (push) Canceled after 0s
Prod / Node.js 14 on MacOS (push) Canceled after 0s
Prod / Node.js 14 on Linux (push) Canceled after 0s
Prod / Node.js 14 on Windows (push) Canceled after 0s
Prod / Node.js 16 on Linux (push) Canceled after 0s
Prod / Node.js 18 on Linux (push) Canceled after 0s
Prod / Node.js 20 on Linux (push) Canceled after 0s
Prod / Node.js 22 on Linux (push) Canceled after 0s
Prod / Node.js 24 on Linux (push) Canceled after 0s
Prod / Node.js 26 on MacOS (push) Canceled after 0s
Prod / Node.js 26 on Windows (push) Canceled after 0s
Prod / [Full Test] Node.js 26 on Linux (push) Canceled after 0s
Prod / Browser(firefox) on Linux (push) Canceled after 0s
Prod / Browser(firefox) on Windows (push) Canceled after 0s
Prod / [Full Test] Browser(chrome) on Linux (push) Canceled after 0s
Prod / CLI (push) Canceled after 0s
Prod / Preview release (push) Canceled after 0s
Release Script Test / Test (push) Canceled after 0s
Dev / Node.js 22 on MacOS (push) Canceled after 0s
Dev / Node.js 22 on Linux (push) Canceled after 0s
Dev / Node.js 22 on Windows (push) Canceled after 0s
Dev / Node.js 26 on MacOS (push) Canceled after 0s
Dev / Node.js 26 on Windows (push) Canceled after 0s
Dev / [Full Test] Node.js 26 on Linux (push) Canceled after 0s
Prod / Build (push) Canceled after 0s
Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
1 parent
43432349d4
commit
5927216227
7 files changed
+181
-13
No files matched your search
@@ -0,0 +1,29 @@
|
|||||||
|
#### Preserve newlines around Chinese/Japanese characters not around Korean letters in all proseWrap settings (#20143 by @tats-u)
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```md
|
||||||
|
<!-- Input -->
|
||||||
|
English
|
||||||
|
English
|
||||||
|
日本語
|
||||||
|
日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語
|
||||||
|
日本語
|
||||||
|
한국어
|
||||||
|
한국어
|
||||||
|
中文
|
||||||
|
中文!
|
||||||
|
한국어
|
||||||
|
(中文)
|
||||||
|
|
||||||
|
<!-- Prettier stable (--prose-wrap=never) -->
|
||||||
|
English English日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語 한국어 한국어 中文中文!한국어(中文)
|
||||||
|
|
||||||
|
<!-- Prettier main -->
|
||||||
|
English English
|
||||||
|
日本語
|
||||||
|
日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語
|
||||||
|
日本語 한국어 한국어 中文
|
||||||
|
中文!
|
||||||
|
한국어
|
||||||
|
(中文)
|
||||||
|
```
|
||||||
@@ -251,7 +251,10 @@ function isBreakable(path, value, proseWrap, isLink, options) {
|
|||||||
* normalized form of link labels. https://spec.commonmark.org/0.30/#matches
|
* normalized form of link labels. https://spec.commonmark.org/0.30/#matches
|
||||||
*/
|
*/
|
||||||
function printWhitespace(path, value, proseWrap, isLink, options) {
|
function printWhitespace(path, value, proseWrap, isLink, options) {
|
||||||
if (proseWrap === "preserve" && value === "\n") {
|
if (
|
||||||
|
(proseWrap === "preserve" || isLineBreakAmbiguous(path)) &&
|
||||||
|
value === "\n"
|
||||||
|
) {
|
||||||
return hardline;
|
return hardline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +279,36 @@ function printWhitespaceNode(path, options) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a line break around a CJ character can be handled differently by browsers.
|
||||||
|
*
|
||||||
|
* If `true`, since Prettier is just a formatter, which should not change the semantics of the code, it should leave such an ambiguous line break as-is
|
||||||
|
* and let the browser decide how to interpret it regardless of `proseWrap`.
|
||||||
|
*
|
||||||
|
* Once all browsers behave consistently in the future, this function will no longer be needed.
|
||||||
|
*
|
||||||
|
* @param {AstPath} path
|
||||||
|
* @returns {boolean} `true` if a line break around a CJ character are removed by some browsers but converted to a space by others.
|
||||||
|
*/
|
||||||
|
function isLineBreakAmbiguous(path) {
|
||||||
|
const { previous, next } = path;
|
||||||
|
// All browsers treat a line break between a CJ letter and a non-CJ character as
|
||||||
|
// equivalent to a space. However, Prettier v3 intentionally decided that, in
|
||||||
|
// some cases, such a line break is equivalent to removing it without
|
||||||
|
// converting it to a space, so in v3 we leave it as-is instead of converting it
|
||||||
|
// to a space or removing it.
|
||||||
|
// See also: https://github.com/prettier/prettier/pull/16805
|
||||||
|
return (
|
||||||
|
(Boolean(previous?.isCJ) || Boolean(next?.isCJ)) &&
|
||||||
|
// A line break between a CJ letter and a Korean letter has already been interchangeable with a space since Prettier v3.0.0.
|
||||||
|
// A line break between a CJK punctuation character and a Korean letter is handled differently depending on the browser and the content language.
|
||||||
|
!(
|
||||||
|
(previous.kind === KIND_K_LETTER && next.kind === KIND_CJ_LETTER) ||
|
||||||
|
(next.kind === KIND_K_LETTER && previous.kind === KIND_CJ_LETTER)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function shouldPreventBreak(path, options) {
|
function shouldPreventBreak(path, options) {
|
||||||
const { proseWrap } = options;
|
const { proseWrap } = options;
|
||||||
if (proseWrap === "never") {
|
if (proseWrap === "never") {
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ This ia an english paragraph with a CJK quote “中文“.
|
|||||||
|
|
||||||
扩展运算符(spread)是三个点(\`...\`)。
|
扩展运算符(spread)是三个点(\`...\`)。
|
||||||
|
|
||||||
::: warning 注意该网站在国外无法访问,故以下演示无效 :::
|
::: warning 注意
|
||||||
|
该网站在国外无法访问,故以下演示无效
|
||||||
|
:::
|
||||||
|
|
||||||
IVS 麻󠄁羽󠄀‼️
|
IVS 麻󠄁羽󠄀‼️
|
||||||
|
|
||||||
@@ -97,7 +99,9 @@ This ia an english paragraph with a CJK quote “中文“.
|
|||||||
|
|
||||||
扩展运算符(spread)是三个点(\`...\`)。
|
扩展运算符(spread)是三个点(\`...\`)。
|
||||||
|
|
||||||
::: warning 注意该网站在国外无法访问,故以下演示无效 :::
|
::: warning 注意
|
||||||
|
该网站在国外无法访问,故以下演示无效
|
||||||
|
:::
|
||||||
|
|
||||||
IVS 麻󠄁羽󠄀‼️
|
IVS 麻󠄁羽󠄀‼️
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,36 @@ nasalカ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク
|
|||||||
================================================================================
|
================================================================================
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`cjkMixed.md - {"proseWrap":"always"} format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["markdown"]
|
||||||
|
proseWrap: "always"
|
||||||
|
printWidth: 80 (default) |
|
||||||
|
=====================================input======================================
|
||||||
|
English
|
||||||
|
English
|
||||||
|
日本語
|
||||||
|
日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語
|
||||||
|
日本語
|
||||||
|
한국어
|
||||||
|
한국어
|
||||||
|
中文
|
||||||
|
中文!
|
||||||
|
한국어
|
||||||
|
(中文)
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
English English
|
||||||
|
日本語
|
||||||
|
日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語
|
||||||
|
日本語 한국어 한국어 中文
|
||||||
|
中文!
|
||||||
|
한국어
|
||||||
|
(中文)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`han-kana-alnum.md - {"proseWrap":"always"} format 1`] = `
|
exports[`han-kana-alnum.md - {"proseWrap":"always"} format 1`] = `
|
||||||
====================================options=====================================
|
====================================options=====================================
|
||||||
parsers: ["markdown"]
|
parsers: ["markdown"]
|
||||||
@@ -290,20 +320,71 @@ Go
|
|||||||
Rust
|
Rust
|
||||||
|
|
||||||
=====================================output=====================================
|
=====================================output=====================================
|
||||||
日本語、にほんご。汉语, 中文. 日本語,にほんご.English
|
日本語
|
||||||
words!? 漢字!汉字?「セリフ」(括弧) 文字(括弧)文字【括弧】日本語English
|
、
|
||||||
|
にほんご
|
||||||
|
。
|
||||||
|
汉语,
|
||||||
|
中文.
|
||||||
|
日
|
||||||
|
本
|
||||||
|
語
|
||||||
|
,
|
||||||
|
に
|
||||||
|
ほ
|
||||||
|
ん
|
||||||
|
ご
|
||||||
|
.
|
||||||
|
English words!?
|
||||||
|
漢字
|
||||||
|
!
|
||||||
|
汉字
|
||||||
|
?
|
||||||
|
「セリフ」
|
||||||
|
(括弧)
|
||||||
|
文字
|
||||||
|
(括弧)
|
||||||
|
文字
|
||||||
|
【括弧】
|
||||||
|
日本語
|
||||||
|
English
|
||||||
|
|
||||||
「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)」「禁則(きんそく)処理(しょり)」「禁則(きんそく)処理(しょり)!!!!」「禁則(きんそく)処理(しょり)!!!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)」
|
||||||
|
「禁則(きんそく)処理(しょり)」
|
||||||
|
「禁則(きんそく)処理(しょり)!!!!」
|
||||||
|
「禁則(きんそく)処理(しょり)!!!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
「禁則(きんそく)処理(しょり)!」
|
||||||
|
|
||||||
中点・中点
|
中点
|
||||||
|
・
|
||||||
|
中点
|
||||||
|
|
||||||
禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか?レディ、ゴー!
|
禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか?レデ
|
||||||
|
ィ、ゴー!
|
||||||
|
|
||||||
[ウ ィキペディア]
|
[ウ ィキペディア]
|
||||||
|
|
||||||
[ウ ィキペディア]: https://ja.wikipedia.org/
|
[ウ ィキペディア]: https://ja.wikipedia.org/
|
||||||
|
|
||||||
C言語・C++・Go・Rust
|
C言
|
||||||
|
語
|
||||||
|
・
|
||||||
|
C++
|
||||||
|
・
|
||||||
|
Go
|
||||||
|
・
|
||||||
|
Rust
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
`;
|
`;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
English
|
||||||
|
English
|
||||||
|
日本語
|
||||||
|
日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語
|
||||||
|
日本語
|
||||||
|
한국어
|
||||||
|
한국어
|
||||||
|
中文
|
||||||
|
中文!
|
||||||
|
한국어
|
||||||
|
(中文)
|
||||||
@@ -18,7 +18,10 @@ const snippets = [
|
|||||||
// (39 + 40 + 41) * 2 === 40 * 3 * 2 === 40 * 6
|
// (39 + 40 + 41) * 2 === 40 * 3 * 2 === 40 * 6
|
||||||
// lineWidth is 80 and "文" is double-width
|
// lineWidth is 80 and "文" is double-width
|
||||||
// This is being saved for after Chrome and Safari bug is fixed.
|
// This is being saved for after Chrome and Safari bug is fixed.
|
||||||
output: /* `${"文".repeat(40)}\n`.repeat(6) */ `${"文".repeat(40 * 6)}\n`,
|
get output() {
|
||||||
|
/* `${"文".repeat(40)}\n`.repeat(6) */
|
||||||
|
return this.code.replace(/ (?=\n)/g, "");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -36,7 +39,13 @@ const snippets = [
|
|||||||
name: "Should remove newline around CJ(K) punctuation(-like)",
|
name: "Should remove newline around CJ(K) punctuation(-like)",
|
||||||
code,
|
code,
|
||||||
// Note: replaceAll is not supported in Node 14.
|
// Note: replaceAll is not supported in Node 14.
|
||||||
output: `${code.replace(/\n/g, "")}\n`,
|
// In CSS, a line break between a CJK and a non-CJK character is always interchangeable
|
||||||
|
// with a space, but Prettier v3 made a design mistake where, in some cases,
|
||||||
|
// it was treated as equivalent to being deleted
|
||||||
|
// (see https://github.com/prettier/prettier/issues/14936).
|
||||||
|
// Therefore, .replace is disabled until it gets fixed in
|
||||||
|
// https://github.com/prettier/prettier/pull/16805.
|
||||||
|
output: code, // `${code.replace(/\n/g, "")}\n`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// This preamble is unnecessary after #16805
|
// This preamble is unnecessary after #16805
|
||||||
const preamble = "a 字 a 字 a 字";
|
const preamble = "a 字 a 字 a 字";
|
||||||
const code = `${preamble}\n${"葛\u{e0100}\n".repeat(3)}${"𠮷\n".repeat(2)}終\n`;
|
const code = `${preamble}\n${"葛\u{e0100}\n".repeat(3)}${"𠮷\n".repeat(2)}終\n`;
|
||||||
const output = `${preamble}${"葛\u{e0100}".repeat(3)}${"𠮷".repeat(2)}終\n`;
|
// Once browser behavior is standardized across browsers, comment out output and switch to the output below.
|
||||||
|
// const output = `${preamble}${"葛\u{e0100}".repeat(3)}${"𠮷".repeat(2)}終\n`;
|
||||||
|
|
||||||
runFormatTest(
|
runFormatTest(
|
||||||
{
|
{
|
||||||
@@ -10,7 +11,7 @@ runFormatTest(
|
|||||||
{
|
{
|
||||||
code,
|
code,
|
||||||
name: "Make sure non-BMP CJK characters are treated as CJK",
|
name: "Make sure non-BMP CJK characters are treated as CJK",
|
||||||
output,
|
output: code,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user