Skip to content

fix: handle markdown backslash escapes in EPUB, HTML, PDF, and DOCX exports - #92

Merged
rogerdigital merged 1 commit into
mainfrom
fix/markdown-backslash-escapes
Sep 21, 2026
Merged

rogerdigital merged 1 commit into
mainfrom
fix/markdown-backslash-escapes

Conversation

@rogerdigital

Copy link
Copy Markdown
Owner

Fixes #91

Problem

Escaped punctuation (\*, \|, \[, …) was not recognized by the basic markdown converter (markdownToBasicHtml) or the DOCX inline parser, so an escaped asterisk was treated as an emphasis delimiter:

  • In EPUB tables (the reported crash): two \* in the same row paired into an <em> that crossed <td> boundaries, producing invalid XHTML — Apple Books fails with Opening and ending tag mismatch: em … and td. EPUB always uses this converter, so every export with escaped asterisks in tables was affected.
  • Outside tables: \* rendered literally with its backslash; two escapes in one paragraph produced wrong italics plus a leaked backslash.
  • Same class of issues: \| split a table cell in two, \[text\](url) still rendered as a link, \_/\\/\# kept their backslashes, and bare multiplication (3 * 4 * 5) was wrongly italicized (no CommonMark whitespace rules).
  • DOCX had the same emphasis-pairing and pipe-splitting behavior (rendering errors only, no invalid XML).

Fix

  • Extract backslash escapes into private-use placeholder sentinels before any syntax rule runs, restore them as literal characters afterwards — in markdownToBasicHtml and DOCX parseInline, sharing one exported MARKDOWN_ESCAPE_RE (CommonMark escapable punctuation). This alone fixes escaped asterisks, pipes, brackets, and all other escapes in both converters.
  • Split table rows on unescaped pipes only (\| stays inside the cell) — basic converter table step and DOCX parseTableRow.
  • Require non-whitespace content edges for bold/italic, per CommonMark delimiter rules, so 3 * 4 * 5 stays literal.

Restored characters are HTML-escaped like surrounding text (\< comes back as &lt;). Code blocks and inline code are extracted before the escape pass, so their content is untouched.

Verification

  • 12 new tests: 9 unit tests in html-document.test.ts (escaped */|/[/\, HTML-escape on restore, inline code untouched, multiplication boundary), 1 end-to-end EPUB test asserting balanced <em> tags in the chapter XHTML, 2 DOCX tests. All failed before the fix, pass after.
  • Full suite: 425 tests passing; tsc type check, esbuild production build, and eslint clean.

…xports

Escaped punctuation (\*, \|, \[, …) was not recognized by the basic
markdown converter or the DOCX inline parser, so an escaped asterisk
paired as an emphasis delimiter: inside EPUB tables it produced an
<em> that crossed <td> boundaries, yielding invalid XHTML that Apple
Books refuses to open. Outside tables, escapes rendered with a
strailing backslash.

- Extract backslash escapes into placeholders before any syntax rule
  runs and restore them as literal characters afterwards (basic HTML
  converter and DOCX parseInline, sharing MARKDOWN_ESCAPE_RE)
- Split table rows on unescaped pipes only so \| keeps a literal pipe
  inside the cell (basic converter and DOCX parseTableRow)
- Require non-whitespace content edges for bold/italic per CommonMark
  delimiter rules, so bare multiplication asterisks (3 * 4 * 5) stay
  literal

Fixes #91
@rogerdigital
rogerdigital merged commit 5a6dbb8 into main Sep 21, 2026
1 check passed
@rogerdigital
rogerdigital deleted the fix/markdown-backslash-escapes branch September 21, 2026 16:13
@rogerdigital rogerdigital mentioned this pull request Sep 22, 2026
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.

Epub error due to escaped asterisk

1 participant