Repository: prettier/prettier (JavaScript)
Date: 2024-09-25 15:16:44+00:00
Task type: Bug Fix

Issue:
Markdown: Disable breaking a line at the place around Chinese or Japanese characters even when `proseWrap` is `always`
<!--

BEFORE SUBMITTING AN ISSUE:

1.  Search for your issue on GitHub: https://github.com/prettier/prettier/issues
    A large number of opened issues are duplicates of existing issues.
    If someone has already opened an issue for what you are experiencing,
    you do not need to open a new issue — please add a 👍 reaction to the
    existing issue instead.

2.  We get a lot of requests for adding options, but Prettier is
    built on the principle of being opinionated about code formatting.
    This means we add options only in the case of strict technical necessity.
    Find out more: https://prettier.io/docs/en/option-philosophy.html

Don't fill the form below manually! Let a program create a report for you:

1. Go to https://prettier.io/playground
2. Paste your code and set options
3. Press the "Report issue" button in the lower right

-->

**Prettier 3.3.3**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEBRKBzANgSwM4AWABIKemgNOaB5UeVZdXbQzU-c4y9UetvsXgvFDBwQAGhAQADjBzQ8yUAEMATkogB3AArKEclAqxqFATzliARkoVgA1nBgBlBQFs4AGRxRhSAGb6+5yxs7ewkrDwxkGCUAVzgxPiccSJi4kDgADwk4JRwXWH0AFWyoZRw4XV8sfxA8cKw4AEVoiHhkSuqAKzx0+zrG5tafP1SARwG4DVUJXRAFPABaTzgAExXRECiFHFxMAGEIJycFZDS8AFZ12sx6gEEYKJwzaPgNbPdPNuGxAhgnLAB1Ag4eB4UJCew6YE4ABuwKMJzAeFMIGhsQAklBVrB7GAclIbpj7DAjPVPlVUhJVHx-pYJCd9IYTOsPHwlDBJgoMEcydVQkpWScjkprMt1FB1pSPDB-jhljACMgACwABjESjgYxw6o5XOOQ3JYhgCjMMrlCqQACYxNE+AVjRUvmknGYVqtlq4FJhopy4AAxCBKI73cL054QEAAXwjQA)

```markdown
# Options (if any):
--prose-wrap=always --print-width=40
```

**Input:**

```md
English 日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語 English sentence
```

**Output:**

```md
English 日本語日本語日本語日本語日本語日
本語日本語日本語日本語日本語日本語日本語
日本語日本語日本語日本語日本語日本語
English sentence

```

**Expected output:**

```md
English 日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語 English
sentence
```

**Why?**

<!-- short explanation of expected output -->

The result expected in #14936 breaks the existing Markdown documents. We should temporally disable breaking a line not only between Chinese/Japanese characters but also between Latin and Chinese/Japanese characters.
This issue is opened for closed by #16691.


Issue discussion:

