Fix adjacent markdown syntax in blockquote (#16596)

Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
Florian Diemingerandfisker authored and GitHub committed 2025-03-28 20:00:57 +08:00
1 parent 36b346c9f4
commit 91c563e323
5 files changed
+641 -16

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
#### Fix adjacent markdown syntax in blockquote (#16596 by @fiji-flo)
<!-- prettier-ignore -->
```md
<!-- Input -->
> `x`
> `y`
> _x_
> _y_
> [foo](http://foo)
> [bar](http://bar)
> `this` behaves
> `correctly`
<!-- Prettier stable -->
> `x` > `y`
> _x_ > _y_
> [foo](http://foo) > [bar](http://bar)
> `this` behaves `correctly`
<!-- Prettier main -->
> `x` `y`
> _x_ _y_
> [foo](http://foo) [bar](http://bar)
> `this` behaves `correctly`
```
+29 -16
View File
@@ -2,7 +2,8 @@ import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
import { getOrderedListItemInfo, mapAst, splitText } from "./utils.js";
// 0x0 ~ 0x10ffff
const isSingleCharRegex = /^.$/su;
const isSingleCharRegex = /^\\?.$/su;
const isNewLineBlockquoteRegex = /^\n *>[ >]*$/u;
function preprocess(ast, options) {
ast = restoreUnescapedCharacter(ast, options);
@@ -14,21 +15,33 @@ function preprocess(ast, options) {
}
function restoreUnescapedCharacter(ast, options) {
return mapAst(ast, (node) =>
node.type !== "text" ||
node.value === "*" ||
node.value === "_" || // handle these cases in printer
!isSingleCharRegex.test(node.value) ||
node.position.end.offset - node.position.start.offset === node.value.length
? node
: {
...node,
value: options.originalText.slice(
node.position.start.offset,
node.position.end.offset,
),
},
);
return mapAst(ast, (node) => {
if (node.type !== "text") {
return node;
}
const { value } = node;
if (
value === "*" ||
value === "_" || // handle these cases in printer
!isSingleCharRegex.test(value) ||
node.position.end.offset - node.position.start.offset === value.length
) {
return node;
}
const text = options.originalText.slice(
node.position.start.offset,
node.position.end.offset,
);
if (isNewLineBlockquoteRegex.test(text)) {
return node;
}
return { ...node, value: text };
});
}
function mergeChildren(ast, shouldMerge, mergeNode) {
@@ -43,6 +43,90 @@ proseWrap: "always"
================================================================================
`;
exports[`code.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
> NOTE: To use \`unobtrusive\`, \`unobtrusive/import\`, \`unobtrusive/react\`, and \`unobtrusive/flowtype\` together, your eslint config would look like this:
>\`\`\`json
>{
> "extends": [
> "unobtrusive",
> "unobtrusive/import",
> "unobtrusive/react",
> "unobtrusive/flowtype"
> ],
> "env": {
> "browser": true
> }
>}
>\`\`\`
=====================================output=====================================
> NOTE: To use \`unobtrusive\`, \`unobtrusive/import\`, \`unobtrusive/react\`, and \`unobtrusive/flowtype\` together, your eslint config would look like this:
>
> \`\`\`json
> {
> "extends": [
> "unobtrusive",
> "unobtrusive/import",
> "unobtrusive/react",
> "unobtrusive/flowtype"
> ],
> "env": {
> "browser": true
> }
> }
> \`\`\`
================================================================================
`;
exports[`code.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
> NOTE: To use \`unobtrusive\`, \`unobtrusive/import\`, \`unobtrusive/react\`, and \`unobtrusive/flowtype\` together, your eslint config would look like this:
>\`\`\`json
>{
> "extends": [
> "unobtrusive",
> "unobtrusive/import",
> "unobtrusive/react",
> "unobtrusive/flowtype"
> ],
> "env": {
> "browser": true
> }
>}
>\`\`\`
=====================================output=====================================
> NOTE: To use \`unobtrusive\`, \`unobtrusive/import\`, \`unobtrusive/react\`, and \`unobtrusive/flowtype\` together, your eslint config would look like this:
>
> \`\`\`json
> {
> "extends": [
> "unobtrusive",
> "unobtrusive/import",
> "unobtrusive/react",
> "unobtrusive/flowtype"
> ],
> "env": {
> "browser": true
> }
> }
> \`\`\`
================================================================================
`;
exports[`ignore-code.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -158,6 +242,236 @@ proseWrap: "always"
================================================================================
`;
exports[`ignore-code.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
> \`\`\`\`md
> <!-- prettier-ignore -->
> \`\`\`js
> ugly ( code ) ;
> \`\`\`
> \`\`\`\`
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
> - test
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`md
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`
> \`\`\`\`md
> > \`\`\`md
> > <!-- prettier-ignore -->
> > - This is a long long
> > long long long long
> > long long paragraph.
> > \`\`\`
> \`\`\`\`
>
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
>
> \`\`\`\`js
> // prettier-ignore
> const x = 1,
> b = 2
> \`\`\`\`
=====================================output=====================================
> \`\`\`\`md
> <!-- prettier-ignore -->
> \`\`\`js
> ugly ( code ) ;
> \`\`\`
> \`\`\`\`
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
> - test
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`md
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`
> \`\`\`\`md
> > \`\`\`md
> > <!-- prettier-ignore -->
> > - This is a long long
> > long long long long
> > long long paragraph.
> > \`\`\`
> \`\`\`\`
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`js
> // prettier-ignore
> const x = 1,
> b = 2
> \`\`\`
================================================================================
`;
exports[`ignore-code.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
> \`\`\`\`md
> <!-- prettier-ignore -->
> \`\`\`js
> ugly ( code ) ;
> \`\`\`
> \`\`\`\`
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
> - test
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`md
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`
> \`\`\`\`md
> > \`\`\`md
> > <!-- prettier-ignore -->
> > - This is a long long
> > long long long long
> > long long paragraph.
> > \`\`\`
> \`\`\`\`
>
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
>
> \`\`\`\`js
> // prettier-ignore
> const x = 1,
> b = 2
> \`\`\`\`
=====================================output=====================================
> \`\`\`\`md
> <!-- prettier-ignore -->
> \`\`\`js
> ugly ( code ) ;
> \`\`\`
> \`\`\`\`
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
> - test
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`md
> \`\`\`md
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`
\`\`\`\`
> \`\`\`\`md
> > \`\`\`md
> > <!-- prettier-ignore -->
> > - This is a long long
> > long long long long
> > long long paragraph.
> > \`\`\`
> \`\`\`\`
> <!-- prettier-ignore -->
> - This is a long long
> long long long long
> long long paragraph.
> \`\`\`js
> // prettier-ignore
> const x = 1,
> b = 2
> \`\`\`
================================================================================
`;
exports[`nested.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -173,6 +487,185 @@ proseWrap: "always"
================================================================================
`;
exports[`nested.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
>>> 123
=====================================output=====================================
> > > 123
================================================================================
`;
exports[`nested.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
>>> 123
=====================================output=====================================
> > > 123
================================================================================
`;
exports[`notext-end.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "always"
| printWidth
=====================================input======================================
> [!NOTE]
> \`DOOM\`
> _b_
>> \`A\`
>> \`B\`
> *a*
>> # foo
>> \`a\` > \`b\`
> This is a quote with an italic _across multuple lines
> which should just work_. So make sure there is no > if we set
> proseWrap to \`never\`
> This is a quote with a link [across multuple lines
> which should just work](). So make sure there is no > if we set
> proseWrap to \`never\`
=====================================output=====================================
> [!NOTE] \`DOOM\`
> _b_
>
> > \`A\` \`B\`
> _a_
>
> > # foo
> >
> > \`a\` > \`b\`
> This is a quote with an italic _across multuple lines which should just work_.
> So make sure there is no > if we set proseWrap to \`never\`
> This is a quote with a link [across multuple lines which should just work]().
> So make sure there is no > if we set proseWrap to \`never\`
================================================================================
`;
exports[`notext-end.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
> [!NOTE]
> \`DOOM\`
> _b_
>> \`A\`
>> \`B\`
> *a*
>> # foo
>> \`a\` > \`b\`
> This is a quote with an italic _across multuple lines
> which should just work_. So make sure there is no > if we set
> proseWrap to \`never\`
> This is a quote with a link [across multuple lines
> which should just work](). So make sure there is no > if we set
> proseWrap to \`never\`
=====================================output=====================================
> [!NOTE] \`DOOM\`
> _b_
>
> > \`A\` \`B\`
> _a_
>
> > # foo
> >
> > \`a\` > \`b\`
> This is a quote with an italic _across multuple lines which should just work_. So make sure there is no > if we set proseWrap to \`never\`
> This is a quote with a link [across multuple lines which should just work](). So make sure there is no > if we set proseWrap to \`never\`
================================================================================
`;
exports[`notext-end.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
> [!NOTE]
> \`DOOM\`
> _b_
>> \`A\`
>> \`B\`
> *a*
>> # foo
>> \`a\` > \`b\`
> This is a quote with an italic _across multuple lines
> which should just work_. So make sure there is no > if we set
> proseWrap to \`never\`
> This is a quote with a link [across multuple lines
> which should just work](). So make sure there is no > if we set
> proseWrap to \`never\`
=====================================output=====================================
> [!NOTE]
> \`DOOM\`
> _b_
>
> > \`A\`
> > \`B\`
> _a_
>
> > # foo
> >
> > \`a\` > \`b\`
> This is a quote with an italic _across multuple lines
> which should just work_. So make sure there is no > if we set
> proseWrap to \`never\`
> This is a quote with a link [across multuple lines
> which should just work](). So make sure there is no > if we set
> proseWrap to \`never\`
================================================================================
`;
exports[`paragraph.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -191,6 +684,39 @@ proseWrap: "always"
================================================================================
`;
exports[`paragraph.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
> This is a long long long long long long long long long long long long long long long paragraph.
> This is a long long long long long long long long long long long long long long long paragraph.
=====================================output=====================================
> This is a long long long long long long long long long long long long long long long paragraph. This is a long long long long long long long long long long long long long long long paragraph.
================================================================================
`;
exports[`paragraph.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
> This is a long long long long long long long long long long long long long long long paragraph.
> This is a long long long long long long long long long long long long long long long paragraph.
=====================================output=====================================
> This is a long long long long long long long long long long long long long long long paragraph.
> This is a long long long long long long long long long long long long long long long paragraph.
================================================================================
`;
exports[`simple.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
@@ -205,3 +731,33 @@ proseWrap: "always"
================================================================================
`;
exports[`simple.md - {"proseWrap":"never"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
> 123
=====================================output=====================================
> 123
================================================================================
`;
exports[`simple.md - {"proseWrap":"preserve"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "preserve"
| printWidth
=====================================input======================================
> 123
=====================================output=====================================
> 123
================================================================================
`;
@@ -1 +1,3 @@
runFormatTest(import.meta, ["markdown"], { proseWrap: "always" });
runFormatTest(import.meta, ["markdown"], { proseWrap: "preserve" });
runFormatTest(import.meta, ["markdown"], { proseWrap: "never" });
@@ -0,0 +1,19 @@
> [!NOTE]
> `DOOM`
> _b_
>> `A`
>> `B`
> *a*
>> # foo
>> `a` > `b`
> This is a quote with an italic _across multuple lines
> which should just work_. So make sure there is no > if we set
> proseWrap to `never`
> This is a quote with a link [across multuple lines
> which should just work](). So make sure there is no > if we set
> proseWrap to `never`