Markdown 待办列表与复选框写法

Markdown 写作约 4 分钟

Markdown 的待办列表就是一个普通列表项,开头写 [ ] 表示未完成,写 [x] 表示已完成,写法是 - [ ] 买牛奶。这个语法来自 GitHub 风格 Markdown(GFM),不在核心 CommonMark 里,所以不带 GFM 扩展的解析器会把方括号原样显示出来。文件里除了这几个字符以外不存任何状态,好处是容易搜索和比对差异,也说明所谓「点复选框」永远是编辑器在背后改写了一行文字。

基本写法

- [ ] 写初稿
- [x] 想好标题
- [ ] 补截图
  - [ ] 裁剪第二张
  - [x] 压缩第一张

GFM 规范里,待办项是第一个块为段落、且段落以标记开头的列表项,标记之后至少要有一个空白字符才能接正文。标记由左方括号、一个空白字符或者大小写的 x、右方括号组成,括号里是空白就是未勾选,否则就是已勾选。规范还特别写明它不定义复选框怎么交互,所以不同软件的点击行为并不一样。

出问题的多半是两处。右括号后面的空格不能省,- [ ]买牛奶 不是待办。另外括号里什么都没有的 [] 也不算标记,未完成要写且只写一个空格。

嵌套和普通列表一样,子项在连字符下缩进两个空格即可,规范自带的示例也是这样。子项全部勾完以后父项不会自动勾上,在文件里每个框彼此独立。

无序、有序和数字待办

列表符号可以是 -、* 或 +,规范对列表项的描述也适用于 1. [ ] 第一步 这样的有序项,妙言预览背后的 cmark-gfm 会把它画成带复选框的编号列表,适合步骤有先后的清单。

这是标准层面的说法,具体编辑器写回文件时可以更严格,所以连字符在这里有分量。妙言自己的点击逻辑(下面会讲)只认 - [ ] 和 - [x],想让点击稳定,就用连字符加小写 x。GFM 的其他补充可以看 Markdown 语法速查与 GFM 差异。

各处渲染差异

  • GitHub。 GitHub 的格式指南用的就是这套写法,在 issue 和评论里,官方文档说待办会渲染成可以点击的复选框。这个点击是 GitHub 的功能,不属于 Markdown 本身。
  • 不带 GFM 扩展的 CommonMark。 它就是一个普通的无序列表项,文字以 [ ] 开头,你看到的是方括号。
  • 其他编辑器。 渲染出来的框能不能点击不在规范里,各家自己决定,依赖点击之前先试一次。

妙言的预览用的是 Swift 版 cmark-gfm,开启了表格、脚注、删除线和待办四个扩展(V4.5.0 的 Business/Markdown.swift),所以待办列表在预览里是真正的 input 复选框。

在妙言里点击复选框发生了什么

V4.5.0 的预览页脚本(common.js)会启用所有复选框,并按文档顺序编号。点击时把编号发给应用,应用(MPreviewHandlers.swift 里的 HandlerCheckbox)遍历笔记正文,找到对应顺位的 - [ ] 或 - [x],换成另一种写法并保存笔记。

边界情况都由这个机制决定。应用是按位置匹配的,预览里第 N 个复选框,被当成源文本里第 N 个 - [ ] 或 - [x]。笔记里如果有正则不统计的写法,比如 * [ ]、+ [ ]、1. [ ] 或大写 X,预览照样画出框,编号就会错位,点一下可能改到另一行。如果 - [ ] 出现在不会被渲染成待办的地方,比如围栏代码块或引用块里,也会错位,因为文本匹配不认识代码围栏和引用。点击改错了行时,先查这两种原因。

编辑时可以用「格式」菜单里的「待办」(⌘T),当前行不是待办就插入 - [ ],已经是待办就在 - [ ] 和 - [x] 之间切换。它改写的是这一行开头的六个字符,用在缩进的子任务上会把标记弄坏,子任务在预览里点框更稳。输入 /task 再按 Tab 会插入三行模板,两条未完成、一条已完成,占位文字是中文,「Tab快捷输入」菜单里也列着这一项。

引用块里的待办

> - [ ] 问清截止时间
> - [x] 发出初稿

妙言 V4.5.0 用的 cmark-gfm 不会把这里画成复选框,引用块里是一个普通的无序列表,每项文字以 [ ] 和 [x] 开头,每行都带 >、列表前再加一行空的 > 也一样。别的渲染器可能处理得不同,笔记最终在哪里看,就在哪里试一下。在妙言里还有一层代价,点击切换照样会把引用块里的 - [ ] 算进去,于是笔记里排在它后面的复选框都会改错行。待办最好放在引用块外面,需要引用的背景写成列表上方的一段。

在多篇笔记里找未完成事项

待办是纯文本,所以搜索工具就能列出还剩什么。笔记文件夹里用 ripgrep 可以带着文件名和行号列出所有未完成项:

rg -n -F -- '- [ ]' ~/Notes

-F 把模式当固定字符串,方括号不会被当成正则字符类,-- 防止开头的连字符被当成选项。缩进的子任务同样能匹配,因为这个字符串可以出现在一行的任何位置,已完成的换成 '- [x]'。用 grep 的话是:

grep -rn --include='*.md' -F -- '- [ ]' ~/Notes

想按文件统计未完成数量就加 -c。这也是坚持一种写法的最大理由,如果有些笔记写的是 * [ ],一次搜索就会漏掉它们。更多在命令行里处理笔记的办法见 在终端里处理 Markdown 笔记。

局限与更合适的工具

待办列表只是清单,不是任务管理器,没有截止日期、提醒和重复,状态只有未完成和已完成两种。购物清单、发布检查表和笔记里的当日计划,用它刚好。需要截止日期和提醒时,换专门的工具,笔记留作参考。

常见问题

为什么我的复选框显示成 [ ] 文字?

渲染器没有 GFM 的待办扩展,或者写法有一点偏差。检查连字符后和右括号后是否有空格,以及括号之间是否正好一个字符。

不点击能直接在文件里勾选吗?

可以,把括号里的空格改成 x 就行,任何编辑器里的点击做的也只是这件事。

大写的 [X] 有效吗?

GFM 规范两种大小写都接受,妙言预览也会画成已勾选的框,但妙言的点击切换只匹配小写 x,所以小写更稳妥。

导出的 PDF 或 HTML 里待办还在吗?

导出是从预览生成的,所以重要的话可以检查一次导出文件。导出文件里的复选框只是笔记当时的快照,不能用来修改笔记。