Show HN:通过编写 Markdown 转 HTML 编译器来学习 Rust
Show HN: Learning Rust by writing a Markdown to HTML compiler

原始链接: https://andreadimatteo.com/md-to-html-compiler.html

软件工程师 Andrea 最近用 Rust 编写了一个自定义的 Markdown 转 HTML 编译器,以此作为学习该语言的一种方式。由于厌倦了 Hugo 等框架的复杂性,Andrea 花了大约 12 到 13 个小时,从零开始打造了一个极简的个人博客工具。 该编译器通过扫描本地文件中的 Markdown 语法,将其转换为中间表示(AST),并通过模板输出带有样式的 HTML。该工具支持标准的 CommonMark 功能,包括标题、列表、代码块以及各种行内样式。它还能解析 YAML 元数据(如标题、日期和草稿状态),以便管理站点结构。 除了基本的编译功能外,生成的网站还具有简单的搜索栏、标签过滤以及实验性的类似 Vim 的导航功能。虽然 Andrea 设计该项目主要是为了个人使用,但这一努力也成为了对编译器设计概念的一次实践探索。源代码现已公开,供有兴趣了解其实现的人参考。

一位 Rust 新手开发者创建了一个轻量级的单文件 Markdown 转 HTML 编译器,用于驱动其个人微型博客。该项目是开发者在完成《Rust 程序设计语言》一书半数内容后的实战练习。 除了掌握这门语言的目标外,作者还强调了一个现代动机:针对人工智能优化网站。通过提供简洁、格式良好的 Markdown 接口,开发者可以确保其内容更易于被日益增多的浏览网页的各类大语言模型(LLM)访问和解析。作者已在 Hacker News 上分享了该项目,目前正在寻求反馈和贡献。
相关文章

原文

Hi, this is Andrea.

I'm new to Rust and thought that a very pratical way to get in touch with it was writing something. I've thought of writing my own .md to .html compiler for for a while. So here we are, both my micro-blog and my project have come to life. Before even thinking of writing it, I was using Hugo. It was really nice, but you know, sometimes it's just too much, I just wanted a very simple thing, not taking a lifetime choosing a theme and other stuff, or maybe as a SWE I thought I could just build it myself, and after 12-13 hours of my not really spare time I came eventually with something.

It's very basic, written with no GenAI tools, and as much docs as possible. I've implemented very basic .md syntax for now, eventually will expand later. Some time ago I read the dragon book, so writing a compiler was not a completely new thing, but it was fun to see that some of my own choices were pretty similar to actual .md to .html compilers, even Hugo itself.

The compilation follows the following steps:

  • scan `post/` dir
  • for each file scan for blocks elements
  • for each block scan for inline elements
  • we then end up with an intermediate representation (building ASTs is always pretty cool):
[
    Heading {
        level: H1,
        content: [
            Text(
                "this\n",
            ),
        ],
    },
    Heading {
        level: H2,
        content: [
            Text(
                "is\n",
            ),
        ],
    },
    Paragraph(
        [
            Text(
                "a very ",
            ),
            Italic(
                "simple",
            ),
            Text(
                " ",
            ),
            Bold(
                "post",
            ),
            Text(
                "\n",
            ),
        ],
    ),
]
  • output as `.html` with templates (very basic)

Output to file was particularly simple since redefining Display on Block => Inline made it no different than a simple display.

Here's a demo of the generated index and a couple posts.

demo

Let's now delve into some more technicalities: Every post starts with a YAML front matter block delimited by ---:

---
title: Building a markdown compiler
date: 2026-07-27
description: A short line shown in the index
tags: [rust, web]
draft: false
---

[markdown body]

title and date are required, the rest are optional. date is YYYY-MM-DD and drives the ordering of the index. Setting draft: true skips the post entirely. This is the list of the current CommonMark coverage:

  • headings: `#` through `######`
  • paragraphs: blocks of text separated by an empty line
  • codeblocks: ``` or ~~~
  • ordered lists: `- [text]`
  • unordered list: `n) [text]` or `n. [text]`
  • blockquotes: `> quote`
  • inline code: `code`
  • inline strikethrough: ~text~
  • inline bold: **text**
  • inline italic: *text*
  • links: [text](url)
  • images: ![alt](url), images url refer to `static/` dir.

The index.html is the whole post list, no pagination and no client side router, filtering can be done through the searhc bar on top of the page, (shortcut to searchbar is / and search text can be deleted with esc), or the tags on the single posts or still on top of page. You can navigate through posts and within posts with vim-like-moves (this is vibe-coded and theme dependent, hence I won't keep track of it try it, it's pretty cool, you can also yank text :) ). Don't think this tool will ever be useful for anyone besides me, but it was fun to make and surely will expand, the code can be found at this repo.

联系我们 contact @ memedata.com