默认文档:中文。English version: README.en.md
BeautifulBlog 是一个静态网站生成器。它与 Hexo 等工具一样,最终产物是可以部署到普通静态文件服务器上的网站文件;关键区别在于,主题不是由生成器套用的页面模板,而是一个由主题作者控制的独立网站程序。
生成器负责提供文章转换结果、索引和生命周期通知。主题自己决定如何读取这些数据、组织页面、实现导航、选择展示方式,以及是否加入浏览器端交互。生成器不规定主题必须有哪种首页、文章页或 URL 结构,只要求主题与约定的数据和钩子接口兼容。
| 模板式生成器 | BeautifulBlog |
|---|---|
| 生成器读取主题模板,再把文章填入模板并拼成页面 | 主题是独立的网站代码,拥有自己的页面结构和运行逻辑 |
| 主题主要描述布局、样式和模板语法 | 主题可以自行实现首页、路由、搜索、目录、推荐和交互 |
| 生成器控制文章如何进入页面 | 生成器提供文章数据及变更通知,主题决定如何使用 |
| 主题通常在生成器定义的模板生命周期内工作 | 主题可包含浏览器端程序;Node 端钩子用于和生成器协作 |
发布结果仍是静态文件。主题可以用 JavaScript 在浏览器中加载文章或提供交互,但不要求线上运行 BeautifulBlog 的 Node 服务。
articles/ 文章源文件
│
├── 格式转换器读取文章和 front matter
▼
content/ 标准化文章数据、HTML 内容、附件和 files.json 索引
│
├── 生成器通知当前主题的 hooks
▼
sites/<主题名>/ 主题源码:浏览器网站程序 + Node 生命周期钩子
│
└── 复制到 nowSite/ 当前运行主题的副本
│
└── 生成器内置静态服务器或外部静态托管
生成器的文章转换器负责把 Markdown、TXT、PDF 等输入转为当前约定的中间结果。主题可以使用这些 HTML 和元数据,也可以按自己的组织方式组合它们;生成器不会把文章自动塞进主题的首页或模板。
主题目录包含两类代码:
- 浏览器端网站:通常由
index.html和脚本、样式、静态资源组成。它是网站本身,可以独立决定如何呈现content/中的数据。 - Node 端 hooks:
hooks.js由生成器进程加载,用来接收主题切换、完整生成和文章变更等事件。它不是浏览器脚本,也不会被当作页面模板执行。
当前站点主要通过三类约定与生成器协作:
- 内容文件:每篇文章生成同路径的 JSON 元数据和 HTML 内容,并可能带有附件目录。元数据包含标题、日期、front matter 自定义字段、内容长度、修改时间和源文章标识。
- 文章索引:
content/files.json的fileList保存文章元数据 URL、标题、源文章标识和附件目录 URL。主题可用它构建列表,也可选择自己的索引策略。 - 生命周期 hooks:主题导出符合
ISiteHooks的对象。当前实现会在切换主题时调用beforeUnload和loaded;blog generate y强制重新生成完成后调用generated;监视到文章新增、修改或删除并重新生成后调用articleChanged(context, type, dest)。其他重新生成流程目前不一定触发generated。
主题还可以通过 hooks 导出的 metainfo.articleExtensions 声明自己支持的原始文章扩展名,并实现可选的 interceptArticle(context)。生成器会把 sourcePath、destinationPath、extension、当前配置和全局配置传给它;回调返回 TransformResult 时,主题完全接管该文章,生成器只负责把结果写成标准的 HTML、JSON 和附件目录;回调返回 undefined 时,才回退到默认 transformer。这样主题可以处理生成器原本不认识的格式,也可以决定自己的解析、元数据和输出结构。
init、install、uninstall 虽出现在接口定义中,但当前生成器流程没有完整调用它们;主题不应依赖这些事件。数据文件也尚无独立的 schema 版本号,新增或调整字段时应保留兼容读取,并在后续版本中完善版本化约定。
base_url 是部署路径前缀。主题请求文章、脚本、样式和附件时必须保留该前缀,不能依赖网站部署在域名根目录,也不能写入开发机绝对路径。
独立博客目录通常包含:
articles/ 文章源文件
content/ 生成的文章内容、元数据、附件和索引
config/ base_url、当前主题等配置
sites/ 可选主题源码
nowSite/ 当前主题运行副本,由工具同步覆盖
assets/ 博客级共享资源
默认主题的目录职责、构建方式、数据契约和演进计划见 默认站点构建指南。
开发环境使用 Node.js 24.12 或以上版本和 pnpm 10:
pnpm install
pnpm build
pnpm test
pnpm blog -h从 CLI 创建独立博客目录:
pnpm blog init ./my-blog进入博客目录后,使用安装好的 blog 命令启动同步服务器:
blog sync 8080命令会按配置重新生成 content/、同步所选主题到 nowSite/,然后启动静态服务器并监视文章和主题文件。访问地址会在启动日志中输出,路径前缀由 config/<名称>.json 的 base_url 决定。CLI 的完整子命令和参数以 blog -h 为准。
主题作者负责网站自身的结构和行为。可以从 sites/default 开始,也可以创建全新的主题目录。常见工作包括:
- 自行设计首页、文章阅读、导航和 URL 结构。
- 自行决定文章列表、分类、标签、搜索、归档和推荐如何呈现。
- 使用约定的内容索引和元数据,或在主题中建立自己的数据层。
- 在 Node hooks 中响应主题加载、全量生成及单篇文章变更,执行必要的索引刷新或其他副作用。
- 将主题构建为浏览器可运行的文件,并确保
nowSite/副本具备独立服务所需的资源。
主题 TypeScript、钩子签名及默认主题构建方式见 默认站点构建指南。主题不要手动修改 nowSite/,它是工具同步生成的运行副本。
blog init <目录>:创建独立博客目录和默认主题。blog generate [y|n] [verbose]:生成文章内容;第一个参数为y时强制重新转换。blog changesite [主题名]:切换当前主题。blog sync [端口]:启动静态服务器并监视文章和主题变更。blog refresh:重新生成内容并同步当前主题。blog new <a|c> <相对目录> <名称>:创建文章或子目录。blog config <add|del|use> <参数>:管理配置。
pnpm build
pnpm test
pnpm packpnpm build 编译生成器、检查默认主题并打包浏览器入口;pnpm test 在构建后运行测试。pnpm pack 生成 npm 包。独立程序构建命令为 pnpm pkgwin、pnpm pkglinux 和 pnpm pkgall。
- 主题是网站程序,不是通用模板;默认主题只是示例实现,不代表生成器要求的页面形态。
- 当前内置转换器提供通用 HTML 和元数据,但 transformer 插件体系仍在完善。
- 主题原始文章拦截已支持;主题切换和强制刷新采用非破坏式提交,旧主题不支持某种格式或拦截器失败时会保留已有 HTML、JSON、附件和索引。
ISiteHooks声明的部分安装生命周期目前尚未接入调用流程。- 内容索引和元数据格式需要增加 schema 版本,并定义向后兼容策略。
- README 曾规划 EJS/Hexo 模板兼容;这属于可选适配方向,不应改变主题独立控制网站的核心模式。