Skip to content

fix: parse EOF backtick fences after paragraphs - #4039

Open
deepakganesh78 wants to merge 2 commits into
markedjs:masterfrom
deepakganesh78:fix/issue4038-backtick-fence-eof
Open

fix: parse EOF backtick fences after paragraphs#4039
deepakganesh78 wants to merge 2 commits into
markedjs:masterfrom
deepakganesh78:fix/issue4038-backtick-fence-eof

Conversation

@deepakganesh78

@deepakganesh78 deepakganesh78 commented Aug 2, 2026

Copy link
Copy Markdown

Fixes #4038

Reproduction

On current master, EOF fenced code blocks are swallowed into the preceding paragraph for both fence characters:

import { marked } from './lib/marked.esm.js';

marked.parse('foo\n```', { gfm: false }); // before: "<p>foo\n```</p>\n"
marked.parse('foo\n~~~', { gfm: false }); // before: "<p>foo\n~~~</p>\n"

CommonMark treats backtick and tilde fences the same for paragraph interruption, and an unclosed fence is closed by EOF. With this change, foo\n````, foo\n```js, foo\n~~~`, and `foo\n~~~js` all end the paragraph and produce a fenced code block.

Root cause

The block fence tokenizer already accepts EOF after an opening fence, but the paragraph/table interruption regexes only recognized a fence when the opening fence line ended with \n. At EOF, paragraph parsing consumed the fence as literal text before the fence tokenizer could run. The first version of this PR only allowed EOF in the backtick branch; the tilde branch had the same bug.

Fix

Allow the paragraph/table interruption checks to match either a newline or EOF after the opening fence line for both backtick and tilde fences. The backtick-specific lookahead is kept so inline code spans are not treated as fences; tildes share the same trailing line/EOF handling.

Compatibility notes

This changes parsing only for fenced code blocks at EOF when they interrupt a paragraph or GFM table row. Newline-terminated fences and inline code span cases such as a `b` c and foo\n`bar` were verified unchanged. The existing long-tilde ReDoS fixture was updated to the now-correct EOF-fence output while still covering the same large input.

Validation

Empirical outputs after rebuild (npm run build:esbuild):

  • foo\n```` ->

    foo

    \n
    \n
    \n`
  • foo\n```js -> <p>foo</p>\n<pre><code class="language-js">\n</code></pre>\n
  • foo\n~~~ -> <p>foo</p>\n<pre><code>\n</code></pre>\n
  • foo\n~~~js -> <p>foo</p>\n<pre><code class="language-js">\n</code></pre>\n
  • newline-terminated fence inputs still produce the same fenced code blocks.
  • a \b` c->

    a b c

    \n`
  • foo\n\bar`->

    foo\nbar

    \n`

Regression verification:

  • With unmodified src/rules.ts, node --test --test-reporter=spec test/run-spec-tests.js reported tests 1771, pass 1765, fail 6; both backtick_fence_eof_interrupts_paragraph and tilde_fence_eof_interrupts_paragraph failed (plus the updated long-tilde ReDoS fixture).
  • With the fix, npm run test:specs reported tests 1771, pass 1771, fail 0.
  • npm run test:types: passed (exit 0; attw reports the existing ignored CJS-to-ESM warning only).
  • npm run test:lint: passed (exit 0).
  • npm run test:umd: passed (exit 0).
  • npm run test:cjs: passed (exit 0).
  • Pre-existing Windows path-with-spaces bin unit failures remain separate: npm run test:unit reported tests 190, pass 185, fail 5 (exec, stdin, string, input, input file positional, input last file positional fail with Cannot find module 'E:\Work\Code').

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

Backtick code fence at EOF does not interrupt a paragraph

1 participant