Skip to content

fix: drop the leading whitespace after a hard line break - #4075

Open
Kjubikstronk wants to merge 1 commit into
markedjs:masterfrom
Kjubikstronk:fix-hardbreak-leading-space
Open

fix: drop the leading whitespace after a hard line break#4075
Kjubikstronk wants to merge 1 commit into
markedjs:masterfrom
Kjubikstronk:fix-hardbreak-leading-space

Conversation

@Kjubikstronk

Copy link
Copy Markdown

Marked version: 18.0.11 (53cb13f)

Markdown flavor: CommonMark

Description

CommonMark ignores leading spaces at the start of the line following a hard line break. The br rule is:

const br = /^( {2,}|\)\n(?!\s*$)/;

It consumes the break itself but not the next line's indentation, so that indentation stays on the following text token and is rendered.

Expectation

foo··
·····bar

gives <p>foo<br />\nbar</p>.

Result

<p>foo<br> bar</p>. The five spaces survive.

What was attempted

Appending * to the rule, so the break consumes the indentation that follows it.

This one is easy to measure wrongly, which is worth writing down. Neither of the comparisons normally used here can see it:

  • marked's own suite compares through htmlIsEqual, which leaves ignoreWhitespaces at its default of true, so the difference is invisible and examples 636 and 637 already report as passing with no shouldFail flag.
  • An exact string comparison fails both before and after the change, because marked emits <br> where the spec's reference output has <br /> followed by a newline.

Under the spec's own test/normalize.py, which normalises the self-closing slash but keeps a single space that begins a text node after a tag, the whole-spec count goes from 28 to 26. The two that move are exactly 636 and 637, and nothing else changes, in both the CommonMark and GFM runs.

Credit where it is due: I originally measured this with the two comparisons above, concluded it was not a bug, and said so in #4050. @exit0-run showed the normalize.py measurement and was right.

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.

Three tests in test/unit/marked.test.js under hard line break, covering the two-space and backslash spellings plus a soft break as a control. The first two fail without the change; the control passes either way. Full spec suite (1789) and unit suite (194) pass.

Committer

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

CommonMark ignores leading spaces at the start of the line following a hard
line break. The br rule consumed the break but not that indentation, so it
stayed on the following text token.

Fixes CommonMark examples 636 and 637. Neither marked's differ nor an exact
comparison can see this: the differ ignores whitespace, and exact still
differs on <br> versus <br />. Under the spec's own normalize.py the count
goes from 28 to 26.
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

@Kjubikstronk 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 1, 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 1, 2026 12:20am UTC

Request Review

Comment thread test/unit/marked.test.js

describe('hard line break', () => {
it('should drop the leading whitespace of the continuation line', () => {
assert.strictEqual(marked.parse('foo \n bar\n'), '<p>foo<br>bar</p>\n');

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.

Shouldn't there be a new line character after the <br>?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

marked does not emit one, and that part is not new to this PR. Its own fixtures already encode the current output:

test/specs/new/breaks.html

<p>A<br>B</p>

test/specs/new/breakline.html

<p>A<br>break line test<br>Special <code>code</code>A<br>break line test</p>

CommonMark's reference is <p>foo<br />\nbar</p>, so marked differs from it on both the self closing slash and the newline. The spec suite never flags either, because htmlIsEqual normalises both.

So the newline is a separate question from this fix, and adding it here would change breaks, breakline, and every other fixture with a <br> in it. Happy to open a separate issue if you think marked should match the reference there.

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.

We have an extension (marked-xhtml) for the self closing slash, so we don't need that in marked. I think we should add the new line after br but that can be a separate issue.

Comment thread test/unit/marked.test.js

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.

Let's add tests in test/specs/new instead of marked.test.js

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I tried that first and the fixture cannot fail.

I added test/specs/new/hardbreak_leading_whitespace.md with the three cases, reverted the br change, and reran. It still passes:

> hardbreak_leading_whitespace
  ok hardbreak_leading_whitespace should pass

runTests compares with htmlIsEqual, and testutils constructs @markedjs/html-differ with only ignoreSelfClosingSlash and ignoreComments set, so ignoreWhitespaces stays at its default of true. The bug here is only whitespace, <p>foo<br> bar</p> against <p>foo<br>bar</p>, so nothing under test/specs can see it, and there is no per fixture option to turn the normalisation off.

That is the same blind spot that let examples 636 and 637 report as passing all along, which is what made me call this a non bug in #4050 in the first place.

I am happy to add the fixture anyway if you want it as documentation, but it would pass whether or not the code is correct. If marked.test.js is the wrong home for the real assertions, tell me where you would like them and I will move them.

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.

You can use renderExact option like test/specs/new/whiltespace_lines.md

@UziTech

UziTech commented Sep 1, 2026

Copy link
Copy Markdown
Member

Should this also remove tabs or other whitespace at the beginning of the next line?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants