From 6c339cd882bfa735bb574358f31225faff1477d9 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 26 Dec 2025 19:43:49 +0800 Subject: [PATCH] Upgrade to latest micromark (markdown only) (#18277) Co-authored-by: fisker Cheung Co-authored-by: fisker Co-authored-by: Jed Fox Co-authored-by: seiya <20365512+seiyab@users.noreply.github.com> --- .github/renovate.json5 | 6 +- changelog_unreleased/markdown/18277.md | 5 + changelog_unreleased/markdown/18473.md | 39 + cspell.json | 5 +- jest.config.js | 3 + package.json | 11 + scripts/build/packages/prettier.js | 4 + src/language-markdown/clean.js | 12 +- src/language-markdown/embed.js | 4 +- src/language-markdown/parse/index.js | 3 +- .../parse/micromark/mdast-util-gfm.js | 33 + .../micromark-extension-html-text.js | 812 ++++++++++++ .../micromark/micromark-extension-liquid.js | 112 ++ src/language-markdown/parse/parse-markdown.js | 58 + .../parse/{parse.js => parse-mdx.js} | 38 +- src/language-markdown/print/children.js | 87 +- src/language-markdown/print/heading.js | 31 + src/language-markdown/print/ignored.js | 35 + src/language-markdown/print/index.js | 1 + src/language-markdown/print/list.js | 129 +- src/language-markdown/print/mdast.js | 90 +- src/language-markdown/print/preprocess.js | 356 ++++- src/language-markdown/print/table.js | 21 +- src/language-markdown/print/whitespace.js | 24 +- src/language-markdown/print/word.js | 98 +- src/language-markdown/printers.js | 3 +- src/language-markdown/utilities.js | 19 +- src/main/front-matter/parse.js | 8 +- tests/config/run-format-test.js | 3 +- .../__snapshots__/format.test.js.snap | 350 ++--- .../__snapshots__/format.test.js.snap | 291 ++++ .../markdown/blockquote/check-accidental.md | 1 + .../markdown/blockquote/interrupt-others.md | 11 + tests/format/markdown/blockquote/list.md | 17 + .../break/__snapshots__/format.test.js.snap | 3 +- .../__snapshots__/format.test.js.snap | 41 + .../markdown/break/list-item/format.test.js | 2 + .../markdown/break/list-item/list-item.md | 4 + .../code/__snapshots__/format.test.js.snap | 5 +- .../__snapshots__/format.test.js.snap | 20 +- .../__snapshots__/format.test.js.snap | 475 ++++--- .../commonmark-test-suite/format.test.js | 7 - .../__snapshots__/format.test.js.snap | 14 +- tests/format/markdown/emphasis/special.md | 4 +- .../__snapshots__/format.test.js.snap | 43 +- .../markdown/gfm-test-suite/format.test.js | 2 +- .../heading/__snapshots__/format.test.js.snap | 21 - .../setext/__snapshots__/format.test.js.snap | 185 +++ tests/format/markdown/heading/setext/child.md | 10 + .../heading/setext/definition-before.md | 11 + .../markdown/heading/setext/format.test.js | 30 + .../markdown/heading/setext/issue-6013-2.md | 3 + .../markdown/heading/setext/issue-6013.md | 7 + .../markdown/heading/{ => setext}/setext.md | 0 .../html/__snapshots__/format.test.js.snap | 882 ++++++++++++ tests/format/markdown/html/format.test.js | 2 + tests/format/markdown/html/inline-html.md | 28 + tests/format/markdown/html/inline-vs-block.md | 2 + .../markdown/html/multiline-attribute.md | 33 + .../image/__snapshots__/format.test.js.snap | 49 + tests/format/markdown/image/alt.md | 17 + .../link/__snapshots__/format.test.js.snap | 47 +- tests/format/markdown/link/escape-in-link.md | 1 + .../__snapshots__/format.test.js.snap | 63 +- .../__snapshots__/format.test.js.snap | 8 + .../case-and-space/case-and-space.md | 4 + tests/format/markdown/linkReference/cjk.md | 2 + .../liquid/__snapshots__/format.test.js.snap | 6 +- .../list/__snapshots__/format.test.js.snap | 1179 ++++++++++++++++- .../list/followed-by-indented-things.md | 127 ++ .../__snapshots__/format.test.js.snap | 37 + .../markdown/list/task-list/format.test.js | 1 + .../format/markdown/list/task-list/in-html.md | 11 + .../__snapshots__/format.test.js.snap | 12 +- .../math/__snapshots__/format.test.js.snap | 5 +- .../__snapshots__/format.test.js.snap | 6 +- .../__snapshots__/format.test.js.snap | 8 +- tests/format/markdown/splitCjkText/link.md | 2 + .../table/__snapshots__/format.test.js.snap | 18 + tests/format/markdown/table/escape.md | 9 + .../__snapshots__/format.test.js.snap | 547 +++++++- tests/format/markdown/wiki-link/multi-line.md | 66 + .../word/__snapshots__/format.test.js.snap | 4 +- yarn.lock | 757 ++++++++++- 84 files changed, 6944 insertions(+), 596 deletions(-) create mode 100644 changelog_unreleased/markdown/18277.md create mode 100644 changelog_unreleased/markdown/18473.md create mode 100644 src/language-markdown/parse/micromark/mdast-util-gfm.js create mode 100644 src/language-markdown/parse/micromark/micromark-extension-html-text.js create mode 100644 src/language-markdown/parse/micromark/micromark-extension-liquid.js create mode 100644 src/language-markdown/parse/parse-markdown.js rename src/language-markdown/parse/{parse.js => parse-mdx.js} (60%) create mode 100644 src/language-markdown/print/heading.js create mode 100644 src/language-markdown/print/ignored.js create mode 100644 tests/format/markdown/blockquote/check-accidental.md create mode 100644 tests/format/markdown/blockquote/interrupt-others.md create mode 100644 tests/format/markdown/blockquote/list.md create mode 100644 tests/format/markdown/break/list-item/__snapshots__/format.test.js.snap create mode 100644 tests/format/markdown/break/list-item/format.test.js create mode 100644 tests/format/markdown/break/list-item/list-item.md create mode 100644 tests/format/markdown/heading/setext/__snapshots__/format.test.js.snap create mode 100644 tests/format/markdown/heading/setext/child.md create mode 100644 tests/format/markdown/heading/setext/definition-before.md create mode 100644 tests/format/markdown/heading/setext/format.test.js create mode 100644 tests/format/markdown/heading/setext/issue-6013-2.md create mode 100644 tests/format/markdown/heading/setext/issue-6013.md rename tests/format/markdown/heading/{ => setext}/setext.md (100%) create mode 100644 tests/format/markdown/html/inline-html.md create mode 100644 tests/format/markdown/html/inline-vs-block.md create mode 100644 tests/format/markdown/html/multiline-attribute.md create mode 100644 tests/format/markdown/image/alt.md create mode 100644 tests/format/markdown/link/escape-in-link.md create mode 100644 tests/format/markdown/list/followed-by-indented-things.md create mode 100644 tests/format/markdown/list/task-list/__snapshots__/format.test.js.snap create mode 100644 tests/format/markdown/list/task-list/format.test.js create mode 100644 tests/format/markdown/list/task-list/in-html.md diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 781717cc7..2cdc58bc7 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -75,9 +75,13 @@ matchManagers: ["github-actions"], }, { - groupName: "docusaurus", + groupName: "Docusaurus", matchPackageNames: ["@docusaurus/*"], }, + { + groupName: "Markdown dependencies", + matchPackageNames: ["micromark-*", "mdast-", "remark-", "unified"], + }, ], ignoreDeps: [ // It's a dependency of `remark-parse`, use same version to reduce size diff --git a/changelog_unreleased/markdown/18277.md b/changelog_unreleased/markdown/18277.md new file mode 100644 index 000000000..6abef72af --- /dev/null +++ b/changelog_unreleased/markdown/18277.md @@ -0,0 +1,5 @@ +#### [HIGHLIGHT] Upgrade parser to latest micromark (#18277 by @seiyab, @j-f1, @fisker) + +We've upgraded Prettier's Markdown parser from the outdated remark-parse v8 to the modern micromark v4. This upgrade significantly enhances CommonMark and GFM compliance, resolves numerous long-standing parsing bugs, and lays a stronger foundation for future enhancements. + +A huge thank you to @seiyab for their tremendous effort in driving this major upgrade! diff --git a/changelog_unreleased/markdown/18473.md b/changelog_unreleased/markdown/18473.md new file mode 100644 index 000000000..0b697d4bf --- /dev/null +++ b/changelog_unreleased/markdown/18473.md @@ -0,0 +1,39 @@ +#### Support setext headings (#18473 by @fisker) + + +```md + +Setext Heading 1 +================ + +Setext Heading 2 +---------------- + +Multiline +Setext +Heading +------- + + +# Setext Heading 1 + +## Setext Heading 2 + +Multiline +Setext +Heading + +--- + + +Setext Heading 1 +================ + +Setext Heading 2 +---------------- + +Multiline +Setext +Heading +------- +``` diff --git a/cspell.json b/cspell.json index bb540d307..856d5e60e 100644 --- a/cspell.json +++ b/cspell.json @@ -153,8 +153,8 @@ "llms", "lydell", "Marek", - "marko", "Mariusz", + "marko", "Masad", "Matejka", "Mateusz", @@ -162,6 +162,7 @@ "Memberish", "meriyah", "Michał", + "micromark", "Microsyntax", "Mikael", "minimise", @@ -231,6 +232,8 @@ "sbdchd", "scandir", "sdbm", + "seiyab", + "Setext", "setlocal", "setq", "shellsession", diff --git a/jest.config.js b/jest.config.js index 49fbbb8a7..9849f485e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -84,6 +84,9 @@ const config = { "/tests/integration/integration-test-setup.js", ], runner: "jest-light-runner/child-process", + testEnvironmentOptions: { + customExportConditions: ["development"], + }, snapshotSerializers: [ "jest-snapshot-serializer-raw", "jest-snapshot-serializer-ansi", diff --git a/package.json b/package.json index 7808baec3..258b4b355 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,18 @@ "json5": "2.2.3", "leven": "4.1.0", "linguist-languages": "9.1.11", + "mdast-util-from-markdown": "2.0.2", + "mdast-util-gfm": "3.1.0", + "mdast-util-math": "3.0.0", + "mdast-util-wiki-link": "0.1.2", "meriyah": "7.0.0", + "micromark-extension-gfm": "3.0.0", + "micromark-extension-math": "3.1.0", + "micromark-extension-wiki-link": "0.0.4", + "micromark-factory-space": "2.0.1", + "micromark-util-character": "2.1.1", + "micromark-util-symbol": "2.0.1", + "micromark-util-types": "2.0.2", "micromatch": "4.0.8", "minimist": "1.2.8", "n-readlines": "3.4.0", diff --git a/scripts/build/packages/prettier.js b/scripts/build/packages/prettier.js index 080205dfe..9c4ac206e 100644 --- a/scripts/build/packages/prettier.js +++ b/scripts/build/packages/prettier.js @@ -725,6 +725,10 @@ const pluginFiles = [ { input: "src/plugins/markdown.js", replaceModule: [ + { + module: getPackageFile("decode-named-character-reference/index.dom.js"), + path: getPackageFile("decode-named-character-reference"), + }, { module: getPackageFile("parse-entities/decode-entity.browser.js"), path: getPackageFile("parse-entities/decode-entity.js"), diff --git a/src/language-markdown/clean.js b/src/language-markdown/clean.js index 031283dd4..a3a0d1ee1 100644 --- a/src/language-markdown/clean.js +++ b/src/language-markdown/clean.js @@ -35,10 +35,6 @@ function clean(original, cloned, parent) { cloned.value = original.value.replaceAll("\n", " "); } - if (original.type === "wikiLink") { - cloned.value = original.value.trim().replaceAll(/[\t\n]+/g, " "); - } - if ( original.type === "definition" || original.type === "linkReference" || @@ -47,6 +43,14 @@ function clean(original, cloned, parent) { cloned.label = collapseWhiteSpace(original.label); } + // Maybe we should fix this + if ( + original.type === "imageReference" && + original.referenceType === "collapsed" + ) { + cloned.alt = collapseWhiteSpace(original.alt); + } + if ( (original.type === "link" || original.type === "image") && original.url && diff --git a/src/language-markdown/embed.js b/src/language-markdown/embed.js index 19cbe6f19..7e0d8aea8 100644 --- a/src/language-markdown/embed.js +++ b/src/language-markdown/embed.js @@ -41,7 +41,9 @@ function embed(path, options) { } const doc = await textToDoc( - getFencedCodeBlockValue(node, options.originalText), + options.parser === "mdx" + ? getFencedCodeBlockValue(node, options.originalText) + : node.value, textToDocOptions, ); diff --git a/src/language-markdown/parse/index.js b/src/language-markdown/parse/index.js index 21ae39b9a..67f8042e9 100644 --- a/src/language-markdown/parse/index.js +++ b/src/language-markdown/parse/index.js @@ -1 +1,2 @@ -export { parseMarkdown, parseMdx } from "./parse.js"; +export { parseMarkdown } from "./parse-markdown.js"; +export { parseMdx } from "./parse-mdx.js"; diff --git a/src/language-markdown/parse/micromark/mdast-util-gfm.js b/src/language-markdown/parse/micromark/mdast-util-gfm.js new file mode 100644 index 000000000..616ba02e1 --- /dev/null +++ b/src/language-markdown/parse/micromark/mdast-util-gfm.js @@ -0,0 +1,33 @@ +// There is no way to disable autolink +// Hackly find and replace `gfm-autolink-literal` +// https://github.com/remarkjs/remark-gfm/issues/16#issuecomment-899046315 + +import { gfmFromMarkdown as originalGfmFromMarkdown } from "mdast-util-gfm"; +import * as assert from "#universal/assert"; + +/** +@import {Extension} from "mdast-util-from-markdown"; +*/ + +/** +@returns {Extension[]} +*/ +export function gfmFromMarkdown() { + const mdastExtensions = originalGfmFromMarkdown(); + const autolinkExtension = mdastExtensions.find((extension) => + Boolean(extension.enter.literalAutolink), + ); + + if (process.env.NODE_ENV !== "production") { + assert.ok( + autolinkExtension && + Array.isArray(autolinkExtension.transforms) && + autolinkExtension.transforms.length === 1, + ); + } + + // Prevent the autolink extension generate nodes without position + autolinkExtension.transforms = []; + + return mdastExtensions; +} diff --git a/src/language-markdown/parse/micromark/micromark-extension-html-text.js b/src/language-markdown/parse/micromark/micromark-extension-html-text.js new file mode 100644 index 000000000..e0a09be25 --- /dev/null +++ b/src/language-markdown/parse/micromark/micromark-extension-html-text.js @@ -0,0 +1,812 @@ +// copied from https://github.com/micromark/micromark/blob/774a70c6bae6dd94486d3385dbd9a0f14550b709/packages/micromark-core-commonmark/dev/lib/html-text.js +// and modified to preserve whitespace inside quoted attribute values + +/** + * @import { + * Code, + * Construct, + * State, + * TokenizeContext, + * Tokenizer + * } from 'micromark-util-types' + */ + +import { factorySpace } from "micromark-factory-space"; +import { + asciiAlpha, + asciiAlphanumeric, + markdownLineEnding, + markdownLineEndingOrSpace, + markdownSpace, +} from "micromark-util-character"; +import { codes, constants, types } from "micromark-util-symbol"; + +/** @type {Construct} */ +const htmlText = { + name: "htmlText", + tokenize: tokenizeHtmlText, + add: "before", +}; + +/** + * @this {TokenizeContext} + * Context. + * @type {Tokenizer} + */ +function tokenizeHtmlText(effects, ok, nok) { + // eslint-disable-next-line unicorn/no-this-assignment + const self = this; + /** @type {NonNullable | undefined} */ + let marker; + /** @type {number} */ + let index; + /** @type {State} */ + let returnState; + + return start; + + /** + * Start of HTML (text). + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function start(code) { + assert(code === codes.lessThan, "expected `<`"); + effects.enter(types.htmlText); + effects.enter(types.htmlTextData); + effects.consume(code); + return open; + } + + /** + * After `<`, at tag name or other stuff. + * + * ```markdown + * > | a c + * ^ + * > | a c + * ^ + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function open(code) { + if (code === codes.exclamationMark) { + effects.consume(code); + return declarationOpen; + } + + if (code === codes.slash) { + effects.consume(code); + return tagCloseStart; + } + + if (code === codes.questionMark) { + effects.consume(code); + return instruction; + } + + // ASCII alphabetical. + if (asciiAlpha(code)) { + effects.consume(code); + return tagOpen; + } + + return nok(code); + } + + /** + * After ` | a c + * ^ + * > | a c + * ^ + * > | a &<]]> c + * ^ + * ``` + * + * @type {State} + */ + function declarationOpen(code) { + if (code === codes.dash) { + effects.consume(code); + return commentOpenInside; + } + + if (code === codes.leftSquareBracket) { + effects.consume(code); + index = 0; + return cdataOpenInside; + } + + if (asciiAlpha(code)) { + effects.consume(code); + return declaration; + } + + return nok(code); + } + + /** + * In a comment, after ` | a c + * ^ + * ``` + * + * @type {State} + */ + function commentOpenInside(code) { + if (code === codes.dash) { + effects.consume(code); + return commentEnd; + } + + return nok(code); + } + + /** + * In comment. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function comment(code) { + if (code === codes.eof) { + return nok(code); + } + + if (code === codes.dash) { + effects.consume(code); + return commentClose; + } + + if (markdownLineEnding(code)) { + returnState = comment; + return lineEndingBefore(code); + } + + effects.consume(code); + return comment; + } + + /** + * In comment, after `-`. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function commentClose(code) { + if (code === codes.dash) { + effects.consume(code); + return commentEnd; + } + + return comment(code); + } + + /** + * In comment, after `--`. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function commentEnd(code) { + return code === codes.greaterThan + ? end(code) + : code === codes.dash + ? commentClose(code) + : comment(code); + } + + /** + * After ` | a &<]]> b + * ^^^^^^ + * ``` + * + * @type {State} + */ + function cdataOpenInside(code) { + const value = constants.cdataOpeningString; + + if (code === value.charCodeAt(index++)) { + effects.consume(code); + return index === value.length ? cdata : cdataOpenInside; + } + + return nok(code); + } + + /** + * In CDATA. + * + * ```markdown + * > | a &<]]> b + * ^^^ + * ``` + * + * @type {State} + */ + function cdata(code) { + if (code === codes.eof) { + return nok(code); + } + + if (code === codes.rightSquareBracket) { + effects.consume(code); + return cdataClose; + } + + if (markdownLineEnding(code)) { + returnState = cdata; + return lineEndingBefore(code); + } + + effects.consume(code); + return cdata; + } + + /** + * In CDATA, after `]`, at another `]`. + * + * ```markdown + * > | a &<]]> b + * ^ + * ``` + * + * @type {State} + */ + function cdataClose(code) { + if (code === codes.rightSquareBracket) { + effects.consume(code); + return cdataEnd; + } + + return cdata(code); + } + + /** + * In CDATA, after `]]`, at `>`. + * + * ```markdown + * > | a &<]]> b + * ^ + * ``` + * + * @type {State} + */ + function cdataEnd(code) { + if (code === codes.greaterThan) { + return end(code); + } + + if (code === codes.rightSquareBracket) { + effects.consume(code); + return cdataEnd; + } + + return cdata(code); + } + + /** + * In declaration. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function declaration(code) { + if (code === codes.eof || code === codes.greaterThan) { + return end(code); + } + + if (markdownLineEnding(code)) { + returnState = declaration; + return lineEndingBefore(code); + } + + effects.consume(code); + return declaration; + } + + /** + * In instruction. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function instruction(code) { + if (code === codes.eof) { + return nok(code); + } + + if (code === codes.questionMark) { + effects.consume(code); + return instructionClose; + } + + if (markdownLineEnding(code)) { + returnState = instruction; + return lineEndingBefore(code); + } + + effects.consume(code); + return instruction; + } + + /** + * In instruction, after `?`, at `>`. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function instructionClose(code) { + return code === codes.greaterThan ? end(code) : instruction(code); + } + + /** + * After ` | a c + * ^ + * ``` + * + * @type {State} + */ + function tagCloseStart(code) { + // ASCII alphabetical. + if (asciiAlpha(code)) { + effects.consume(code); + return tagClose; + } + + return nok(code); + } + + /** + * After ` | a c + * ^ + * ``` + * + * @type {State} + */ + function tagClose(code) { + // ASCII alphanumerical and `-`. + if (code === codes.dash || asciiAlphanumeric(code)) { + effects.consume(code); + return tagClose; + } + + return tagCloseBetween(code); + } + + /** + * In closing tag, after tag name. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function tagCloseBetween(code) { + if (markdownLineEnding(code)) { + returnState = tagCloseBetween; + return lineEndingBefore(code); + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagCloseBetween; + } + + return end(code); + } + + /** + * After ` | a c + * ^ + * ``` + * + * @type {State} + */ + function tagOpen(code) { + // ASCII alphanumerical and `-`. + if (code === codes.dash || asciiAlphanumeric(code)) { + effects.consume(code); + return tagOpen; + } + + if ( + code === codes.slash || + code === codes.greaterThan || + markdownLineEndingOrSpace(code) + ) { + return tagOpenBetween(code); + } + + return nok(code); + } + + /** + * In opening tag, after tag name. + * + * ```markdown + * > | a c + * ^ + * ``` + * + * @type {State} + */ + function tagOpenBetween(code) { + if (code === codes.slash) { + effects.consume(code); + return end; + } + + // ASCII alphabetical and `:` and `_`. + if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) { + effects.consume(code); + return tagOpenAttributeName; + } + + if (markdownLineEnding(code)) { + returnState = tagOpenBetween; + return lineEndingBefore(code); + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenBetween; + } + + return end(code); + } + + /** + * In attribute name. + * + * ```markdown + * > | a d + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeName(code) { + // ASCII alphabetical and `-`, `.`, `:`, and `_`. + if ( + code === codes.dash || + code === codes.dot || + code === codes.colon || + code === codes.underscore || + asciiAlphanumeric(code) + ) { + effects.consume(code); + return tagOpenAttributeName; + } + + return tagOpenAttributeNameAfter(code); + } + + /** + * After attribute name, before initializer, the end of the tag, or + * whitespace. + * + * ```markdown + * > | a d + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeNameAfter(code) { + if (code === codes.equalsTo) { + effects.consume(code); + return tagOpenAttributeValueBefore; + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeNameAfter; + return lineEndingBefore(code); + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenAttributeNameAfter; + } + + return tagOpenBetween(code); + } + + /** + * Before unquoted, double quoted, or single quoted attribute value, allowing + * whitespace. + * + * ```markdown + * > | a e + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeValueBefore(code) { + if ( + code === codes.eof || + code === codes.lessThan || + code === codes.equalsTo || + code === codes.greaterThan || + code === codes.graveAccent + ) { + return nok(code); + } + + if (code === codes.quotationMark || code === codes.apostrophe) { + effects.consume(code); + marker = code; + return tagOpenAttributeValueQuoted; + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeValueBefore; + return lineEndingBefore(code); + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenAttributeValueBefore; + } + + effects.consume(code); + return tagOpenAttributeValueUnquoted; + } + + /** + * In double or single quoted attribute value. + * + * ```markdown + * > | a e + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeValueQuoted(code) { + if (code === marker) { + effects.consume(code); + marker = undefined; + return tagOpenAttributeValueQuotedAfter; + } + + if (code === codes.eof) { + return nok(code); + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeValueQuoted; + return lineEndingBefore(code); + } + + effects.consume(code); + return tagOpenAttributeValueQuoted; + } + + /** + * In unquoted attribute value. + * + * ```markdown + * > | a e + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeValueUnquoted(code) { + if ( + code === codes.eof || + code === codes.quotationMark || + code === codes.apostrophe || + code === codes.lessThan || + code === codes.equalsTo || + code === codes.graveAccent + ) { + return nok(code); + } + + if ( + code === codes.slash || + code === codes.greaterThan || + markdownLineEndingOrSpace(code) + ) { + return tagOpenBetween(code); + } + + effects.consume(code); + return tagOpenAttributeValueUnquoted; + } + + /** + * After double or single quoted attribute value, before whitespace or the end + * of the tag. + * + * ```markdown + * > | a e + * ^ + * ``` + * + * @type {State} + */ + function tagOpenAttributeValueQuotedAfter(code) { + if ( + code === codes.slash || + code === codes.greaterThan || + markdownLineEndingOrSpace(code) + ) { + return tagOpenBetween(code); + } + + return nok(code); + } + + /** + * In certain circumstances of a tag where only an `>` is allowed. + * + * ```markdown + * > | a e + * ^ + * ``` + * + * @type {State} + */ + function end(code) { + if (code === codes.greaterThan) { + effects.consume(code); + effects.exit(types.htmlTextData); + effects.exit(types.htmlText); + return ok; + } + + return nok(code); + } + + /** + * At eol. + * + * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about + * > empty tokens. + * + * ```markdown + * > | a + * ``` + * + * @type {State} + */ + function lineEndingBefore(code) { + assert(returnState, "expected return state"); + assert(markdownLineEnding(code), "expected eol"); + effects.exit(types.htmlTextData); + effects.enter(types.lineEnding); + effects.consume(code); + effects.exit(types.lineEnding); + return lineEndingAfter; + } + + /** + * After eol, at optional whitespace. + * + * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about + * > empty tokens. + * + * ```markdown + * | a + * ^ + * ``` + * + * @type {State} + */ + function lineEndingAfter(code) { + // Always populated by defaults. + assert( + self.parser.constructs.disable.null, + "expected `disable.null` to be populated", + ); + + if (!markdownSpace(code)) { + return lineEndingAfterPrefix(code); + } + + if (marker === codes.quotationMark || marker === codes.apostrophe) { + return lineEndingAfterPrefix(code); + } + + return factorySpace( + effects, + lineEndingAfterPrefix, + types.linePrefix, + self.parser.constructs.disable.null.includes("codeIndented") + ? undefined + : constants.tabSize, + )(code); + } + + /** + * After eol, after optional whitespace. + * + * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about + * > empty tokens. + * + * ```markdown + * | a + * ^ + * ``` + * + * @type {State} + */ + function lineEndingAfterPrefix(code) { + effects.enter(types.htmlTextData); + return returnState(code); + } +} + +function overrideHtmlTextSyntax() { + return { + text: { + [codes.lessThan]: htmlText, + }, + }; +} + +// eslint-disable-next-line no-unused-vars +function assert(..._args) { + // Do nothing in Prettier +} + +export { overrideHtmlTextSyntax }; diff --git a/src/language-markdown/parse/micromark/micromark-extension-liquid.js b/src/language-markdown/parse/micromark/micromark-extension-liquid.js new file mode 100644 index 000000000..8d2db09f5 --- /dev/null +++ b/src/language-markdown/parse/micromark/micromark-extension-liquid.js @@ -0,0 +1,112 @@ +import { markdownLineEnding } from "micromark-util-character"; +import { codes, types } from "micromark-util-symbol"; + +/** + * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension + * @typedef {import('mdast-util-from-markdown').Token} Token + * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext + * @typedef {import('mdast-util-from-markdown').Handle} Handle + * @typedef {import('micromark-util-types').State} State + */ + +const nodeType = "liquidNode"; + +/** + * @returns {FromMarkdownExtension} + */ +function liquidFromMarkdown() { + return { + canContainEols: [nodeType], + enter: { [nodeType]: enterInlineMath }, + exit: { [nodeType]: exitInlineMath }, + }; + + /** @type {Handle} */ + function enterInlineMath(token) { + this.enter( + // @ts-expect-error + { type: nodeType }, + token, + ); + this.buffer(); + } + + /** @type {Handle} */ + function exitInlineMath(token) { + const d = this.resume(); + /** @type {any} */ + const node = this.stack.at(-1); + node.value = d; + this.exit(token); + } +} + +/** + * @returns {import('micromark-util-types').Extension} + */ +function liquidSyntax() { + return { + text: { + [codes.leftCurlyBrace]: { + name: "liquid", + tokenize: liquidTokenize, + }, + }, + }; + + function liquidTokenize(effects, ok, nok) { + return start; + + /** @type {State} */ + function start(code) { + effects.enter("liquidNode"); + effects.enter(types.data); + effects.consume(code); + return function (code) { + switch (code) { + case codes.percentSign: + case codes.leftCurlyBrace: + effects.consume(code); + return inside; + default: + return nok; + } + }; + } + + /** @type {State} */ + function inside(code) { + switch (code) { + case codes.percentSign: + case codes.rightCurlyBrace: + effects.consume(code); + return mayExit; + case codes.eof: + return nok; + default: + if (markdownLineEnding(code)) { + effects.enter(types.lineEnding); + effects.consume(code); + effects.exit(types.lineEnding); + return inside; + } + effects.consume(code); + return inside; + } + } + + /** @type {State} */ + function mayExit(code) { + if (code !== codes.rightCurlyBrace) { + effects.consume(code); + return inside; + } + effects.consume(code); + effects.exit(types.data); + effects.exit(nodeType); + return ok; + } + } +} + +export { liquidFromMarkdown, liquidSyntax }; diff --git a/src/language-markdown/parse/parse-markdown.js b/src/language-markdown/parse/parse-markdown.js new file mode 100644 index 000000000..78fb6412d --- /dev/null +++ b/src/language-markdown/parse/parse-markdown.js @@ -0,0 +1,58 @@ +import { fromMarkdown } from "mdast-util-from-markdown"; +import { mathFromMarkdown } from "mdast-util-math"; +import { fromMarkdown as wikiLinkFromMarkdown } from "mdast-util-wiki-link"; +import { gfm as gfmSyntax } from "micromark-extension-gfm"; +import { math as mathSyntax } from "micromark-extension-math"; +import { syntax as wikiLinkSyntax } from "micromark-extension-wiki-link"; +import parseFrontMatter from "../../main/front-matter/parse.js"; +import { gfmFromMarkdown } from "./micromark/mdast-util-gfm.js"; +import { overrideHtmlTextSyntax } from "./micromark/micromark-extension-html-text.js"; +import { + liquidFromMarkdown, + liquidSyntax, +} from "./micromark/micromark-extension-liquid.js"; + +let markdownParseOptions; +function getMarkdownParseOptions() { + return (markdownParseOptions ??= { + extensions: [ + gfmSyntax(), + mathSyntax(), + wikiLinkSyntax(), + liquidSyntax(), + overrideHtmlTextSyntax(), + ], + mdastExtensions: [ + gfmFromMarkdown(), + mathFromMarkdown(), + wikiLinkFromMarkdown(), + liquidFromMarkdown(), + ], + }); +} + +function parseMarkdown(text) { + const { frontMatter, content } = parseFrontMatter(text); + const ast = fromMarkdown(content, getMarkdownParseOptions()); + + if (frontMatter) { + const [start, end] = [frontMatter.start, frontMatter.end].map( + ({ line, column, index }) => ({ + line, + column: column + 1, + offset: index, + }), + ); + + ast.children.unshift({ + ...frontMatter, + // @ts-expect-error -- Expected + type: "frontMatter", + position: { start, end }, + }); + } + + return ast; +} + +export { parseMarkdown }; diff --git a/src/language-markdown/parse/parse.js b/src/language-markdown/parse/parse-mdx.js similarity index 60% rename from src/language-markdown/parse/parse.js rename to src/language-markdown/parse/parse-mdx.js index 193da46fd..38cff8d44 100644 --- a/src/language-markdown/parse/parse.js +++ b/src/language-markdown/parse/parse-mdx.js @@ -22,27 +22,21 @@ import wikiLink from "./unified-plugins/wiki-link.js"; * interface Sentence { children: Array } * interface InlineCode { children: Array } */ -function createParse({ isMDX }) { - return (text) => { - const processor = unified() - .use(remarkParse, { - commonmark: true, - ...(isMDX && { blocks: [BLOCKS_REGEX] }), - }) - .use(footnotes) - .use(frontMatter) - .use(remarkMath) - .use(isMDX ? esSyntax : noop) - .use(liquid) - .use(isMDX ? htmlToJsx : noop) - .use(wikiLink); - return processor.run(processor.parse(text)); - }; + +function parseMdx(text) { + const processor = unified() + .use(remarkParse, { + commonmark: true, + blocks: [BLOCKS_REGEX], + }) + .use(footnotes) + .use(frontMatter) + .use(remarkMath) + .use(esSyntax) + .use(liquid) + .use(htmlToJsx) + .use(wikiLink); + return processor.run(processor.parse(text)); } -function noop() {} - -const parseMarkdown = /* @__PURE__ */ createParse({ isMDX: false }); -const parseMdx = /* @__PURE__ */ createParse({ isMDX: true }); - -export { parseMarkdown, parseMdx }; +export { parseMdx }; diff --git a/src/language-markdown/print/children.js b/src/language-markdown/print/children.js index daaa5e0a3..4cf826c88 100644 --- a/src/language-markdown/print/children.js +++ b/src/language-markdown/print/children.js @@ -3,6 +3,7 @@ import { INLINE_NODE_TYPES, INLINE_NODE_WRAPPER_TYPES, isPrettierIgnore, + isSetextHeading, } from "../utilities.js"; /** @@ -58,26 +59,62 @@ function shouldPrePrintHardline({ node, parent }) { const SIBLING_NODE_TYPES = new Set(["listItem", "definition"]); -function shouldPrePrintDoubleHardline({ node, previous, parent }, options) { - if ( - isLooseListItem(previous, options) || - (node.type === "list" && - parent.type === "listItem" && - previous.type === "code") - ) { - return true; +/** + * @param {AstPath} path + * @returns {boolean} + */ +function shouldPrePrintDoubleHardline(path, options) { + const { node, previous, parent } = path; + + if (options.parser === "mdx") { + if ( + isLooseListItemLegacy(previous, options) || + (node.type === "list" && + parent.type === "listItem" && + previous.type === "code") + ) { + return true; + } + } else { + if ( + isSetextHeading(node) && + node.position.start.line < previous.position.end.line + ) { + return false; + } + + if ( + isPreviousNodeLooseListItem(path) || + (node.type === "list" && + parent.type === "listItem" && + previous.type === "code") + ) { + return true; + } } const isSequence = previous.type === node.type; const isSiblingNode = isSequence && SIBLING_NODE_TYPES.has(node.type); - const isInTightListItem = - parent.type === "listItem" && - (node.type === "list" || !isLooseListItem(parent, options)); + let isInTightListItem; + if (options.parser === "mdx") { + isInTightListItem = + parent.type === "listItem" && + (node.type === "list" || !isLooseListItemLegacy(parent, options)); + } else { + isInTightListItem = + parent.type === "listItem" && + (node.type === "list" || !path.callParent(isLooseListItem)); + } const isPrevNodePrettierIgnore = isPrettierIgnore(previous) === "next"; const isBlockHtmlWithoutBlankLineBetweenPrevHtml = node.type === "html" && previous.type === "html" && previous.position.end.line + 1 === node.position.start.line; + const isBlockHtmlWithoutBlankLineBetweenPrevParagraph = + options.parser !== "mdx" && + node.type === "html" && + previous.type === "paragraph" && + previous.position.end.line + 1 === node.position.start.line; const isHtmlDirectAfterListItem = node.type === "html" && parent.type === "listItem" && @@ -89,6 +126,7 @@ function shouldPrePrintDoubleHardline({ node, previous, parent }, options) { isInTightListItem || isPrevNodePrettierIgnore || isBlockHtmlWithoutBlankLineBetweenPrevHtml || + isBlockHtmlWithoutBlankLineBetweenPrevParagraph || isHtmlDirectAfterListItem ); } @@ -100,7 +138,7 @@ function shouldPrePrintTripleHardline({ node, previous }) { return isPrevNodeList && isIndentedCode; } -function isLooseListItem(node, options) { +function isLooseListItemLegacy(node, options) { return ( node.type === "listItem" && (node.spread || @@ -110,4 +148,29 @@ function isLooseListItem(node, options) { ); } +function isLooseListItem({ node, parent, next }) { + return ( + node.type === "listItem" && + (node.spread || + (parent.type === "list" && + next?.type === "listItem" && + node.position.end.line + 1 < next.position.start.line)) + ); +} + +/** + * @param {AstPath} path + * @returns {boolean} + */ +function isPreviousNodeLooseListItem(path) { + if (path.index === 0) { + return false; + } + return isLooseListItem({ + node: path.previous, + parent: path.parent, + next: path.node, + }); +} + export { printChildren }; diff --git a/src/language-markdown/print/heading.js b/src/language-markdown/print/heading.js new file mode 100644 index 000000000..10e75a567 --- /dev/null +++ b/src/language-markdown/print/heading.js @@ -0,0 +1,31 @@ +import { hardline } from "../../document/index.js"; +import { isSetextHeading } from "../utilities.js"; +import { printChildren } from "./children.js"; + +function printAtxHeading(path, options, print) { + return [ + "#".repeat(path.node.depth) + " ", + printChildren(path, options, print), + ]; +} + +function printSetextHeading(path, options, print) { + const { originalText } = options; + const { node } = path; + const end = node.position.end.offset; + const lineStart = originalText.lastIndexOf("\n", end - 1) + 1; + const lastLine = originalText.slice(lineStart, end); + const start = Math.max(lastLine.indexOf("="), lastLine.indexOf("-")); + const underline = lastLine.slice(start); + return [printChildren(path, options, print), hardline, underline]; +} + +function printHeading(path, options, print) { + if (options.parser !== "mdx" && isSetextHeading(path.node)) { + return printSetextHeading(path, options, print); + } + + return printAtxHeading(path, options, print); +} + +export { printHeading }; diff --git a/src/language-markdown/print/ignored.js b/src/language-markdown/print/ignored.js new file mode 100644 index 000000000..99cc25666 --- /dev/null +++ b/src/language-markdown/print/ignored.js @@ -0,0 +1,35 @@ +/** + * @import AstPath from "../../common/ast-path.js"; + * @import {Doc} from "../../document/index.js"; + */ + +/** + * @param {AstPath} path + * @param {*} options + * @returns {Doc} + */ +function printPrettierIgnored(path, options) { + const originalText = options.originalText.slice( + path.node.position.start.offset, + path.node.position.end.offset, + ); + + if (options.parser === "mdx") { + return originalText; + } + + switch (path.node.type) { + case "list": + if ( + path.findAncestor((p) => p.type === "blockquote") && + options.proseWrap !== "always" + ) { + return originalText.replace(/\n>\s*$/, ""); + } + return originalText; + default: + return originalText; + } +} + +export { printPrettierIgnored }; diff --git a/src/language-markdown/print/index.js b/src/language-markdown/print/index.js index 888d7260e..f81f4f600 100644 --- a/src/language-markdown/print/index.js +++ b/src/language-markdown/print/index.js @@ -1 +1,2 @@ +export { printPrettierIgnored } from "./ignored.js"; export { printMdast } from "./mdast.js"; diff --git a/src/language-markdown/print/list.js b/src/language-markdown/print/list.js index 86ae1e663..1a56bff36 100644 --- a/src/language-markdown/print/list.js +++ b/src/language-markdown/print/list.js @@ -25,6 +25,8 @@ function printList(path, options, print) { options, ); + const minIndent = requiredIndent(path); + return printChildren(path, options, print, { processor() { const prefix = getPrefix(); @@ -47,6 +49,129 @@ function printList(path, options, print) { ), ]; + function getPrefix() { + const rawPrefix = node.ordered + ? (path.isFirst + ? node.start + : isGitDiffFriendlyOrderedList + ? 1 + : node.start + path.index) + + (nthSiblingIndex % 2 === 0 ? ". " : ") ") + : nthSiblingIndex % 2 === 0 + ? "- " + : "* "; + + let prefix = + node.isAligned && node.ordered + ? alignListPrefix(rawPrefix, options) + : rawPrefix; + + if (prefix.length >= minIndent) { + return prefix; + } + + prefix = prefix.trimEnd(); + const trailingSpaces = Math.min(minIndent - prefix.length, 4); // 5+ will cause indented code block + if (trailingSpaces > 0) { + prefix += " ".repeat(trailingSpaces); + } + const leadingSpaces = Math.min(minIndent - prefix.length, 3); // 4+ will cause indented code block + if (leadingSpaces > 0) { + prefix = " ".repeat(leadingSpaces) + prefix; + } + + return prefix; + } + }, + }); +} + +function printListItem(path, options, print, listPrefix) { + const { node } = path; + const prefix = node.checked === null ? "" : node.checked ? "[x] " : "[ ] "; + return [ + prefix, + printChildren(path, options, print, { + processor({ node, isFirst }) { + if ( + (isFirst && node.type !== "list") || + (node.type === "code" && node.isIndented) + ) { + return align(" ".repeat(prefix.length), print()); + } + + const alignment = " ".repeat( + clamp(options.tabWidth - listPrefix.length, 0, 3), // 4+ will cause indented code block + ); + return [alignment, align(alignment, print())]; + }, + }), + ]; +} + +/** + * If the list is followed by a indented code block, its content have to be + * indented deeper than the code block. + * @param {AstPath} path + * @return {number} + */ +function requiredIndent(path) { + const { node, next } = path; + if (node.checked === null) { + return 0; + } + if (!(next?.type === "code" && next.isIndented)) { + return 0; + } + + const leadingSpaces = /^[ \t]*/.exec(next.value)?.[0] ?? ""; + return ( + 4 + // base indent of the code block + [...leadingSpaces].reduce( + (count, char) => count + (char === "\t" ? 4 : 1), + 0, + ) + + 1 // at least one space more than the code block + ); +} + +/** + * @param {AstPath} path + * @param {*} options + * @param {() => Doc} print + * @return {Doc} + */ +function printListLegacy(path, options, print) { + const { node } = path; + const nthSiblingIndex = getNthListSiblingIndex(node, path.parent); + + const isGitDiffFriendlyOrderedList = hasGitDiffFriendlyOrderedList( + node, + options, + ); + + return printChildren(path, options, print, { + processor() { + const prefix = getPrefix(); + const { node: childNode } = path; + + if ( + childNode.children.length === 2 && + childNode.children[1].type === "html" && + childNode.children[0].position.start.column !== + childNode.children[1].position.start.column + ) { + return [prefix, printListItemLegacy(path, options, print, prefix)]; + } + + return [ + prefix, + align( + " ".repeat(prefix.length), + printListItemLegacy(path, options, print, prefix), + ), + ]; + function getPrefix() { const rawPrefix = node.ordered ? (path.isFirst @@ -69,7 +194,7 @@ function printList(path, options, print) { }); } -function printListItem(path, options, print, listPrefix) { +function printListItemLegacy(path, options, print, listPrefix) { const { node } = path; const prefix = node.checked === null ? "" : node.checked ? "[x] " : "[ ] "; return [ @@ -108,4 +233,4 @@ function clamp(value, min, max) { return Math.max(min, Math.min(value, max)); } -export { printList }; +export { printList, printListLegacy }; diff --git a/src/language-markdown/print/mdast.js b/src/language-markdown/print/mdast.js index 2c0050078..62cb30998 100644 --- a/src/language-markdown/print/mdast.js +++ b/src/language-markdown/print/mdast.js @@ -27,15 +27,17 @@ import { splitText, } from "../utilities.js"; import { printChildren } from "./children.js"; -import { printList } from "./list.js"; +import { printHeading } from "./heading.js"; +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 { printWord } from "./word.js"; +import { printWord, printWordLegacy } from "./word.js"; /** - * @import {Doc} from "../../document/index.js" + * @import AstPath from "../../common/ast-path.js"; + * @import {Doc} from "../../document/index.js"; */ function prevOrNextWord(path) { @@ -72,7 +74,13 @@ function printMdast(path, options, print) { parts.push([parts.pop(), node.value]); continue; } - const doc = printWhitespace(path, node.value, options.proseWrap, true); + const doc = printWhitespace( + path, + node.value, + options.proseWrap, + true, + options, + ); if (getDocType(doc) === DOC_TYPE_STRING) { parts.push([parts.pop(), doc]); continue; @@ -95,7 +103,7 @@ function printMdast(path, options, print) { case "sentence": return printSentence(path, print); case "word": - return printWord(path); + return options.parser !== "mdx" ? printWord(path) : printWordLegacy(path); case "whitespace": { const { next } = path; @@ -105,7 +113,7 @@ function printMdast(path, options, print) { ? "never" : options.proseWrap; - return printWhitespace(path, node.value, proseWrap); + return printWhitespace(path, node.value, proseWrap, false, options); } case "emphasis": { let style; @@ -131,10 +139,16 @@ function printMdast(path, options, print) { case "delete": return ["~~", printChildren(path, options, print), "~~"]; case "inlineCode": { - const code = + let code = options.proseWrap === "preserve" ? node.value : node.value.replaceAll("\n", " "); + if ( + options.parser !== "mdx" && + path.hasAncestor((node) => node.type === "tableCell") + ) { + code = code.replaceAll("|", String.raw`\|`); + } const backtickCount = getMinNotPresentContinuousCount(code, "`"); const backtickString = "`".repeat(backtickCount); const padding = @@ -188,7 +202,7 @@ function printMdast(path, options, print) { case "image": return [ "![", - node.alt || "", + printImageAlt(node, options), "](", printUrl(node.url, ")"), printTitle(node.title, options), @@ -197,10 +211,7 @@ function printMdast(path, options, print) { case "blockquote": return ["> ", align("> ", printChildren(path, options, print))]; case "heading": - return [ - "#".repeat(node.depth) + " ", - printChildren(path, options, print), - ]; + return printHeading(path, options, print); case "code": { if (node.isIndented) { // indented code block @@ -222,7 +233,9 @@ function printMdast(path, options, print) { node.meta ? " " + node.meta : "", hardline, replaceEndOfLine( - getFencedCodeBlockValue(node, options.originalText), + options.parser === "mdx" + ? getFencedCodeBlockValue(node, options.originalText) + : node.value, hardline, ), hardline, @@ -241,6 +254,9 @@ function printMdast(path, options, print) { ); } case "list": + if (options.parser === "mdx") { + return printListLegacy(path, options, print); + } return printList(path, options, print); case "thematicBreak": { const { ancestors } = path; @@ -265,18 +281,21 @@ function printMdast(path, options, print) { ? "[]" : "", ]; - case "imageReference": + case "imageReference": { + const alt = printImageAlt(node, options); + switch (node.referenceType) { case "full": - return ["![", node.alt || "", "]", printLinkReference(node)]; + return ["![", alt, "]", printLinkReference(node)]; default: return [ - "![", - node.alt, - "]", + ...(options.parser === "mdx" + ? ["![", alt, "]"] + : ["!", printLinkReference(node)]), node.referenceType === "collapsed" ? "[]" : "", ]; } + } case "definition": { const lineOrSpace = options.proseWrap === "always" ? line : " "; return group([ @@ -284,7 +303,9 @@ function printMdast(path, options, print) { ":", indent([ lineOrSpace, - printUrl(node.url), + options.parser !== "mdx" && node.url === "" + ? "<>" + : printUrl(node.url), node.title === null ? "" : [lineOrSpace, printTitle(node.title, options, false)], @@ -344,6 +365,7 @@ function printMdast(path, options, print) { case "math": return [ "$$", + node.meta ? " " + node.meta : "", hardline, node.value ? [replaceEndOfLine(node.value, hardline), hardline] : "", "$$", @@ -352,11 +374,12 @@ function printMdast(path, options, print) { // remark-math trims content but we don't want to remove whitespaces // since it's very possible that it's recognized as math accidentally return options.originalText.slice(locStart(node), locEnd(node)); + case "text": + return replaceEndOfLine(node.value, hardline); case "frontMatter": // Handled in core case "tableRow": // handled in "table" case "listItem": // handled in "list" - case "text": // handled in other types default: /* c8 ignore next */ throw new UnexpectedNodeError(node, "Markdown"); @@ -484,8 +507,10 @@ function printTitle(title, options, printSpace = true) { return " " + printTitle(title, options, false); } - // title is escaped after `remark-parse` v7 - title = title.replaceAll(/\\(?=["')])/g, ""); + // title is escaped before `remark-parse` v10 + if (options.parser === "mdx") { + title = title.replaceAll(/\\(?=["')])/g, ""); + } if (title.includes('"') && title.includes("'") && !title.includes(")")) { return `(${title})`; // avoid escaped quotes @@ -496,14 +521,27 @@ function printTitle(title, options, printSpace = true) { return `${quote}${title}${quote}`; } -// `remark-parse` lowercase the `label` as `identifier`, we don't want do that -// https://github.com/remarkjs/remark/blob/daddcb463af2d5b2115496c395d0571c0ff87d15/packages/remark-parse/lib/tokenize/reference.js -function printLinkReference(node) { - return `[${collapseWhiteSpace(node.label)}]`; +function printLinkReference(node, options) { + // `remark-parse` lowercase the `label` as `identifier`, we don't want do that + // https://github.com/remarkjs/remark/blob/daddcb463af2d5b2115496c395d0571c0ff87d15/packages/remark-parse/lib/tokenize/reference.js + const label = collapseWhiteSpace(node.label); + if (options?.parser === "mdx") { + return `[${label}]`; + } + const name = label.replaceAll(/[\\[\]]/g, (s) => `\\${s}`); + return `[${name}]`; } function printFootnoteReference(node) { return `[^${node.label}]`; } +function printImageAlt(node, options) { + if (options.parser !== "mdx" && node.originalAltText) { + return node.originalAltText; + } + + return node.alt || ""; +} + export { printMdast }; diff --git a/src/language-markdown/print/preprocess.js b/src/language-markdown/print/preprocess.js index 4210a061f..11f8e4072 100644 --- a/src/language-markdown/print/preprocess.js +++ b/src/language-markdown/print/preprocess.js @@ -6,11 +6,30 @@ const isSingleCharRegex = /^\\?.$/su; const isNewLineBlockquoteRegex = /^\n *>[ >]*$/; function preprocess(ast, options) { - ast = restoreUnescapedCharacter(ast, options); + if (options.parser === "mdx") { + ast = restoreUnescapedCharacter(ast, options); + } else { + ast = addRawToText(ast, options); + } ast = mergeContinuousTexts(ast); - ast = transformIndentedCodeblockAndMarkItsParentList(ast, options); - ast = markAlignedList(ast, options); - ast = splitTextIntoSentences(ast); + if (options.parser === "mdx") { + ast = transformIndentedCodeblockAndMarkItsParentList(ast, options); + } else { + ast = transformIndentedCodeblock(ast, options); + } + if (options.parser !== "mdx") { + ast = markOriginalImageAndLinkAlt(ast, options); + } + if (options.parser === "mdx") { + ast = markAlignedListLegacy(ast, options); + } else { + ast = markAlignedList(ast, options); + } + if (options.parser === "mdx") { + ast = splitTextIntoSentencesLegacy(ast); + } else { + ast = splitTextIntoSentences(ast); + } return ast; } @@ -44,6 +63,19 @@ function restoreUnescapedCharacter(ast, options) { }); } +function addRawToText(ast, options) { + return mapAst(ast, (node) => { + if (node.type === "text") { + // https://github.com/remarkjs/remark-gfm/issues/16 + node.raw = options.originalText.slice( + node.position.start.offset, + node.position.end.offset, + ); + } + return node; + }); +} + function mergeChildren(ast, shouldMerge, mergeNode) { return mapAst(ast, (node) => { if (!node.children) { @@ -85,7 +117,7 @@ function mergeContinuousTexts(ast) { ); } -function splitTextIntoSentences(ast) { +function splitTextIntoSentencesLegacy(ast) { return mapAst(ast, (node, index, [parentNode]) => { if (node.type !== "text") { return node; @@ -112,6 +144,140 @@ function splitTextIntoSentences(ast) { }); } +function splitTextIntoSentences(ast) { + const canOpenAccidentalWikiLink = new Set(); + const riskyParagraphPositions = new Set(); // we can't use nodes themselves because they will be cloned. + + walkAst(ast, (node, parentStack) => { + if (node.type === "wikiLink") { + markAncestors(parentStack); // word wrapping can accidentally merge nodes like `[[foo\n[[wiki link]]` + return; + } + + if (node.type !== "text") { + return; + } + + if (node.raw.includes("[[")) { + for (const ancestor of parentStack) { + if (ancestor.type === "paragraph") { + canOpenAccidentalWikiLink.add(ancestor); + } + } + } + + if (node.raw.includes("]]")) { + markAncestors(parentStack); + } + }); + + return mapAst(ast, (node, index, parentStack) => { + if (node.type !== "text") { + return node; + } + + // NOTE: there's trade-off between using `node.value` or `node.raw` here. + // Using `node.raw`, we can better preserve the original text, especially escaped characters. + // Using `node.value`, we don't need to care about markers like `\n > ` in `blockquote`s. + let text = node.raw; + + const paragraphIndex = parentStack.findIndex( + (ancestor) => ancestor?.type === "paragraph", + ); + + const paragraphNode = + paragraphIndex === -1 ? undefined : parentStack[paragraphIndex]; + + if (paragraphNode) { + if ( + parentStack + .slice(paragraphIndex + 1) + .some((ancestor) => ancestor?.type === "blockquote") + ) { + text = getBlockquoteRawText(text, node); + } + + const parentNode = parentStack[0]; + + if (parentNode?.type === "paragraph") { + if (index === 0) { + text = htmlWhitespace.trimStart(text); + } + if (index === parentNode.children.length - 1) { + text = htmlWhitespace.trimEnd(text); + } + } + } + + if (paragraphNode && riskyParagraphPositions.has(paragraphNode.position)) { + return { + type: "text", + position: node.position, + value: text, + }; + } + + return { + type: "sentence", + position: node.position, + children: splitText(text), + }; + }); + + function walkAst(ast, handler) { + return (function preorder(node, parentStack) { + handler(node, parentStack); + if (node.children) { + for (const child of node.children) { + preorder(child, [node, ...parentStack]); + } + } + })(ast, []); + } + + function markAncestors(parentStack) { + for (const ancestor of parentStack) { + if ( + ancestor.type === "paragraph" && + canOpenAccidentalWikiLink.has(ancestor) + ) { + riskyParagraphPositions.add(ancestor.position); + } + } + } +} + +function getBlockquoteRawText(text, node) { + const angleBracketsRegex = /^([ \t]*>[ \t]*)*/; + const rawLines = text.split("\n"); + const valueLines = node.value.split("\n"); + const resultLines = rawLines.map((rawLine, index) => { + const valueLine = valueLines[index] ?? ""; + const leadingTextAngleBrackets = + valueLine.match(angleBracketsRegex)[0] ?? ""; + return rawLine.replace(angleBracketsRegex, leadingTextAngleBrackets); + }); + return resultLines.join("\n"); +} + +function transformIndentedCodeblock(ast, options) { + return mapAst(ast, (node) => { + if (node.type !== "code") { + return node; + } + // the first char may point to `\n`, e.g. `\n\t\tbar`, just ignore it + const isIndented = /^\n?(?: {4,}|\t)/.test( + options.originalText.slice( + node.position.start.offset, + node.position.end.offset, + ), + ); + + node.isIndented = isIndented; + return node; + }); +} + function transformIndentedCodeblockAndMarkItsParentList(ast, options) { return mapAst(ast, (node, index, parentStack) => { if (node.type === "code") { @@ -144,7 +310,187 @@ function transformIndentedCodeblockAndMarkItsParentList(ast, options) { }); } +// remark 11 removes nested links so we need to recover the original alt text +function markOriginalImageAndLinkAlt(ast, options) { + const { originalText } = options; + return mapAst(ast, (node) => { + if (node.type === "image" || node.type === "imageReference") { + node.originalAltText = getBracketContent( + originalText, + node.position.start.offset, + node.position.end.offset, + ); + return node; + } + + if (node.type !== "link" || !node.url) { + return node; + } + + const originalAlt = getBracketContent( + originalText, + node.position.start.offset, + node.position.end.offset, + ); + + if (originalAlt && /[[\]]/.test(originalAlt)) { + node.originalLabelText = originalAlt; + } + + return node; + }); +} + +function getBracketContent(text, startOffset, endOffset) { + const firstBracket = text.indexOf("[", startOffset); + + if (firstBracket === -1 || firstBracket >= endOffset) { + return null; + } + + let depth = 1; + let index = firstBracket + 1; + + while (index < endOffset) { + const char = text[index]; + + if (char === "\\") { + index += 2; + continue; + } + + if (char === "[") { + depth++; + } else if (char === "]") { + depth--; + if (depth === 0) { + return text.slice(firstBracket + 1, index); + } + } + + index++; + } + + return null; +} + function markAlignedList(ast, options) { + return mapAst(ast, (node, index, parentStack) => { + if (node.type === "list" && node.children.length > 0) { + // if one of its parents is not aligned, it's not possible to be aligned in sub-lists + for (let i = 0; i < parentStack.length; i++) { + const parent = parentStack[i]; + if (parent.type === "list" && !parent.isAligned) { + node.isAligned = false; + return node; + } + } + + const next = parentStack[0]?.children[index + 1]; + if (next?.type === "code" && next.isIndented) { + // hard to align in this case + node.isAligned = false; + return node; + } + + node.isAligned = isAligned(node); + } + + return node; + }); + + function getListItemStart(listItem) { + return listItem.children.length === 0 + ? -1 + : listItem.children[0].position.start.column - 1; + } + + function isAligned(list) { + if (!list.ordered) { + /** + * - 123 + * - 123 + */ + return true; + } + + const [firstItem, secondItem] = list.children; + + const firstInfo = getOrderedListItemInfo(firstItem, options); + + if (firstInfo.leadingSpaces.length > 1) { + /** + * 1. 123 + * + * 1. 123 + * 1. 123 + */ + return true; + } + + const firstStart = getListItemStart(firstItem); + + if (firstStart === -1) { + /** + * 1. + * + * 1. + * 1. + */ + return false; + } + + if (list.children.length === 1) { + /** + * aligned: + * + * 11. 123 + * + * not aligned: + * + * 1. 123 + */ + return firstStart % options.tabWidth === 0; + } + + const secondStart = getListItemStart(secondItem); + + if (firstStart !== secondStart) { + /** + * 11. 123 + * 1. 123 + * + * 1. 123 + * 11. 123 + */ + return false; + } + + if (firstStart % options.tabWidth === 0) { + /** + * 11. 123 + * 12. 123 + */ + return true; + } + + /** + * aligned: + * + * 11. 123 + * 1. 123 + * + * not aligned: + * + * 1. 123 + * 2. 123 + */ + const secondInfo = getOrderedListItemInfo(secondItem, options); + return secondInfo.leadingSpaces.length > 1; + } +} + +function markAlignedListLegacy(ast, options) { return mapAst(ast, (node, index, parentStack) => { if (node.type === "list" && node.children.length > 0) { // if one of its parents is not aligned, it's not possible to be aligned in sub-lists diff --git a/src/language-markdown/print/table.js b/src/language-markdown/print/table.js index 9f1165199..2cedecc39 100644 --- a/src/language-markdown/print/table.js +++ b/src/language-markdown/print/table.js @@ -50,13 +50,20 @@ function printTable(path, options, print) { } function printAlign(isCompact) { - return columnMaxWidths.map((width, index) => { - const align = node.align[index]; - const first = align === "center" || align === "left" ? ":" : "-"; - const last = align === "center" || align === "right" ? ":" : "-"; - const middle = isCompact ? "-" : "-".repeat(width - 2); - return `${first}${middle}${last}`; - }); + return columnMaxWidths + .map((width, index) => { + if (options.parser !== "mdx" && index >= contents[0].length) { + // The header row must match the delimiter row in the number of cells. If not, a table will not be recognized + // https://github.github.com/gfm/#example-203 + return null; + } + const align = node.align[index]; + const first = align === "center" || align === "left" ? ":" : "-"; + const last = align === "center" || align === "right" ? ":" : "-"; + const middle = isCompact ? "-" : "-".repeat(width - 2); + return `${first}${middle}${last}`; + }) + .filter((x) => x !== null); } function printRow(columns, isCompact) { diff --git a/src/language-markdown/print/whitespace.js b/src/language-markdown/print/whitespace.js index bfa7cde7f..d588b5edb 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 { + isSetextHeading, KIND_CJ_LETTER, KIND_CJK_PUNCTUATION, KIND_K_LETTER, @@ -15,12 +16,7 @@ import { * `word`. */ -const SINGLE_LINE_NODE_TYPES = new Set([ - "heading", - "tableCell", - "link", - "wikiLink", -]); +const SINGLE_LINE_NODE_TYPES = new Set(["tableCell", "link", "wikiLink"]); /** * A line break between a character from this set and CJ can be converted to a @@ -182,10 +178,15 @@ function isNonCJKOrKoreanLetter(kind) { * @param {boolean} isLink * @returns {boolean} */ -function isBreakable(path, value, proseWrap, isLink) { +function isBreakable(path, value, proseWrap, isLink, options) { if ( proseWrap !== "always" || - path.hasAncestor((node) => SINGLE_LINE_NODE_TYPES.has(node.type)) + path.hasAncestor( + (node) => + SINGLE_LINE_NODE_TYPES.has(node.type) || + (node.type === "heading" && + (options.parser === "mdx" || !isSetextHeading(node))), + ) ) { return false; } @@ -244,10 +245,11 @@ function isBreakable(path, value, proseWrap, isLink) { * @param {AstPath} path * @param {WhitespaceValue} value * @param {ProseWrap} proseWrap - * @param {boolean} [isLink] Special mode of (un)wrapping that preserves the + * @param {boolean} isLink Special mode of (un)wrapping that preserves the + * @param {any} options 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) { +function printWhitespace(path, value, proseWrap, isLink, options) { if (proseWrap === "preserve" && value === "\n") { return hardline; } @@ -256,7 +258,7 @@ function printWhitespace(path, value, proseWrap, isLink) { value === " " || (value === "\n" && lineBreakCanBeConvertedToSpace(path, isLink)); - if (isBreakable(path, value, proseWrap, isLink)) { + if (isBreakable(path, value, proseWrap, isLink, options)) { return canBeSpace ? line : softline; } diff --git a/src/language-markdown/print/word.js b/src/language-markdown/print/word.js index ab7b46c19..2bf7f6843 100644 --- a/src/language-markdown/print/word.js +++ b/src/language-markdown/print/word.js @@ -11,6 +11,102 @@ import { isAutolink } from "../utilities.js"; * @return {Doc} */ function printWord(path) { + const { node } = path; + const emphasisOrStrong = path.findAncestor( + (p) => p.type === "emphasis" || p.type === "strong", + ); + if (!emphasisOrStrong) { + return node.value; + } + const { previous, next, grandparent } = path; + let text = node.value; + + // escape leading `*` or `_` if it's the first character in an emphasis/strong + if ( + path.isFirst && + (text.startsWith("*") || text.startsWith("_")) && + path.callParent(() => path.isFirst) && + grandparent === emphasisOrStrong + ) { + text = `\\${text}`; + } + + // escape internal `*` or `_` that can open or close emphasis/strong + text = text.replaceAll( + /(\\+|^|.)(\*+|_+)($|.)/g, + (match, preceding, delimiterRun, following) => { + if ( + [...preceding].every((c) => c === "\\") && + preceding.length % 2 === 1 + ) { + // already escaped + return match; + } + if ( + canOpenOrCloseStrongOrEmphasis( + preceding.at(-1) || previous?.value.at(-1), + delimiterRun, + following[0] || next?.value[0], + ) + ) { + return `${preceding}\\${delimiterRun}${following}`; + } + return match; + }, + ); + + return text; +} + +/** + * @param {string | undefined} preceding + * @param {string} delimiterRun + * @param {string | undefined} following + * @returns {boolean | null} + */ +function canOpenOrCloseStrongOrEmphasis(preceding, delimiterRun, following) { + if (!preceding || !following) { + return null; // cannot determine + } + + // https://spec.commonmark.org/0.31.2/#emphasis-and-strong-emphasis + const followedByWhitespace = /[\p{Space_Separator}\t\n\f\r]/u.test(following); + const precededByWhitespace = /[\p{Space_Separator}\t\n\f\r]/u.test(preceding); + const followedByPunctuation = PUNCTUATION_REGEXP.test(following); + const precededByPunctuation = PUNCTUATION_REGEXP.test(preceding); + + const isLeftFlanking = + !followedByWhitespace && + (!followedByPunctuation || + (followedByPunctuation && + (precededByWhitespace || precededByPunctuation))); + const isRightFlanking = + !precededByWhitespace && + (!precededByPunctuation || + (precededByPunctuation && + (followedByWhitespace || followedByPunctuation))); + + const indicator = delimiterRun[0]; + if (indicator === "*") { + return isLeftFlanking || isRightFlanking; + } + + if (isLeftFlanking) { + return !isRightFlanking || precededByPunctuation; + } + + if (isRightFlanking) { + return !isLeftFlanking || followedByPunctuation; + } + + return false; +} + +/** + * @param {AstPath} path + * @return {Doc} + */ +function printWordLegacy(path) { const { node } = path; let escapedValue = node.value .replaceAll("*", String.raw`\*`) // escape all `*` @@ -53,4 +149,4 @@ function printWord(path) { return escapedValue; } -export { printWord }; +export { printWord, printWordLegacy }; diff --git a/src/language-markdown/printers.js b/src/language-markdown/printers.js index 8bac61a99..036f0c9b2 100644 --- a/src/language-markdown/printers.js +++ b/src/language-markdown/printers.js @@ -1,7 +1,7 @@ import clean from "./clean.js"; import embed from "./embed.js"; import { insertPragma } from "./pragma.js"; -import { printMdast } from "./print/index.js"; +import { printMdast, printPrettierIgnored } from "./print/index.js"; import preprocess from "./print/preprocess.js"; import getVisitorKeys from "./traverse/get-visitor-keys.js"; import { hasPrettierIgnore } from "./utilities.js"; @@ -21,6 +21,7 @@ const printer = { hasPrettierIgnore, insertPragma, getVisitorKeys, + printPrettierIgnored, }; export { printer as mdast }; diff --git a/src/language-markdown/utilities.js b/src/language-markdown/utilities.js index a6f5f10b4..d5be83624 100644 --- a/src/language-markdown/utilities.js +++ b/src/language-markdown/utilities.js @@ -181,10 +181,19 @@ function splitText(text) { } function getOrderedListItemInfo(orderListItem, options) { - const text = options.originalText.slice( + let text = options.originalText.slice( orderListItem.position.start.offset, orderListItem.position.end.offset, ); + if (options.parser !== "mdx") { + const firstChild = orderListItem.children[0]; + if (firstChild) { + text = options.originalText.slice( + orderListItem.position.start.offset, + firstChild.position.start.offset, + ); + } + } const { numberText, leadingSpaces } = text.match( /^\s*(?\d+)(\.|\))(?\s*)/, @@ -218,6 +227,7 @@ function hasGitDiffFriendlyOrderedList(node, options) { // The final new line should not include in value // https://github.com/remarkjs/remark/issues/512 +// TODO[@fisker]: Use `node.value` directly when we update mdx to use latest remark function getFencedCodeBlockValue(node, originalText) { const { value } = node; if ( @@ -248,6 +258,7 @@ function isAutolink(node) { if (node?.type !== "link" || node.children.length !== 1) { return false; } + const [child] = node.children; return locStart(node) === locStart(child) && locEnd(node) === locEnd(child); } @@ -307,6 +318,11 @@ function hasPrettierIgnore(path) { return path.index > 0 && isPrettierIgnore(path.previous) === "next"; } +function isSetextHeading(node) { + const { start, end } = node.position; + return start.line !== end.line; +} + export { getFencedCodeBlockValue, getNthListSiblingIndex, @@ -317,6 +333,7 @@ export { INLINE_NODE_WRAPPER_TYPES, isAutolink, isPrettierIgnore, + isSetextHeading, KIND_CJ_LETTER, KIND_CJK_PUNCTUATION, KIND_K_LETTER, diff --git a/src/main/front-matter/parse.js b/src/main/front-matter/parse.js index 2cf0bd70a..803f08e66 100644 --- a/src/main/front-matter/parse.js +++ b/src/main/front-matter/parse.js @@ -4,7 +4,13 @@ import { FRONT_MATTER_MARK } from "./constants.js"; const DELIMITER_LENGTH = 3; /** -@typedef {{index: number, line: number, column: number}} Position +@typedef {{ + index: number, + // 1-based line number + line: number, + // 0-based column number + column: number, +}} Position @typedef {{ language: string, explicitLanguage: string | null, diff --git a/tests/config/run-format-test.js b/tests/config/run-format-test.js index aac912e5c..8afb9a248 100644 --- a/tests/config/run-format-test.js +++ b/tests/config/run-format-test.js @@ -27,8 +27,6 @@ const unstableTests = new Map( "js/comments/return-statement.js", "js/comments/tagged-template-literal.js", "js/for/9812-unstable.js", - "markdown/spec/example-234.md", - "markdown/spec/example-235.md", [ "js/multiparser-markdown/codeblock.js", (options) => options.proseWrap === "always", @@ -362,6 +360,7 @@ async function runTest({ }) { let formatOptions = mainParserFormatOptions; let formatResult = mainParserFormatResult; + expect(formatResult).toBeDefined(); // Verify parsers or error tests if ( diff --git a/tests/format/markdown/auto-link/__snapshots__/format.test.js.snap b/tests/format/markdown/auto-link/__snapshots__/format.test.js.snap index 4bb900cdb..8fc974d3b 100644 --- a/tests/format/markdown/auto-link/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/auto-link/__snapshots__/format.test.js.snap @@ -8,7 +8,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a * =====================================output===================================== -- http://www.example.com:80/*a \\* +- http://www.example.com:80/*a * ================================================================================ `; @@ -21,7 +21,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a _ =====================================output===================================== -- http://www.example.com:80/*a \\_ +- http://www.example.com:80/*a _ ================================================================================ `; @@ -34,7 +34,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a* * =====================================output===================================== -- http://www.example.com:80/*a* \\* +- http://www.example.com:80/*a* * ================================================================================ `; @@ -47,7 +47,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a* _ =====================================output===================================== -- http://www.example.com:80/*a* \\_ +- http://www.example.com:80/*a* _ ================================================================================ `; @@ -73,7 +73,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a** * =====================================output===================================== -- http://www.example.com:80/*a** \\* +- http://www.example.com:80/*a** * ================================================================================ `; @@ -86,7 +86,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a** _ =====================================output===================================== -- http://www.example.com:80/*a** \\_ +- http://www.example.com:80/*a** _ ================================================================================ `; @@ -138,7 +138,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*/ * =====================================output===================================== -- http://www.example.com:80/*a*/ \\* +- http://www.example.com:80/*a*/ * ================================================================================ `; @@ -151,7 +151,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*/ _ =====================================output===================================== -- http://www.example.com:80/*a*/ \\_ +- http://www.example.com:80/*a*/ _ ================================================================================ `; @@ -164,7 +164,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*/* * =====================================output===================================== -- http://www.example.com:80/*a*/* \\* +- http://www.example.com:80/*a*/* * ================================================================================ `; @@ -177,7 +177,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*/* _ =====================================output===================================== -- http://www.example.com:80/*a*/* \\_ +- http://www.example.com:80/*a*/* _ ================================================================================ `; @@ -255,7 +255,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*b * =====================================output===================================== -- http://www.example.com:80/*a*b \\* +- http://www.example.com:80/*a*b * ================================================================================ `; @@ -268,7 +268,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/*a*b _ =====================================output===================================== -- http://www.example.com:80/*a*b \\_ +- http://www.example.com:80/*a*b _ ================================================================================ `; @@ -320,7 +320,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a * =====================================output===================================== -- http://www.example.com:80/_a \\* +- http://www.example.com:80/_a * ================================================================================ `; @@ -333,7 +333,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a _ =====================================output===================================== -- http://www.example.com:80/_a \\_ +- http://www.example.com:80/_a _ ================================================================================ `; @@ -346,7 +346,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a* * =====================================output===================================== -- http://www.example.com:80/_a* \\* +- http://www.example.com:80/_a* * ================================================================================ `; @@ -359,7 +359,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a* _ =====================================output===================================== -- http://www.example.com:80/_a* \\_ +- http://www.example.com:80/_a* _ ================================================================================ `; @@ -398,7 +398,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a*/ * =====================================output===================================== -- http://www.example.com:80/_a*/ \\* +- http://www.example.com:80/_a*/ * ================================================================================ `; @@ -411,7 +411,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a*/ _ =====================================output===================================== -- http://www.example.com:80/_a*/ \\_ +- http://www.example.com:80/_a*/ _ ================================================================================ `; @@ -463,7 +463,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a*b * =====================================output===================================== -- http://www.example.com:80/_a*b \\* +- http://www.example.com:80/_a*b * ================================================================================ `; @@ -476,7 +476,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a*b _ =====================================output===================================== -- http://www.example.com:80/_a*b \\_ +- http://www.example.com:80/_a*b _ ================================================================================ `; @@ -515,7 +515,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_ * =====================================output===================================== -- http://www.example.com:80/_a_ \\* +- http://www.example.com:80/_a_ * ================================================================================ `; @@ -528,7 +528,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_ _ =====================================output===================================== -- http://www.example.com:80/_a_ \\_ +- http://www.example.com:80/_a_ _ ================================================================================ `; @@ -554,7 +554,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_* * =====================================output===================================== -- http://www.example.com:80/_a_* \\* +- http://www.example.com:80/_a_* * ================================================================================ `; @@ -619,7 +619,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/ * =====================================output===================================== -- http://www.example.com:80/_a_/ \\* +- http://www.example.com:80/_a_/ * ================================================================================ `; @@ -632,7 +632,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/ _ =====================================output===================================== -- http://www.example.com:80/_a_/ \\_ +- http://www.example.com:80/_a_/ _ ================================================================================ `; @@ -645,7 +645,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/* * =====================================output===================================== -- http://www.example.com:80/_a_/* \\* +- http://www.example.com:80/_a_/* * ================================================================================ `; @@ -658,7 +658,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/* _ =====================================output===================================== -- http://www.example.com:80/_a_/* \\_ +- http://www.example.com:80/_a_/* _ ================================================================================ `; @@ -710,7 +710,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/_ * =====================================output===================================== -- http://www.example.com:80/_a_/_ \\* +- http://www.example.com:80/_a_/_ * ================================================================================ `; @@ -723,7 +723,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_/_ _ =====================================output===================================== -- http://www.example.com:80/_a_/_ \\_ +- http://www.example.com:80/_a_/_ _ ================================================================================ `; @@ -775,7 +775,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a__ * =====================================output===================================== -- http://www.example.com:80/_a__ \\* +- http://www.example.com:80/_a__ * ================================================================================ `; @@ -788,7 +788,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a__ _ =====================================output===================================== -- http://www.example.com:80/_a__ \\_ +- http://www.example.com:80/_a__ _ ================================================================================ `; @@ -840,7 +840,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_b * =====================================output===================================== -- http://www.example.com:80/_a_b \\* +- http://www.example.com:80/_a_b * ================================================================================ `; @@ -853,7 +853,7 @@ printWidth: 80 =====================================input====================================== * http://www.example.com:80/_a_b _ =====================================output===================================== -- http://www.example.com:80/_a_b \\_ +- http://www.example.com:80/_a_b _ ================================================================================ `; @@ -892,7 +892,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a * =====================================output===================================== -*http://www.example.com:80/*a \\* +*http://www.example.com:80/*a * ================================================================================ `; @@ -905,7 +905,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a _ =====================================output===================================== -*http://www.example.com:80/*a \\_ +*http://www.example.com:80/*a _ ================================================================================ `; @@ -918,7 +918,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a* * =====================================output===================================== -*http://www.example.com:80/*a\\* \\* +*http://www.example.com:80/*a* * ================================================================================ `; @@ -931,7 +931,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a* _ =====================================output===================================== -*http://www.example.com:80/*a\\* \\_ +*http://www.example.com:80/*a* _ ================================================================================ `; @@ -944,7 +944,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a* =====================================output===================================== -*http://www.example.com:80/*a\\* +*http://www.example.com:80/*a* ================================================================================ `; @@ -957,7 +957,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a** * =====================================output===================================== -*http://www.example.com:80/*a\\*\\* \\* +*http://www.example.com:80/*a** * ================================================================================ `; @@ -970,7 +970,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a** _ =====================================output===================================== -*http://www.example.com:80/*a\\*\\* \\_ +*http://www.example.com:80/*a** _ ================================================================================ `; @@ -983,7 +983,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a** =====================================output===================================== -*http://www.example.com:80/*a\\*\\* +*http://www.example.com:80/*a** ================================================================================ `; @@ -996,7 +996,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*** =====================================output===================================== -*http://www.example.com:80/*a\\*\\*\\* +*http://www.example.com:80/*a*** ================================================================================ `; @@ -1009,7 +1009,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a**_ =====================================output===================================== -*http://www.example.com:80/*a\\*\\*\\_ +*http://www.example.com:80/*a**_ ================================================================================ `; @@ -1035,7 +1035,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/ _ =====================================output===================================== -*http://www.example.com:80/*a\\*/ \\_ +*http://www.example.com:80/*a*/ _ ================================================================================ `; @@ -1048,7 +1048,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/* * =====================================output===================================== -*http://www.example.com:80/*a*/* \\* +*http://www.example.com:80/*a*/* * ================================================================================ `; @@ -1061,7 +1061,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/* _ =====================================output===================================== -*http://www.example.com:80/*a*/* \\_ +*http://www.example.com:80/*a*/* _ ================================================================================ `; @@ -1087,7 +1087,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/** =====================================output===================================== -*http://www.example.com:80/*a\\*/\\*\\* +*http://www.example.com:80/*a*/** ================================================================================ `; @@ -1100,7 +1100,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/*_ =====================================output===================================== -*http://www.example.com:80/*a*/*\\_ +*http://www.example.com:80/*a*/*_ ================================================================================ `; @@ -1113,7 +1113,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*/_ =====================================output===================================== -*http://www.example.com:80/*a\\*/\\_ +*http://www.example.com:80/*a*/_ ================================================================================ `; @@ -1126,7 +1126,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*_ =====================================output===================================== -*http://www.example.com:80/*a\\*\\_ +*http://www.example.com:80/*a*_ ================================================================================ `; @@ -1152,7 +1152,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*b _ =====================================output===================================== -*http://www.example.com:80/*a\\*b \\_ +*http://www.example.com:80/*a*b _ ================================================================================ `; @@ -1178,7 +1178,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a*b_ =====================================output===================================== -*http://www.example.com:80/*a\\*b\\_ +*http://www.example.com:80/*a*b_ ================================================================================ `; @@ -1191,7 +1191,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/*a_ =====================================output===================================== -*http://www.example.com:80/*a\\_ +*http://www.example.com:80/*a_ ================================================================================ `; @@ -1217,7 +1217,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a _ =====================================output===================================== -\\*http://www.example.com:80/_a \\_ +*http://www.example.com:80/_a _ ================================================================================ `; @@ -1230,7 +1230,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a* * =====================================output===================================== -*http://www.example.com:80/_a* \\* +*http://www.example.com:80/_a* * ================================================================================ `; @@ -1243,7 +1243,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a* _ =====================================output===================================== -*http://www.example.com:80/_a* \\_ +*http://www.example.com:80/_a* _ ================================================================================ `; @@ -1269,7 +1269,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a** =====================================output===================================== -\\*http://www.example.com:80/_a** +*http://www.example.com:80/_a** ================================================================================ `; @@ -1282,7 +1282,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*/ * =====================================output===================================== -*http://www.example.com:80/_a*/ \\* +*http://www.example.com:80/_a*/ * ================================================================================ `; @@ -1295,7 +1295,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*/ _ =====================================output===================================== -*http://www.example.com:80/_a*/ \\_ +*http://www.example.com:80/_a*/ _ ================================================================================ `; @@ -1308,7 +1308,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*/* =====================================output===================================== -*http://www.example.com:80/_a*/\\* +*http://www.example.com:80/_a*/* ================================================================================ `; @@ -1321,7 +1321,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*/_ =====================================output===================================== -*http://www.example.com:80/_a*/\\_ +*http://www.example.com:80/_a*/_ ================================================================================ `; @@ -1334,7 +1334,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*_ =====================================output===================================== -*http://www.example.com:80/_a*\\_ +*http://www.example.com:80/_a*_ ================================================================================ `; @@ -1347,7 +1347,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*b * =====================================output===================================== -*http://www.example.com:80/_a*b \\* +*http://www.example.com:80/_a*b * ================================================================================ `; @@ -1360,7 +1360,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*b _ =====================================output===================================== -*http://www.example.com:80/_a*b \\_ +*http://www.example.com:80/_a*b _ ================================================================================ `; @@ -1373,7 +1373,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*b* =====================================output===================================== -*http://www.example.com:80/_a*b\\* +*http://www.example.com:80/_a*b* ================================================================================ `; @@ -1386,7 +1386,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a*b_ =====================================output===================================== -*http://www.example.com:80/_a*b\\_ +*http://www.example.com:80/_a*b_ ================================================================================ `; @@ -1412,7 +1412,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_ _ =====================================output===================================== -\\*http://www.example.com:80/_a_ \\_ +*http://www.example.com:80/_a_ _ ================================================================================ `; @@ -1425,7 +1425,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_ =====================================output===================================== -\\*http://www.example.com:80/_a_ +*http://www.example.com:80/_a_ ================================================================================ `; @@ -1438,7 +1438,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_* * =====================================output===================================== -*http://www.example.com:80/_a_* \\* +*http://www.example.com:80/_a_* * ================================================================================ `; @@ -1451,7 +1451,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_* _ =====================================output===================================== -*http://www.example.com:80/_a_* \\_ +*http://www.example.com:80/_a_* _ ================================================================================ `; @@ -1477,7 +1477,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_** =====================================output===================================== -\\*http://www.example.com:80/_a_** +*http://www.example.com:80/_a_** ================================================================================ `; @@ -1490,7 +1490,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_*_ =====================================output===================================== -*http://www.example.com:80/_a_*\\_ +*http://www.example.com:80/_a_*_ ================================================================================ `; @@ -1516,7 +1516,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/ _ =====================================output===================================== -\\*http://www.example.com:80/_a_/ \\_ +*http://www.example.com:80/_a_/ _ ================================================================================ `; @@ -1529,7 +1529,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/* * =====================================output===================================== -*http://www.example.com:80/_a_/* \\* +*http://www.example.com:80/_a_/* * ================================================================================ `; @@ -1542,7 +1542,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/* _ =====================================output===================================== -*http://www.example.com:80/_a_/* \\_ +*http://www.example.com:80/_a_/* _ ================================================================================ `; @@ -1568,7 +1568,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/** =====================================output===================================== -\\*http://www.example.com:80/_a_/** +*http://www.example.com:80/_a_/** ================================================================================ `; @@ -1581,7 +1581,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/*_ =====================================output===================================== -*http://www.example.com:80/_a_/*\\_ +*http://www.example.com:80/_a_/*_ ================================================================================ `; @@ -1607,7 +1607,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/_ _ =====================================output===================================== -\\*http://www.example.com:80/_a_/_ \\_ +*http://www.example.com:80/_a_/_ _ ================================================================================ `; @@ -1620,7 +1620,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/_ =====================================output===================================== -\\*http://www.example.com:80/_a_/_ +*http://www.example.com:80/_a_/_ ================================================================================ `; @@ -1646,7 +1646,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_/__ =====================================output===================================== -\\*http://www.example.com:80/_a_/__ +*http://www.example.com:80/_a_/__ ================================================================================ `; @@ -1672,7 +1672,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a__ _ =====================================output===================================== -\\*http://www.example.com:80/_a__ \\_ +*http://www.example.com:80/_a__ _ ================================================================================ `; @@ -1685,7 +1685,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a__ =====================================output===================================== -\\*http://www.example.com:80/_a__ +*http://www.example.com:80/_a__ ================================================================================ `; @@ -1711,7 +1711,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a___ =====================================output===================================== -\\*http://www.example.com:80/_a___ +*http://www.example.com:80/_a___ ================================================================================ `; @@ -1737,7 +1737,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_b _ =====================================output===================================== -\\*http://www.example.com:80/_a_b \\_ +*http://www.example.com:80/_a_b _ ================================================================================ `; @@ -1763,7 +1763,7 @@ printWidth: 80 =====================================input====================================== *http://www.example.com:80/_a_b_ =====================================output===================================== -\\*http://www.example.com:80/_a_b_ +*http://www.example.com:80/_a_b_ ================================================================================ `; @@ -1776,7 +1776,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a * =====================================output===================================== -\\_ http://www.example.com:80/*a \\* +_ http://www.example.com:80/*a * ================================================================================ `; @@ -1802,7 +1802,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a* * =====================================output===================================== -\\_ http://www.example.com:80/*a* \\* +_ http://www.example.com:80/*a* * ================================================================================ `; @@ -1828,7 +1828,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a* =====================================output===================================== -\\_ http://www.example.com:80/*a* +_ http://www.example.com:80/*a* ================================================================================ `; @@ -1841,7 +1841,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a** * =====================================output===================================== -\\_ http://www.example.com:80/*a** \\* +_ http://www.example.com:80/*a** * ================================================================================ `; @@ -1867,7 +1867,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a** =====================================output===================================== -\\_ http://www.example.com:80/*a** +_ http://www.example.com:80/*a** ================================================================================ `; @@ -1880,7 +1880,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*** =====================================output===================================== -\\_ http://www.example.com:80/*a*** +_ http://www.example.com:80/*a*** ================================================================================ `; @@ -1906,7 +1906,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*/ * =====================================output===================================== -\\_ http://www.example.com:80/*a*/ \\* +_ http://www.example.com:80/*a*/ * ================================================================================ `; @@ -1932,7 +1932,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*/* * =====================================output===================================== -\\_ http://www.example.com:80/*a*/* \\* +_ http://www.example.com:80/*a*/* * ================================================================================ `; @@ -1958,7 +1958,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*/* =====================================output===================================== -\\_ http://www.example.com:80/*a*/* +_ http://www.example.com:80/*a*/* ================================================================================ `; @@ -1971,7 +1971,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*/** =====================================output===================================== -\\_ http://www.example.com:80/*a*/** +_ http://www.example.com:80/*a*/** ================================================================================ `; @@ -2023,7 +2023,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*b * =====================================output===================================== -\\_ http://www.example.com:80/*a*b \\* +_ http://www.example.com:80/*a*b * ================================================================================ `; @@ -2049,7 +2049,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/*a*b* =====================================output===================================== -\\_ http://www.example.com:80/*a*b* +_ http://www.example.com:80/*a*b* ================================================================================ `; @@ -2088,7 +2088,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a * =====================================output===================================== -\\_ http://www.example.com:80/_a \\* +_ http://www.example.com:80/_a * ================================================================================ `; @@ -2114,7 +2114,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a* * =====================================output===================================== -\\_ http://www.example.com:80/_a* \\* +_ http://www.example.com:80/_a* * ================================================================================ `; @@ -2140,7 +2140,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a* =====================================output===================================== -\\_ http://www.example.com:80/_a* +_ http://www.example.com:80/_a* ================================================================================ `; @@ -2153,7 +2153,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a** =====================================output===================================== -\\_ http://www.example.com:80/_a** +_ http://www.example.com:80/_a** ================================================================================ `; @@ -2166,7 +2166,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a*/ * =====================================output===================================== -\\_ http://www.example.com:80/_a*/ \\* +_ http://www.example.com:80/_a*/ * ================================================================================ `; @@ -2192,7 +2192,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a*/* =====================================output===================================== -\\_ http://www.example.com:80/_a*/* +_ http://www.example.com:80/_a*/* ================================================================================ `; @@ -2231,7 +2231,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a*b * =====================================output===================================== -\\_ http://www.example.com:80/_a*b \\* +_ http://www.example.com:80/_a*b * ================================================================================ `; @@ -2257,7 +2257,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a*b* =====================================output===================================== -\\_ http://www.example.com:80/_a*b* +_ http://www.example.com:80/_a*b* ================================================================================ `; @@ -2283,7 +2283,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_ * =====================================output===================================== -_ http://www.example.com:80/_a_ \\* +_ http://www.example.com:80/_a_ * ================================================================================ `; @@ -2296,7 +2296,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_ _ =====================================output===================================== -_ http://www.example.com:80/_a_ \\_ +_ http://www.example.com:80/_a_ _ ================================================================================ `; @@ -2322,7 +2322,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_* * =====================================output===================================== -_ http://www.example.com:80/_a_\\* \\* +_ http://www.example.com:80/_a_* * ================================================================================ `; @@ -2335,7 +2335,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_* _ =====================================output===================================== -_ http://www.example.com:80/_a_\\* \\_ +_ http://www.example.com:80/_a_* _ ================================================================================ `; @@ -2348,7 +2348,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_* =====================================output===================================== -_ http://www.example.com:80/_a_\\* +_ http://www.example.com:80/_a_* ================================================================================ `; @@ -2361,7 +2361,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_** =====================================output===================================== -_ http://www.example.com:80/_a_\\*\\* +_ http://www.example.com:80/_a_** ================================================================================ `; @@ -2374,7 +2374,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_*_ =====================================output===================================== -_ http://www.example.com:80/_a_\\*\\_ +_ http://www.example.com:80/_a_*_ ================================================================================ `; @@ -2387,7 +2387,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/ * =====================================output===================================== -_ http://www.example.com:80/_a_/ \\* +_ http://www.example.com:80/_a_/ * ================================================================================ `; @@ -2400,7 +2400,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/ _ =====================================output===================================== -_ http://www.example.com:80/_a_/ \\_ +_ http://www.example.com:80/_a_/ _ ================================================================================ `; @@ -2413,7 +2413,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/* * =====================================output===================================== -_ http://www.example.com:80/_a_/\\* \\* +_ http://www.example.com:80/_a_/* * ================================================================================ `; @@ -2426,7 +2426,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/* _ =====================================output===================================== -_ http://www.example.com:80/_a_/\\* \\_ +_ http://www.example.com:80/_a_/* _ ================================================================================ `; @@ -2439,7 +2439,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/* =====================================output===================================== -_ http://www.example.com:80/_a_/\\* +_ http://www.example.com:80/_a_/* ================================================================================ `; @@ -2452,7 +2452,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/** =====================================output===================================== -_ http://www.example.com:80/_a_/\\*\\* +_ http://www.example.com:80/_a_/** ================================================================================ `; @@ -2465,7 +2465,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/*_ =====================================output===================================== -_ http://www.example.com:80/_a_/\\*\\_ +_ http://www.example.com:80/_a_/*_ ================================================================================ `; @@ -2478,7 +2478,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/_ * =====================================output===================================== -_ http://www.example.com:80/_a_/\\_ \\* +_ http://www.example.com:80/_a_/_ * ================================================================================ `; @@ -2491,7 +2491,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/_ _ =====================================output===================================== -_ http://www.example.com:80/_a_/\\_ \\_ +_ http://www.example.com:80/_a_/_ _ ================================================================================ `; @@ -2504,7 +2504,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/_ =====================================output===================================== -_ http://www.example.com:80/_a_/\\_ +_ http://www.example.com:80/_a_/_ ================================================================================ `; @@ -2517,7 +2517,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/_* =====================================output===================================== -_ http://www.example.com:80/_a_/\\_\\* +_ http://www.example.com:80/_a_/_* ================================================================================ `; @@ -2530,7 +2530,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_/__ =====================================output===================================== -_ http://www.example.com:80/_a_/\\_\\_ +_ http://www.example.com:80/_a_/__ ================================================================================ `; @@ -2543,7 +2543,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a__ * =====================================output===================================== -\\_ http://www.example.com:80/_a__ \\* +_ http://www.example.com:80/_a__ * ================================================================================ `; @@ -2569,7 +2569,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a__ =====================================output===================================== -\\_ http://www.example.com:80/_a__ +_ http://www.example.com:80/_a__ ================================================================================ `; @@ -2582,7 +2582,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a__* =====================================output===================================== -\\_ http://www.example.com:80/_a__* +_ http://www.example.com:80/_a__* ================================================================================ `; @@ -2595,7 +2595,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a___ =====================================output===================================== -\\_ http://www.example.com:80/_a___ +_ http://www.example.com:80/_a___ ================================================================================ `; @@ -2608,7 +2608,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_b * =====================================output===================================== -\\_ http://www.example.com:80/_a_b \\* +_ http://www.example.com:80/_a_b * ================================================================================ `; @@ -2634,7 +2634,7 @@ printWidth: 80 =====================================input====================================== _ http://www.example.com:80/_a_b* =====================================output===================================== -\\_ http://www.example.com:80/_a_b* +_ http://www.example.com:80/_a_b* ================================================================================ `; @@ -2660,7 +2660,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a * =====================================output===================================== -\\_http://www.example.com:80/*a \\* +_http://www.example.com:80/*a * ================================================================================ `; @@ -2686,7 +2686,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a* * =====================================output===================================== -\\_http://www.example.com:80/*a* \\* +_http://www.example.com:80/*a* * ================================================================================ `; @@ -2712,7 +2712,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a* =====================================output===================================== -\\_http://www.example.com:80/*a* +_http://www.example.com:80/*a* ================================================================================ `; @@ -2725,7 +2725,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a** * =====================================output===================================== -\\_http://www.example.com:80/*a** \\* +_http://www.example.com:80/*a** * ================================================================================ `; @@ -2751,7 +2751,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a** =====================================output===================================== -\\_http://www.example.com:80/*a** +_http://www.example.com:80/*a** ================================================================================ `; @@ -2764,7 +2764,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*** =====================================output===================================== -\\_http://www.example.com:80/*a*** +_http://www.example.com:80/*a*** ================================================================================ `; @@ -2790,7 +2790,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*/ * =====================================output===================================== -\\_http://www.example.com:80/*a*/ \\* +_http://www.example.com:80/*a*/ * ================================================================================ `; @@ -2816,7 +2816,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*/* * =====================================output===================================== -\\_http://www.example.com:80/*a*/* \\* +_http://www.example.com:80/*a*/* * ================================================================================ `; @@ -2842,7 +2842,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*/* =====================================output===================================== -\\_http://www.example.com:80/*a*/* +_http://www.example.com:80/*a*/* ================================================================================ `; @@ -2855,7 +2855,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*/** =====================================output===================================== -\\_http://www.example.com:80/*a*/** +_http://www.example.com:80/*a*/** ================================================================================ `; @@ -2907,7 +2907,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*b * =====================================output===================================== -\\_http://www.example.com:80/*a*b \\* +_http://www.example.com:80/*a*b * ================================================================================ `; @@ -2933,7 +2933,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/*a*b* =====================================output===================================== -\\_http://www.example.com:80/*a*b* +_http://www.example.com:80/*a*b* ================================================================================ `; @@ -2972,7 +2972,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a * =====================================output===================================== -\\_http://www.example.com:80/_a \\* +_http://www.example.com:80/_a * ================================================================================ `; @@ -2998,7 +2998,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a* * =====================================output===================================== -\\_http://www.example.com:80/_a* \\* +_http://www.example.com:80/_a* * ================================================================================ `; @@ -3024,7 +3024,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a* =====================================output===================================== -\\_http://www.example.com:80/_a* +_http://www.example.com:80/_a* ================================================================================ `; @@ -3037,7 +3037,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a** =====================================output===================================== -\\_http://www.example.com:80/_a** +_http://www.example.com:80/_a** ================================================================================ `; @@ -3050,7 +3050,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a*/ * =====================================output===================================== -\\_http://www.example.com:80/_a*/ \\* +_http://www.example.com:80/_a*/ * ================================================================================ `; @@ -3076,7 +3076,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a*/* =====================================output===================================== -\\_http://www.example.com:80/_a*/* +_http://www.example.com:80/_a*/* ================================================================================ `; @@ -3115,7 +3115,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a*b * =====================================output===================================== -\\_http://www.example.com:80/_a*b \\* +_http://www.example.com:80/_a*b * ================================================================================ `; @@ -3141,7 +3141,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a*b* =====================================output===================================== -\\_http://www.example.com:80/_a*b* +_http://www.example.com:80/_a*b* ================================================================================ `; @@ -3167,7 +3167,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_ * =====================================output===================================== -_http://www.example.com:80/_a_ \\* +_http://www.example.com:80/_a_ * ================================================================================ `; @@ -3180,7 +3180,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_ _ =====================================output===================================== -_http://www.example.com:80/_a_ \\_ +_http://www.example.com:80/_a_ _ ================================================================================ `; @@ -3206,7 +3206,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_* * =====================================output===================================== -_http://www.example.com:80/_a_\\* \\* +_http://www.example.com:80/_a_* * ================================================================================ `; @@ -3219,7 +3219,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_* _ =====================================output===================================== -_http://www.example.com:80/_a_\\* \\_ +_http://www.example.com:80/_a_* _ ================================================================================ `; @@ -3232,7 +3232,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_* =====================================output===================================== -_http://www.example.com:80/_a_\\* +_http://www.example.com:80/_a_* ================================================================================ `; @@ -3245,7 +3245,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_** =====================================output===================================== -_http://www.example.com:80/_a_\\*\\* +_http://www.example.com:80/_a_** ================================================================================ `; @@ -3258,7 +3258,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_*_ =====================================output===================================== -_http://www.example.com:80/_a_\\*\\_ +_http://www.example.com:80/_a_*_ ================================================================================ `; @@ -3271,7 +3271,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/ * =====================================output===================================== -_http://www.example.com:80/_a_/ \\* +_http://www.example.com:80/_a_/ * ================================================================================ `; @@ -3284,7 +3284,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/ _ =====================================output===================================== -_http://www.example.com:80/_a_/ \\_ +_http://www.example.com:80/_a_/ _ ================================================================================ `; @@ -3297,7 +3297,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/* * =====================================output===================================== -_http://www.example.com:80/_a_/\\* \\* +_http://www.example.com:80/_a_/* * ================================================================================ `; @@ -3310,7 +3310,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/* _ =====================================output===================================== -_http://www.example.com:80/_a_/\\* \\_ +_http://www.example.com:80/_a_/* _ ================================================================================ `; @@ -3323,7 +3323,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/* =====================================output===================================== -_http://www.example.com:80/_a_/\\* +_http://www.example.com:80/_a_/* ================================================================================ `; @@ -3336,7 +3336,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/** =====================================output===================================== -_http://www.example.com:80/_a_/\\*\\* +_http://www.example.com:80/_a_/** ================================================================================ `; @@ -3349,7 +3349,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/*_ =====================================output===================================== -_http://www.example.com:80/_a_/\\*\\_ +_http://www.example.com:80/_a_/*_ ================================================================================ `; @@ -3362,7 +3362,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/_ * =====================================output===================================== -_http://www.example.com:80/_a_/\\_ \\* +_http://www.example.com:80/_a_/_ * ================================================================================ `; @@ -3375,7 +3375,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/_ _ =====================================output===================================== -_http://www.example.com:80/_a_/\\_ \\_ +_http://www.example.com:80/_a_/_ _ ================================================================================ `; @@ -3388,7 +3388,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/_ =====================================output===================================== -_http://www.example.com:80/_a_/\\_ +_http://www.example.com:80/_a_/_ ================================================================================ `; @@ -3401,7 +3401,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/_* =====================================output===================================== -_http://www.example.com:80/_a_/\\_\\* +_http://www.example.com:80/_a_/_* ================================================================================ `; @@ -3414,7 +3414,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_/__ =====================================output===================================== -_http://www.example.com:80/_a_/\\_\\_ +_http://www.example.com:80/_a_/__ ================================================================================ `; @@ -3427,7 +3427,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a__ * =====================================output===================================== -\\_http://www.example.com:80/_a__ \\* +_http://www.example.com:80/_a__ * ================================================================================ `; @@ -3453,7 +3453,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a__ =====================================output===================================== -\\_http://www.example.com:80/_a__ +_http://www.example.com:80/_a__ ================================================================================ `; @@ -3466,7 +3466,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a__* =====================================output===================================== -\\_http://www.example.com:80/_a__* +_http://www.example.com:80/_a__* ================================================================================ `; @@ -3479,7 +3479,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a___ =====================================output===================================== -\\_http://www.example.com:80/_a___ +_http://www.example.com:80/_a___ ================================================================================ `; @@ -3492,7 +3492,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_b * =====================================output===================================== -\\_http://www.example.com:80/_a_b \\* +_http://www.example.com:80/_a_b * ================================================================================ `; @@ -3518,7 +3518,7 @@ printWidth: 80 =====================================input====================================== _http://www.example.com:80/_a_b* =====================================output===================================== -\\_http://www.example.com:80/_a_b* +_http://www.example.com:80/_a_b* ================================================================================ `; diff --git a/tests/format/markdown/blockquote/__snapshots__/format.test.js.snap b/tests/format/markdown/blockquote/__snapshots__/format.test.js.snap index 2dd99cdd6..a6828c667 100644 --- a/tests/format/markdown/blockquote/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/blockquote/__snapshots__/format.test.js.snap @@ -1,5 +1,51 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`check-accidental.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +long long long long long long long long long long long long long long long > > > > this is not quote + +=====================================output===================================== +long long long long long long long long long long long long long long +long > > > > this is not quote + +================================================================================ +`; + +exports[`check-accidental.md - {"proseWrap":"never"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "never" + | printWidth +=====================================input====================================== +long long long long long long long long long long long long long long long > > > > this is not quote + +=====================================output===================================== +long long long long long long long long long long long long long long long > > > > this is not quote + +================================================================================ +`; + +exports[`check-accidental.md - {"proseWrap":"preserve"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "preserve" + | printWidth +=====================================input====================================== +long long long long long long long long long long long long long long long > > > > this is not quote + +=====================================output===================================== +long long long long long long long long long long long long long long long > > > > this is not quote + +================================================================================ +`; + exports[`code.md - {"proseWrap":"always"} format 1`] = ` ====================================options===================================== parsers: ["markdown"] @@ -232,6 +278,7 @@ proseWrap: "always" > - This is a long long > long long long long > long long paragraph. +> > \`\`\`js > // prettier-ignore @@ -472,6 +519,250 @@ proseWrap: "preserve" ================================================================================ `; +exports[`interrupt-others.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +This paragraph +> is interrupted by block quote. + +[This link +> is interrupted by block quote.](http://example.com) + +[[This wiki link +> is interrupted by block quote.]] + +> This is a block quote and this paragraph +> > is interrupted neither by block quote nor indented code block. + +=====================================output===================================== +This paragraph + +> is interrupted by block quote. + +[This link + +> is interrupted by block quote.](http://example.com) + +[[This wiki link + +> is interrupted by block quote.]] + +> This is a block quote and this paragraph > is interrupted neither by block +> quote nor indented code block. + +================================================================================ +`; + +exports[`interrupt-others.md - {"proseWrap":"never"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "never" + | printWidth +=====================================input====================================== +This paragraph +> is interrupted by block quote. + +[This link +> is interrupted by block quote.](http://example.com) + +[[This wiki link +> is interrupted by block quote.]] + +> This is a block quote and this paragraph +> > is interrupted neither by block quote nor indented code block. + +=====================================output===================================== +This paragraph + +> is interrupted by block quote. + +[This link + +> is interrupted by block quote.](http://example.com) + +[[This wiki link + +> is interrupted by block quote.]] + +> This is a block quote and this paragraph > is interrupted neither by block quote nor indented code block. + +================================================================================ +`; + +exports[`interrupt-others.md - {"proseWrap":"preserve"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "preserve" + | printWidth +=====================================input====================================== +This paragraph +> is interrupted by block quote. + +[This link +> is interrupted by block quote.](http://example.com) + +[[This wiki link +> is interrupted by block quote.]] + +> This is a block quote and this paragraph +> > is interrupted neither by block quote nor indented code block. + +=====================================output===================================== +This paragraph + +> is interrupted by block quote. + +[This link + +> is interrupted by block quote.](http://example.com) + +[[This wiki link + +> is interrupted by block quote.]] + +> This is a block quote and this paragraph > is interrupted neither by block quote nor indented code block. + +================================================================================ +`; + +exports[`list.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +> - list in quote +> with multiple lines +> - nested list item +> - nested list item 2 +> across multiple lines +> > quote in nested list in quote +> > with multiple lines + +- > quote in list + > with multiple lines + > - list item in quote in list + > > quote in list item in quote in list + > > with multiple lines + - nested list + +- > quote in list + > this line is indented by tab + +=====================================output===================================== +> - list in quote with multiple lines +> - nested list item +> - nested list item 2 across multiple lines +> > quote in nested list in quote with multiple lines + +- > quote in list with multiple lines + > + > - list item in quote in list + > > quote in list item in quote in list with multiple lines + - nested list + +- > quote in list this line is indented by tab + +================================================================================ +`; + +exports[`list.md - {"proseWrap":"never"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "never" + | printWidth +=====================================input====================================== +> - list in quote +> with multiple lines +> - nested list item +> - nested list item 2 +> across multiple lines +> > quote in nested list in quote +> > with multiple lines + +- > quote in list + > with multiple lines + > - list item in quote in list + > > quote in list item in quote in list + > > with multiple lines + - nested list + +- > quote in list + > this line is indented by tab + +=====================================output===================================== +> - list in quote with multiple lines +> - nested list item +> - nested list item 2 across multiple lines +> > quote in nested list in quote with multiple lines + +- > quote in list with multiple lines + > + > - list item in quote in list + > > quote in list item in quote in list with multiple lines + - nested list + +- > quote in list this line is indented by tab + +================================================================================ +`; + +exports[`list.md - {"proseWrap":"preserve"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "preserve" + | printWidth +=====================================input====================================== +> - list in quote +> with multiple lines +> - nested list item +> - nested list item 2 +> across multiple lines +> > quote in nested list in quote +> > with multiple lines + +- > quote in list + > with multiple lines + > - list item in quote in list + > > quote in list item in quote in list + > > with multiple lines + - nested list + +- > quote in list + > this line is indented by tab + +=====================================output===================================== +> - list in quote +> with multiple lines +> - nested list item +> - nested list item 2 +> across multiple lines +> > quote in nested list in quote +> > with multiple lines + +- > quote in list + > with multiple lines + > + > - list item in quote in list + > > quote in list item in quote in list + > > with multiple lines + - nested list + +- > quote in list + > this line is indented by tab + +================================================================================ +`; + exports[`nested.md - {"proseWrap":"always"} format 1`] = ` ====================================options===================================== parsers: ["markdown"] diff --git a/tests/format/markdown/blockquote/check-accidental.md b/tests/format/markdown/blockquote/check-accidental.md new file mode 100644 index 000000000..434f5fe13 --- /dev/null +++ b/tests/format/markdown/blockquote/check-accidental.md @@ -0,0 +1 @@ +long long long long long long long long long long long long long long long > > > > this is not quote diff --git a/tests/format/markdown/blockquote/interrupt-others.md b/tests/format/markdown/blockquote/interrupt-others.md new file mode 100644 index 000000000..3bf160e36 --- /dev/null +++ b/tests/format/markdown/blockquote/interrupt-others.md @@ -0,0 +1,11 @@ +This paragraph +> is interrupted by block quote. + +[This link +> is interrupted by block quote.](http://example.com) + +[[This wiki link +> is interrupted by block quote.]] + +> This is a block quote and this paragraph +> > is interrupted neither by block quote nor indented code block. diff --git a/tests/format/markdown/blockquote/list.md b/tests/format/markdown/blockquote/list.md new file mode 100644 index 000000000..f574d5ffb --- /dev/null +++ b/tests/format/markdown/blockquote/list.md @@ -0,0 +1,17 @@ +> - list in quote +> with multiple lines +> - nested list item +> - nested list item 2 +> across multiple lines +> > quote in nested list in quote +> > with multiple lines + +- > quote in list + > with multiple lines + > - list item in quote in list + > > quote in list item in quote in list + > > with multiple lines + - nested list + +- > quote in list + > this line is indented by tab diff --git a/tests/format/markdown/break/__snapshots__/format.test.js.snap b/tests/format/markdown/break/__snapshots__/format.test.js.snap index 257a8ae85..0aa6f57ac 100644 --- a/tests/format/markdown/break/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/break/__snapshots__/format.test.js.snap @@ -44,8 +44,7 @@ word very-very-very-very-very-very-very-very-very-very-long-word very-very-very- =====================================output===================================== a - very-very-very-very-very-very-very-very-very-very-long-word -very-very-very-very-very-very-very-very-very-very-long-word +very-very-very-very-very-very-very-very-very-very-long-word very-very-very-very-very-very-very-very-very-very-long-word very-very-very-very-very-very-very-very-very-very-long-word \\ diff --git a/tests/format/markdown/break/list-item/__snapshots__/format.test.js.snap b/tests/format/markdown/break/list-item/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..e95133e97 --- /dev/null +++ b/tests/format/markdown/break/list-item/__snapshots__/format.test.js.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`list-item.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +- 1 + foo +- 2\\ + bar + +=====================================output===================================== +- 1 foo +- 2\\ + bar + +================================================================================ +`; + +exports[`list-item.md format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 + | printWidth +=====================================input====================================== +- 1 + foo +- 2\\ + bar + +=====================================output===================================== +- 1 + foo +- 2\\ + bar + +================================================================================ +`; diff --git a/tests/format/markdown/break/list-item/format.test.js b/tests/format/markdown/break/list-item/format.test.js new file mode 100644 index 000000000..55fbeb39f --- /dev/null +++ b/tests/format/markdown/break/list-item/format.test.js @@ -0,0 +1,2 @@ +runFormatTest(import.meta, ["markdown"]); +runFormatTest(import.meta, ["markdown"], { proseWrap: "always" }); diff --git a/tests/format/markdown/break/list-item/list-item.md b/tests/format/markdown/break/list-item/list-item.md new file mode 100644 index 000000000..6f563879f --- /dev/null +++ b/tests/format/markdown/break/list-item/list-item.md @@ -0,0 +1,4 @@ +- 1 + foo +- 2\ + bar diff --git a/tests/format/markdown/code/__snapshots__/format.test.js.snap b/tests/format/markdown/code/__snapshots__/format.test.js.snap index c4ddf3d1f..ff49ca4c3 100644 --- a/tests/format/markdown/code/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/code/__snapshots__/format.test.js.snap @@ -32,7 +32,6 @@ proseWrap: "always" - 1 - 2 - 3 - \`\`\`js md\` # this is the root indent @@ -213,11 +212,11 @@ proseWrap: "always" -1. Change to your home directory: +1. Change to your home directory: cd -2. List the contents: +2. List the contents: ls -l diff --git a/tests/format/markdown/commonmark-test-suite-legacy/__snapshots__/format.test.js.snap b/tests/format/markdown/commonmark-test-suite-legacy/__snapshots__/format.test.js.snap index c01a76f19..f09814121 100644 --- a/tests/format/markdown/commonmark-test-suite-legacy/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/commonmark-test-suite-legacy/__snapshots__/format.test.js.snap @@ -147,7 +147,7 @@ proseWrap: "always" __a =====================================output===================================== -**a +__a ================================================================================ `; @@ -377,7 +377,8 @@ Header foo -## Header +Header +------ foo @@ -403,7 +404,7 @@ proseWrap: "always" \\[foo]: /url "not a reference" =====================================output===================================== -\\*not emphasized\\* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a +\\*not emphasized* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a list \\* not a list \\# not a header \\[foo]: /url "not a reference" ================================================================================ @@ -572,10 +573,10 @@ Bar =====================================output===================================== Foo Bar - --- -Foo Bar === +Foo Bar +=== ================================================================================ `; @@ -636,7 +637,7 @@ proseWrap: "always" > foo bar =====================================output===================================== -> foo bar +> foo bar ================================================================================ `; @@ -1126,8 +1127,7 @@ proseWrap: "always" - a - b - c -- d -- e +- d - e - f - g - h @@ -1153,7 +1153,7 @@ proseWrap: "always" \\[foo]: /url "not a reference" =====================================output===================================== -\\*not emphasized\\* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a +\\*not emphasized* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a list \\* not a list \\# not a heading \\[foo]: /url "not a reference" ================================================================================ @@ -1297,7 +1297,7 @@ proseWrap: "always" [ref]: /uri =====================================output===================================== -[foo \\*bar][ref] +[foo *bar][ref] [ref]: /uri diff --git a/tests/format/markdown/commonmark-test-suite/__snapshots__/format.test.js.snap b/tests/format/markdown/commonmark-test-suite/__snapshots__/format.test.js.snap index 6d95b19e9..5b36c790c 100644 --- a/tests/format/markdown/commonmark-test-suite/__snapshots__/format.test.js.snap +++ b/tests/format/markdown/commonmark-test-suite/__snapshots__/format.test.js.snap @@ -25,7 +25,9 @@ proseWrap: "always" foo baz bim =====================================output===================================== -foo baz bim +\`\`\` +foo baz bim +\`\`\` ================================================================================ `; @@ -80,7 +82,7 @@ proseWrap: "always" =====================================output===================================== - foo - bar + bar ================================================================================ `; @@ -95,7 +97,7 @@ proseWrap: "always" > foo =====================================output===================================== -> foo +> foo ================================================================================ `; @@ -110,7 +112,7 @@ proseWrap: "always" - foo =====================================output===================================== -- foo +- foo ================================================================================ `; @@ -146,7 +148,7 @@ proseWrap: "always" =====================================output===================================== - foo - bar - - baz + - baz ================================================================================ `; @@ -166,6 +168,21 @@ proseWrap: "always" ================================================================================ `; +exports[`snippet: example-11.md (Tabs) - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +* * * + +=====================================output===================================== +--- + +================================================================================ +`; + exports[`snippet: example-12.md (Backslash escapes) - {"proseWrap":"always"} format 1`] = ` ====================================options===================================== parsers: ["markdown"] @@ -214,7 +231,7 @@ proseWrap: "always" \\ö not a character entity =====================================output===================================== -\\*not emphasized\\* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a +\\*not emphasized* \\
not a tag \\[not a link](/foo) \\\`not code\` 1\\. not a list \\* not a list \\# not a heading \\[foo]: /url "not a reference" \\ö not a character entity @@ -398,7 +415,7 @@ proseWrap: "always" =====================================output=====================================   & © Æ Ď ¾ ℋ ⅆ -∲ ≧̸ +∲ ≧̸ ================================================================================ `; @@ -590,7 +607,7 @@ proseWrap: "always" *foo* =====================================output===================================== -\\*foo\\* _foo_ +*foo* _foo_ ================================================================================ `; @@ -607,7 +624,7 @@ proseWrap: "always" * foo =====================================output===================================== -\\* foo +* foo - foo @@ -718,7 +735,7 @@ proseWrap: "always" __ =====================================output===================================== --- \\*\\* \\_\\_ +-- ** __ ================================================================================ `; @@ -749,7 +766,7 @@ Foo *** =====================================output===================================== -Foo \\*\\*\\* +Foo *** ================================================================================ `; @@ -843,7 +860,7 @@ a------ ---a--- =====================================output===================================== -\\_ \\_ \\_ \\_ a +_ _ _ _ a a------ @@ -921,7 +938,8 @@ Foo bar =====================================output===================================== -## Foo +Foo +--- bar @@ -1285,9 +1303,11 @@ Foo *bar* --------- =====================================output===================================== -# Foo _bar_ +Foo _bar_ +========= -## Foo _bar_ +Foo _bar_ +--------- ================================================================================ `; @@ -1304,7 +1324,8 @@ baz* ==== =====================================output===================================== -Foo _bar baz_ ==== +Foo _bar baz_ +==== ================================================================================ `; @@ -1321,7 +1342,8 @@ baz* ==== =====================================output===================================== -Foo _bar baz_ ==== +Foo _bar baz_ +==== ================================================================================ `; @@ -1340,9 +1362,11 @@ Foo = =====================================output===================================== -## Foo +Foo +------------------------- -# Foo +Foo += ================================================================================ `; @@ -1364,11 +1388,14 @@ proseWrap: "always" === =====================================output===================================== -## Foo +Foo +--- -## Foo +Foo +----- -Foo === +Foo +=== ================================================================================ `; @@ -1409,8 +1436,7 @@ Foo =====================================output===================================== Foo - ---- +---- ================================================================================ `; @@ -1465,7 +1491,8 @@ Foo ----- =====================================output===================================== -## Foo +Foo +----- ================================================================================ `; @@ -1481,7 +1508,8 @@ Foo\\ ---- =====================================output===================================== -## Foo\\ +Foo\\ +---- ================================================================================ `; @@ -1502,11 +1530,13 @@ proseWrap: "always" of dashes"/> =====================================output===================================== -## \`Foo +\`Foo +---- \` -## @@ -1543,9 +1573,7 @@ bar === =====================================output===================================== -> foo - -# bar +> foo bar === ================================================================================ `; @@ -1581,7 +1609,6 @@ Bar =====================================output===================================== Foo Bar - --- ================================================================================ @@ -1606,7 +1633,8 @@ Baz Foo --- -## Bar +Bar +--- Baz @@ -1711,7 +1739,8 @@ proseWrap: "always" ------ =====================================output===================================== -## \\> foo +\\> foo +------ ================================================================================ `; @@ -1732,7 +1761,8 @@ baz =====================================output===================================== Foo -## bar +bar +--- baz @@ -1978,7 +2008,8 @@ Heading foo -## Heading +Heading +------ foo @@ -2501,7 +2532,8 @@ bar # baz =====================================output===================================== -## foo +foo +--- \`\`\` bar @@ -2631,9 +2663,7 @@ _world_.
 **Hello**,
 
-_world_.
-
-
+_world_. ================================================================================ @@ -3097,7 +3127,7 @@ _bar_ =====================================output=====================================