Skip to content

fix: keep lazy lines after a list in a nested blockquote - #4137

Merged
UziTech merged 1 commit into
markedjs:masterfrom
wahidrizka:fix-blockquote-list-raw
Oct 26, 2026
Merged

UziTech merged 1 commit into
markedjs:masterfrom
wahidrizka:fix-blockquote-list-raw

Conversation

@wahidrizka

@wahidrizka wahidrizka commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Marked version: 18.1.1 (cdbdc01)

Markdown flavor: CommonMark|GitHub Flavored Markdown

Description

When a list in a blockquote takes lazy continuation lines, blockquote() cuts the old list raw off the end of its own raw and appends the new list raw. The list raw has no > markers, so that only works for a one-line list. Otherwise the blockquote raw stops matching the source:

marked.lexer('> - a\n> - b\nc')[0].raw
// '> - - a\n- b\nc\n'

A blockquote around this one uses that raw to find out which continuation lines the inner blockquote took, so lazy lines end up outside both blockquotes, and sometimes text is lost:

Expectation

> > - a
> b
c

> > - a
> > - b
>   c
d
<blockquote>
<blockquote>
<ul>
<li>a
b
c</li>
</ul>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li>a</li>
<li>b
c
d</li>
</ul>
</blockquote>
</blockquote>

as commonmark.js renders it.

Result

<blockquote>
<blockquote>
<ul>
<li>a
b</li>
</ul>
</blockquote>
</blockquote>
<p>c</p>
<blockquote>
<blockquote>
<ul>
<li><ul>
<li>a</li>
</ul>
</li>
</ul>
</blockquote>
</blockquote>
<p>d</p>

The second list loses b and c.

What was attempted

The list branch now counts the continuation lines the new list took and adds those lines from the source to raw and text, as the nested blockquote branch above it already does. The lines it did not take are passed on as they are, without the empty first line that splitting the rest of newText used to add.

Found by checking that the raw values of the top-level tokens join back to the source. On 60,000 distinct generated documents with blockquotes, lists and trailing whitespace (gfm: false), raw mismatches drop from 5,345 to 1,206, and 73 render differently: 31 now match commonmark.js and did not before, 42 match it neither before nor after, and none stopped matching. In 27 of the 73, master's output is missing text that commonmark.js has, and the fix has all of it. One goes the other way: in > > - x\n> bar\n # foo the indented lazy line is now read as part of the list item and becomes a heading, where master moved it out of the blockquotes as a code block (commonmark.js keeps it as paragraph text). That comes from lazy lines being passed to list() as item lines, which this does not change. One document gets a raw mismatch that master does not have: the fix reads its last line - as an empty list item, as commonmark.js does, and the list's raw ends in -\n, which master also gives for - on its own. All 652 CommonMark and 28 GFM spec examples render exactly as before.

(Edited: my first numbers counted some generated documents twice and missed the raw mismatch above. These are from 60,000 distinct documents.)

The new lazy line in a nested list lexer test and test/specs/new/blockquote_nested_list_lazy_lines both fail on master. Specs, unit, umd, cjs, types and lint pass locally, except the five bin exec tests, which fail on master too because my checkout path has a space in it.

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.

When a list in a blockquote took lazy lines, the blockquote cut the old
list raw off the end of its own raw. The list raw has no > markers, so
for a list of more than one line the blockquote raw stopped matching
the source, and an outer blockquote then lost track of the lines the
inner one took. Add the source lines the list took instead.
@vercel

vercel Bot commented Oct 13, 2026

Copy link
Copy Markdown

@wahidrizka 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 13, 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 13, 2026 3:49am UTC

Request Review

@UziTech UziTech 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.

Nice catch! 💯

@UziTech
UziTech merged commit 38c7e55 into markedjs:master Oct 26, 2026
8 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 26, 2026
## [18.1.2](v18.1.1...v18.1.2) (2026-10-26)

### Bug Fixes

* allow a tab or end of input after a type 6 html block tag name ([#4128](#4128)) ([e09c40d](e09c40d))
* apply emphasis flanking and rules 9-10 to the whole delimiter run ([#4145](#4145)) ([5d8e234](5d8e234))
* **cli:** await config functions before parsing ([#4138](#4138)) ([3a11ad1](3a11ad1))
* **cli:** create no-clobber output files atomically ([#4135](#4135)) ([e7c4f64](e7c4f64))
* do not continue a block quote paragraph from a whitespace-only line ([#4134](#4134)) ([42f34a8](42f34a8))
* expand a tab after the block quote marker to the next tab stop ([#4110](#4110)) ([2d3899b](2d3899b))
* honor per-call async options when composing hooks ([#4139](#4139)) ([379be9d](379be9d))
* keep a line starting with # but no space in the list item ([#4127](#4127)) ([6b63189](6b63189))
* keep duplicate link definitions in the tokens ([#4132](#4132)) ([2784acc](2784acc))
* keep lazy lines after a list in a nested blockquote ([#4137](#4137)) ([38c7e55](38c7e55))
* keep lazy setext underlines in list items as text ([#4126](#4126)) ([398234c](398234c))
* render nested image alt formatting as plain text ([#4131](#4131)) ([15f59bb](15f59bb))
* stop an unclosed inline raw tag from unescaping later blocks ([#4130](#4130)) ([4562b6f](4562b6f))

### Performance Improvements

* ~16% faster parsing by skipping em/strong masking for runs without *, _ or ~ ([#4142](#4142)) ([f0fd3e0](f0fd3e0))

This branch was successfully deployed

1 active deployment
Preview — 7bb4bd95 Deployed Oct 13, 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.

2 participants