TimeCrackbot
|
4512d3fb24
|
更新 src/content/posts/思考/博客到底可以用来做什么.md
对文章进行修改
Signed-off-by: 时之刃 <tianxuetao1998@hotmail.com>
|
2026-10-06 12:36:29 +00:00 |
|
TimeCrackbot
|
ddfd0c0402
|
文章修改
|
2026-10-06 20:26:15 +08:00 |
|
TimeCrackbot
|
940bac3106
|
修改文章
|
2026-10-06 20:25:27 +08:00 |
|
TimeCrackbot
|
2673e236f7
|
修改文章
|
2026-10-04 20:01:50 +08:00 |
|
TimeCrackbot
|
daf3b34b8c
|
更新一篇文章:“工作效率的提升”同时对之前的一些文章进行删改,增加文章简介。
|
2026-09-27 10:32:12 +08:00 |
|
TimeCrackbot
|
ec80ea7bd0
|
修复: 回到顶部按钮和进度条不显示的bug
|
2026-09-21 09:47:35 +08:00 |
|
TimeCrackbot
|
219cb712a6
|
修复:增加回到顶部功能,优化博客性能
|
2026-09-21 09:37:31 +08:00 |
|
TimeCrackbot
|
b0e7d40faf
|
提升网页渲染性能,取消织纹效果和模糊效果
|
2026-09-21 09:08:35 +08:00 |
|
TimeCrackbot
|
df81abb303
|
提升网页渲染性能,将纸纹效果、模糊效果取消
|
2026-09-21 09:08:23 +08:00 |
|
TimeCrackbot
|
081d5fa65f
|
修改网站的favicon,并将favicon迁移到site.ts中
|
2026-09-20 20:59:26 +08:00 |
|
TimeCrackbot
|
eca2ad599f
|
文件更新
|
2026-09-18 21:41:48 +08:00 |
|
你的名字
|
429fecb6e9
|
fix:文章修改
|
2026-09-18 10:08:16 +08:00 |
|
dsh
|
8e08fc5094
|
内容 schema 兜住 YAML 空值,修掉手写偶得触发的构建失败
问题
新增的 src/content/thoughts/20260622-夏至已至.md 让 build 直接失败:
InvalidContentEntryDataError: thoughts → 20260622-夏至已至
tags: Expected type "array", received "object"
images: Expected type "array", received "object"
报错里那个 "object" 很误导 —— 它其实是 null(JS 里 typeof null === "object")。
根因
该文件的 frontmatter 写了两个空字段:
images:
tags:
YAML 把「只写 key、后面什么都不跟」解析成 null,而不是 undefined。
而 schema 用的是 z.array(z.string()).optional().default([]) ——
.optional() 只放行 undefined,.default() 也只对 undefined 生效,
所以 null 会直接被判为类型不符。
这不是那一个文件的问题,而是一类写法的问题:手写 frontmatter 时把不要的字段
留空太自然了。而且这类报错信息完全指不出真正的原因,很浪费时间。
改法
在 content.config.ts 顶部加三个 helper,把 null 当作「没填」处理:
text(fallback = "") 文本,留空 → fallback
optionalText() 可选文本,留空 → undefined(保持原类型)
textList() 字符串数组,留空 → []
然后套用到 posts / thoughts / studies 里所有「留空应该算默认值」的字段
(description / image / tags / category / lang / password / prev* / next*、
thoughts 的 title / tags / location / weather / images、studies 的三个可选文本)。
注意:只改了「留空该走默认」的字段。像 posts.title、published、
studies.title / status / started 这些必填项保持原样 —— 它们留空本来就该报错。
验证
- 清内容缓存重建:pnpm build 退出码 0,不再报 InvalidContentEntryDataError
- 那条偶得正常产出(tags / images 都成了空数组,location / weather 保留)
- 抽查其他条目:树莓派那篇的标签与任务列表、首页的偶得列表均正常
|
2026-09-17 20:35:56 +08:00 |
|
TimeCrackbot
|
90d24f8948
|
文章错误修改
|
2026-09-17 20:30:00 +08:00 |
|
TimeCrackbot
|
812140b2a5
|
文章更新
|
2026-09-17 20:29:37 +08:00 |
|
dsh
|
6a74061689
|
修复偶得里任务列表不渲染:给 markdown-it 补上 GFM 任务列表
问题
站主反馈偶得里 `- [ ] 每天至少阅读1小时…` 没渲染成复选框,`[ ]` 原样显示;
同样的语法在文章里正常。原因不是语法写错,而是**两套渲染器**:
文章:Astro 内容管线 → Sätteri,配置里开了 gfm → 任务列表正常
偶得:src/lib/thoughts.ts 里裸的 new MarkdownIt() → 不含 GFM 扩展
实测确认:这条偶得(20260822-好好工作.md,任务列表嵌在引用块里)产出的是
<blockquote><ul><li>[ ] 每天至少阅读1小时…</li></ul></blockquote>
改法
新增 src/plugins/markdown-it/task-lists.mjs,输出刻意与 Sätteri 那边逐字对齐:
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" disabled> 文字</li>
</ul>
这样以后给任务列表写 CSS,文章和偶得两边都吃得到。
几个实现细节
- 判断任务项看的是 list_item_open → paragraph_open → inline 这个固定结构;
紧凑列表里 paragraph 是 hidden 的但 token 仍在,所以照样能判
- 找父级列表是按 token 层级往回扫,不是假设它在最外层 —— 因为站主的用法
正是把任务列表放在引用块里
- class 用 addClass 去重:一个列表里每个任务项都会来加一次,直接用 attrJoin
会变成 class="contains-task-list contains-task-list contains-task-list …"
- 方括号后必须跟空白才算任务项,`- [ ]紧贴文字` 按普通文本处理(与 GFM 一致)
验证
- 该偶得现在产出 contains-task-list / task-list-item / checkbox,与文章
树莓派云服务器的使用总结 里那处逐字一致
- 边界用例:`[x]`/`[X]` 正确勾选、有序任务列表可用、嵌套列表只标父级、
多个列表各自只加一次 class、普通列表项不受影响
- pnpm build 退出码 0
顺带在操作指南里记了「两套渲染器」这个根因,以及偶得目前还缺的 GFM 能力
(裸链接自动转换、脚注、数学公式、callout、智能标点)。
|
2026-09-17 20:15:48 +08:00 |
|
TimeCrackbot
|
a7ce870400
|
修改:调整关于页和profile内容
|
2026-09-17 20:07:03 +08:00 |
|
dsh
|
e174138bbf
|
代码字体换成 Maple Mono,并修好断掉的等宽回退链
按站主要求,代码/等宽字体改用 Maple Mono(ZeoSeven 上编号 443,
那边叫 ZSFT-443)。它是一款专为编程设计的开源等宽字体,带连字,
这里用可变字体单文件(normal 114 KB / italic 135 KB)。
改动
- global.css 顶部加两条 @font-face(放在所有 @import 之后),
指向 https://fontsapi.zeoseven.com/443/{main,italic}.woff2
- 字族名直接叫 "Maple Mono" 而不是 ZeoSeven 的编号 "ZSFT-443" ——
@font-face 的名字由我们自己定,用真实字体名更好维护
- --font-mono 从 "Geist Mono", "Geist Mono Fallback" 换成
"Maple Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
Consolas, "Liberation Mono", monospace
顺带修掉一个真 bug
原来那串只有 "Geist Mono", "Geist Mono Fallback" —— 两个名字既没有
@font-face 也没装在机器上,等于整条回退链是断的,浏览器会退回默认字体
(不是等宽)。受影响的是内联代码(global.css 里那条 var(--font-mono))
和组件里 29 处 font-mono(时间线日期、偶得时间戳、专题元信息、灯箱说明…)。
代码块不用另外改
astro.config.mjs 里 expressive-code 的 codeFontFamily 已经写成
"var(--font-mono), ui-monospace, …",所以改 --font-mono 一处,
代码块、内联代码、组件里那些 font-mono 一起生效。
正文与 Google Fonts 保持不动(站主确认)。
验证:pnpm build 退出码 0
- 产物 CSS 里两条 @font-face 都在,外部 URL 未被 Vite 改写
- --font-mono 已解析为 "Maple Mono", ui-monospace, …
- experssive-code 侧仍引用 var(--font-mono),自动继承
- 字体文件实测可下(main 116712B / italic 137812B)
|
2026-09-17 20:00:15 +08:00 |
|
dsh
|
cfcd24a3f8
|
回滚字体改动,恢复到 ef72d52 的状态
按站主要求,把字体相关改动整体回退。用 revert 而不是 reset —— 这些提交
已经推送并部署过,保留历史比改写历史安全。
撤销的两个提交:
- f56a6ed 门面字体改为霞鹜新致宋(LXGW Neo ZhiSong)
- e92ee27 字体系统重做:脱离 Google Fonts,统一思源黑/宋,门面加霞鹜文楷
回滚后恢复到:
- 西文与中文全部来自 Google Fonts
(Inter / Noto Sans SC / Playfair Display / Noto Serif SC)
- 门面档用鸿蒙 Sans SC(jsdelivr 的 Regular + Semibold)
- --font-display-sans 回到 "HarmonyOS Sans SC"
- 站点名与首页那句话去掉 font-display-sans
- 操作指南里的字体说明表一并删除(缓存那条 FAQ 保留)
⚠️ 一并回来的已知问题
--font-mono 又变回 "Geist Mono", "Geist Mono Fallback" —— 这两个名字既没有
@font-face 也没装在机器上,font-mono 的回退链是断的,浏览器会退回默认字体
(不是等宽)。全站几十处 font-mono(时间线日期、偶得时间戳、内联代码…)受影响。
这是回滚的既定代价;要单独修的话就是一行。
验证:四个字体文件(BaseLayout / global.css / hero.tsx / site-header.astro)
与 ef72d52 逐字一致(git diff 为空),文档也一致。
|
2026-09-17 19:49:46 +08:00 |
|
dsh
|
f56a6eda11
|
门面字体改为霞鹜新致宋(LXGW Neo ZhiSong)
按站主要求,门面档(fontProfile="interface")整体换成霞鹜新致宋。
文章页不受影响,仍是思源黑体 —— 宋体在长正文里不如黑体好读。
- BaseLayout:门面档额外加载 ZeoSeven 的 22 号字体,替换掉原来的霞鹜文楷
(文楷 regular + bold 两档一起删掉)
- global.css:--font-display-sans 换成新致宋;恢复按下 font-profile-interface
覆盖字族的规则,让门面整体走宋体(思源黑体兜底)
- 站点名与首页那句话本来就挂在 --font-display-sans 上,无需改动
为什么必须用 ZeoSeven 而不是 jsdelivr
jsdelivr 上的 lxgw-neo-zhisong-webfont@1.0.0 是**单文件 4.45 MB、没有
unicode-range 分包**,挂上去等于每个访客都要下 4.45 MB,不能用。
ZeoSeven 的 /22/main/result.css 把字体切成 145 个 unicode-range 分包
(CSS 158 KB / gzip 54 KB),浏览器只下当前页面命中的那几个。
Fontsource 没有收录这款字(三个包名都 404),所以没有更统一的来源。
实测 ZeoSeven 响应稳定(连续 3 次均 200,耗时约 0.11s),分包可下。
已知取舍
新致宋只有 400 一个字重,门面里的 font-medium / font-semibold / font-bold
会由浏览器合成加粗。宋体的合成加粗偏糊,如果观感不好,把那几处字重去掉
改用常规字重即可。这一点已写进操作指南。
体积(样式表 gzip)
门面:原 127.4 KB(思源黑 + 思源宋 + Inter + Playfair + 文楷两档)
→ 118.9 KB(思源黑 + 思源宋 + Inter + Playfair + 新致宋)
文章页:不变
验证:pnpm build 退出码 0
- 首页加载 zeoseven/22/main/result.css;文章页不加载
- 两类页面均无 lxgw-wenkai 残留
- 产物 CSS 里 --font-display-sans 为 "LXGW Neo ZhiSong",
body.font-profile-interface 覆盖规则与思源黑体兜底均在
|
2026-09-17 19:44:21 +08:00 |
|
dsh
|
e92ee27818
|
字体系统重做:脱离 Google Fonts,统一思源黑/宋,门面加霞鹜文楷
一、全部改走 jsdelivr 上的 Fontsource,不再依赖 Google Fonts
之前文章页的 Inter / Noto Sans SC / Playfair Display / Noto Serif SC
全部来自 fonts.googleapis.com —— 而文章页恰恰是最该稳的页面。
现在 5 份样式表都由 BaseLayout 顶部的 fontStylesheets 统一声明。
二、CJK 用可变字体(关键)
@fontsource-variable/noto-sans-sc 一份 CSS 覆盖 font-weight: 100 900,
不用为 400/500/600/700 各加载一份(那样是 4 × 105 KB = 420 KB)。
每份 CSS 内含约 100 条带 unicode-range 的 @font-face,浏览器只下载当前
页面命中的分包。完整思源黑体 3.3 MB / 101 个分包,一页通常只用到 100–300 KB。
三、层次:楷(门面点睛)> 宋(标题)> 黑(正文/UI)
- 正文/UI:思源黑体 Noto Sans SC Variable(两档都用)
- 标题:思源宋体 Noto Serif SC Variable
- 门面点睛:霞鹜文楷 LXGW WenKai(regular + bold)—— 用在站点名、
首页那句话、以及 --font-display-sans 覆盖的卡片标题
- 西文:Inter Variable(正文)+ Playfair Display(展示)
霞鹜文楷只在 fontProfile="interface" 的页面加载;文章页没加载它,
而 --font-display-sans 里它排在思源黑体前面,靠浏览器自动回退。
四、删掉鸿蒙 Sans
两档现在都用思源黑体,所以 body.font-profile-interface 那条按档覆盖字族的
规则删掉了。class 保留,它现在只用来决定是否加载文楷。
五、顺带修掉 --font-mono 断掉的回退链
原来只有 "Geist Mono", "Geist Mono Fallback" —— 这两个名字既没有 @font-face
也没装在机器上,等于整条回退链失效,浏览器退回默认字体(不是等宽)。
全站几十处 font-mono(时间线日期、偶得时间戳、内联代码、灯箱说明…)都在受影响。
补上 ui-monospace / SFMono-Regular / Menlo / Consolas / monospace。
体积账(gzip 后的样式表,和 .woff2 分包的实际下载是两回事)
文章页 62.5 KB -> 64.6 KB
门面 125.5 KB -> 127.4 KB
基本持平,换来摆脱 Google Fonts + 字体统一 + 多一款文楷
验证:pnpm build 退出码 0
- 文章页只加载 Inter + Playfair + 思源黑 + 思源宋;首页额外加载文楷两档
- 两类页面里 Google Fonts 与鸿蒙均已消失
- 产物 CSS 里 5 个字族名与 ui-monospace 回退均在
- 站点名与首页那句话的 class 已带 font-display-sans
- 字体文件实测可下载(jsdelivr 相对路径解析正常)
|
2026-09-17 19:35:12 +08:00 |
|
dsh
|
ef72d52de4
|
标题后的 # 锚点:补上缺失的样式,并修跳转定位与无障碍
问题
- 插件 src/plugins/satteri/autolink-headings.mjs 会在每个标题末尾追加
<a class="anchor"><span class="anchor-icon">#</span></a>,但项目里从来
没给 .anchor / .anchor-icon 写过任何样式(源码和产物 CSS 都查过,零条规则)
- 结果是那个 # 以纯文本形式常驻显示在每一个标题后面,看起来像 Markdown 语法错误
- 另外标题有 id 却没有 scroll-margin-top,点 # 跳过去标题顶部紧贴视口上沿,
正好藏在 69px 高的 sticky 导航栏下面
改法
- global.css 补样式:默认 opacity:0 隐藏,鼠标悬停标题(或键盘聚焦锚点)才浮现,
悬停锚点本身转朱红;触屏没有 hover,直接 display:none(跨标题跳转用目录即可)
- 补 :is(h1..h6)[id] { scroll-margin-top: calc(var(--header-h,69px) + 1.25rem) }
- 插件里给锚点补无障碍名称:aria-label="链接到「标题文字」",图标加 aria-hidden。
否则读屏会连着念二十几个「#,链接」,完全不知道跳到哪
踩到的坑(已写进操作指南)
Astro 的文章缓存只在 markdown 内容变化时失效,改插件代码不会重新渲染,
必须先 rm -rf node_modules/.astro .astro。第一次改完插件产物没变就是这个原因。
验证:清缓存重建后,产物 HTML 里锚点带上了 aria-label 与 aria-hidden;
产物 CSS 里 .anchor 的 5 条规则 + scroll-margin-top 均正确,
@media(hover:none) 的作用域也确认无误
|
2026-09-17 18:37:20 +08:00 |
|
TimeCrackbot
|
93362376f8
|
fix: 消除文章页 dev 下的 "Invalid hook call" 告警
现象
dev 下每次打开文章页,终端都会打印 2 次 React 的 "Invalid hook call"。
生产构建没有;首页、/thoughts/、/friends/ 也没有。
根因(用临时 Vite 插件抓的调用栈定位)
不是 React 多副本,也不是 hooks 写法有问题,而是 Astro 的渲染器探测:
1. TableOfContents 首屏 headings 为空 → `return null`(数据在 useEffect 里填,
SSR 期不执行)
2. @astrojs/react 的 check 会试渲染一次,拿到 null 就认不出这是 React 组件 → false
3. Astro 转向下一个渲染器 @astrojs/mdx
4. MDX 的 check 把组件**当普通函数裸调** `await Component({...})`,不在 React
渲染树里 → useState 找不到 dispatcher → 报 Invalid hook call → 抛错被 catch
5. 两个渲染器都说不是自己的,Astro 最终仍用 React 正确渲染了组件
所以页面和组件一直是对的,只有日志是错的。生产构建没有是因为 React 生产版
剥掉了这段 dev-only 警告(栈里是 react.development.js)。
Hero 之类的组件不报,是因为它们探测时返回真实 JSX,第 2 步就被 React 认出来了。
修法
去掉 `if (headings.length === 0) return null`,改为始终返回 <nav>,无标题时用
`hidden` 收起,视觉结果不变。这样第 2 步就能认出是 React 组件,根本不会走到
MDX 的探测。代价是文章页 SSR 多出 2 个 display:none 的空 <nav>(两个 TOC 实例各一个),
以及 island 上多了 Astro 的 await-children 标记。
另一条路(未采用):项目里 0 个 .mdx,直接删掉 @astrojs/mdx 也能消除告警,
且零 DOM 变化。选择保留 MDX 是为了不因一个纯噪音的警告砍掉一个能力。
验证
dev 下逐个请求 5 类页面(含之前必现的 2 个文章页)告警数全为 0;
生产构建与基线的差异只剩本次有意的隐藏 nav、资源哈希和 island uid;
pnpm build 41 页 + pagefind 通过;astro check 仍是 1 error/0 warnings(原有报错)。
|
2026-09-17 18:16:43 +08:00 |
|
TimeCrackbot
|
f4a49ef94c
|
feat: 支持 Obsidian 风格 callout,并把脚注文案中文化
Callout
- 接入 satteri-callouts(HAST 插件),用 Obsidian 语法:
> [!tip] 标题
> 内容
> [!warning]- 默认折叠
类型名大小写不敏感,支持嵌套、可折叠、标题内联 Markdown。
- 样式没有用它自带的主题 CSS(Obsidian 原版是高饱和蓝/青/紫,还靠
mix-blend-mode 叠底色,在暖纸底上会发脏),改为新建 src/styles/callouts.css,
复用主题已有的 --admonitions-color-* token,与 .admonition(免责声明块)
统一成「3px 左边框 + 彩色标题、无底色」。
- 类型映射:tip/hint→tip,note/info/todo/abstract/summary/tldr→note,
important/example→important,warning/attention/question/help/faq→warning,
caution→caution,success/check/done→(新增的)success,
danger/error/failure/fail/missing/bug→destructive,quote/cite→muted-foreground。
- global.css 补一个 --admonitions-color-success(浅色 oklch(0.62 0.16 150) /
深色 oklch(0.7 0.18 150)),与 tip(180)/note(250)/important(310) 同明度彩度。
脚注中文化
features.gfm.footnotes 设 label「脚注」、backLabel「返回第 {reference} 条」、
backContent「↑」,替换默认的 Footnotes / Back to reference。
正文
- 周末愉快.md:`::: tip 下周计划`(冒号后有空格,从来不是合法指令,
一直渲染成普通段落)改成 `> [!tip] 下周计划`,任务列表一并加 `>` 前缀。
- 关于价值感和归属感的思考.md 的 `> [!tip] Tip` 本来就合法,一行未改,
现在自动变成真 callout。
顺带修
autolink-headings 不再给脚注区那个 sr-only 的「脚注」标题加 # 锚点。
验证
- 两处 callout 均正确渲染;callout 内的图片仍带 data-lightbox-src
(说明 imageLightbox 与 satteriCallouts 的执行顺序没问题)。
- 临时加了一篇带脚注和折叠 callout 的文章验证:脚注文案、返回链接、
折叠态 <details>/<summary> 结构都正确,验证后已删除。
- 整页对比基线:37/41 一致,4 处差异中 2 处是本次有意的 callout 生效,
另 2 处是已知的智能标点引号方向(Sätteri 的结果更正确)。
- pnpm build 41 页 + pagefind 通过。
|
2026-09-17 18:01:44 +08:00 |
|
TimeCrackbot
|
5e808a9cd4
|
feat: 接入 KaTeX 渲染,完成 Sätteri 迁移(Phase 3)
方案:用现成的 satteri-katex(MDAST 插件,40 行,是 rehype-katex 的移植),
而不是自己写。它跑在 MDAST 阶段,天然绕开下面这个坑。
为什么不能用 HAST 阶段做
Sätteri 把块级公式输出成 <pre><code class="language-math math-display">,
而 expressive-code 过滤所有 <pre>,会把它当成未知语言渲染成带行号的
plaintext 代码块 —— 实测 10 个块级公式全部被吃掉(math-display: 0)。
unified 时期没这问题,是因为 rehype-katex 排在 rehypePlugins 第一位,
先把 <pre><code> 换掉了。satteri-katex 的源码注释里记录的是同一个坑。
插件顺序
satteriKatex() 放在 mdastPlugins 最后:它把 math 节点换成 KaTeX 的 html
节点,若排在 reading-time / excerpt 之前,字数统计会把 KaTeX 标记也算进去。
顺带修掉一个之前漏掉的回归
reading-time / excerpt 原本用 ctx.textContent(),但它只拼接纯 text 节点,
会漏掉代码块、行内代码、公式、图片 alt。实测 LaTeX 那篇字数 830 → 488。
改用 mdast-util-to-string 的 toString()(与迁移前的实现一致),字数完全复原。
之前没发现是因为我的对比脚本只截取了 <article> 区域,而字数在它外面的 header 里。
现改为整页对比。
清理依赖(10 个,已确认无引用)
remark-math / rehype-katex / remark-directive /
remark-github-admonitions-to-directives / remark-sectionize / rehype-slug /
rehype-components / rehype-autolink-headings / @astrojs/markdown-remark /
hastscript / unist-util-visit
验证(与 unified() 基线整页对比,41 页)
- 39 页语义完全一致;2 页只剩智能标点在中文/emoji 旁的引号方向差异
(Sätteri 的结果更正确:把开引号排成 “ 而不是 ”)。
- LaTeX 页:class="katex" 76、katex-display 10,与基线完全一致;
块级公式不再被 expressive-code 吞掉。
- 字数/阅读时长与基线逐篇一致(830/4、1042/5、416/2)。
- pnpm build 41 页 + pagefind 通过;astro check 仍是 1 error/0 warnings
(原有 footer.astro 报错,与本次无关)。
|
2026-09-17 17:52:56 +08:00 |
|
TimeCrackbot
|
26e873b9f6
|
refactor: Markdown 管线迁移到 Sätteri(Phase 1 + Phase 2)
把 markdown.processor 从 unified() 换成 Astro 7 的默认管线 satteri(),
并把原来 12 个 remark/rehype 插件逐一移植到 Sätteri 的 MDAST/HAST 插件模型。
内置能力直接替代(零代码)
- remark-math → features.math
- remark-directive → 未启用(见下)
- rehype-slug → satteriHeadingIdsPlugin()
新增 src/plugins/satteri/(6 个插件,约 200 行)
- reading-time.mjs after 钩子写 ctx.data.astro.frontmatter.minutes/words
- excerpt.mjs 取第一段写 frontmatter.excerpt
- shift-headings.mjs 工厂按 fileURL 判断,只对 posts 下的文章生效
- sectionize.mjs remark-sectionize 的等价实现(递归分组 + data.hName)
- autolink-headings.mjs 标题锚点,输出与 rehype-autolink-headings 逐字一致
- image-lightbox.mjs 上一版 rehype 图片灯箱的 HAST 版
删除(已迁移或本就无效)
- remark-reading-time / remark-excerpt / remark-shift-headings /
remark-directive-rehype / rehype-component-admonition /
rehype-image-lightbox —— 共 6 个旧插件文件
- 未启用 features.directive:内容里的 `::: tip`(冒号后有空格)和
`> [!tip] Tip` 在迁移前后都渲染成普通段落/引用,属于死语法;
保持现状以免升级顺手把它激活。
行为对齐
- smartPunctuation: { dashes: false } —— Astro 的 unified 管线会把直引号
排成弯引号但不转换 ---,Sätteri 默认会转,显式关掉 dashes 才能逐字一致。
验证(与 unified() 构建逐页对比,41 页)
- 正文 HTML 完全一致 35 页;把 HTML 实体和表格对齐写法归一化后,
只剩 3 页有差异:1 页是 KaTeX 尚未迁移(见下),2 页是中文/emoji 旁的
引号方向(Sätteri 的结果更正确)。
- meta description 仍由 excerpt 正确生成;阅读时长与基线一致。
- astro check:1 error / 0 warnings,与迁移前完全相同(原有 footer.astro 报错)。
- pnpm build 41 页通过;dev server 正常。
尚未迁移
- KaTeX:Sätteri 的 math 只负责解析,不渲染。数学公式目前落成
<code class="language-math">,是可见的回归,Phase 3 处理。
- package.json 里 remark-*/rehype-* 依赖暂未清理,等 Phase 3 确定后再收。
|
2026-09-17 17:38:37 +08:00 |
|
TimeCrackbot
|
c1643ae95d
|
feat: 文章正文图片支持灯箱;删除未使用的 GitHub Card 插件
灯箱
- 相册页原本已有一套无依赖灯箱(事件委托 + ClientRouter 友好),
但它写在 gallery/[album].astro 里,只有相册页能用。
现抽成 src/components/ImageLightbox.astro,挂到 BaseLayout,全站可用。
- 新增 src/plugins/rehype-image-lightbox.mjs:给正文里的 <img> 注入
data-lightbox-src。跳过链接内的图片(点击应跳转)和显式标记
data-lightbox-ignore 的图片。
- 顺带让灯箱大图继承原图的 alt 文本(原先固定为空)。
- 正文图片加 cursor: zoom-in 提示。
清理
- 删除 src/plugins/rehype-component-github-card.mjs(165 行)及其在
rehypeComponents 里的 github 映射:内容里从未使用过 ::github 指令。
验证:构建 41 页通过;文章页正文图片 4/4 带上 data-lightbox-src,
相册页 5 个触发元素不受影响;灯箱脚本按页内联(2.8KB 压缩后);
正文渲染文本与线上基线一致,无回归。
|
2026-09-17 17:29:23 +08:00 |
|
TimeCrackbot
|
738fe3175e
|
chore: 升级 Astro 5.16.5 → 7.3.3
依赖
- astro 5 → 7.3.3,@astrojs/{mdx,react,rss,sitemap,check}、astro-expressive-code
与 @swup/astro 同步升到最新
- 新增 @astrojs/markdown-remark(Astro 7 默认改用 Sätteri 处理器,
本项目依赖大量 remark/rehype 插件,故显式固定回 unified 管线)
内容集合迁移到 Content Layer API(Astro 6 已移除旧 API)
- src/content/config.ts → src/content.config.ts,三个集合改用 glob() loader
- z 改从 astro/zod 导入
- 所有 entry.slug → entry.id;entry.render() → render(entry)
Astro 7 兼容
- 修复 bookshelf-content.astro 里多行 {/* */} 注释导致的 Rust 编译器
"Unterminated regular expression"
- 删除该文件里一处多余的 </div>(旧 Go 编译器会静默纠正,新编译器不会)
- global.css: @import "tailwindcss" → "tailwindcss/index.css"
(Vite 8 不再解析裸包名的 style 条件)
- astro.config.mjs 显式设置 compressHTML: true,保持 v6 的空白处理行为
验证:构建 41 页通过;与线上(Astro 5 构建)对比 39 个 URL 无一丢失,
仅新增新文章 DIY-computer 的 2 个 URL;逐页渲染文本与线上一致;
pnpm build 与 dev server 均正常。
|
2026-09-17 17:14:08 +08:00 |
|
TimeCrackbot
|
fe9adb246f
|
文章更新
|
2026-09-17 16:58:41 +08:00 |
|
TimeCrackbot
|
426c21b93c
|
文章更新:为小站更新内容<1. 我的台式机组装好了;2.偶得1篇>
|
2026-09-17 16:47:03 +08:00 |
|
TimeCrackbot
|
fcedd32d02
|
更新微信读书阅读进度
|
2026-09-16 18:29:16 +08:00 |
|
dsh
|
2c876f8776
|
彩蛋调整:文案改回原句,去掉悬停变色/下划线,那句话改回纯文本
按站主要求三处调整:
1) 文案改回原文
他还需要一个诗意的世界。 → 他还应该拥有诗意的世界。
(仍是 12 字,和最长那句 15 字的关系不变,固定字号不受影响)
2) 去掉悬停的变色与下划线
现在那句话悬停时完全不变化,保持纯排版。
删掉 .hero-quote-link 的两条规则,以及 reduced-motion 里对它的引用。
3) 那句话不再可点
去掉 h1 里的 <a>,文字恢复成纯文本。豆瓣链接只剩卡片里那一处。
交互全部落在署名上:悬停/聚焦淡入署名 → 点署名展开卡片 → 卡片里去豆瓣。
这样读的时候不会误触跳走。
署名按钮补了 aria-label(「查看这句话的出处:王小波《万寿寺》」),
因为现在它是唯一的交互元素,读屏用户需要知道它是干嘛的。
验证:pnpm build 退出码 0
- 新文案在 hero.*.js 里,旧文案无残留
- dist/index.html 里豆瓣链接只剩 1 处、h1 内为纯 <span>、无 hero-quote-link
- 产物 CSS 从 16 条 hero-quote 规则减到 14 条,
仍保留署名淡入、展开态常显、@media(hover:none) 手机常显
|
2026-09-16 18:24:49 +08:00 |
|
dsh
|
0f74467933
|
首屏彩蛋:那句话出自王小波《万寿寺》,可跳豆瓣
交互(默认完全看不出可点,保持留白):
- 悬停/聚焦:整句话由墨黑转朱红 + 朱红细下划线,署名随之淡入
- 点那句话 → 直接去豆瓣人物页
- 点署名 → 展开一张极简作者卡片,卡片里也能去豆瓣
结构上的几个考量:
- 用 <h1><a> 而不是把 h1 变成链接:保住标题语义,点击热区只包住文字
而不是整行 1024px(点旁边空白也跳走会很怪)
- 光标 ::after 挂在 h1 上(链接外面),点那个闪烁的竖线不会触发跳转
- 署名占一行固定高度(2.25rem)平时透明,hover 才淡入 —— 空间一直留着,
所以展开卡片时下面的按钮不会往上跳
- 卡片是手风琴式展开(max-height 过渡),留在文档流里,不盖住下面的按钮
- @media (hover: none) 下署名常显 —— 否则手机上这个彩蛋永远看不到
- aria-expanded / aria-controls / aria-label + focus-within 可见焦点,
键盘和读屏用户都能用
- prefers-reduced-motion 下关掉所有过渡
出处核实:多个豆瓣《万寿寺》原文摘录页都收录这句,确认为王小波《万寿寺》。
豆瓣链接在 curl 下会跳 sec.douban.com(反爬),真实浏览器可正常打开。
验证:pnpm build 退出码 0;dist/index.html 里豆瓣链接出现 2 次、
h1 内为 <a>、署名与卡片均在、卡片默认 data-open="false";
产物 CSS 含 16 条 hero-quote 规则(含 @media(hover:none))
|
2026-09-16 18:03:32 +08:00 |
|
dsh
|
ee5ec50602
|
首屏打字机改为固定字号 + CSS 光标,并修掉首屏白屏
按 Firefly banner 的做法重做,三件事:
1) 字号固定,不随句子长度变
- 文案从 4 句(14/11/4/4 字,差 3.5 倍)压成 2 句长度接近的王小波
- 字号用 text-[clamp(1.125rem,5.6vw,4rem)],只跟视口缩放
· 手机 390px → 21.8px(15 个字一行刚好放得下)
· 桌面 1280px → 64px(比 Firefly 的 3rem 更大更醒目)
- 容器 max-w-4xl(896px) → max-w-5xl(1024px):15 字 × 64px = 954px,4xl 装不下
- 实测 320/360/390/430/640/768/1024/1280/1920 全部放得下,无溢出
2) 光标改成 CSS ::after
- 删掉整套运行时测量:measureRef / designRef / fontSize state /
fitFontSize / ResizeObserver / CURSOR_EM / CURSOR_GAP_PX / 两个隐藏量具
- hero.tsx 298 → 208 行,两个文件净减 52 行
- 顺带消除测量误差,光标跟着字号自动缩放
3) 去掉和打字机重复的 Flannery O'Connor 引语
另外修掉两个自己发现的问题:
- 【真 bug】首屏在 JS 加载前是隐形的
SSR 出来的包裹层带 opacity-0,要等 React hydrate 才变可见,
慢网络下第一屏是白屏、LCP 被拖后。改成 CSS 入场动画(.hero-enter),
SSR 即可见;顺带删掉只为它存在的 mounted state
- 【算错】第一版 clamp 封顶写了 4.25rem(68px),但容器 896px 装不下
1013px,≥1280px 会溢出。一起修掉了
验证:pnpm build 退出码 0;dist 里已无 hero-cursor span、无隐藏量具、
无 Flannery 引语,h1 class 为 hero-typewriter + clamp 字号
|
2026-09-16 17:47:20 +08:00 |
|
TimeCrackbot
|
c597427b9a
|
chore: 优化文章结构,把一些之前用AI生成的文章都删除掉了
|
2026-09-15 19:53:43 +08:00 |
|
dsh
|
71026ee291
|
文档:记录两个部署目标的服务方式,并开启线上压缩
排查「树莓派预览打不开」时发现两件事,都不是这次部署造成的,但都修了/记了:
1) 树莓派上根本没有 web 服务
- nginx 未安装(Unit nginx.service could not be found),80 端口无人监听
- deploy.sh 一直把文件 rsync 到 /home/pi/www/Astro_firefly(这次也确实到了,
index.html 17:54、59 个 KaTeX 字体都在),但没有服务对外提供
- 补了 Caddy 容器 blog-caddy(--restart unless-stopped,配置 /home/pi/caddy/Caddyfile,
站点根挂到 /srv:ro),http://192.168.1.87 现在正常,各页面 200
2) 云服务器的 Caddy 一条 encode 都没有,全站裸传
- twikoo.min.js 506 KB、主 CSS 231 KB、首页 HTML 134 KB
- 站点块加 encode zstd gzip(改前按已有习惯备份成
Caddyfile.bak.gzip.20260915_175943,validate 通过后 reload)
- 实测 twikoo.min.js 506108 -> 160547 B(省 68%),CSS 230615 -> 40822 B(省 82%)
- Caddy 按 Accept-Encoding 协商 zstd / gzip,所有页面仍 200
README 与操作指南补了「两个目标各自怎么服务的」和 Pi Caddy 的重建命令,
并注明 1Panel 管的 Caddyfile 手改后要注意什么、reload 为什么是安全的。
|
2026-09-15 18:00:33 +08:00 |
|
TimeCrackbot
|
d0e504d1c3
|
刷新微信读书数据快照(仅 updatedAt 变化)
|
2026-09-15 17:53:30 +08:00 |
|
dsh
|
9a822e7105
|
关于页移除技术栈标签
- 删掉「关于本站」里那排 emoji 标签(🐧 Linux / 🐳 Docker / 🚀 Astro …)
- 一并删掉只为它存在的 skills 数组(删掉渲染后就没引用了)
- 顺手修复:手动删除时把上一节的 </section> 也一起带走了,JSX 变成
4 个 <section> 对 3 个 </section>,构建直接报
`Unexpected closing "div" tag does not match opening "section" tag`(:165)
- 清掉删除后残留的一行游离空格
验证:pnpm build 退出码 0;dist/about/index.html 里 🐧🐳🚀📋 / VS Code
均消失,章节只剩 关于我 / 关于本站 / 博客旅程 / 评论
|
2026-09-15 17:51:54 +08:00 |
|
TimeCrackbot
|
61625c3740
|
更新站点文案:tagline / description / keywords
- tagline:抵抗遗忘 -> 记录时间
- description:改为「只是分享自己的看法。」
- keywords:收敛为 技术 / Linux / Obsidian
(这几处是站主本人改的,随本次推送一起备份。
reading.json 只变了 updatedAt 时间戳。)
|
2026-09-15 17:21:23 +08:00 |
|
dsh
|
61c39557df
|
首屏打字文案改成长句也不溢出:按实际字宽自适应字号
问题
- h1 是 whitespace-nowrap + 固定字号 text-[min(10.5vw,3rem)] sm:text-6xl
md:text-7xl lg:text-8xl。其实旧文案就已经临界:旧句「折腾 Linux 的乐趣」
约 9.5 字宽,390px 屏上设计字号 40.9px 需要 389px,而 px-6 之后只有 342px。
换成王小波那句(14 字)后溢出更明显。桌面端同理:lg 的 96px × 14 字
= 1344px,而容器 max-w-4xl 只有 896px。
做法
- 不再拍固定字号,改成按「这一句完整文本」的实际渲染宽度算
- 关键点:只会**缩小**,不会放大。上限取当前断点的设计字号 ——
短句(记录思考/总结生活)保持原来的视觉分量,只有放不下的长句让步
- 量的是完整句子不是当前已打出的部分,所以打字机逐字出现时不会重排
- 字号只在句子切换的那一刻变一次,那时 h1 是空的,看不出跳动;
另加了 300ms 的 font-size 过渡
- 光标从固定像素改成 em 单位(w-[0.08em] h-[0.9em]),跟着字号缩放
- 算字号时扣掉光标自身的占宽(ml-2 的 8px + 0.08em),否则右边会顶出去
实现细节
- 设计字号不写死在 JS 里:用一个带同样响应式类的隐藏探针读计算值,
断点逻辑仍然只在 class 里有一处
- 两个隐藏量具放在 h-0 + overflow-hidden 的绝对定位容器里,不参与布局、
不会撑出横向滚动条
- ResizeObserver 跟随容器变化;document.fonts.ready 后再量一次
(网络字体加载完字宽会变)
预期效果(含光标占位,实测可用宽度)
390px 设计 40.9px:14字 24.3px / 11字 30.9px / 4字 40.9px(保持)
430px 设计 45.1px:14字 27.2px / 11字 34.6px / 4字 45.1px(保持)
768px 设计 72.0px:14字 51.9px / 11字 65.9px / 4字 72.0px(保持)
1280px 设计 96.0px:14字 64.7px / 11字 82.2px / 4字 96.0px(保持)
长句刚好占满可用宽度,短句维持原设计大小,无一溢出。
注:hero.tsx 里同时带入了你自己改的那四句文案(王小波那句 + 记录思考 /
总结生活)。src/data/site.ts 里你的 tagline/description/keywords 改动我没有提交。
|
2026-09-15 12:50:09 +08:00 |
|
dsh
|
a994839b5a
|
修复 KaTeX 字体全部 404:60 条构建警告,dist 里一个字体都没输出
问题
- 构建时刷 60 条 `fonts/KaTeX_*.woff2 referenced in ... didn't resolve`
- 更要紧的是这不是纯警告:dist 里 0 个字体文件,而 CSS 里写的是相对路径
url(fonts/KaTeX_AMS-Regular.woff2),CSS 输出在 /_astro/ 下,
浏览器会去找 /_astro/fonts/… —— 那个目录不存在,数学公式全部退化成系统字体
根因
- global.css 顶部写的是 @import "katex/dist/katex.min.css"
- postcss 只挂了 @tailwindcss/postcss,Tailwind v4 会自己解析并**内联** @import,
内联之后 KaTeX 的 url() 被算成相对 src/styles/ 去找,自然找不到
(确认过不是我引入的:把 package.json 的 type:module 去掉重跑,一样 60 条;
这条 @import 从初始提交就在)
修法
- global.css 里删掉那行 @import
- 改成在 BaseLayout.astro 的 frontmatter 里 `import "katex/dist/katex.min.css"`
- 走 Vite 的 CSS 模块管线,url() 按 node_modules/katex/dist/ 解析,
字体带哈希输出到 _astro/,CSS 里替换成绝对路径
验证
- 构建:KaTeX 警告 60 -> 0;dist 字体 0 -> 59 个、共 1.2MB
- CSS:20 条 @font-face,59 处 url(/_astro/KaTeX_*.woff2) 全部绝对化
- LaTeX 那篇文章含 17 处 class="katex" 标记,引用的就是这份 CSS
- dev server:ERROR 0,KaTeX 警告 0,首页 200
- 全量构建日志现在只剩 1 条预期内的 [WARN] glob-loader(studies 集合为空)
|
2026-09-15 12:45:24 +08:00 |
|
dsh
|
9c0851fd12
|
修复 pnpm dev 启动刷红:Sketch.astro 脚本误识别 + .pnpm-store 撑爆 inotify
两个独立问题叠在一起,用户看到的只是第一个(扫描失败会中止启动,
第二个来不及暴露)。
1) Sketch.astro 的 frontmatter 里出现字面量的 script 开标签
Astro 编译器靠扫描源码文本收集内联脚本,分不清真标签和字符串/注释。
原代码用模板字符串拼 iframe 里的 resize 脚本,那个字面量开标签被当成
组件脚本抽出来交给 Vite,里面的 ${JSON.stringify(...)} 直接报
`Expected "}" but found "{"`,dev 依赖扫描失败、整个 /src 刷红。
-> 改成 "\x3Cscript>" / "\x3C/script>" 拼接。
注意闭标签原本写作 <\/script> 所以没被误判,只有开标签要处理。
修完第一版又把解释写进注释、注释里带了字面量开标签,于是换了条错误
(`Unexpected "。"`)继续报;这次注释也改成不带字面量的写法。
2) .pnpm-store 被 Vite 的 watcher 一起监听
项目根目录下的 .pnpm-store 是 pnpm 内容寻址仓库(54269 个文件 / 672MB,
已被 .gitignore 忽略),Vite 默认 watch 项目根,直接撑爆 inotify
(max_user_watches = 65536),启动后无限刷
`ENOSPC: System limit for number of file watchers reached`。
-> astro.config.mjs 加 vite.server.watch.ignored: ["**/.pnpm-store/**"]。
顺带:package.json 加 "type": "module",消掉 Node 对
src/plugins/*.js 的 MODULE_TYPELESS_PACKAGE_JSON 警告(两个文件本来就是 ESM)。
验证
- 删掉 node_modules/.vite 强制重新做依赖扫描后启动 pnpm dev:
ERROR 0 / Failed to scan 0 / ENOSPC 0,ready in 496ms
/、/bookshelf/、/bookshelf/books/ 均 200
- pnpm build 退出码 0,MODULE_TYPELESS 警告 0
- 仅剩 [WARN] glob-loader 提示 src/content/studies 为空,属预期
- 操作指南补了这条 FAQ,说明两个原因和"注释里也不能写"这个坑
|
2026-09-15 12:22:44 +08:00 |
|
dsh
|
30c958c2f0
|
代码块阴槽调浅一档:#ece6da -> #f2ece1
上一版 0.925 偏重,用户反馈太深。改成 0.945(顶栏 0.893 -> 0.915),
色相和彩度不变,仍然是暖色槽而不是冷白补丁。
明度差对比(页面底 0.964 = #f8f3e9):
0.958 #f6f1e6 差 1.018:1 ← 再浅一档,几乎看不出边界
0.945 #f2ece1 差 1.058:1 ← 本次采用
0.925 #ece6da 差 1.124:1 ← 上一版
0.905 #e5dfd3 差 1.19:1
正文对比度 12.4:1,暗色模式未动。三档都写进 README 和 global.css 注释,
以后想调只改一个数字。
|
2026-09-15 12:07:25 +08:00 |
|
dsh
|
cd0da2a19d
|
页脚三栏统一成卡片;代码块改暖色阴槽;导航字号/移动端菜单位置调整
页脚
- 「最新文章」和「联系」也套上 bg-card + border/50 + rounded-xl + p-5,
标题用和「站点信息」同一套红竖线样式,三栏现在是一个语言
- 栏间距 gap-12 -> gap-5,卡片自己撑开视觉分隔
- 去掉 md:justify-self-center / md:justify-self-end,卡片改为填满各自栅格
代码块(浅色)
- --codeblock-bg oklch(0.97 0.003 85) -> oklch(0.925 0.017 84) #f6f5f3 -> #ece6da
- --codeblock-topbar-bg 0.94/0.003 -> 0.893/0.018
- 原来那个值是中性灰白(彩度 0.003),而页面底是暖纸 #f8f3e9,
在暖底上就是一块冷白补丁;现在比页面底更深且色相一致
- 正文对比度仍有 11.7:1,暗色模式未动
桌面导航
- 链接 text-sm -> text-sm lg:text-[15px]
- 间距 gap-8 -> gap-6 lg:gap-7
- 只在 lg 以上放大:768-1023 这段页眉本来就挤(导航 9 项 + 搜索框 + 主题按钮
加起来超过可用宽度),再放大只会更难看,这段维持原样不做回归
移动端菜单
- 从 left-3 right-3 横向铺满,改成 right-3 w-60(240px)+ max-w 兜底
- 展开原点 top center -> top right
- 竖向空间占用不变(max-h 仍在),横向不再占满一屏
验证(dist)
- 页脚 3 个 bg-card 容器 / 3 个红竖线标题,三个标题都在卡片内
- 构建出的 CSS: codeblock-bg:oklch(92.5% .017 84),暗色分支未变
- 页眉 class 确认为 text-sm lg:text-[15px] + gap-6 lg:gap-7
- 移动端面板 class 确认为 right-3 w-60 ...,transform-origin: top right
|
2026-09-15 12:04:50 +08:00 |
|
dsh
|
0719d8ba5d
|
书架首页改成「在读」,书籍挪到 /bookshelf/books/
原来 /bookshelf/ 是书籍页,点顶部导航「书架」直接进书籍,
和「先看在读」的预期相反。
- /bookshelf/ -> 在读页(view="reading")
- /bookshelf/books/ -> 书籍页(view="books")
- 顶部导航「书架」保持指向 /bookshelf/,现在落在在读页,不用改导航
- 侧栏「馆藏」:在读 -> /bookshelf/,书籍 -> /bookshelf/books/
- /bookshelf/reading/ 这个临时 URL 撤掉(还没上线,没有外链负担)
因为导航的 isCurrent 用的是 startsWith,在 /bookshelf/books/ 下
顶部「书架」仍然是高亮状态,符合预期。
验证
- /bookshelf/ : title「在读 20 本」、id=reading、20 张卡、20 条进度条、
无书籍区块;侧栏「在读」带 aria-current
- /bookshelf/books/ : title「书籍」、id=books、已读完分组 6 张、无进度条;
侧栏「书籍」带 aria-current
- 顶部导航「书架」href = /bookshelf/
|
2026-09-15 11:11:32 +08:00 |
|
dsh
|
a88bb536ab
|
书籍页:手工书单为空时隐藏统计行和搜索/筛选条
books.json 是空的,所以「书籍」页顶上挂着一排
「0 本已读 / 0 本推荐 / 0 个领域」加搜索框、领域和评价筛选 ——
没数据可显示也没东西可筛,纯占地方。
改成 hasManualBooks = allBooks.length > 0 控制:
- 为空时整块(统计行 + 搜索框 + 领域筛选 + 评价筛选)不渲染
- 往 books.json 加了书自动回来,不用改代码
- 顺带补一个兜底空态:手工书单和微信读书都已读完都为空时,
显示「书架还是空的」并提示两条填充路径
验证(双向都测了)
- books.json 为空时构建:本已读 / data-bookshelf-search /
data-filter-books-category / data-filter-books-status 在产物里均 0 次;
已读完分组和 6 张卡片不受影响
- 临时往 books.json 注入 1 本假书再构建:统计行、搜索框、领域筛选、
评价筛选、手工书卡全部出现(测完已 git checkout 还原)
- 在读页未受影响:20 张卡 / 20 条进度条
|
2026-09-15 11:05:39 +08:00 |
|
dsh
|
95e5111fd8
|
书架拆成「在读」和「书籍」两个独立页面
问题:两块内容挤在 /bookshelf/ 一页里,往下滚就从「在读」滑进「书籍」,
不像两个分类该有的样子。
拆法
- src/pages/bookshelf.astro -> src/pages/bookshelf/index.astro(书籍页)
- 新增 src/pages/bookshelf/reading.astro(在读页)
- 两页共用 bookshelf-content.astro,只多收一个 view: "reading" | "books",
决定渲染哪一块;外壳(页眉/侧栏/页脚/样式)完全同一份,样式不会跑偏
- 在读页标题带真实本数:「在读 20 本 | 时之刃的小站」
侧栏「馆藏」改成真导航
- 在读 -> /bookshelf/reading/,数量 = 未读完本数(20)
- 书籍 -> /bookshelf/,数量 = 手工书单 + 微信读书已读完(0 + 6 = 6)
原来这里只算 books.json 的 total,所以显示 0,正是截图里的问题
- 当前页用 aria-current="page" + 主色底高亮
页面互相不串
- /bookshelf/ : id=books、搜索框、已读完分组 6 张、无在读区块、0 条进度条
- /bookshelf/reading/: id=reading、在读卡片 20 张、20 条进度条、无书籍区块、
无搜索框、无已读完分组、0 张 data-weread-card
顺带更正 README 首段还写着的「读书/论文/漫画书架」。
|
2026-09-15 10:58:27 +08:00 |
|
dsh
|
8a867132de
|
已读完的书卡改成和「在读」同一套样式,补开始/读完时间
可行性(先说结论)
- 「开始阅读时间」在官方文档里没列,但 /book/getprogress 的原始回包里有
book.startReadingTime,6 本已读完的全都有
- 顺带纠正我上一轮的错误结论:真正常为 0 的是 recordReadingTime,
book.readingTime 是有值的(西线无战事 6190 秒 = 103 分),
已存进 JSON 的 readingSeconds,卡片暂未展示
抽公共组件
- 新增 src/components/reading-card.astro,在读和已读完共用,样式强制统一:
横版卡片、封面在左、信息在右
- 两处只在底部两行不同:
在读 进度条 + 百分比 / 最近阅读 X
已读完 开始 X / 读完 Y(无进度条)
数据层
- fetch-reading.mjs 每个条目新增 startedAt / finishedAt / readingSeconds
- src/lib/reading.ts 的 ReadingBook 类型同步补上(都可选,老数据不会炸)
- startReadingTime / finishTime 缺失时卡片自动少一行,不会渲染出「开始 —」
时间显示走 Asia/Shanghai。所以西线无战事的 startReadingTime
1786207913(UTC 08-08T15:31Z)在页面上是「开始 2026-08-09」,
这才是本地日期。
静态验证(dist/bookshelf/index.html)
- 在读区 20 张卡 / 20 条进度条 / 20 个「最近阅读」
- 已读完区 6 张卡 / 0 条进度条 / 6 个「开始 X」/ 6 个「读完 X」
- 抽一张:西线无战事(译文经典) 雷马克 · 文学-外国文学
开始 2026-08-09 读完 2026-09-06,确认不含进度条
- 搜索/领域筛选的 data-weread-card 仍挂在新卡片上,筛选不受影响
|
2026-09-15 10:51:50 +08:00 |
|
dsh
|
4df235ea21
|
已读完的书挪进「书籍」,抓取上限去掉(8 -> 整架 26 本)
抓取范围
- TOP_N 默认从 8 改成 0=不限制。原来那个 8 是我拍的「最近动过的前 8 本」,
不是接口限制;整架 26 本也就 1+26 个请求,完全够用
- --top N 仍可用,想只抓最近几本时加
分组调整
- 「最近在读」只留 progress < 100 的(20 本),进度条不再出现 100%
- 新增「书籍」区底部的「微信读书 · 已读完」分组(6 本),卡片结构与手工
书单一致,左上角带「已读完」徽标;因为微信读书的数据没有书评/简介,
这一组点击直接跳 weread.qq.com,不弹窗
- 这一组带 data-weread-card + data-category="微信读书",所以搜索框和
「领域」筛选同样作用得到;领域筛选里会多出一个「微信读书」选项
- 筛选逻辑把 [data-book-card] 的选择器扩成 [data-book-card],
[data-weread-card],分组计数也一并算上
实测数据分布(整架 26 本)
- 已读完 6 / 在读中 16(1%-97%)/ 没开始 4(0%)
静态验证(dist/bookshelf/index.html)
- 在读区 20 张卡片,进度条 30/0/77/28/13/97/0/5/16/3/10/1/4/13/4/0/1/10/6/0,
区内无「已读完」字样
- 已读完分组 6 张卡片,6 个徽标、6 个微信读书跳转链接,均带 data-weread-card
- 手工书单 3 张卡片未受影响;领域筛选新增「微信读书」按钮
|
2026-09-15 10:45:29 +08:00 |
|
dsh
|
95dd0d9552
|
书架页新增「最近在读」:构建时抓微信读书,顺带移除漫画/论文
数据链路
- scripts/fetch-reading.mjs:调腾讯官方 Agent Gateway
(POST https://i.weread.qq.com/api/agent/gateway,Bearer wrk-...),
/shelf/sync 拿书架,再对前 N 本调 /book/getprogress 拿进度,
写出 src/data/reading.json
- src/lib/reading.ts:读 JSON + 按 YYYY-MM-DD 格式化(官方硬性要求),
文件缺失返回 null 让页面走空态而不是构建报错
- src/components/bookshelf-content.astro:只渲染,页面本身不发请求
接口实测得到的几个结论(都写进脚本注释和 README 了)
- skill_version 必填,业务参数平铺顶层
- /shelf/sync 一次给全封面/书名/作者/分类/最近阅读时间/deepLink,
只有进度要额外请求,所以请求数 = 1 + N
- progress 是 0-100 整数,只有 100 算读完
- recordReadingTime 恒为 0,所以卡片不做「累计时长」
- deepLink 实测是普通 https,浏览器能直接打开
失败兜底(这次最关键的一条)
- pnpm reading:失败 exit 1,明确报错
- pnpm build:串的是 `fetch-reading.mjs --soft`,Key 失效/断网/接口挂了
都保留上一次的 reading.json 并 exit 0,不会阻塞部署
- 实测:错误 Key 时 pnpm reading exit 1;pnpm build 完整跑通 exit 0 且
reading.json 未被改动;不设 Key 也 exit 0
- process.loadEnvFile 不覆盖已存在的环境变量,所以 CI 设的 Key 优先于 .env
Key 安全
- 只写进 .env(gitignore,权限 600),已确认 git status 里没有它
- deploy.sh 是本地构建再 rsync,凭据不会上传服务器
- .env.example 补了占位和申请地址
书架页改版
- 移除漫画/论文两个分类:删掉 tab 切换、两个视图、对应筛选和 JS,
956 行 -> 620 行;sidebar 的 tab 按钮改成 #reading / #books 页内锚点
- 新增「最近在读」区块置顶(Collection · 01),书籍顺延为 02
- 卡片:封面(hot-link 腾讯 CDN,referrerpolicy=no-referrer)+ 书名 +
作者 · 分类 + 进度条 + 最近阅读日期,整卡跳 weread.qq.com
- 读完标「已读完」,0% 标「还没开始」
- 过滤私密阅读(secret=1)和从没打开过的书;有声书不处理
静态验证(dist/bookshelf/index.html)
- 8 张在读卡片,链接均指向 weread.qq.com/book-detail
- 8 条进度条宽度 30/0/77/100/28/13/97/0,与脚本输出一致
- 8 张封面全部 hot-link,无本地副本
- 漫画/论文/comics/papers/data-type-btn/switchType 均已从产物消失
- 其他页面(首页/时间线/关于/文章页)不含该区块,未受影响
|
2026-09-15 10:40:11 +08:00 |
|