Skip to content

fix: allow tabs in the thematic break that ends a list item - #4087

Merged
UziTech merged 1 commit into
markedjs:masterfrom
giaBaoJS:fix/hr-tabs-end-list-item
Sep 8, 2026
Merged

UziTech merged 1 commit into
markedjs:masterfrom
giaBaoJS:fix/hr-tabs-end-list-item

Conversation

@giaBaoJS

@giaBaoJS giaBaoJS commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Marked version: 18.0.11 (master, 4417582)

Markdown flavor: CommonMark

Description

A thematic break whose characters are separated or followed by tabs does not end an open list item.

Input (tabs shown as <TAB>):

- foo
_<TAB>_<TAB>_

Expected:

<ul>
<li>foo</li>
</ul>
<hr>

Actual:

<ul>
<li>foo<hr>
</li>
</ul>

A trailing tab is enough to trigger it for every break character, and with - the result is worse, because the line is then read as a setext underline:

- foo
---<TAB>

Expected <ul><li>foo</li></ul><hr>, actual <ul><li><h2>foo</h2></li></ul>.

The same input with spaces instead of tabs (_ _ _, --- ) is already handled correctly, and *<TAB>*<TAB>* happens to work only because nextBulletRegex catches the leading * first.

Spec

CommonMark 0.31.2, section 4.1 Thematic breaks:

A line consisting of optionally up to three spaces of indentation, followed by a sequence of three or more matching -, _, or * characters, each followed optionally by any number of spaces or tabs, forms a thematic break.

A thematic break is not paragraph continuation text, so it cannot be a lazy continuation line of the list item (section 5.2, rule 5) and closes the list. Spec example 57 (- foo / *** / - bar) already covers the space-only form, which marked passes. commonmark 0.31.2, the reference implementation already in devDependencies, produces the expected output above for all three tab variants.

Root cause

other.hrRegex in src/rules.ts, used by the list tokenizer to decide that a following line closes the item, allowed only spaces after each break character, while the block hr rule it is supposed to mirror already allows [ \t]. The break line therefore fell through to the paragraph-continuation path and stayed inside the item.

Spec suite

Before: 1801 tests, 1801 pass, 0 fail.
After: 1803 tests, 1803 pass, 0 fail (the two added tests). The CommonMark and GFM completion tables are unchanged, including the known failures (Entity and numeric character references 15/17, Links 84/90, GFM Autolinks 15/19 and 11/14, Disallowed Raw HTML 0/1). npm run test:unit (191 pass), npm run test:lint and tsc are clean.

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.

CommonMark 0.31.2 says each -, _, or * of a thematic break may be
followed by any number of spaces or tabs, but the hrRegex that closes a
list item allowed spaces only, so a break written with tabs was taken as
paragraph continuation instead. "- foo" followed by a line of
underscores separated by tabs put the hr inside the list item, and
"- foo" followed by "---" plus a tab turned foo into a setext heading.

The block hr rule already allows tabs; this makes the list item check
agree with it.
@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

@giaBaoJS 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 Sep 6, 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 Sep 6, 2026 5:10am 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.

Thanks! 💯

@UziTech
UziTech merged commit afbb27c into markedjs:master Sep 8, 2026
8 checks passed
github-actions Bot pushed a commit that referenced this pull request Sep 12, 2026
## [18.0.13](v18.0.12...v18.0.13) (2026-09-12)

### Bug Fixes

* allow tabs in the thematic break that ends a list item ([#4087](#4087)) ([afbb27c](afbb27c))
* avoid O(n^2) scanning in reflinkSearch ([#4090](#4090)) ([c6a25bb](c6a25bb))
* case fold reference link labels ([#4077](#4077)) ([aed9336](aed9336))
* drop the leading whitespace after a hard line break ([#4075](#4075)) ([123ce04](123ce04))
* match html block start conditions when ending a list item ([#4072](#4072)) ([c2facac](c2facac))
* respect raw tokens when closing link labels ([#4066](#4066)) ([ef394f7](ef394f7))
* strip a tab that follows spaces in an indented code block ([#4080](#4080)) ([dbb393d](dbb393d))
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.

3 participants