Step 1 of 5 · Reading · ~3 min
Read
Inline Elements
Bold and Italic
*italic* or _italic_ -> <em>italic</em>
**bold** or __bold__ -> <strong>bold</strong>
**bold *and italic*** -> <strong>bold <em>and italic</em></strong>
Emphasis is the part of Markdown that has the most edge cases per character of syntax, and the CommonMark spec spends more rules on it than on every block type combined. The reason is simple: an asterisk is also multiplication, a footnote marker, and a decorative bullet. The parser has to decide, per asterisk, whether it is markup or text.
When is an asterisk markup?
The spec's answer is flanking. An asterisk can open emphasis only if it is part of a left-flanking delimiter run: nothing whitespace-y directly after it, and if what follows is punctuation then something whitespace-y or punctuation must precede it. Closing is the mirror image.
The first branch alone buys you most of the correctness a small parser needs:
Row two is the win: the lookarounds refuse a delimiter that touches whitespace,
so ordinary arithmetic survives. Row three shows that mid-word emphasis with *
is intentional and must keep working. Row four is where even the guarded pattern
diverges from the spec — real CommonMark leaves a*"quoted"* alone, because an
opener preceded by a letter and followed by punctuation is not left-flanking.
A regex approximates the rule; only a delimiter-run scanner implements it.
Why do underscores behave differently?
Because snake_case_names are everywhere. _ may only open or close at a word
boundary, so un_bel_ievable stays literal while un*bel*ievable emphasises.
The asymmetry is deliberate, not an accident of history.
Which delimiter do you match first?
Longest run first, always. This is the same maximal-munch rule a lexer uses.
| Order | **bold** becomes |
|---|---|
✓ try ** before * | <strong>bold</strong> |
✗ try * before ** | *<em>bold</em>* |
One spec detail worth knowing: the reference renderer emits ***x*** as
<em><strong>x</strong></em> — em on the outside, because the spec prefers the
interpretation with the least nesting depth on the strong element. This
course's tests use the opposite order, <strong><em>x</em></strong>, which is
what most hand-written parsers produce. Match the tests here; remember the spec
answer when you read someone else's output and it looks flipped.
Your exercise
Apply inline code, then ***x***, then **x**, then *x*, to each line.
The mistake the grader catches is an unguarded * pattern. One visible test
is the line * spaced *, which must come back byte-for-byte unchanged. With
\*(.+?)\* you emit <em> spaced </em> and fail. Add the (?=\S) and
(?<=\S) guards.
The second one is subtler: **bold *and italic*** needs its own combined
pattern. Running plain **...** over it consumes only two of the three closing
asterisks and leaves a stray * in your output. Handle the strong-wrapping-em
shape before the general ** rule, and stash each replacement you make so a
later pass cannot re-enter the HTML you already produced.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…