Reading — step 1 of 5
Learn
Backslash Escapes
Escaping HTML handles characters on the way out: a < in the source becomes
< in the output. Backslash escapes are the mirror problem, on the way in.
An author who wants a literal asterisk in the rendered text needs a way to tell
the parser "this one is not markup", and a backslash is the only tool Markdown
gives them.
What can be escaped?
Exactly the 32 ASCII punctuation characters, and nothing else.
\*not emphasized* -> *not emphasized*
\# not a heading -> # not a heading
1\. not a list -> 1. not a list
\a and \3 -> \a and \3
A backslash before a letter, a digit, a space, or a non-ASCII character is just a backslash. Markdown is a plain-text format first, and Windows paths and LaTeX fragments have to survive it intact.
Why can't you just strip the backslashes?
Because whichever order you pick, one pass ruins the other. Strip first and the emphasis pass sees a bare asterisk and treats it as markup. Strip last and the emphasis pass has already consumed the asterisk you were protecting.
The way out is to take the character out of the string entirely: replace it with a placeholder no other rule can match, run every other pass, and put the real character back at the very end.
Line one is the bug in miniature: the author asked for a literal asterisk and got emphasis anyway. Line two is the same document with the escape honoured, and the real emphasis later in the line still works.
Which contexts ignore escapes?
Inside verbatim spans a backslash is just a byte, so the rule is off:
| Context | \[ renders as |
|---|---|
| paragraph text | [ |
| link destination or title | [ |
| fenced code info string | [ |
| code span or code block | \[ |
| autolink or raw HTML | \[ |
That last group is why a production pipeline stashes code spans before it
stashes escapes. Both stashes use the same trick; the order between them is what
decides whether `\[` keeps its backslash.
Two rules that catch people
An escaped backslash does not escape the next character. \\*x* is one literal
backslash followed by real emphasis, because the first backslash consumed the
second. Walk the string left to right taking two characters at a time and you get
that for free; reach for str.replace and you will not.
And a backslash at the very end of a line is not an escape at all — it is a hard line break. That rule belongs to paragraph assembly, not to this pass, so an escape pass that works one line at a time should leave a trailing backslash alone.
Your exercise
Stash escapes, escape HTML, apply emphasis, restore.
The mistake the grader catches is restoring too early. A visible test feeds
\*not emphasized*; if you put the asterisk back before the emphasis pass runs,
the pass sees two asterisks in *not emphasized* and wraps the line in <em>.
Restore last, after every other rule has had its turn.
The second one is the placeholder itself. Your stash runs before escape_html,
so the placeholder has to be something escaping cannot touch — digits between two
NUL bytes work, a string like [[0]] does not, because a later rule can match
brackets. And a restored character goes back through escape_html too: a hidden
test feeds both \< and a bare < on one line and expects < for each.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…