Books

电子书收藏,部署在 books.lulununu.com

架构

main 保存 Markdown、抓取工具与工作流;部署流程使用严格扩展名白名单构建临时站点,再发布为无父提交的干净 release 分支。tools/.github/、Markdown 源文件和依赖配置不得进入线上部署。

凭据配置

SPL/O'Reilly 凭据只能存放在 GitHub Actions Secrets:

路径:Repository Settings → Secrets and variables → Actions。禁止把账号、PIN 或密码写进 tools/login.js、workflow、测试或日志。

下载新书流程

1. 确认书籍格式

⚠️ 只支持旧版 O'Reilly 阅读器(URL 含 kindle_split_xxx.html,页面有 #book-content 元素)。

新版阅读器(URL 含 .xhtml,如第二版 CSS in Depth 9781633438354)不兼容,会报 Element with id "book-content" not found

判断方法:通过 ezproxy 打开书籍任意章节,检查页面是否有 #book-content

2. 获取起始 URL

找到书的任意章节页面 URL,通常是第一个 kindle_split 页面,例如:

https://www.oreilly.com/library/view/css-in-depth/9781617293450/OEBPS/Text/kindle_split_001.html

3. 触发批量下载

在 GitHub Actions 手动触发 Batch Convert O'Reilly Book workflow:

gh workflow run convert-book.yml --repo aibeta/books \
  --field url="<起始URL>" \
  --field wait="10" \
  --field retry="3"

workflow 会自动:

  1. 打开起始页面,提取 TOC 中可见的章节链接
  2. 逐页处理:下载内容 → 提取新发现的链接 → 加入队列(迭代爬取,解决 TOC 折叠问题)
  3. 每个章节保存为 oreilly/<书名>/XX-kindle_split_YYY.md
  4. 自动合并所有章节为 book.md(按 kindle_split 编号排序,跳过目录/索引等)
  5. Commit & push 到 main

4. 部署

push 到 main 后会自动触发 generate-index.yml

抓书 workflow 会显式调用可复用的部署 workflow,不再依赖 bot push 触发另一个 workflow。

5. 验证

访问 https://books.lulununu.com/oreilly/<书名>/ 确认所有章节和 book.html 可访问。

单章节下载

gh workflow run convert-chapter.yml --repo aibeta/books \
  --field url="<章节URL>" \
  --field wait="10"

本地合并(手动)

cd tools && go build -o dist/web-html-2-local main.go
./dist/web-html-2-local --merge oreilly/<书名>/

最终产物(每本书)

oreilly/<书名>/
├── book.md          # 合并后的完整 markdown(含目录,图片用相对路径)
├── book.html        # 自动生成的 HTML(带自定义样式)
├── images/          # 提取的图片文件
│   ├── 001.png
│   ├── 002.png
│   └── ...
├── 01-kindle_split_001.md   # 源文件(保留但不生成 html)
├── 02-kindle_split_002.md
└── ...

合并逻辑

文件限制(Cloudflare Pages)

部署安全约束

线上 release 分支只能包含 HTML、图片、字体、CSS 和明确允许的文档资源。以下路径或类型出现即视为部署失败:

凭据一旦进入线上部署,必须立即轮换;删除当前文件不能撤销 Git 历史、旧 Pages deployment 或 CDN 缓存中的泄露。

开发流程(TDD)

所有功能和 bug 修复都遵循 TDD 流程:

功能开发

  1. 写测试描述期望行为,确认测试失败(红)
  2. 写实现,确认测试通过(绿)
  3. 提交

Bug 修复

  1. 分析根因
  2. 写能复现 bug 的测试,确认失败(红)
  3. 修复代码,确认测试通过(绿)
  4. 提交

运行测试

npm ci
npm test
bash tools/oreilly-login.test.sh
bash .github/workflows/generate-index.test.sh
bash .github/workflows/build-site.test.sh
(cd tools && go test ./... -v)

绝对不能跳过测试直接写实现。