脚本详解:generate-archive.ps1
归档 · 标签云 · 最新文章 · 搜索索引
这个脚本干什么
generate-archive.ps1 是整个构建流程的第一站。它扫描所有博客内容文件,提取元数据,一口气生成四种东西——最新文章组件、文章归档页、标签云页、以及搜索索引。四种产出分别服务于侧边栏、独立页面、和 CGI 搜索引擎。
它必须在 build.ps1 之前跑,因为 build.ps1 需要读取它生成的 latest-posts.html 注入侧边栏。如果顺序反了,访问者看到的就是旧数据。这个依赖关系由 rebuild-all.ps1 保证,不需要人工记忆。
元数据扫描
脚本的第一件事是遍历博客目录,从每个 .html 文件的 HTML 注释中提取四段元数据:
日期(date)—— 兼容 2026-04-28 和 2026-04-28 23:30 两种格式
标题(title)—— 文章的显示名称
标签(tags)—— 逗号分隔的关键词,用于标签云
草稿标记(draft: true)—— 如果存在,整篇文章被跳过,不出现在任何产出中
所有文章信息存入一个 PowerShell 对象数组,按日期降序排列。这一步是整个脚本的数据基础,后续四种产出都从这个数组派生。
产出 A:最新文章组件
取前 5 篇文章,生成 src/components/latest-posts.html。这个文件会被 build.ps1 注入到每个页面的右侧边栏,所以网站上的"最新文章"列表永远是最新的。
这里有一个值得说的细节:标题截断用的是像素宽度估算而非字符数。中文字符估算 11px,ASCII 估算 6px,总宽度超过 110px 就截断到 10 个字符。用字符数截断对于纯中文没问题,但中英混排的标题会差很多——"AAAAAAAAAA" 和 "中中中中中"同样是 5 个字,像素宽度能差一倍。在 CSS text-overflow 出现之前,手工宽度计算是唯一的方案,而且恰好 IE5.5 不支持 text-overflow。
输出文件用 UTF-8 without BOM 编码。因为它会被注入到已有 BOM 的页面中, 带 BOM 的话注入位置会多出乱码字符。
产出 B:文章归档页
归档页的核心是按年-月分组。日期格式统一为 YYYY-MM-DD, 取前 7 个字符就是 YYYY-MM。用 PowerShell 的 Group-Object 一键分组,然后按月份降序排列,最新的排最上面。
每个月份渲染为一个标题("2026年4月")+ 一个两列表格:左边是日期(黄色,130px 宽),右边是文章标题(青色链接)。这个页面没有侧边栏——它采用双栏布局,左边放博客文章,右边放其他页面(下载中心、FAQ 等),用 980px 的 table 居中。
归档页输出到 dist/archive.html(中文)或 dist/en/archive.html(英文)。
产出 C:标签云页
标签云是四个产出中逻辑最复杂的一个。它需要构建一个标签→文章的反向索引:遍历所有文章的标签,用一个哈希表把每个标签映射到包含它的文章列表。
标签的字号根据文章数量分级:3 篇以上大号(size="4"),2 篇中号(size="3"), 1 篇小号(size="2")。三个级别足够区分,不需要更复杂的热度算法。
标签云下方是每个标签对应的文章列表,用 <a name="tag名"> 做锚点,点击标签云中的链接即可跳转。标签云也有独立的中英文版本。
产出 D:搜索索引
搜索索引是一个纯文本文件 data/build/search_index.txt, 被 cgi-bin/search.py 读取用于全文搜索。格式是每篇文章一个 TITLE/DATE/LINK/TEXT 记录块,用 --- 分隔。
文本提取的流程很简单:读 HTML → 正则剥离所有标签 → 替换 → 压缩连续空白为单个空格。不需要 NLP,不需要分词,纯字符串匹配。对于几十篇文章的个人博客,这个方案完全够用。
搜索是完全免 JavaScript 的——搜索框是一个 HTML 表单,提交到 CGI, 服务端做全文匹配,返回带高亮的结果页面。整个过程和 2002 年的搜索引擎工作原理一致。
双语支持
脚本通过 -Lang 参数控制语言(默认 "zh")。英文模式下,博客内容从 blog/en/ 读取,界面文字自动切换("最新文章"→"Latest Posts"), 输出到 dist/en/ 子目录。中文和英文的归档、标签、搜索索引完全独立, 不会混在一起。
设计思路
如果把这个脚本拆成四个独立的脚本,代码会更模块化,但每次全站构建需要扫描 4 次博客目录。 一次扫描、四处输出的设计减少了 I/O。在这个只有几十篇文章的站点上,差异可能只有几百毫秒,但它体现了一种"提前想好数据流"的工程习惯——知道数据从哪里来、要到哪里去、中间经过几次变换。
PowerShell 的 Group-Object、Sort-Object、Select-Object 等管道命令在这里发挥了类似 SQL 中 GROUP BY、ORDER BY、LIMIT 的作用—— 只不过操作的是内存中的对象数组而非数据库表。
|