🧬 A CSS Engine in OCaml - Cascade

编程工具 OCaml CSS 2026-04-03

核心发现

作者将个人网站重写为 OCaml 的过程中遇到了样式问题:使用 Tailwind CSS,希望整个流水线(Markdown 到样式化 HTML 到 CSS)是一个单一的 dune 构建,没有 Node.js 依赖。这意味着需要将 Tailwind 的 CSS 生成移植到 OCaml。为了确保移植正确,需要将 CSS 输出与 JavaScript 原始版本进行比较。现有 CSS diff 工具要么已废弃,要么局限于 CSS 2/3,无法处理 @layer、容器查询、嵌套或 Tailwind v4 生成的现代色彩空间。

技术亮点

代码示例

类型化 API 使拼写错误成为编译时错误,颜色传给 padding 是类型错误:

open Cascade.Css

let btn = Selector.class_ "btn"

let rules =
  [ rule ~selector:btn
    [ display Inline_block
    ; background_color (hex "#3b82f6")
    ; color (hex "#ffffff")
    ; padding (Rem 0.5) ]
  ; rule ~selector:btn
    [ background_color (hex "#2563eb") ] ]

优化器效果

优化模式会合并重复规则,保留后定义的属性值(遵循 cascade 顺序):

/* 优化前:两个 .btn 规则 */
.btn { display: inline-block; background-color: #3b82f6; color: white; padding: 0.5rem; }
.btn { background-color: #2563eb; }

/* 优化后:合并为一个规则 */
.btn { display: inline-block; background-color: #2563eb; color: #fff; padding: 0.5rem; }

安装方式

# 通过 Homebrew
brew install samoht/tap/cascade

# 或通过 opam
opam pin add cascade https://github.com/samoht/cascade.git

启示

这个项目展示了语言多样性在 Web 工具链中的可能性。通过类型系统保证 CSS 构建的正确性,用结构化对比替代字符串 diff,是一次有趣的技术探索。对于需要处理大量 CSS 的项目,这种方法值得借鉴。

← 返回洞察列表