Skip to content

Step 1 of 5 · Reading · ~3 min

Read

Block Elements

Setext Headings

Markdown's older heading style underlines the text instead of prefixing it:

Release 2.1
===========

Known issues
------------

Same output as # Release 2.1 and ## Known issues. Only two levels exist — = gives H1, - gives H2, and there is no setext H3. A parser has to support both styles anyway, because a decade of real-world documents contains both.

How long does the underline have to be?

Any length. The spec says "a sequence of = characters or a sequence of - characters" and imposes no minimum, so Release 2.1 followed by a single = is a perfectly valid H1. Length is decoration, not syntax.

What the underline may not contain is internal whitespace. = = is not an underline — that document is just a paragraph. Up to three spaces of indentation before the underline is fine; four is too many and turns the line into indented code.

Why is a row of dashes the hardest line in Markdown?

Because --- means three different things depending on what sits above it.

Rendering diagram…

This is the first place in the course where a line cannot be classified on its own. The block scanner needs lookbehind — it has to know what the previous line turned out to be:

python

Note the asymmetry in rows two and four. A lone === with nothing above it is not a break of any kind — it is literal text. A lone --- is a thematic break. The characters are not interchangeable outside the underline role.

What counts as "text above"?

Only lines that would otherwise be a paragraph. A blockquote, a list item, an ATX heading or a code fence above the dashes does not get underlined:

Above the dashesResult
Release 2.1<h2>Release 2.1</h2>
> Release 2.1blockquote, then a separate <hr />
- Release 2.1list item, then a separate <hr />
✗ nothing (blank)<hr />

And the sharpest edge of all: the heading swallows every paragraph line above it, not just one. Foo, then Bar, then --- is a single two-line H2 — not a paragraph followed by a heading. If you want them separate, put a blank line between them.

Your exercise

Convert setext headings, emit <hr /> for a bare row of dashes, and pass everything else through untouched.

The mistake the grader catches is checking the dashes before checking what is above them. If your loop tests "is this line a thematic break?" first, the input para followed by --- emits <p>-less text and then <hr />, while the test demands <h2>para</h2> on one line. The order of your branches is the whole exercise: look ahead from the text line to the underline, and only fall back to the thematic break when no paragraph line precedes it.

The second trap is forgetting to consume both lines. After emitting the heading your index has to advance by two, or the underline reappears in the output as a stray ===.

Up nextBold and ItalicInline Elements

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…