Skip to main content

ikwukao

Back to Journal

Engineering Journal

Converting Markdown Blocks into Semantic HTML

How block-level Markdown parsing can transform headings, paragraphs, lists, quotes, and code blocks into structured semantic HTML.

4 min read Markdown, HTML, Python, Web Development, Parsing, Static Site Generator

Converting Markdown Blocks into Semantic HTML

Markdown documents are written as a continuous stream of text, but browsers consume structured HTML.

Bridging those two representations requires more than replacing a few characters.

A static site generator needs to understand the boundaries between blocks and determine what each block represents.

That was one of the central problems in my Static Site Generator project.

What Is a Markdown Block?

A block is a logical unit of Markdown content.

For example:

# Introduction

This project explores static site generation.

- Markdown parsing
- HTML rendering
- File generation

contains three major blocks:

Heading
Paragraph
List

Identifying those blocks gives the rest of the pipeline a reliable structure to work with.

Why Block Parsing Comes First

Consider this Markdown:

# Engineering Notes

A static site generator transforms content into HTML.

## Architecture

The system contains several processing stages.

Before inline formatting is considered, the parser needs to understand the document hierarchy.

A simplified representation could be:

Heading level 1
Paragraph
Heading level 2
Paragraph

Once the blocks are classified, each one can be processed independently.

Headings

A Markdown heading such as:

## Architecture

can become:

<h2>Architecture</h2>

The important information is:

  • heading level
  • heading content

The parser therefore needs to identify the number of leading # characters and associate that with the correct HTML element.

Paragraphs

Paragraphs are generally the default block.

For example:

Static websites are easy to deploy.

becomes:

<p>Static websites are easy to deploy.</p>

However, paragraphs cannot simply consume every line.

The parser needs to know where a paragraph ends and another block begins.

Blank lines are therefore important structural boundaries.

Unordered Lists

A list such as:

- Parser
- Renderer
- Generator

represents one list containing three items.

The resulting HTML is:

<ul>
  <li>Parser</li>
  <li>Renderer</li>
  <li>Generator</li>
</ul>

This requires the parser to group consecutive list items into a single parent structure.

It should not generate three unrelated <ul> elements.

Ordered Lists

Ordered lists follow the same general principle:

1. Parse
2. Transform
3. Render

becomes:

<ol>
  <li>Parse</li>
  <li>Transform</li>
  <li>Render</li>
</ol>

The block parser therefore needs to distinguish between ordered and unordered list markers.

Blockquotes

A blockquote:

> Build systems that are easy to understand.

can become:

<blockquote>
  <p>Build systems that are easy to understand.</p>
</blockquote>

The important point is that the quote itself is a structural element.

Its contents may still require inline Markdown processing.

This demonstrates why block parsing and inline parsing should remain separate.

Code Blocks

Code blocks are another special case.

For example:

```python
print("hello")
```

contains content that should generally be preserved rather than interpreted as Markdown.

The generator needs to recognize the code-block boundary and prevent the contents from being processed as ordinary Markdown.

That is an important parsing boundary.

Block Classification

A useful mental model is:

Raw Markdown
Split into blocks
Classify each block
     ├── Heading
     ├── Paragraph
     ├── List
     ├── Quote
     └── Code

Only after this stage should the system move toward HTML generation.

Semantic HTML

The goal is not merely to make HTML that looks correct.

The generated markup should express meaning.

A heading should be a heading.

A list should be a list.

A quotation should be a blockquote.

Code should be represented as code.

This improves accessibility, browser interpretation, maintainability, and search-engine understanding.

Why Semantics Matter for SEO

Search engines do not simply look at visible text.

Document structure provides important context.

A properly structured document gives crawlers a clearer hierarchy:

h1
 ├── paragraph
 ├── h2
 │    ├── paragraph
 │    └── list
 └── h2

This is considerably more useful than generating a page composed almost entirely of generic <div> elements.

Testing Block Parsing

Block parsing benefits from explicit test cases.

For example:

heading
paragraph
unordered list
ordered list
blockquote
code block

Each case should produce the expected structural representation.

Edge cases matter too.

The parser needs predictable behavior around:

  • multiple blank lines
  • empty documents
  • adjacent blocks
  • malformed headings
  • incomplete code fences
  • list boundaries

Keeping the Parser Maintainable

The temptation when implementing a parser is to create one large function containing every rule.

That approach becomes difficult to maintain.

A better design is to separate concerns into smaller operations:

markdown_to_blocks
block_to_block_type
block-specific conversion
HTML node generation

Each stage can then be tested independently.

Final Thoughts

Block-level parsing is the foundation of a Markdown-to-HTML pipeline.

Once Markdown is divided into meaningful structural units, the rest of the generator becomes significantly easier to reason about.

The broader lesson is useful beyond static websites:

Good parsers do not merely transform text. They recover structure.

That structure becomes the foundation for everything that follows.

ikwukao

Backend • Distributed Systems • Platform Engineering

I design and build reliable backend systems, distributed platforms, cloud-native infrastructure, and developer tooling with Go, Python, Linux, Kubernetes, and modern DevOps practices.

Building reliable systems from Nigeria · GMT+1

Explore

Connect

© 2026 Ikwuka Okoye. All rights reserved.

Built with Hugo, Tailwind CSS & Go-inspired simplicity.