修复偶得里任务列表不渲染:给 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、智能标点)。
This commit is contained in:
dsh
2026-09-17 20:15:48 +08:00
parent a7ce870400
commit 6a74061689
6 changed files with 127 additions and 12 deletions
+26
View File
@@ -299,6 +299,32 @@ sudo sysctl fs.inotify.max_user_watches=524288
如果连空态提示都看不到,检查 `src/data/reading.json` 是否存在(这个文件要提交进 git)。
**同样的 Markdown,偶得和文章的渲染结果不一样**
因为**它们走的根本不是同一套渲染器**:
| | 渲染器 | 位置 |
|---|---|---|
| 文章 | Astro 内容管线 → **Sätteri**(`astro.config.mjs` 里开了 `gfm`)| `render(post)` |
| 偶得 | **markdown-it**,裸配置 | `src/lib/thoughts.ts` 里的 `new MarkdownIt()` |
裸的 markdown-it 不含 GFM 扩展,所以要什么能力就得自己挂插件。
目前只挂了任务列表(`src/plugins/markdown-it/task-lists.mjs`),
它输出的 HTML 刻意和 Sätteri 那边对齐(`contains-task-list` /
`task-list-item` / `<input type="checkbox" disabled>`),以后加样式两边通用。
**已知还缺的 GFM 能力**(偶得里写了不会生效,文章里正常):
- 裸链接自动转链接(markdown-it 需要 `linkify: true`,当前没开)
- 脚注
- 数学公式(`$…$`)—— 文章那边有 KaTeX,偶得没有
- Obsidian callout(`> [!tip]`)
- 智能标点(引号、破折号)
要在偶得里补哪一项,就先看它在文章那边是由哪个管线功能提供的,再决定是给
markdown-it 挂插件、还是把偶得也改用 Astro 内容管线(后者改动大:偶得页是
React island,内容要序列化成 HTML 字符串传给客户端)。
**改了 markdown 插件却不生效**
Astro 会把渲染好的文章缓存到 `node_modules/.astro`,而这个缓存**只按 markdown