diff --git a/src/language-markdown/print/mdast.js b/src/language-markdown/print/mdast.js index a229b0489..e754480c0 100644 --- a/src/language-markdown/print/mdast.js +++ b/src/language-markdown/print/mdast.js @@ -22,7 +22,6 @@ import { getFencedCodeBlockValue, getNthListSiblingIndex, isAutolink, - isNewLine, isPrettierIgnore, splitText, } from "../utilities.js"; @@ -32,7 +31,7 @@ import { printList, printListLegacy } from "./list.js"; import { printParagraph } from "./paragraph.js"; import { printSentence } from "./sentence.js"; import { printTable } from "./table.js"; -import { printWhitespace } from "./whitespace.js"; +import { printWhitespace, printWhitespaceNode } from "./whitespace.js"; import { printWord, printWordLegacy } from "./word.js"; /** @@ -57,28 +56,6 @@ function prevOrNextWord(path) { return hasPrevOrNextWord; } -function hasFakeWhitespaceAfterNextToken(path) { - const { siblings, index } = path; - if (!siblings || typeof index !== "number") { - return false; - } - const afterNext = siblings[index + 2]; - return afterNext?.type === "whitespace" && afterNext.value === ""; -} - -/** - * @param {AstPath} path - * @returns {boolean} - */ -function isNextTokenFakeSetextH2Line(path) { - if (!isNewLine(path.node) || path.next?.value !== "-") { - return false; - } - - const afterNext = path.siblings[path.index + 2]; - return !afterNext || isNewLine(afterNext); -} - function printMdast(path, options, print) { const { node } = path; @@ -133,22 +110,8 @@ function printMdast(path, options, print) { return options.parser !== "mdx" ? printWord(path, options) : printWordLegacy(path); - case "whitespace": { - const { next } = path; - - const proseWrap = - // leading char that may cause different syntax - next && - /^>|^(?:[*+-]|#{1,6}|\d+[).])$/.test(next.value) && - // Avoid https://github.com/prettier/prettier/issues/18861 - !hasFakeWhitespaceAfterNextToken(path) && - // Next fake setext h2 `-` is going to be escaped, so no need to join adjacent words - !(options.proseWrap === "preserve" && isNextTokenFakeSetextH2Line(path)) - ? "never" - : options.proseWrap; - - return printWhitespace(path, node.value, proseWrap, false, options); - } + case "whitespace": + return printWhitespaceNode(path, options); case "emphasis": { let style; if (isAutolink(node.children[0])) { diff --git a/src/language-markdown/print/whitespace.js b/src/language-markdown/print/whitespace.js index d588b5edb..9cef69da2 100644 --- a/src/language-markdown/print/whitespace.js +++ b/src/language-markdown/print/whitespace.js @@ -1,5 +1,6 @@ import { hardline, line, softline } from "../../document/index.js"; import { + isNewLine, isSetextHeading, KIND_CJ_LETTER, KIND_CJK_PUNCTUATION, @@ -265,4 +266,60 @@ function printWhitespace(path, value, proseWrap, isLink, options) { return canBeSpace ? " " : ""; } -export { printWhitespace }; +function printWhitespaceNode(path, options) { + return printWhitespace( + path, + path.node.value, + shouldPreventBreak(path, options) ? "never" : options.proseWrap, + false, + options, + ); +} + +function shouldPreventBreak(path, options) { + const { proseWrap } = options; + if (proseWrap === "never") { + return true; + } + + if (path.isLast) { + return false; + } + + if ( + // leading char that may cause different syntax + /^>|^(?:[*+-]|#{1,6}|\d+[).])$/.test(path.next.value) && + // Avoid https://github.com/prettier/prettier/issues/18861 + !hasFakeWhitespaceAfterNextToken(path) && + // Next fake setext h2 `-` is going to be escaped, so no need to join adjacent words + !(proseWrap === "preserve" && isNextTokenFakeSetextH2Line(path)) + ) { + return true; + } + + return false; +} + +/** + * @param {AstPath} path + * @returns {boolean} + */ +function hasFakeWhitespaceAfterNextToken(path) { + const afterNext = path.siblings[path.index + 2]; + return afterNext?.type === "whitespace" && afterNext.value === ""; +} + +/** + * @param {AstPath} path + * @returns {boolean} + */ +function isNextTokenFakeSetextH2Line(path) { + if (!isNewLine(path.node) || path.next.value !== "-") { + return false; + } + + const afterNext = path.siblings[path.index + 2]; + return !afterNext || isNewLine(afterNext); +} + +export { printWhitespace, printWhitespaceNode };