From ebb8e1328261798a96228f9f18cac767cef983eb Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Wed, 19 Oct 2022 17:40:59 +0900 Subject: [PATCH] Markdown: improve whitespace handling in CJK (#11597) --- changelog_unreleased/markdown/11597.md | 104 +++++++ cspell.json | 1 + src/language-markdown/print-preprocess.js | 6 +- src/language-markdown/print-whitespace.js | 284 ++++++++++++++++++ src/language-markdown/printer-markdown.js | 50 +-- src/language-markdown/utils.js | 117 +++++--- .../__snapshots__/jsfmt.spec.js.snap | 23 +- .../__snapshots__/jsfmt.spec.js.snap | 264 +++++++++++++++- .../markdown/splitCjkText/han-kana-alnum.md | 7 + .../markdown/splitCjkText/jsfmt.spec.js | 31 +- tests/format/markdown/splitCjkText/korean.md | 61 ++++ .../splitCjkText/symbolSpaceNewLine.md | 59 ++++ 12 files changed, 892 insertions(+), 115 deletions(-) create mode 100644 changelog_unreleased/markdown/11597.md create mode 100644 src/language-markdown/print-whitespace.js create mode 100644 tests/format/markdown/splitCjkText/han-kana-alnum.md create mode 100644 tests/format/markdown/splitCjkText/symbolSpaceNewLine.md diff --git a/changelog_unreleased/markdown/11597.md b/changelog_unreleased/markdown/11597.md new file mode 100644 index 000000000000..58448064c476 --- /dev/null +++ b/changelog_unreleased/markdown/11597.md @@ -0,0 +1,104 @@ +#### [HIGHLIGHT] Improve handling of whitespace for Chinese, Japanese, and Korean (#11597 by @tats-u) + +##### Stop inserting spaces between Chinese or Japanese and Western characters + +Previously, Prettier would insert spaces between Chinese or Japanese and Western characters (letters and digits). While some people prefer this style, it isn’t standard, and is in fact contrary to official guidelines. Please see [here](https://github.com/tats-u/prettier-plugin-md-nocjsp#why-this-plugin-is-needed) for more details. We decided it’s not Prettier’s job to enforce a particular style in this case, so spaces aren’t inserted anymore, while existing ones are preserved. If you need a tool for enforcing spacing style, consider [textlint-ja](https://github.com/textlint-ja/textlint-rule-preset-ja-spacing/tree/master/packages/textlint-rule-ja-space-between-half-and-full-width) or [lint-md](https://github.com/lint-md/lint-md) (rules `space-round-alphabet` and `space-round-number`). + +The tricky part of this change were ambiguous line breaks between Chinese or Japanese and Western characters. When Prettier unwraps text, it needs to decide whether such a line break should be simply removed or replaced with a space. For that Prettier examines the surrounding text and infers the preferred style. + + +```markdown + +漢字 +Alphabetsひらがな12345カタカナ67890 + +漢字 Alphabets ひらがな 12345 カタカナ 67890 + + +漢字 Alphabets ひらがな 12345 カタカナ 67890 + +漢字 Alphabets ひらがな 12345 カタカナ 67890 + + +漢字Alphabetsひらがな12345カタカナ67890 + +漢字 Alphabets ひらがな 12345 カタカナ 67890 +``` + +##### Comply to line breaking rules in Chinese and Japanese + +There are rules that prohibit certain characters from appearing at the beginning or the end of a line in [Chinese](https://www.w3.org/TR/clreq/#prohibition_rules_for_line_start_end) and [Japanese](https://www.w3.org/TR/jlreq/#characters_not_starting_a_line). E.g., full stop characters `。`, `.`, and `.` shouldn’t start a line whereas `(` shouldn’t end a line. Prettier now follows these rules when it wraps text, that is when `proseWrap` is set to `always`. + + +```markdown + +HTCPCPのエラー418は、ティーポットにコーヒーを淹(い)れさせようとしたときに返されるステータスコードだ。 + + +HTCPCP の +エラー +418 は、 +ティーポ +ットにコ +ーヒーを +淹(い) +れさせよ +うとした +ときに返 +されるス +テータス +コードだ +。 + + +HTCPCPの +エラー +418は、 +ティー +ポットに +コーヒー +を淹 +(い)れ +させよう +としたと +きに返さ +れるス +テータス +コード +だ。 +``` + +##### Do not break lines inside Korean words + +Korean uses spaces to divide words, and an inappropriate division may change the meaning of a sentence: + +- `노래를 못해요.`: I’m not good at singing. +- `노래를 못 해요.`: I can’t sing (for some reason). + +Previously, when `proseWrap` was set to `always`, successive Hangul characters could get split by a line break, which could later be converted to a space when the document is edited and reformatted. This doesn’t happen anymore. Korean text is now wrapped like English. + + +```markdown + +노래를 못해요. + + +노래를 못 +해요. + + +노래를 못 해요. + + +노래를 +못해요. + + +노래를 못해요. +``` + +A line break between Hangul and non-Hangul letters and digits is converted to a space when Prettier unwraps the text. Consider this example: + +> 3분 기다려 주지. + +In this sentence, if you break the line between “3” and “분”, a space will be inserted there when the text gets unwrapped. diff --git a/cspell.json b/cspell.json index 24865fa5ef04..6ce4e229ad45 100644 --- a/cspell.json +++ b/cspell.json @@ -319,6 +319,7 @@ "templating", "tempy", "testname", + "textlint", "tldr", "Tomasek", "toplevel", diff --git a/src/language-markdown/print-preprocess.js b/src/language-markdown/print-preprocess.js index ac836ea665c6..4446a2a80434 100644 --- a/src/language-markdown/print-preprocess.js +++ b/src/language-markdown/print-preprocess.js @@ -8,7 +8,7 @@ function preprocess(ast, options) { ast = mergeContinuousTexts(ast); ast = transformIndentedCodeblockAndMarkItsParentList(ast, options); ast = markAlignedList(ast, options); - ast = splitTextIntoSentences(ast, options); + ast = splitTextIntoSentences(ast); return ast; } @@ -63,7 +63,7 @@ function mergeContinuousTexts(ast) { ); } -function splitTextIntoSentences(ast, options) { +function splitTextIntoSentences(ast) { return mapAst(ast, (node, index, [parentNode]) => { if (node.type !== "text") { return node; @@ -83,7 +83,7 @@ function splitTextIntoSentences(ast, options) { return { type: "sentence", position: node.position, - children: splitText(value, options), + children: splitText(value), }; }); } diff --git a/src/language-markdown/print-whitespace.js b/src/language-markdown/print-whitespace.js new file mode 100644 index 000000000000..7a865b055b21 --- /dev/null +++ b/src/language-markdown/print-whitespace.js @@ -0,0 +1,284 @@ +import { hardline, line, softline } from "../document/builders.js"; +import { + KIND_CJK_PUNCTUATION, + KIND_CJ_LETTER, + KIND_K_LETTER, + KIND_NON_CJK, + getAncestorNode, +} from "./utils.js"; + +/** + * @typedef {import("./utils.js").WordNode} WordNode + * @typedef {import("./utils.js").WhitespaceValue} WhitespaceValue + * @typedef {import("./utils.js").WordKind} WordKind + * @typedef {import("../common/ast-path.js").default} AstPath + * @typedef {"always" | "never" | "preserve"} ProseWrap + * @typedef {{ next?: WordNode | null, previous?: WordNode | null }} + * AdjacentNodes Nodes adjacent to a `whitespace` node. Are always of type + * `word`. + */ + +const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link", "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. + */ +const lineBreakBetweenTheseAndCJConvertsToSpace = new Set( + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" +); + +/** + * Determine the preferred style of spacing between Chinese or Japanese and non-CJK + * characters in the parent `sentence` node. + * + * @param {AstPath} path + * @returns {boolean} `true` if Space tends to be inserted between CJ and + * non-CJK, `false` otherwise. + */ +function isInSentenceWithCJSpaces({ parent: sentenceNode }) { + if (sentenceNode.usesCJSpaces === undefined) { + const stats = { " ": 0, "": 0 }; + const { children } = sentenceNode; + + for (let i = 1; i < children.length - 1; ++i) { + const node = children[i]; + if ( + node.type === "whitespace" && + (node.value === " " || node.value === "") + ) { + const previousKind = children[i - 1].kind; + const nextKind = children[i + 1].kind; + if ( + (previousKind === KIND_CJ_LETTER && nextKind === KIND_NON_CJK) || + (previousKind === KIND_NON_CJK && nextKind === KIND_CJ_LETTER) + ) { + ++stats[node.value]; + } + } + } + + // Inject a property to cache the result. + sentenceNode.usesCJSpaces = stats[" "] > stats[""]; + } + + return sentenceNode.usesCJSpaces; +} + +/** + * Check whether the given `"\n"` node can be converted to a space. + * + * For example, if you would like to squash English text + * + * "You might want\nto use Prettier." + * + * into a single line, you would replace `"\n"` with `" "`: + * + * "You might want to use Prettier." + * + * However, Chinese and Japanese don't use U+0020 Space to divide words, so line + * breaks shouldn't be replaced with spaces for those languages. + * + * PRs are welcome to support line breaking rules for other languages. + * + * @param {AstPath} path + * @param {boolean} isLink + * @returns {boolean} + */ +function lineBreakCanBeConvertedToSpace(path, isLink) { + if (isLink) { + return true; + } + + /** @type {AdjacentNodes} */ + const { previous, next } = path; + + // e.g. " \nletter" + if (!previous || !next) { + return true; + } + + const previousKind = previous.kind; + const nextKind = next.kind; + + if ( + // "\n" between non-CJK or Korean characters always can be converted to a + // space. Korean Hangul simulates Latin words. See + // https://github.com/prettier/prettier/issues/6516 + (isNonCJKOrKoreanLetter(previousKind) && + isNonCJKOrKoreanLetter(nextKind)) || + // Han & Hangul: same way preferred + (previousKind === KIND_K_LETTER && nextKind === KIND_CJ_LETTER) || + (nextKind === KIND_K_LETTER && previousKind === KIND_CJ_LETTER) + ) { + return true; + } + + // Do not convert \n to a space: + if ( + // around CJK punctuation + previousKind === KIND_CJK_PUNCTUATION || + nextKind === KIND_CJK_PUNCTUATION || + // between CJ + (previousKind === KIND_CJ_LETTER && nextKind === KIND_CJ_LETTER) + ) { + return false; + } + + // The rest of this function deals only with line breaks between CJ and + // non-CJK characters. + + // Convert a line break between CJ and certain non-letter characters (e.g. + // ASCII punctuation) to a space. + // + // E.g. :::\n句子句子句子\n::: → ::: 句子句子句子 ::: + // + // Note: line breaks like "(\n句子句子\n)" or "句子\n." are suppressed in + // `isBreakable(...)`. + if ( + lineBreakBetweenTheseAndCJConvertsToSpace.has(next.value[0]) || + lineBreakBetweenTheseAndCJConvertsToSpace.has(previous.value.at(-1)) + ) { + return true; + } + + // Converting a line break between CJ and non-ASCII punctuation to a space is + // undesired in many cases. PRs are welcome to fine-tune this logic. + // + // Examples where \n must not be converted to a space: + // + // 1. "〜" (U+301C, belongs to Pd) in + // + // "ア〜\nエの中から1つ選べ。" + // + // 2. "…" (U+2026, belongs to Po) in + // + // "これはひどい……\nなんと汚いコミットログなんだ……" + if (previous.hasTrailingPunctuation || next.hasLeadingPunctuation) { + return false; + } + + // If the sentence uses the style with spaces between CJ and non-CJK, "\n" can + // be converted to a space. + 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 + */ +function isNonCJKOrKoreanLetter(kind) { + return kind === KIND_NON_CJK || kind === KIND_K_LETTER; +} + +/** + * Check whether whitespace can be printed as a line break. + * + * @param {AstPath} path + * @param {WhitespaceValue} value + * @param {ProseWrap} proseWrap + * @param {boolean} isLink + * @param {boolean} canBeSpace + * @returns {boolean} + */ +function isBreakable(path, value, proseWrap, isLink, canBeSpace) { + if (proseWrap !== "always" || getAncestorNode(path, SINGLE_LINE_NODE_TYPES)) { + return false; + } + + if (isLink) { + return value !== ""; + } + + // Spaces are always breakable + if (value === " ") { + return true; + } + + /** @type {AdjacentNodes} */ + const { previous, next } = path; + + // 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))) + ) { + return false; + } + + // 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) { + return false; + } + + return true; +} + +/** + * @param {AstPath} path + * @param {WhitespaceValue} value + * @param {ProseWrap} proseWrap + * @param {boolean} [isLink] Special mode of (un)wrapping that preserves the + * normalized form of link labels. https://spec.commonmark.org/0.30/#matches + */ +function printWhitespace(path, value, proseWrap, isLink) { + if (proseWrap === "preserve" && value === "\n") { + return hardline; + } + + const canBeSpace = + value === " " || + (value === "\n" && lineBreakCanBeConvertedToSpace(path, isLink)); + + if (isBreakable(path, value, proseWrap, isLink, canBeSpace)) { + return canBeSpace ? line : softline; + } + + return canBeSpace ? " " : ""; +} + +export { printWhitespace }; diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index 727069c560d0..d29853284ae8 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -35,8 +35,11 @@ import { INLINE_NODE_TYPES, INLINE_NODE_WRAPPER_TYPES, isAutolink, + getAncestorNode, + getAncestorCounter, } from "./utils.js"; import visitorKeys from "./visitor-keys.js"; +import { printWhitespace } from "./print-whitespace.js"; const getVisitorKeys = createGetVisitorKeys(visitorKeys); @@ -44,7 +47,6 @@ const getVisitorKeys = createGetVisitorKeys(visitorKeys); * @typedef {import("../document/builders.js").Doc} Doc */ -const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link", "wikiLink"]; const SIBLING_NODE_TYPES = new Set([ "listItem", "definition", @@ -59,14 +61,11 @@ function genericPrint(path, options, print) { options.originalText.slice( node.position.start.offset, node.position.end.offset - ), - options + ) ).map((node) => node.type === "word" ? node.value - : node.value === "" - ? "" - : printLine(path, node.value, options) + : printWhitespace(path, node.value, options.proseWrap, true) ); } @@ -137,7 +136,7 @@ function genericPrint(path, options, print) { ? "never" : options.proseWrap; - return printLine(path, node.value, { proseWrap }); + return printWhitespace(path, node.value, proseWrap); } case "emphasis": { let style; @@ -505,43 +504,6 @@ function getNthSiblingIndex(node, parentNode, condition) { } } -function getAncestorCounter(path, typeOrTypes) { - const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; - - let counter = -1; - let ancestorNode; - - while ((ancestorNode = path.getParentNode(++counter))) { - if (types.includes(ancestorNode.type)) { - return counter; - } - } - - return -1; -} - -function getAncestorNode(path, typeOrTypes) { - const counter = getAncestorCounter(path, typeOrTypes); - return counter === -1 ? null : path.getParentNode(counter); -} - -function printLine(path, value, options) { - if (options.proseWrap === "preserve" && value === "\n") { - return hardline; - } - - const isBreakable = - options.proseWrap === "always" && - !getAncestorNode(path, SINGLE_LINE_NODE_TYPES); - return value !== "" - ? isBreakable - ? line - : " " - : isBreakable - ? softline - : ""; -} - function printTable(path, options, print) { const { node } = path; diff --git a/src/language-markdown/utils.js b/src/language-markdown/utils.js index fa52c1b80060..139142b2e53e 100644 --- a/src/language-markdown/utils.js +++ b/src/language-markdown/utils.js @@ -1,3 +1,4 @@ +import assert from "node:assert"; import { locStart, locEnd } from "./loc.js"; import { cjkPattern, @@ -36,38 +37,39 @@ const INLINE_NODE_WRAPPER_TYPES = [ const kRegex = new RegExp(kPattern); const punctuationRegex = new RegExp(punctuationPattern); +const KIND_NON_CJK = "non-cjk"; +const KIND_CJ_LETTER = "cj-letter"; +const KIND_K_LETTER = "k-letter"; +const KIND_CJK_PUNCTUATION = "cjk-punctuation"; + +/** + * @typedef {" " | "\n" | ""} WhitespaceValue + * @typedef { KIND_NON_CJK | KIND_CJ_LETTER | KIND_K_LETTER | KIND_CJK_PUNCTUATION } WordKind + * @typedef {{ + * type: "whitespace", + * value: WhitespaceValue, + * kind?: never + * }} WhitespaceNode + * @typedef {{ + * type: "word", + * value: string, + * kind: WordKind, + * hasLeadingPunctuation: boolean, + * hasTrailingPunctuation: boolean, + * }} WordNode + * Node for a single CJK character or a sequence of non-CJK characters + * @typedef {WhitespaceNode | WordNode} TextNode + */ + /** * split text into whitespaces and words * @param {string} text */ -function splitText(text, options) { - const KIND_NON_CJK = "non-cjk"; - const KIND_CJ_LETTER = "cj-letter"; - const KIND_K_LETTER = "k-letter"; - const KIND_CJK_PUNCTUATION = "cjk-punctuation"; - - /** - * @type {Array< - * { type: "whitespace", value: " " | "\n" | "" } - * | { - * type: "word", - * value: string, - * kind: string, - * hasLeadingPunctuation: boolean, - * hasTrailingPunctuation: boolean - * } - * >} - */ +function splitText(text) { + /** @type {Array} */ const nodes = []; - const tokens = ( - options.proseWrap === "preserve" - ? text - : text.replace( - new RegExp(`(${cjkPattern})\n(${cjkPattern})`, "g"), - "$1$2" - ) - ).split(/([\t\n ]+)/); + const tokens = text.split(/([\t\n ]+)/); for (const [index, token] of tokens.entries()) { // whitespace if (index % 2 === 1) { @@ -120,6 +122,7 @@ function splitText(text, options) { : { type: "word", value: innerToken, + // Korean uses space to divide words, but Chinese & Japanese do not kind: kRegex.test(innerToken) ? KIND_K_LETTER : KIND_CJ_LETTER, hasLeadingPunctuation: false, hasTrailingPunctuation: false, @@ -128,35 +131,33 @@ function splitText(text, options) { } } + // Check for `canBeConvertedToSpace` in ./print-whitespace.js etc. + if (process.env.NODE_ENV !== "production") { + for (let i = 1; i < nodes.length; i++) { + assert( + !(nodes[i - 1].type === "whitespace" && nodes[i].type === "whitespace"), + "splitText should not create consecutive whitespace nodes" + ); + } + } + return nodes; function appendNode(node) { const lastNode = nodes.at(-1); - if (lastNode && lastNode.type === "word") { - if ( - (lastNode.kind === KIND_NON_CJK && - node.kind === KIND_CJ_LETTER && - !lastNode.hasTrailingPunctuation) || - (lastNode.kind === KIND_CJ_LETTER && - node.kind === KIND_NON_CJK && - !node.hasLeadingPunctuation) - ) { - nodes.push({ type: "whitespace", value: " " }); - } else if ( - !isBetween(KIND_NON_CJK, KIND_CJK_PUNCTUATION) && - // disallow leading/trailing full-width whitespace - ![lastNode.value, node.value].some((value) => /\u3000/.test(value)) - ) { - nodes.push({ type: "whitespace", value: "" }); - } + if ( + lastNode?.type === "word" && + !isBetween(KIND_NON_CJK, KIND_CJK_PUNCTUATION) && + // disallow leading/trailing full-width whitespace + ![lastNode.value, node.value].some((value) => /\u3000/.test(value)) + ) { + nodes.push({ type: "whitespace", value: "" }); } nodes.push(node); function isBetween(kind1, kind2) { return ( - // @ts-expect-error (lastNode.kind === kind1 && node.kind === kind2) || - // @ts-expect-error (lastNode.kind === kind2 && node.kind === kind1) ); } @@ -238,6 +239,26 @@ function isAutolink(node) { return locStart(node) === locStart(child) && locEnd(node) === locEnd(child); } +function getAncestorCounter(path, typeOrTypes) { + const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + + let counter = -1; + let ancestorNode; + + while ((ancestorNode = path.getParentNode(++counter))) { + if (types.includes(ancestorNode.type)) { + return counter; + } + } + + return -1; +} + +function getAncestorNode(path, typeOrTypes) { + const counter = getAncestorCounter(path, typeOrTypes); + return counter === -1 ? null : path.getParentNode(counter); +} + export { mapAst, splitText, @@ -248,4 +269,10 @@ export { INLINE_NODE_TYPES, INLINE_NODE_WRAPPER_TYPES, isAutolink, + KIND_NON_CJK, + KIND_CJ_LETTER, + KIND_K_LETTER, + KIND_CJK_PUNCTUATION, + getAncestorCounter, + getAncestorNode, }; diff --git a/tests/format/markdown/paragraph/__snapshots__/jsfmt.spec.js.snap b/tests/format/markdown/paragraph/__snapshots__/jsfmt.spec.js.snap index 6bb45612bc67..7e789a3c56fa 100644 --- a/tests/format/markdown/paragraph/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/markdown/paragraph/__snapshots__/jsfmt.spec.js.snap @@ -31,16 +31,15 @@ IVS 麻󠄁羽󠄀‼️ 這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長 很長的段落 -這是一個 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! 全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白 全  形 空白全  形 空白全  形 空白 @@ -90,7 +89,7 @@ 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! 全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白 @@ -139,7 +138,7 @@ 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! 全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白全  形 空白 diff --git a/tests/format/markdown/splitCjkText/__snapshots__/jsfmt.spec.js.snap b/tests/format/markdown/splitCjkText/__snapshots__/jsfmt.spec.js.snap index a2568471fa0e..4b68052c1481 100644 --- a/tests/format/markdown/splitCjkText/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/markdown/splitCjkText/__snapshots__/jsfmt.spec.js.snap @@ -38,6 +38,70 @@ proseWrap: "always" ================================================================================ `; +exports[`han-kana-alnum.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +這是一個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日。 + +=====================================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日。 + +================================================================================ +`; + exports[`korean.md - {"proseWrap":"always"} format 1`] = ` ====================================options===================================== parsers: ["markdown"] @@ -47,9 +111,98 @@ proseWrap: "always" =====================================input====================================== 예문Latin예문Latin 예문Latin예문 Latin예문Latin 예문 Latin 예문 +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. + +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 +RTX3000 +시리즈는 +삼성전자와 +TSMC에 +의해 +제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. + +대한민국(듣기 (도움말·정보), 大韓民國, 영어: Republic of Korea; ROK[3])은 동아시아의 한반도 중남부에 있는 공화국이다. + +서쪽으로는 서해를 사이에 두고 중화인민공화국이, 동쪽으로는 동해를 사이에 두고 일본이 있으며 +북쪽으로는 조선민주주의인민공화국과 맞닿아 있다. + +역대 대통령은 李承晩 과 許政 과 尹潽善 과 朴正熙 과 崔圭夏 과 朴忠勳 과 全斗煥 과 盧泰愚 과 金泳三 과 金大中 과 盧武鉉 과 李明博 과 朴槿惠 과 文在寅 과 尹錫悅 과 음... +역대 대통령은 +李承晩 +과 +許政 +과 +尹潽善 +과 +朴正熙 과 +崔圭夏 과 +朴忠勳 과 +全斗煥 과 +盧泰愚 과 +金泳三 +과 金大中 +과 盧武鉉 +과 李明博 +과 朴槿惠 +과 文在寅 +과 尹錫悅 과 +음... + +역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... 역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... + =====================================output===================================== 예문Latin예문Latin 예문Latin예문 Latin예문Latin 예문 Latin 예문 +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. 한국어와 +English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. 한국어와 +English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. 한국어와 +English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. 한국어와 +English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. + +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. NVIDIA의 RTX3000 +시리즈는 삼성전자와 TSMC에 의해 제조된다. NVIDIA의 RTX3000 시리즈는 삼성전자와 +TSMC에 의해 제조된다. NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. + +대한민국(듣기 (도움말·정보), 大韓民國, 영어: Republic of Korea; ROK[3])은 +동아시아의 한반도 중남부에 있는 공화국이다. + +서쪽으로는 서해를 사이에 두고 중화인민공화국이, 동쪽으로는 동해를 사이에 두고 +일본이 있으며 북쪽으로는 조선민주주의인민공화국과 맞닿아 있다. + +역대 대통령은 李承晩 과 許政 과 尹潽善 과 朴正熙 과 崔圭夏 과 朴忠勳 과 全斗煥 +과 盧泰愚 과 金泳三 과 金大中 과 盧武鉉 과 李明博 과 朴槿惠 과 文在寅 과 尹錫悅 +과 음... 역대 대통령은 李承晩 과 許政 과 尹潽善 과 朴正熙 과 崔圭夏 과 朴忠勳 과 +全斗煥 과 盧泰愚 과 金泳三 과 金大中 과 盧武鉉 과 李明博 과 朴槿惠 과 文在寅 과 +尹錫悅 과 음... + +역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰 +愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... 역대 +대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과 +金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... + ================================================================================ `; @@ -78,16 +231,15 @@ 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! ================================================================================ `; @@ -115,3 +267,95 @@ English 混合著中文的一段 Paragraph! ================================================================================ `; + +exports[`symbolSpaceNewLine.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +日本語 +、 +にほんご +。 +汉语, +中文. +日 +本 +語 +, +に +ほ +ん +ご +. +English +words!? +漢字 +! +汉字 +? +「セリフ」 +(括弧) +文字 +(括弧) +文字 +【括弧】 +日本語 +English + +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)!!!!」 +「禁則(きんそく)処理(しょり)!!!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 + +中点 +・ +中点 + +禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか?レデ +ィ、ゴー! + +[ウ +ィキペディア] + +[ウ +ィキペディア]: https://ja.wikipedia.org/ + +=====================================output===================================== +日本語、にほんご。汉语, 中文. 日本語,にほんご.English words!? 漢字!汉字?「セ +リフ」(括弧) 文字(括弧)文字【括弧】日本語English + +「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則 +(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)」「禁則(きんそ +く)処理(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理 +(しょり)」「禁則(きんそく)処理(しょり)」「禁則(きんそく)処理(しょ +り)!!!!」「禁則(きんそく)処理(しょり)!!!」「禁則(きんそく)処理 +(しょり)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょ +り)!」「禁則(きんそく)処理(しょり)!」「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 + +中点・中点 + +禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか?レ +ディ、ゴー! + +[ウ ィキペディア] + +[ウ ィキペディア]: https://ja.wikipedia.org/ + +================================================================================ +`; diff --git a/tests/format/markdown/splitCjkText/han-kana-alnum.md b/tests/format/markdown/splitCjkText/han-kana-alnum.md new file mode 100644 index 000000000000..55e90bc7237e --- /dev/null +++ b/tests/format/markdown/splitCjkText/han-kana-alnum.md @@ -0,0 +1,7 @@ +這是一個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日。 diff --git a/tests/format/markdown/splitCjkText/jsfmt.spec.js b/tests/format/markdown/splitCjkText/jsfmt.spec.js index 8ad59f4c81ae..eb4f5df98e2e 100644 --- a/tests/format/markdown/splitCjkText/jsfmt.spec.js +++ b/tests/format/markdown/splitCjkText/jsfmt.spec.js @@ -1 +1,30 @@ -run_spec(import.meta, ["markdown"], { proseWrap: "always" }); +const code = Array.from({ length: 6 }) + // less "文" <= [..., "文...文 ", "文...文", ...] => more "文" + .map((_, i) => ["文".repeat(39 + (i >> 1)), i & 1 ? "" : " "]) + // ["", "", ...] + .reduce( + (previousInputLines, [base, space]) => [ + ...previousInputLines, + `${base}${space}\n`, + ], + [] + ) + .join(""); +// (39 + 40 + 41) * 2 === 40 * 3 * 2 === 40 * 6 +// lineWidth is 80 and "文" is double-width +const output = `${"文".repeat(40)}\n`.repeat(6); + +run_spec( + { + importMeta: import.meta, + snippets: [ + { + code, + name: "Should ignore single trailing space after han before New Line before han", + output, + }, + ], + }, + ["markdown"], + { proseWrap: "always" } +); diff --git a/tests/format/markdown/splitCjkText/korean.md b/tests/format/markdown/splitCjkText/korean.md index 2bd2c9797af0..ba7608861d30 100644 --- a/tests/format/markdown/splitCjkText/korean.md +++ b/tests/format/markdown/splitCjkText/korean.md @@ -1 +1,62 @@ 예문Latin예문Latin 예문Latin예문 Latin예문Latin 예문 Latin 예문 + +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 +English를 +섞어 +보았습니다. +한국어와 English를 섞어 보았습니다. 한국어와 English를 섞어 보았습니다. + +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 +RTX3000 +시리즈는 +삼성전자와 +TSMC에 +의해 +제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. +NVIDIA의 RTX3000 시리즈는 삼성전자와 TSMC에 의해 제조된다. + +대한민국(듣기 (도움말·정보), 大韓民國, 영어: Republic of Korea; ROK[3])은 동아시아의 한반도 중남부에 있는 공화국이다. + +서쪽으로는 서해를 사이에 두고 중화인민공화국이, 동쪽으로는 동해를 사이에 두고 일본이 있으며 +북쪽으로는 조선민주주의인민공화국과 맞닿아 있다. + +역대 대통령은 李承晩 과 許政 과 尹潽善 과 朴正熙 과 崔圭夏 과 朴忠勳 과 全斗煥 과 盧泰愚 과 金泳三 과 金大中 과 盧武鉉 과 李明博 과 朴槿惠 과 文在寅 과 尹錫悅 과 음... +역대 대통령은 +李承晩 +과 +許政 +과 +尹潽善 +과 +朴正熙 과 +崔圭夏 과 +朴忠勳 과 +全斗煥 과 +盧泰愚 과 +金泳三 +과 金大中 +과 盧武鉉 +과 李明博 +과 朴槿惠 +과 文在寅 +과 尹錫悅 과 +음... + +역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... 역대 대통령은 李承晩과 許政과 尹潽善과 朴正熙과 崔圭夏과 朴忠勳과 全斗煥과 盧泰愚과 金泳三과 金大中과 盧武鉉과 李明博과 朴槿惠과 文在寅과 尹錫悅과 음... diff --git a/tests/format/markdown/splitCjkText/symbolSpaceNewLine.md b/tests/format/markdown/splitCjkText/symbolSpaceNewLine.md new file mode 100644 index 000000000000..f46aaee81100 --- /dev/null +++ b/tests/format/markdown/splitCjkText/symbolSpaceNewLine.md @@ -0,0 +1,59 @@ +日本語 +、 +にほんご +。 +汉语, +中文. +日 +本 +語 +, +に +ほ +ん +ご +. +English +words!? +漢字 +! +汉字 +? +「セリフ」 +(括弧) +文字 +(括弧) +文字 +【括弧】 +日本語 +English + +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)」 +「禁則(きんそく)処理(しょり)!!!!」 +「禁則(きんそく)処理(しょり)!!!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 +「禁則(きんそく)処理(しょり)!」 + +中点 +・ +中点 + +禁則処理にわざと違反した文章のテストを今から行います。準備はいいでしょうか?レデ +ィ、ゴー! + +[ウ +ィキペディア] + +[ウ +ィキペディア]: https://ja.wikipedia.org/