Skip to content

Fix escaped angle brackets in blockquotes - #19602

Closed
fede-oss wants to merge 4 commits into
prettier:mainfrom
fede-oss:fix/markdown-escaped-blockquote-marker
Closed

fede-oss wants to merge 4 commits into
prettier:mainfrom
fede-oss:fix/markdown-escaped-blockquote-marker

Conversation

@fede-oss

@fede-oss fede-oss commented Jul 11, 2026 •

Copy link
Copy Markdown

Description

Fixes #19528.

The Markdown blockquote preprocessor previously replaced an empty raw prefix with a parsed leading >. When the source contained an escaped \>, that replacement inserted an extra unescaped angle bracket. This change skips blockquote-marker normalization when the raw line has no leading marker.

The regression fixture covers plain, strong, and standalone escaped angle brackets under all supported proseWrap modes.

Checklist

  • I’ve added tests to confirm my change works.
  • (If changing the API or CLI) I’ve documented the changes I’ve made (in the docs/ directory). (Not applicable; no API or CLI change.)
  • (If the change is user-facing) I’ve added my changes to changelog_unreleased/*/XXXX.md file following changelog_unreleased/TEMPLATE.md.
  • I’ve read the contributing guidelines.
  • I did not use AI to generate this PR.

Tested with:

@netlify

netlify Bot commented Jul 11, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for prettier ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 1551f05
🔍 Latest deploy log https://app.netlify.com/projects/prettier/deploys/6a53d7f495f91c0008746c33
😎 Deploy Preview https://deploy-preview-19602--prettier.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@fisker
fisker requested a review from seiyab July 12, 2026 05:27
@pkg-pr-new

pkg-pr-new Bot commented Jul 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

yarn add https://pkg.pr.new/@prettier/[email protected]
yarn add https://pkg.pr.new/@prettier/[email protected]
yarn add https://pkg.pr.new/[email protected]

commit: 931ae23

@seiyab

seiyab commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Still suspicious case:


Prettier PR #19602
Playground link

--parser markdown

Input:

> \>
> \>

Output:

> \> >\>

This is not a regression but stable Prettier also yields wired output for it. So I won't strongly reject this PR just because of it but it should be worth to inform you.
I'm still reviewing it and I haven't understand the change (and remembered things around it) enough yet.

@seiyab

seiyab commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Prettier PR #19602
Playground link

--parser markdown

Input:

> *text* > \>

Output:

> _text_ > >\>

@seiyab seiyab left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weakly approve this.

  • 🟡 We need a new issue for #19602 (comment) and #19602 (comment) if we merge it as-is.
  • 🟢 Problems above is not a regression. And this doesn't look to cause other regressions.
  • 🟢 This PR resolves all cases reported in #19528 and make a progress at least.

@fisker fisker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fede-oss Can you address the problems mentioned in #19602 (review)?

@LHMQ878

LHMQ878 commented Jul 26, 2026 •

Copy link
Copy Markdown

@fede-oss @fisker @seiyab I ran into the same bug from the other side: I opened #19726 for
#19528 without noticing this PR, and @fisker rightly closed it as a duplicate with the same
two open cases. Since this PR has been waiting on exactly those two cases, here is what I
found while digging into them - hopefully useful rather than duplicated effort. Happy for it
to land here, in whatever form you prefer.

Why both of our patches miss those two cases

Both versions keep the original substitution:

return rawLine.replace(angleBracketsRegex, leadingTextAngleBrackets);

Instrumenting getBlockquoteRawText for the two-line input shows what it actually receives:

text  = "\>\n> \>"     <- raw: the continuation line still carries the "> " marker
value = ">\n>"           <- value: escapes resolved, both lines are a literal ">"

Per line:

line rawLine raw match valueLine value match outcome
0 \> "" > > guard catches it
1 > \> "> " > > marker replaced by content > -> >\>

The guard only helps when the whole raw line has no marker, so it fixes the single-line
cases in #19528 but not a continuation line. The deeper problem is that the value line's
leading >s are content, while the raw line's leading >s are structure - so
substituting one for the other is what invents the extra marker.

What worked for me

Strip only the markers that node.value does not already carry, and never splice value text
back in:

const rawAngleBrackets = rawLine.match(angleBracketsRegex)[0];
if (!rawAngleBrackets) {
  return rawLine;
}
const valueLine = valueLines[index] ?? "";
const contentAngleBrackets = valueLine.match(angleBracketsRegex)[0];
const markerLength = Math.max(
  0,
  rawAngleBrackets.length - contentAngleBrackets.length,
);
return rawLine.slice(markerLength);

The Math.max(0, ...) matters: for > *text* > \> the value side is longer than the raw side
(raw " > " vs value " > >"), and without the clamp it over-strips and drops the inner >.

Results on the two blocking cases

input before after
> \> + > \> > \> >\> input preserved
> *text* > \> > _text_ > >\> > _text_ > \>

Checked 10 inputs total - the three from #19528, both cases from your review comments, plus
nested > >, a three-line quote, tab-indented markers, and > a > b \>. All are unchanged
from input (apart from normal emphasis normalisation) and idempotent on a second pass.

yarn jest tests/format/markdown stays green at 63 suites / 1479 tests / 1468 snapshots, and
tests/format/mdx passes as well. I also grepped the regenerated snapshots to confirm no
>\> sequence is frozen anywhere.

How would you like to proceed?

This PR already has @seiyab's approval and only needs those cases closed out, so the cleanest
path is probably for you to fold the snippet in here - please treat it as yours, no
attribution needed. If you'd rather not, I can push it as a follow-up on top of this branch,
or reopen #19726 rebased on it - whichever the maintainers prefer. I'd just rather not open a
competing PR against work that's already been reviewed.

@fisker

fisker commented Jul 26, 2026 •

Copy link
Copy Markdown
Member

This PR won't be merged until the two cases that seiyab pointed out been addressed.

The author of this PR seems not responding, you can continue work in #19726.

@fisker

fisker commented Aug 2, 2026

Copy link
Copy Markdown
Member

Close due to lake of response.

@fisker fisker closed this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Markdown: Prettier 3.9.x incorrectly inserts > before \>

4 participants