chan.dev / posts

Create Markdown "Components" with Remark Containers

🌱 This post is in the growth phase. It may still be useful as it grows up.

Let’s talk about how weird markdown is.

You can write HTML directly into a markdown file. This actually makes Markdown awesome! But things get weird in practice.

Let’s look at why Prettier — a tool designed to format code beuatifully — makes this HTML uglier.

<section>
<div class="flex gap-x-3">
<div class="w-1/2">
A _liiiiittle_ markdown.
</div>
<div class="w-1/2">
Some **other** markdown.
</div>
</div>
</section>

The problem

Let’s start with a simplistic example. And work our way up.

<div>
A _little_ markdown.
</div>
Output:
A _little_ markdown.

Here, the word _little_ is treated as raw text and not markdown. But it can be processed as markdown by adding a newline between the opining div and text content.

<div>
A _little_ markdown.
</div>
Output:

A little markdown.

Brilliant! Markdown in HTML.

But what if you have more than one level of nesting?

<div><!-- first level -->
<div><!-- second level -->
A _little_ markdown.
</div>
</div>
Output:
A _little_ markdown.
</div>

Well that brilliance was short lived. What happened?

Original markdown code block syntax

Markdown — as specified by the author — interprets 4 spaces (or 1 tab) as a code block.

To produce a code block in Markdown, simply indent every line of the block by at least 4 spaces or 1 tab. This is a normal paragraph:

This is a code block.

As developers, we commonly use GitHub Flavored Markdown. This specialization of markdown adds fenced code blocks as an optional syntax.

But it doesn’t replace the “4 space or 1 tab” specification.

Anything nested “4 spaces or 1 tab” deep is intepreted as code. This doesn’t just cause chaos on the content line but any HTML written at that depth. This is why you get that hanging </div> (above).

Prettier makes things uglier, but correct


To process the text content as markdown, there needs to be a newline separating the opening div and the markdown text. Again, very cool that

The Markdown parser needs one preceeding line of whitespace, it will just spit out normal text.

And it doesn’t end there. Most AST-based markdown formatters will correct that to have new lines above and below the markdown. And this introduces another problem

<section>
<div>
<div>
A _liiiiittle_ markdown.
</div>
</div>
</section>
<div class="flex gap-x-3">
<div class="w-1/2">
A _liiiiittle_ markdown.
</div>
<div class="w-1/2">
Some **other** markdown.
</div>
</div>

A liiiiittle markdown.

Some other markdown.

It’s great that I can just drop in a tailwindcss flex recipe. But do you see what I mean by wierd?

Anything that I want parsed as markdown requires surronding newlines. And that’s not all!

<div class="flex gap-x-3">
<div class="w-1/2">
A _liiiiittle_ markdown.
</div>

A liiiiittle markdown.