Skip to content

Escape Markdown syntax in converted text - #31

Closed
trsdn wants to merge 1 commit into
fix/19-pre-block-content-lossfrom
fix/16-markdown-escaping
Closed

trsdn wants to merge 1 commit into
fix/19-pre-block-content-lossfrom
fix/16-markdown-escaping

Conversation

@trsdn

@trsdn trsdn commented Aug 19, 2026 •

Copy link
Copy Markdown
Owner

Fixes #16.

Stacked on #30 (→ #29 → #28). Review those first.

Problem

Text nodes went straight into the output with no escaping, so prose containing Markdown punctuation was re-read as formatting on the next render.

Change

Three escaping passes, all skipped where content is already literal (<pre>, inline <code>, and URLs):

  1. Inline characters — \ ` * [ ] always; ~~ runs; _ only at word boundaries.
  2. Leading block markers — a paragraph or list item starting with #, >, -, +, an ordered marker, or a ---/=== run gets neutralised.
  3. Inline code delimiters — sized longer than the longest backtick run inside, with padding spaces when the content starts or ends with a backtick.

Two deliberate refinements:

  • _ is not escaped inside words. file_name_here stays readable rather than becoming file\_name\_here; intra-word underscores do not open emphasis.
  • Ordered markers escape the delimiter, not the digit — 1\. text, not \1. text, because a backslash before a digit is not an escape sequence and would render literally.

Verification

Input Before After
<p>… multiply 2 * 3 * 4</p> 2 * 3 * 4 2 \* 3 \* 4
<p># not a heading</p> # not a heading (renders as H1) \# not a heading
<p>1. not ordered</p> 1. not ordered (renders as a list) 1\. not ordered
<p>… file_name_here …</p> file_name_here file_name_here (unchanged)
<code>a b` `a ` b` (broken) ``a b`` `
<p>call <code>a_b_c</code></p> `a_b_c` `a_b_c` (unchanged)

I also ran a full Markdown → HTML → Markdown round trip over a document with headings, emphasis, links, nested lists, tables, a blockquote and a fenced block: no content is corrupted or over-escaped.

dotnet build -c Release -r win-x64 succeeds with 0 warnings.

Note

That round trip surfaced three further pre-existing defects unrelated to escaping, filed separately as #32, #33 and #34.

Text nodes were written straight into the output, so prose containing
Markdown punctuation was re-interpreted as formatting the next time it was
rendered.

Escape the inline characters that can open a construct, escape a leading
character that would turn a paragraph or list item into a heading, list,
blockquote or thematic break, and size inline code delimiters to be longer
than any backtick run they contain.

Underscores are only escaped at word boundaries so identifiers such as
file_name_here stay readable, and an ordered marker is neutralised on its
delimiter ("1\.") because a backslash before a digit is not an escape
sequence and would render literally.

Escaping is skipped inside pre and inline code, where the content is
already literal.

Fixes #16

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b721ad5f-9add-4f55-b9c8-7e6d7b0fb3e7
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.

1 participant