When building a developer-focused blog, having a robust markdown processor isn’t just a nice to have, it’s essential. Markdown makes writing blog posts easy, and processing it effectively means presenting code snippets beautifully, clearly, and functionally.
In this post, I’ll explain step-by-step how I built a flexible and powerful markdown processing pipeline using unified, remark, rehype, and rehype-pretty-code to render visually appealing and interactive code blocks.
Why Markdown
Markdown is a lightweight markup language that’s easy to read and write. Developers commonly use it because:
- It’s simple, intuitive, and fast to write.
- It cleanly separates content from presentation.
- It integrates smoothly with static site generators and frameworks.
The Goal: Great Markdown Experience
I wanted my markdown processor to:
- Efficiently parse markdown to HTML.
- Display syntax-highlighted code snippets.
- Include an interactive copy button for code blocks.
Let’s dive into how I achieved this.
Step-by-Step Implementation
1. Reading the Markdown Files
The first step is straightforward: read the markdown file content from a directory.
const filePath = path.join(articlesDirectory, `${slug}.md`);
const fileContent = fs.readFileSync(filePath, "utf-8");
articlesDirectoryis the folder containing all your markdown files.slugis the unique identifier for each markdown file.
2. Parsing Frontmatter
Frontmatter provides metadata about the markdown post (e.g., title, description, tags).
I use the popular library gray-matter:
const { content, data } = matter(fileContent);
contentcontains the markdown body.datacontains metadata like title, date, etc.
3. Markdown Processing Pipeline
Now, let’s convert markdown content into HTML. We’ll use a powerful combination of tools:
- unified: A toolchain for content transformation.
- remark: Parses markdown into a syntax tree (MDAST).
- rehype: Converts markdown syntax tree (MDAST) into an HTML syntax tree (HAST).
- rehype-pretty-code: Highlights code snippets beautifully.
Here’s the full implementation:
const htmlContent = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypePrettyCode, {
theme: "github-dark",
transformers: [
transformerCopyButton({
visibility: "always",
feedbackDuration: 3_000,
}),
],
})
.use(rehypeStringify)
.process(content);
4. Understanding the Processors
Let’s break down each step clearly:
remarkParse: Converts markdown text into an abstract syntax tree (AST).remarkRehype: Transforms the markdown AST into an HTML-compatible syntax tree.rehypePrettyCode: Provides syntax highlighting for code blocks. I’m using the github-dark theme for clear visibility.transformerCopyButton: Adds a copy button to code blocks, improving user experience.rehypeStringify: Generates an HTML string from the processed syntax tree.
5. The Result
This implementation allows markdown files to render into clean, syntax-highlighted HTML effortlessly:
- ✅ Beautiful code syntax highlighting.
- ✅ Easy-to-use copy-to-clipboard functionality.
- ✅ Highly customizable themes and transformations.
Enhancements and Customizations
This solution is highly flexible. You can easily:
- Switch between multiple themes (dracula, nord, github-dark, etc.).
- Add other remark/rehype plugins to enrich your markdown experience (e.g., adding image optimizations, emoji support, or automatic link transformations).
Conclusion
Building a robust markdown processor significantly improves the readability and overall experience of your blog, especially for technical audiences. Using unified, remark, rehype, and rehype-pretty-code, you gain complete control over how your markdown content is presented, enhancing readability and interaction.