Solution patch:
diff --git a/changelog_unreleased/markdown/16691.md b/changelog_unreleased/markdown/16691.md
new file mode 100644
index 000000000000..c9c81a124a82
--- /dev/null
+++ b/changelog_unreleased/markdown/16691.md
@@ -0,0 +1,153 @@
+#### Don't break a line a between Chinese or Japanese and others (#16691 by @tats-u)
+
+Markdown documents are mainly converted to HTML or components of JavaScript-based frameworks. This means that paragraphs in Markdown are eventually processed by the browser according to [CSS rules](https://drafts.csswg.org/css-text-4/). This is because many Markdown converter preserve line breaks in paragraphs in input Markdown and HTML itself does not specify how browsers should handle line breaks in text in HTML.
+
+According to [CSS rules (CSS Text Module Level 3 or later)](https://drafts.csswg.org/css-text-4/#line-break-transform), browsers should remove line breaks between Chinese/Japanese characters instead of replacing them with spaces. However, this rule has been ignored by WebKit-based or Webkit-derived browsers (Chrome, Safari, and so on) for long time.
+
+For example, the following HTML paragraph:
+
+<!-- prettier-ignore -->
+```html
+<p>
+日本語
+汉语
+漢語
+<p>
+```
+
+generated from the following Markdown:
+
+```md
+日本語
+汉语
+漢語
+```
+
+should be rendered as follows according to CSS rules and actually is rendered such by Firefox:
+
+```md
+日本語汉语漢語
+```
+
+However, Chrome and Safari render it as follows:
+
+```md
+日本語 汉语 漢語
+```
+
+This is why we should stop Prettier from line breaking between Chinese/Japanese characters. We decided to stop Prettier from forcing users to use a plugin for a Markdown converter that concatenates lines that start or end with Chinese/Japanese characters ([remark-join-cjk-lines](https://www.npmjs.com/package/remark-join-cjk-lines), for example).
+
+Also, [a line break between Chinese/Japanese and others are equivalent to a space](https://github.com/w3c/csswg-drafts/blob/076914a198bf3ac642001619e08acefdf607d61d/css-text/Overview.bs#L712) according to before [the commit suspending a concrete rule in CSS Text Module Level 3 by commenting it out](https://github.com/w3c/csswg-drafts/commit/b3bb0ed18b3168981c54c437bcfb5881ef49975b) fixing [an issue on the CSS Working Group Editor Drafts](https://github.com/w3c/csswg-drafts/issues/5086). Firefox follows this rule. Therefore, all browsers render the following paragraph:
+
+````html
+<!-- prettier-ignore -->
+```html
+<p>日本語 English 汉语 한국어 漢語</p>
+
+<p></p>
+````
+
+as follows:
+
+```md
+日本語 English 汉语 한국어 漢語
+```
+
+However, Prettier has broken a line between Chinese/Japanese characters in Markdown for a long time, and between Chinese/Japanese and latin characters in some cases since 3.0.0. For example, the following Markdown paragraph:
+
+```md
+日本語English汉语
+English
+漢語
+```
+
+is formatted as follows if `--prose-wrap` is set to the other value than `preserve` in Prettier 3.x:
+
+```md
+日本語English汉语English漢語
+```
+
+However, the following HTML, which is generated by a Markdown-to-HTML converter based on the above Markdown:
+
+<!-- prettier-ignore -->
+```html
+<p>
+日本語English汉语
+English
+漢語
+</p>
+```
+
+is rendered as follows by all browsers:
+
+```md
+日本語English汉语 English 漢語
+```
+
+This is why we should stop Prettier from line breaking al　so around Chinese/Japanese characters in Markdown. We are going to conform Prettier's behavior to this rule in a future version. After that, line breaks between Chinese/Japanese and others will be allowed again under certain rules.
+
+One of the few exceptions is spaces and line breaks between Chinese/Japanese and Korean letters. The following Markdown paragraphs are equivalent even in the current Prettier version:
+
+```md
+현재 韓國의 大統領은 尹錫悅이다.
+```
+
+```md
+현재
+韓國의
+大統領은
+尹錫悅이다.
+```
+
+You get the former if you format the latter with `--prose-wrap=always` and a sufficiently long `--print-width` value or with `--prose-wrap=never`, and you get the latter if you format the former with `--prose-wrap=always` with a extremely short `--print-width` value. Therefore, we do not have to touch such spaces and line breaks.
+
+Another exception is those between a Chinese/Japanese character and a meaningful symbol in Markdown like `*`, `` ` ``, `[`, and `]`. For example, the following Markdown paragraph is equivalent even in the current Prettier version:
+
+```md
+**Yarn** のCLI経由でフォーマットするには `yarn prettier -w ` を実行してください。
+```
+
+```md
+**Yarn**
+のCLI経由でフォーマットするには
+`yarn prettier -w .`
+を実行してください。
+```
+
+<!-- prettier-ignore -->
+```md
+<!-- Input (--prose-wrap=always --print-width=20) -->
+日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어
+
+日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어
+
+<!-- Prettier stable -->
+日本語 汉语 漢語
+English 한국어 日本
+語 汉语 漢語 English
+한국어 日本語 汉语
+漢語 English 한국어
+日本語 汉语 漢語
+English 한국어
+
+日本語汉语漢語
+English한국어日本語
+汉语漢語
+English한국어日本語
+汉语漢語
+English한국어日本語
+汉语漢語
+English한국어
+
+<!-- Prettier main -->
+日本語 汉语 漢語 English
+한국어
+日本語 汉语 漢語 English
+한국어
+日本語 汉语 漢語 English
+한국어
+日本語 汉语 漢語 English
+한국어
+
+日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어
+```
diff --git a/src/language-markdown/print-whitespace.js b/src/language-markdown/print-whitespace.js
index b57e83bec356..3479ee41447e 100644
--- a/src/language-markdown/print-whitespace.js
+++ b/src/language-markdown/print-whitespace.js
@@ -24,32 +24,6 @@ const SINGLE_LINE_NODE_TYPES = new Set([
   "wikiLink",
 ]);
 
-/**
- * These characters must not immediately precede a line break.
- *
- * e.g. `"（"`:
- *
- * - Bad:  `"檜原村（\nひのはらむら）"`
- * - Good: `"檜原村\n（ひのはらむら）"` or
- *         `"檜原村（ひ\nのはらむら）"`
- */
-const noBreakAfter = new Set(
-  "$(£¥·'\"〈《「『【〔〖〝﹙﹛＄（［｛￡￥[{‵︴︵︷︹︻︽︿﹁﹃﹏〘｟«",
-);
-
-/**
- * These characters must not immediately follow a line break.
- *
- * e.g. `"）"`:
- *
- * - Bad:  `"檜原村（ひのはらむら\n）以外には、"`
- * - Good: `"檜原村（ひのはらむ\nら）以外には、"` or
- *         `"檜原村（ひのはらむら）\n以外には、"`
- */
-const noBreakBefore = new Set(
-  "!%),.:;?]}¢°·'\"†‡›℃∶、。〃〆〕〗〞﹚﹜！＂％＇），．：；？］｝～–—•〉》」︰︱︲︳﹐﹑﹒﹓﹔﹕﹖﹘︶︸︺︼︾﹀﹂﹗｜､』】〙〟｠»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠〜～‼⁇⁈⁉・゙゚",
-);
-
 /**
  * A line break between a character from this set and CJ can be converted to a
  * space. Includes only ASCII punctuation marks for now.
@@ -193,16 +167,6 @@ function lineBreakCanBeConvertedToSpace(path, isLink) {
   return isInSentenceWithCJSpaces(path);
 }
 
-/**
- * @param {WordKind | undefined} kind
- * @returns {boolean} `true` if `kind` is defined and not CJK punctuation
- */
-function isLetter(kind) {
-  return (
-    kind === KIND_NON_CJK || kind === KIND_CJ_LETTER || kind === KIND_K_LETTER
-  );
-}
-
 /**
  * @param {WordKind | undefined} kind
  * @returns {boolean} `true` if `kind` is Korean letter or non-CJK
@@ -218,10 +182,9 @@ function isNonCJKOrKoreanLetter(kind) {
  * @param {WhitespaceValue} value
  * @param {ProseWrap} proseWrap
  * @param {boolean} isLink
- * @param {boolean} canBeSpace
  * @returns {boolean}
  */
-function isBreakable(path, value, proseWrap, isLink, canBeSpace) {
+function isBreakable(path, value, proseWrap, isLink) {
   if (
     proseWrap !== "always" ||
     path.hasAncestor((node) => SINGLE_LINE_NODE_TYPES.has(node.type))
@@ -233,32 +196,46 @@ function isBreakable(path, value, proseWrap, isLink, canBeSpace) {
     return value !== "";
   }
 
-  // Spaces are always breakable
-  if (value === " ") {
+  /** @type {AdjacentNodes} */
+  const { previous, next } = path;
+
+  // [1]: We will make a breaking change to the rule to convert spaces between
+  //      a Chinese or Japanese character and another character in the future.
+  //      Such a space must have been always interchangeable with a line break.
+  //      https://wpt.fyi/results/css/css-text/line-breaking?label=master&label=experimental&aligned&q=segment-break-transformation-rules-
+  // [2]: we should not break lines even between Chinese/Japanese characters because Chrome & Safari replaces "\n" between such characters with " " now.
+  // [3]: Hangul (Korean) must simulate Latin words; see https://github.com/prettier/prettier/issues/6516
+  //      [printable][""][Hangul] & vice versa => Don't break
+  //      [printable][\n][Hangul] will be interchangeable to [printable][" "][Hangul] in the future
+  //      (will be compatible with Firefox's behavior)
+
+  if (!previous || !next) {
+    // empty side is Latin ASCII symbol (e.g. *, [, ], or `)
+    // value is " " or "\n" (not "")
+    // [1] & [2]? No, it's the only exception because " " & "\n" have been always interchangeable only here
     return true;
   }
 
-  /** @type {AdjacentNodes} */
-  const { previous, next } = path;
+  if (value === "") {
+    // [1] & [2] & [3]
+    // At least either of previous or next is non-Latin (=CJK)
+    return false;
+  }
 
-  // Simulates Latin words; see https://github.com/prettier/prettier/issues/6516
-  // [Latin][""][Hangul] & vice versa => Don't break
-  // [Han & Kana][""][Hangul], either
   if (
-    value === "" &&
-    ((previous?.kind === KIND_K_LETTER && isLetter(next?.kind)) ||
-      (next?.kind === KIND_K_LETTER && isLetter(previous?.kind)))
+    // See the same product terms as the following in lineBreakCanBeConvertedToSpace
+    // The behavior is consistent between browsers and Prettier in that line breaks between Korean and Chinese/Japanese letters are equivalent to spaces.
+    // Currently, [CJK punctuation][\n][Hangul] is interchangeable to [CJK punctuation][""][Hangul],
+    // but this is not compatible with Firefox's behavior.
+    // Will be changed to [CJK punctuation][" "][Hangul] in the future
+    (previous.kind === KIND_K_LETTER && next.kind === KIND_CJ_LETTER) ||
+    (next.kind === KIND_K_LETTER && previous.kind === KIND_CJ_LETTER)
   ) {
-    return false;
+    return true;
   }
 
-  // https://en.wikipedia.org/wiki/Line_breaking_rules_in_East_Asian_languages
-  const violatesCJKLineBreakingRules =
-    !canBeSpace &&
-    ((next && noBreakBefore.has(next.value[0])) ||
-      (previous && noBreakAfter.has(previous.value.at(-1))));
-
-  if (violatesCJKLineBreakingRules) {
+  // [1] & [2]
+  if (previous.isCJ || next.isCJ) {
     return false;
   }
 
@@ -281,7 +258,7 @@ function printWhitespace(path, value, proseWrap, isLink) {
     value === " " ||
     (value === "\n" && lineBreakCanBeConvertedToSpace(path, isLink));
 
-  if (isBreakable(path, value, proseWrap, isLink, canBeSpace)) {
+  if (isBreakable(path, value, proseWrap, isLink)) {
     return canBeSpace ? line : softline;
   }
 
diff --git a/src/language-markdown/utils.js b/src/language-markdown/utils.js
index 8e4f984f445f..0003852a2443 100644
--- a/src/language-markdown/utils.js
+++ b/src/language-markdown/utils.js
@@ -50,6 +50,7 @@ const K_REGEXP = /\p{Script_Extensions=Hangul}/u;
  *   type: "word",
  *   value: string,
  *   kind: WordKind,
+ *   isCJ: boolean,
  *   hasLeadingPunctuation: boolean,
  *   hasTrailingPunctuation: boolean,
  * }} WordNode
@@ -98,6 +99,7 @@ function splitText(text) {
             type: "word",
             value: innerToken,
             kind: KIND_NON_CJK,
+            isCJ: false,
             hasLeadingPunctuation: PUNCTUATION_REGEXP.test(innerToken[0]),
             hasTrailingPunctuation: PUNCTUATION_REGEXP.test(innerToken.at(-1)),
           });
@@ -106,24 +108,43 @@ function splitText(text) {
       }
 
       // CJK character
-      appendNode(
-        PUNCTUATION_REGEXP.test(innerToken)
-          ? {
-              type: "word",
-              value: innerToken,
-              kind: KIND_CJK_PUNCTUATION,
-              hasLeadingPunctuation: true,
-              hasTrailingPunctuation: true,
-            }
-          : {
-              type: "word",
-              value: innerToken,
-              // Korean uses space to divide words, but Chinese & Japanese do not
-              kind: K_REGEXP.test(innerToken) ? KIND_K_LETTER : KIND_CJ_LETTER,
-              hasLeadingPunctuation: false,
-              hasTrailingPunctuation: false,
-            },
-      );
+
+      // punctuation for CJ(K)
+      // Korean doesn't use them in horizontal writing usually
+      if (PUNCTUATION_REGEXP.test(innerToken)) {
+        appendNode({
+          type: "word",
+          value: innerToken,
+          kind: KIND_CJK_PUNCTUATION,
+          isCJ: true,
+          hasLeadingPunctuation: true,
+          hasTrailingPunctuation: true,
+        });
+        continue;
+      }
+
+      // Korean uses space to divide words, but Chinese & Japanese do not
+      // This is why Korean should be treated like non-CJK
+      if (K_REGEXP.test(innerToken)) {
+        appendNode({
+          type: "word",
+          value: innerToken,
+          kind: KIND_K_LETTER,
+          isCJ: false,
+          hasLeadingPunctuation: false,
+          hasTrailingPunctuation: false,
+        });
+        continue;
+      }
+
+      appendNode({
+        type: "word",
+        value: innerToken,
+        kind: KIND_CJ_LETTER,
+        isCJ: true,
+        hasLeadingPunctuation: false,
+        hasTrailingPunctuation: false,
+      });
     }
   }
 


Test patch:
diff --git a/tests/format/markdown/paragraph/__snapshots__/format.test.js.snap b/tests/format/markdown/paragraph/__snapshots__/format.test.js.snap
index 7e789a3c56fa..df219d78e104 100644
--- a/tests/format/markdown/paragraph/__snapshots__/format.test.js.snap
+++ b/tests/format/markdown/paragraph/__snapshots__/format.test.js.snap
@@ -28,21 +28,11 @@ IVS 麻󠄁羽󠄀‼️
 ⿰あ⿱あ⿲あ⿳あ⿴あ⿵あ⿶あ⿷あ⿸あ⿹あ⿺あ⿻あ
 
 =====================================output=====================================
-這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長
-很長的段落
-
-這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段
-Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的
-一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中
-文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合
-著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English
-混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個
-English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是
-一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
-這是一個English混合著中文的一段Paragraph！
-
-全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白
-全　　形　空白全　　形　空白全　　形　空白
+這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長的段落
+
+這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
+
+全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白
 
 This ia an english paragraph with a CJK quote "中文".
 
diff --git a/tests/format/markdown/splitCjkText/__snapshots__/format.test.js.snap b/tests/format/markdown/splitCjkText/__snapshots__/format.test.js.snap
index 436493b6a903..4b9b76376fa4 100644
--- a/tests/format/markdown/splitCjkText/__snapshots__/format.test.js.snap
+++ b/tests/format/markdown/splitCjkText/__snapshots__/format.test.js.snap
@@ -22,25 +22,20 @@ nasalカ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク
 かつてはワ行のワ、ヰ、ヱ、ヲに濁点を付して [v] 音を表現すること（ワ゛、ヰ゛、ヱ゛、ヲ゛）も行われたが、一般的にはならなかった。
 
 =====================================output=====================================
-這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長
-很長的段落
+這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長的段落
 
-全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白
-全　　形　空白全　　形　空白
+全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白全　　形　空白
 
-空白全形空白全形空白全形空白　空白全形空白全形空白全形空白　空白全形空白全形空白
-全形空白　空白全形空白全形空白全形空白
+空白全形空白全形空白全形空白　空白全形空白全形空白全形空白　空白全形空白全形空白全形空白　空白全形空白全形空白全形空白
 
 何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
 
 カ゚キ゚ク゚ケ゚コ゚でガギグゴ
 
-nasalカ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚
-ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚
-ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚
+nasalカ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚カ゚キ゚ク゚ケ゚コ゚
 
-かつてはワ行のワ、ヰ、ヱ、ヲに濁点を付して [v] 音を表現すること（ワ゛、ヰ゛、ヱ
-゛、ヲ゛）も行われたが、一般的にはならなかった。
+かつてはワ行のワ、ヰ、ヱ、ヲに濁点を付して [v]
+音を表現すること（ワ゛、ヰ゛、ヱ゛、ヲ゛）も行われたが、一般的にはならなかった。
 
 ================================================================================
 `;
@@ -61,50 +56,13 @@ MarkdownフォーマッターPrettierはサイコー！Markdownフォーマッ
 Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。
 
 =====================================output=====================================
-這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段
-Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的
-一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中
-文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合
-著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English
-混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個
-English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是
-一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
-這是一個English混合著中文的一段Paragraph！
-
-Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語
-が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざった
-Paragraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れ
-た！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはど
-うする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？English
-と日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざっ
-たParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現
-れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierは
-どうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうす
-る？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日
-本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざった
-Paragraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れ
-た！Prettierはどうする？
-
-MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイ
-コー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierは
-サイコー！MarkdownフォーマッターPrettierはサイコー！Markdownフォーマッター
-Prettierはサイコー！MarkdownフォーマッターPrettierはサイコー！Markdownフォーマッ
-ターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！Markdownフォー
-マッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！Markdown
-フォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイ
-コー！MarkdownフォーマッターPrettierはサイコー！
-
-Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在
-2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的
-第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われま
-した。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11
-月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初の
-Commitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29
-日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit
-是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われまし
-た。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月
-29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初の
-Commitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。
+這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
+
+Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？Englishと日本語が混ざったParagraphが現れた！Prettierはどうする？
+
+MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！MarkdownフォーマッターPrettierはサイコー！
+
+Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。Prettierの最初のCommitは2016年11月29日に行われました。Prettier的第一次Commit是在2016年11月29日。
 
 ================================================================================
 `;
@@ -205,10 +163,10 @@ NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다.
 全斗煥 과 盧泰愚 과 金泳三 과 金大中 과 盧武鉉 과 李明博 과 朴槿惠 과 文在寅 과
 尹錫悅 과 음...
 
-역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰
-愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... 역대
-대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과
-金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음...
+역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과
+盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음...
+역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과
+盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음...
 
 ================================================================================
 `;
@@ -238,15 +196,7 @@ proseWrap: "always"
 這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
 
 =====================================output=====================================
-這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段
-Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的
-一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中
-文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合
-著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English
-混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個
-English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是
-一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
-這是一個English混合著中文的一段Paragraph！
+這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！這是一個English混合著中文的一段Paragraph！
 
 ================================================================================
 `;
@@ -261,16 +211,7 @@ proseWrap: "always"
 這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！
 
 =====================================output=====================================
-這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段
-Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著
-中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個
-English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段
-Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著
-中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個
-English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段
-Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著
-中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個
-English 混合著中文的一段 Paragraph！
+這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！這是一個 English 混合著中文的一段 Paragraph！
 
 ================================================================================
 `;
@@ -343,22 +284,14 @@ English
 ィキペディア]: https://ja.wikipedia.org/
 
 =====================================output=====================================
-日本語、にほんご。汉语, 中文. 日本語，にほんご．English words!? 漢字！汉字？「セ
-リフ」(括弧) 文字（括弧）文字【括弧】日本語English
-
-「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則
-（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）」「禁則（きんそ
-く）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理
-（しょり）」「禁則（きんそく）処理（しょり）」「禁則（きんそく）処理（しょ
-り）！！！！」「禁則（きんそく）処理（しょり）！！！」「禁則（きんそく）処理
-（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょ
-り）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」
-「禁則（きんそく）処理（しょり）！」
+日本語、にほんご。汉语, 中文. 日本語，にほんご．English
+words!? 漢字！汉字？「セリフ」(括弧) 文字（括弧）文字【括弧】日本語English
+
+「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）」「禁則（きんそく）処理（しょり）」「禁則（きんそく）処理（しょり）！！！！」「禁則（きんそく）処理（しょり）！！！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」「禁則（きんそく）処理（しょり）！」
 
 中点・中点
 
-禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか？レ
-ディ、ゴー！
+禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか？レディ、ゴー！
 
 [ウ ィキペディア]
 
diff --git a/tests/format/markdown/splitCjkText/format.test.js b/tests/format/markdown/splitCjkText/format.test.js
index 0d2bf9867906..3e9f1215ba19 100644
--- a/tests/format/markdown/splitCjkText/format.test.js
+++ b/tests/format/markdown/splitCjkText/format.test.js
@@ -12,7 +12,8 @@ const code = Array.from({ length: 6 })
   .join("");
 // (39 + 40 + 41) * 2 === 40 * 3 * 2 === 40 * 6
 // lineWidth is 80 and "文" is double-width
-const output = `${"文".repeat(40)}\n`.repeat(6);
+// This is being saved for after Chrome and Safari bug is fixed.
+const output = /* `${"文".repeat(40)}\n`.repeat(6) */ `${"文".repeat(40 * 6)}\n`;
 
 runFormatTest(
   {