Notist
On this page
  1. 扩展 Notist(Experimental)
  2. 文档生命周期
  3. 扩展
  4. 配置
  5. stdio 协议
  6. 示例

扩展 Notist(Experimental)

文档扩展在指定阶段接收文档,返回修改后的文档或诊断。Rust 实现注册 DocumentExtension;外部程序通过 [[extensions]] 配置为 command,以 stdin / stdout 交换 JSON。check、html、Book 与 SSG 都会运行对应阶段的扩展。

站点层的页面集合、路由与发布扩展见 SSG 站点扩展;完整的类型与来源规则见 文档扩展设计。

文档生命周期

每篇文档经历以下阶段,强调节点为 DocumentExtension 钩子:

文档扩展处理单篇文档的树,不负责站点输入集合、路由与模板;站点构建先完成全部文档的分析,再完成全部文档的求值。站点生命周期见 SSG 站点扩展。

扩展

stage

输入

说明

before_check

LoweredDocument

可变。修改 Expr 森林、注解与文档属性,结果进入名称解析、类型检查与结构定稿。

after_check

Item

只读。检查语义、收集信息并返回诊断,不能返回 document。

after_evaluate

Item

可变。修改最终输出树,结果直接交给输出后端。

  • 每个扩展声明一个非空、无重复的 stages 子集;每份文档的每个所选阶段运行一次。

  • 同一阶段先运行 Rust 扩展,再按配置顺序运行 command 扩展。

  • 可变阶段修改文档副本,校验通过后替换当前文档;失败时丢弃本次修改,并停止当前文档剩余的扩展调用。

  • replace 是同一配置表中的另一种 kind:按同签名把 from 的函数调用映射到 to 的实现,保留原调用身份。

Rust 扩展实现 DocumentExtension,通过 Context.with_extension 或 Vault.with_extension 注册。

配置

顶层 [[extensions]] 定义包的文档扩展,build / serve 与单文件命令共用这些规则。站点扩展独立位于 site.extensions。

字段

类型

说明

kind

"replace" / "command"

必填。

imports

table

仅 replace:别名到模块路径的映射,路径相对包清单。

from / to

string

仅 replace:替换的函数身份。

command

string[]

仅 command:程序与参数,不经过 shell。

stages

string[]

仅 command:before_check / after_check / after_evaluate 的非空唯一子集。

replace 不接受 command / stages;command 不接受 imports / from / to。

[package]
name = "example"

[[extensions]]
kind = "command"
command = ["python3", "scripts/check_document.py"]
stages = ["after_check"]

[site]

文档与站点扩展配置见 Notist.toml 配置。

stdio 协议

command 每次阶段调用启动一个新进程,工作目录为声明该扩展的配置文件所在目录。stdin 写入一个 JSON 请求后关闭;stdout 只能写一个 JSON 响应,日志写 stderr。

请求字段:

字段

内容

version

协议版本,当前为 1。

stage

before_check、after_check 或 after_evaluate。

path

当前文档的来源身份。

sources

文档及模块的源码修订,以及已解析定义的名称拥有快照。

functions

已加载 Registry 的公开函数签名。

document

before_check 为 LoweredDocument,其他阶段为 Item。

响应必须带 version,可选 document 与 diagnostics:

  • 省略 document 或写 null 保持当前文档不变。

  • after_check 只读,不接受 document。

  • diagnostics 非空时本次 hook 失败,回滚修改。

  • 非零退出状态、启动或通信失败、无效 JSON、版本不符和错误 stage 都转成扩展诊断。

document 直接使用核心类型的 serde 表示:span 为 [start,end] UTF-8 字节范围,枚举使用外部标签形式,如 {"Str":"text"};Dict 是有序键值对数组。完整字段与来源规则见 文档扩展设计。

{
  "version": 1,
  "diagnostics": [
    {"phase": "Semantic", "span": [0, 0], "message": "missing package metadata"}
  ]
}

示例

仓库中的 examples/extensions 演示 before_check 的 Expr 修改:metadata.py 读取 Cargo.toml,返回生成的 Expr 与文档属性。仓库根目录执行:

cargo run -p notist-cli -- html examples/extensions/README.not --out-dir target/extension-example

脚本需要 Python 3.11 或更新版本。站点层生成页面的完整用例见 从 Cargo examples 生成站点。