Extension(Experimental)
站点扩展在 beforecompile 处理源码集合,在 beforetemplate 处理模板数据。同一次构建的两个事件由同一扩展实例处理,可以在内部保留状态。外部命令使用 [site.extensions.<name>],内置扩展使用 [site.extensions.builtins.<name>]。
构建生命周期
强调节点为扩展钩子。单文档编译的内部阶段见 扩展 Notist。
compile 校验输入、计算页面 URL 与输出路径、分析和求值文档、提取页面元信息。
render 由 SSG 解析链接与资源路径,调用 notist-html 渲染正文并生成组件资源。
template 加载模板,将正文与模板数据组合为完整页面。静态资源与 Sass 属于站点资源处理,不单列节点。
site.data 不进入 .not 求值环境,不经过 before_compile。
serve 每次重建创建新实例或新进程;失败时保留上一次成功预览。
阶段输入
事件 | 输入 | 可修改 |
|---|---|---|
| 发现后的源码集合 | documents |
| 正文已渲染的 Pages、加载后的模板 data | data |
documents 的键是内容目录下的规范相对路径,使用
/;值是完整源码,扩展名决定前端。可以添加、删除或替换文档,不写回源文件。data 的键是数据文件去掉扩展名后的相对路径,例如 data/example.toml 对应 example,嵌套键使用 folder/example。
每个阶段先按 Builder 注册顺序运行原生扩展,再按 extension_order 运行配置扩展;未指定时按完整扩展名排序。
每个钩子修改副本,成功且校验通过后才交给下一个扩展;失败停止构建,不提交本次修改。
同一实例贯穿两个事件,内部状态仅属于本次构建。错误会终止该实例,不会用失败状态重试。
Page 是页面展示模型,不包含文档树:
Book 在 beforecompile 读取实际输入中的 SUMMARY、解析结构并按需筛选文档,结构保存在实例内;beforetemplate 将结构与最终 Pages 匹配,一次性生成 site.data.book。SUMMARY 不作为普通页面发布,模板 data 不充当内部状态通道。
配置
[]
= ["python3", "scripts/catalog.py", "../Cargo.toml"]
= ["scripts", "../Cargo.toml", "../examples"]
字段 | 类型 | 说明 |
|---|---|---|
| string[] | 程序与参数,第一项非空;不经过 shell。 |
| path[] | 相对包根的额外依赖;目录递归监听。 |
command、watch 与进程 CWD 均相对 Notist.toml 所在的包根。每个命令接收两个事件,不需要配置 stages;不处理的事件也必须响应。未知配置字段、空 command 或无效 extension_order 会导致失败。
watch 在扩展执行前登记,失败构建也会保留这些依赖。Rust 扩展通过 SiteContext.resources 读取的依赖由宿主记录。路径基准见 Notist.toml 配置。
内置 Book:
[]
= "SUMMARY.not"
表存在即启用,builtins 是保留命名空间。Book 扩展不选择或修改主题,详见 Notist Book。顶层 extensions 配置文档扩展,site.extensions 配置站点扩展。
JSON I/O 协议
协议版本为 2。一个构建启动一个进程,通过 stdin / stdout 交换 JSON Lines:每行一个完整 JSON 对象,每个事件恰好一行响应,写入后立即 flush。stdout 只用于协议,日志写 stderr。宿主发送事件并等待响应后才继续,不广播并发修改。
两个事件复用同一进程,可以保留 SUMMARY 解析结果等内部状态。最后一个事件处理完成后,宿主关闭 stdin;扩展应在 EOF 时退出,宿主检查退出码与多余输出后才允许构建成功。任何阶段失败都会终止并回收进程,下一次构建启动新进程。不能等待 stdin EOF 才开始处理请求。
请求
每个请求都有 version、event、root、config。root 是包根绝对路径,也是进程 CWD;config 是完整 SiteConfig,字段见 Notist.toml 配置。
before_compile 只携带源码集合,不含 data 或 pages:
before_template 携带最终 pages 和前序扩展修改后的 data,不含源码集合:
上例省略 config 的其余字段,pages 的元素使用上述 Page 结构。Rust 命令可用 notist_ssg::command 的 Request、Event、Response 类型读取和生成协议。
响应
响应必须携带相同的 version 和 event。beforecompile 只能返回 documents;beforetemplate 只能返回 data,不能返回 pages 或 documents:
省略可修改字段或写 null 表示不修改;无操作响应仍需 version 与 event。
返回映射表示完整替换,不是增量补丁;空映射表示清空。要保留已有键,先修改请求中的映射,再整体返回。
响应拒绝未知字段、阶段不匹配、版本不匹配。beforecompile 不允许返回 data,beforetemplate 不允许返回 pages。
可选 errors 是字符串数组,非空立即终止构建,即使同时返回修改也不会应用:
最小 Python 扩展
= None
=
=
=
=
=
=
=
=
=
=
输入校验与失败
文档路径必须是规范相对路径:不能为空、不能为绝对路径、不能含反斜杠、
.或..段、空段或隐藏段;不能占用_notist;扩展名必须由已注册前端支持。beforecompile 后检查文档路径及输出冲突;beforetemplate 后检查 data 键,键必须是规范相对路径。
生成文档的源身份是 content 下的相对路径,imports、链接、嵌入与诊断以此为基准。根注解照常生效,新目录进入 site.directories。
配置了扩展时 content 目录可以不存在,内容可以全部由扩展提供。每次构建重新发现输入,删除的生成页面不会残留。
任一阶段失败停止构建,保留已有输出或上一次成功预览;脚本自行写文件、上传等外部副作用不会回滚。
无效 JSON、缺少换行、版本不符、未知字段、非法路径、非零退出码和多余 stdout 都会使构建失败。错误信息包含扩展名与阶段。
路径与输出规则见 Notist SSG。
Rust 接入
两个事件默认不修改输入。finish 是成功路径上的资源收尾,不是数据修改阶段;失败清理由实例的 Drop 完成。SiteContext 提供只读 config 与 resources。
use ;
use ;
let builder = default.with_extension;
Builder 注册的原生扩展需实现 Clone;每次构建从注册的原型克隆一个新实例,两个事件调用同一实例。Clone 必须隔离构建内可变状态,不应通过共享锁把中间结果带到另一构建。
build / serve 运行站点扩展,单文件 check / cst / core / json / query / html 不运行。完整示例见 examples/ssg-extensions 与 从 Cargo examples 生成站点。接口与协议处于实验阶段。