扩展 Notist(Experimental)
文档扩展在指定阶段接收文档,返回修改后的文档或诊断。Rust 实现注册 DocumentExtension;外部程序通过 [[extensions]] 配置为 command,以 stdin / stdout 交换 JSON。check、html、Book 与 SSG 都会运行对应阶段的扩展。
站点层的页面集合、路由与发布扩展见 SSG 站点扩展;完整的类型与来源规则见 文档扩展设计。
文档生命周期
每篇文档经历以下阶段,强调节点为 DocumentExtension 钩子:
文档扩展处理单篇文档的树,不负责站点输入集合、路由与模板;站点构建先完成全部文档的分析,再完成全部文档的求值。站点生命周期见 SSG 站点扩展。
扩展
stage | 输入 | 说明 |
|---|---|---|
|
| 可变。修改 Expr 森林、注解与文档属性,结果进入名称解析、类型检查与结构定稿。 |
|
| 只读。检查语义、收集信息并返回诊断,不能返回 document。 |
|
| 可变。修改最终输出树,结果直接交给输出后端。 |
每个扩展声明一个非空、无重复的 stages 子集;每份文档的每个所选阶段运行一次。
同一阶段先运行 Rust 扩展,再按配置顺序运行 command 扩展。
可变阶段修改文档副本,校验通过后替换当前文档;失败时丢弃本次修改,并停止当前文档剩余的扩展调用。
replace是同一配置表中的另一种 kind:按同签名把from的函数调用映射到to的实现,保留原调用身份。
Rust 扩展实现 DocumentExtension,通过 Context.with_extension 或 Vault.with_extension 注册。
配置
顶层 [[extensions]] 定义包的文档扩展,build / serve 与单文件命令共用这些规则。站点扩展独立位于 site.extensions。
字段 | 类型 | 说明 |
|---|---|---|
|
| 必填。 |
| table | 仅 replace:别名到模块路径的映射,路径相对包清单。 |
| string | 仅 replace:替换的函数身份。 |
| string[] | 仅 command:程序与参数,不经过 shell。 |
| string[] | 仅 command: |
replace 不接受 command / stages;command 不接受 imports / from / to。
[]
= "example"
[[]]
= "command"
= ["python3", "scripts/check_document.py"]
= ["after_check"]
[]
文档与站点扩展配置见 Notist.toml 配置。
stdio 协议
command 每次阶段调用启动一个新进程,工作目录为声明该扩展的配置文件所在目录。stdin 写入一个 JSON 请求后关闭;stdout 只能写一个 JSON 响应,日志写 stderr。
请求字段:
字段 | 内容 |
|---|---|
| 协议版本,当前为 1。 |
|
|
| 当前文档的来源身份。 |
| 文档及模块的源码修订,以及已解析定义的名称拥有快照。 |
| 已加载 Registry 的公开函数签名。 |
|
|
响应必须带 version,可选 document 与 diagnostics:
省略
document或写null保持当前文档不变。after_check只读,不接受document。diagnostics非空时本次 hook 失败,回滚修改。非零退出状态、启动或通信失败、无效 JSON、版本不符和错误 stage 都转成扩展诊断。
document 直接使用核心类型的 serde 表示:span 为 [start,end] UTF-8 字节范围,枚举使用外部标签形式,如 {"Str":"text"};Dict 是有序键值对数组。完整字段与来源规则见 文档扩展设计。
示例
仓库中的 examples/extensions 演示 before_check 的 Expr 修改:metadata.py 读取 Cargo.toml,返回生成的 Expr 与文档属性。仓库根目录执行:
脚本需要 Python 3.11 或更新版本。站点层生成页面的完整用例见 从 Cargo examples 生成站点。