feat(books): 书架定稿方案 C——抽书阅读 + 多本置顶默认展开

用户拍板选 C,置顶标记改为向上箭头图标(不写文字),并确认支持多本置顶。

- 抽书列表:情绪色脊 + 定宽标题列 + 展开 chevron,details 原生展开看封面与简介
- 置顶:所有 pinned 书排最前且默认展开,标记换成 ↑+横线 图标
- 删除一次性预览路由 /books-preview/ 与其 lint 白名单

验证: 构建 exit 0;content-lint 53 页 0/0/0;Playwright 实测展开/箭头旋转/
      作者列对齐/390 无溢出;两本临置顶实测均排前且同时展开

Spec: none (先行上线,完整 5i 包仍在 spec/2026-11-02_blog-5i-fonts-polish)

Co-authored-by: GLM-5.3
This commit is contained in:
wait4xandGLM-5.3 committed 2026-11-03 12:28:30 +08:00
1 parent d6e08a29f9
commit d096d45c58
5 files changed
+208 -679

No files matched your search

+2 -1
View File
@@ -16,6 +16,7 @@ if (MODE === 'skip') {
const SKIP_PREFIX = ['/admin/', '/photos-originals/']; // admin=CMS 路由;photos-originals=部署期 rsync 叠加层(不在 dist,另有部署链保障)
const SKIP_FILE = new Set(['/404.html']); // Astro 404 页不参与配对
function walk(dir, out = []) {
for (const e of readdirSync(dir)) {
const p = join(dir, e);
@@ -48,8 +49,8 @@ const fails = [];
const warns = [];
for (const f of files) {
const html = readFileSync(f, 'utf8');
const rel = f.slice(DIST.length) || '/';
const html = readFileSync(f, 'utf8');
// 站内 <a href>:仅根相对路径;#锚点/mailto/tel/外部/data: 全跳过
for (const m of html.matchAll(/<a\s[^>]*href="([^"]*)"/g)) {