技术预览提交反馈

插件

更新于 2026年11月12日

每篇文章都由 textlane 编译。它是一条 Rust 编写的 Markdown 管线,也能运行 JavaScript 插件。plugins 选项把你的插件加入其中,分两个位置:

  • md 作用于 Markdown 树(mdast),remark 风格的插件放在这里
  • html 作用于 HTML 树(hast),rehype 风格的插件放在这里
livemark.config.ts
import { defineConfig } from "livemark"
import * as html from "textlane/html"
import { remarkHello } from "./plugins/remark-hello.ts"

export default defineConfig({
  plugins: {
    md: [remarkHello],
    html: [html.externalLinks({ target: "_blank" })],
  },
})

插件可以是什么

每个位置都是一个列表,接受与 textlane 的 use 相同的条目:

  • JavaScript 插件:unified 风格的 attacher,即返回 transformer 的函数,transformer 原地修改树或返回一棵新树。大多数 remark 和 rehype 的转换插件都属于这一类。
  • 原生插件:textlane/md 和 textlane/html 导出的插件,例如 html.externalLinks() 或 md.shiftHeading()。它在 Rust 中运行,比 JavaScript 插件更快。
  • 带选项的插件:[plugin, options] 二元组。

JavaScript 插件转换的是已经解析好的树,不能新增语法、解析器或编译器。需要新的块级语法时,请使用指令,并在 md 插件中处理它。

各位置的运行时机

解析 → GFM、数学、指令、MDX → md 插件 → 标题 id、组件、路径改写
→ HTML → 语法高亮、KaTeX → html 插件 → 标题 slug、目录 → MDX
  • md 插件在 Livemark 把指令渲染为组件之前运行,因此能看到所有指令。Livemark 不认识的指令会原样传给它们;如果插件不处理,它会按源文本显示。
  • html 插件在语法高亮之后、标题 slug 和目录之前运行,因此插件新增的标题会获得锚点,并出现在“本页内容”大纲中。

编写插件

下面这个 md 插件把 ::hello 指令替换为一个段落:

plugins/remark-hello.ts
import type { Root } from "mdast"

export function remarkHello() {
  return (tree: Root) => {
    tree.children = tree.children.map(node =>
      node.type === "leafDirective" && node.name === "hello"
        ? { type: "paragraph", children: [{ type: "text", value: "Hello!" }] }
        : node,
    )
  }
}

安装 @types/mdast 或 @types/hast 以获得树的类型;若要为指令节点提供类型,请以 import type {} from "mdast-util-directive" 的形式导入一次 mdast-util-directive。

重新编译

编辑配置文件,或它导入的任何本地文件(如 plugins/remark-hello.ts),都会重启开发服务器并重新编译所有文章。从 npm 安装的插件会随文章一起被缓存,因此升级后请删除 .livemark/.cache/ 以重新编译。

用 ❤ 和 Livemark 构建