Skip to content

fix: do not continue a block quote paragraph from a whitespace-only line - #4134

Open
OsamaAnsar wants to merge 1 commit into
markedjs:masterfrom
OsamaAnsar:fix/blockquote-whitespace-only-line
Open

OsamaAnsar wants to merge 1 commit into
markedjs:masterfrom
OsamaAnsar:fix/blockquote-whitespace-only-line

Conversation

@OsamaAnsar

Copy link
Copy Markdown

Marked version: 18.1.1 (master at cdbdc01)

Markdown flavor: CommonMark

Description

  • Fixes #### : no existing issue that I could find, so the issue is described below.

Expectation

Text after a block quote line that has two or more trailing spaces after the > should end the quote, like it does for > and > . CommonMark, commonmark.js and markdown-it all give:

> a
>  
b
<blockquote>
<p>a</p>
</blockquote>
<p>b</p>

Result

On master the unquoted line b is swallowed into the block quote (marked.parse('> a\n> \nb')):

<blockquote>
<p>a
 
b</p>
</blockquote>

With three trailing spaces ('> a\n> \nb') b is also inside the quote and gets a hard line break: <blockquote>\n<p>a\n<br>b</p>\n</blockquote>\n. And '> \nb' (a quote whose only line is whitespace) gives <blockquote>\n<p>b</p>\n</blockquote>\n instead of an empty quote followed by <p>b</p>. '> a\n>\nb' and '> a\n> \nb' already work.

What was attempted

In the blockquote rule, > ? consumes one space after the marker, and a whitespace-only remainder (> leaves a single space) then matches the paragraph alternative, which lazily continues onto the next unquoted line. The fix keeps whitespace-only lines out of that branch with a negative lookahead that guards only the paragraph alternative, so they fall through to the existing [^\n]* branch like > and > do:

-const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/)
+const blockquote = edit(/^( {0,3}> ?(?:(?![ \t]*(?:\n|$))(paragraph)|[^\n]*)(?:\n|$))+/)

After the fix (same inputs): '> a\n> \nb' -> <blockquote>\n<p>a\n </p>\n</blockquote>\n<p>b</p>\n, '> a\n> \nb' -> <blockquote>\n<p>a\n </p>\n</blockquote>\n<p>b</p>\n, '> \nb' -> <blockquote>\n</blockquote>\n<p>b</p>\n. A stray whitespace-only line is still left inside the quote's paragraph (<p>a\n </p>); this PR does not try to remove it. The spec runner's HTML differ ignores that whitespace.

How I checked it:

  • npm test (build:reset, build:docs, specs, unit, umd, cjs, types, lint): exit 0. Specs 1915/1915 and unit 199/199 with the fix; on unmodified master the specs are 1911 pass with my 2 new spec files failing (4 failing test entries: suite + case each), so no existing spec changed.
  • Reverted only the src/rules.ts change, rebuilt, and confirmed the built bundle no longer had the lookahead and reproduced the master output above: both new specs fail. Restored the change, rebuilt: both pass.
  • npm run test:redos: the block.normal.blockquote and block.gfm.blockquote regexes are reported safe with the change.
  • A/B fuzz of master vs this branch over 500,000 random block-structure inputs (quote markers with 0-3 trailing spaces, lists, headings, fences, setext lines, html starts, link definitions, tabs, blank lines), filtered to inputs where commonmark.js and markdown-it produce the same normalized HTML (about 342,000 of them): 0 cases where master matched both and this branch does not; 1,941 cases where master differed from both and this branch matches. Output differed from master on 2,922 inputs in total, including some where the two reference parsers disagree and some where neither version matches them (existing unrelated differences); I did not triage those.
  • Quick timing on a 5,000-repeat blockquote/list/paragraph document, 20 parses each, run twice: master 79.3 / 76.8 ms per parse, this branch 77.4 / 79.4 ms. No measurable difference.

Test files added under test/specs/new/: blockquote_whitespace_only_line (two quotes with 2 and 3 trailing spaces followed by an unquoted line) and blockquote_whitespace_only_empty (> then an unquoted line).

Nearby open PRs: #4110 (tab after the block quote marker) changes Tokenizer.ts/rules.ts around block quote markers but not this regex; I did not find an open PR that changes the blockquote rule.

Contributor

  • Test(s) exist to ensure functionality and minimize regression (if no tests added, list tests covering this PR); or,
  • no tests required for this PR.
  • If submitting new feature, it has been documented in the appropriate places.

Committer

In most cases, this should be a different person than the contributor.

In `> a\n>  \nb` the marker consumes one space and the remaining
whitespace-only text matched the lazy paragraph branch of the blockquote
rule, which then swallowed the following unquoted line into the quote.
A line with only whitespace after the marker is blank and must end the
paragraph, as for `>` and `> `.
@vercel

vercel Bot commented Oct 12, 2026

Copy link
Copy Markdown

@OsamaAnsar is attempting to deploy a commit to the MarkedJS Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented Oct 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
marked-website Ready Ready Preview Oct 12, 2026 7:16pm UTC

Request Review

This branch was successfully deployed

1 active deployment
Preview — 0112ce84 Deployed Oct 12, 2026 by vercel[bot]
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.

1 participant