做语法高亮这件事,很多编辑器生态其实一直在重复一件麻烦事:parser 是一套逻辑,highlighter 又是另一套逻辑

前者通常更接近语言本身,后者却常常是手写 regex、补 edge case、修一堆多年遗留的高亮 bug。结果就是,真正复杂一点的语法一出现,颜色先乱。

今天想记录的 johnsoncodehk/monogram,就是在反过来做这件事。它的目标不是再写一份更大的 TextMate 规则,而是把 grammar 本身 作为唯一事实来源:先把 grammar 跑成真正可执行的 parser,再从同一份定义生成 TextMate、tree-sitter、Monarch 等高亮产物。

按 GitHub API 和仓库页面在 2026-06-21 的公开信息,这个仓库当前大约有 119 stars3 forks,主要语言是 TypeScript,创建于 2026-05-27,最近一次公开更新时间是 2026-06-21。截至今天,GitHub metadata 里还没有列出 SPDX license,releases 页面也还没有公开发布 release

项目概览

属性详情
仓库johnsoncodehk/monogram
定位从一份 grammar 派生 parser 和多种语法高亮产物
Stars119
Forks3
主要语言TypeScript
创建时间2026-05-27
最近更新时间2026-06-21
License 状态GitHub metadata 未列出 SPDX license
Latest release截至 2026-06-21 暂无公开 release

它最值得看的点,是把 “先写高亮” 反过来变成 “先证明 grammar”

Monogram README 里最核心的一句话,其实就是:

Write a language’s grammar once, as an executable definition.

它的思路不是先写一堆高亮规则,再尽量靠近 parser;而是先把 grammar 做成一个真的能执行的 parser,然后再从这份 grammar 里派生出高亮器。

这带来一个很直接的变化:

  • 不再把语法高亮建立在手工 regex 猜测上;
  • 先让 parser 决定语法结构;
  • 再让高亮结果跟着 parser 已经证明过的结构走。

对于 TypeScript 这种存在大量歧义边界的语言,这个方向很有意义。像 README 里举的例子,typeof x < y 这种写法,如果只是 regex 高亮,就得猜 < 到底是泛型还是小于号;而 parser 根本不用猜,它按 grammar 走就行。

一份 grammar,往外派生的不只是 TextMate

Monogram 的另一个亮点,是它并不把结果收束在某一种编辑器格式里。

README 明确写到,同一份 grammar 可以产出:

  • lexer;
  • CST parser;
  • TextMate grammar;
  • VS Code language configuration;
  • CST node types;
  • tree-sitter grammar 和 highlights query;
  • Monarch tokenizer。

这意味着它想解决的不是“某个编辑器高亮偶尔不准”,而是更大的问题:语法相关的多个下游产物,能不能共用同一份结构化定义

这件事如果做稳,对工具链的价值会比“又一个高亮仓库”大得多。因为 parser、编辑器高亮、语言配置、tree-sitter 生态,本来就经常各自演化,最后同步成本越来越高。

README 里给出的验证口径,比常见 side project 更硬

很多语法相关项目都会说自己“更准确”或者“更聪明”,但 Monogram README 在这方面给出的不是形容词,而是比较具体的验证方式。

它提到项目当前主要覆盖四种语言:

  • TypeScript;
  • JavaScript;
  • HTML;
  • YAML。

其中 TypeScript 的状态被写成:

  • 100% valid-code coverage
  • 97.8% bidirectional vs tsc

这里的重点不是数字本身,而是它强调了一个思路:先把 grammar 当 parser 去对照官方语法或参考实现,再去谈高亮是否值得信任

如果一个项目真想把 highlighter 建在 parser 之上,这个验证顺序是对的。否则就还是只是在做另一版“看起来更聪明的高亮规则”。

它不只是研究味很重,已经开始接真实生态

README 里一个很有说服力的信号,是它已经明确写出:

  • vuejs/language-tools 在使用 Monogram 派生的 Vue TextMate grammar 和 VS Code language configuration。

这很重要。因为很多 parser 或 grammar 项目概念都很好,但只停在 demo 或 benchmark。

Monogram 至少已经开始往真实编辑器生态里送产物,而不是只停留在“理论上可以生成”。

对一个 2026-05-27 才创建、目前 stars 还不高的仓库来说,这说明它不是纯粹停在论文式想法,而是在试图成为真正可接入的 developer tool。

Node 24+ 这个要求,也透露出它的工程取向

Monogram 的 quick start 很短:

npm install
node src/cli.ts typescript.ts

README 还特别标明它要求 Node 24+,因为它直接运行 .ts,不额外依赖 tsx 或单独 build step。

这其实也能看出作者的偏好:尽量让 grammar 本身就是可以直接执行、直接生成产物的东西,而不是再围一层很重的构建链。

对小而专的语言工具来说,这种选择挺合理。因为这类项目最怕的是核心思想不复杂,但外围脚手架反而把使用门槛抬高。

为什么这个项目值得开发者关注

我觉得 Monogram 真正有意思的地方,不只是“能生成高亮器”,而是它提出了一个很清楚的工程方向:

如果 parser 才是最接近语言事实的一层,那高亮、language config、tree-sitter query 这些衍生物,为什么不能从 parser grammar 往下生成?

这条路的价值主要在三点:

  • 可以把 grammar 和 highlighter 的长期分叉收回来;
  • 能把许多歧义语法问题交给 parser 结构,而不是 regex 猜测;
  • 更适合让多个编辑器/工具链产物共享同一份语言定义。

当然,Monogram 现在仍然是一个活跃中的研究型项目,README 里也明确这样定位它。再加上目前仓库尚未公开 release、license metadata 也还没补齐,说明它离“成熟、稳定、广泛集成”的状态还有路要走。

但正因为它还早,才更值得现在关注。很多语言工具真正稀缺的,不是把已有做法再包装一层,而是像这样敢于重新定义 source of truth 放在哪里

小结

johnsoncodehk/monogram 值得看的不是“又一个语法工具”,而是它把 grammar -> parser -> highlighter 这条链重新理顺了。

先证明 grammar,再派生高亮;先让语言结构说话,再让颜色跟上。这种做法未必最省事,但如果目标是长期维护多种语法产物,它显然比继续手写一堆彼此漂移的规则更有前途。