删除线
GFM 删除线语法:规则细节、与 HTML 标签的语义分工、跨平台兼容与工程用法。
认知导入(Layer 1 进阶层) 前置知识:004 强调语法(粗体/斜体)。 边界说明:删除线
~~是 GFM 扩展而非 CommonMark 核心,本篇会讲清它在哪些平台可用、哪些平台会”原样吐出波浪号”。 强制练习:在任意 Markdown 编辑器输入~~作废~~观察渲染,再输入~作废~(单波浪号)对比结果。
1. 删除线是什么
删除线(strikethrough)在文字上画一条横线,语义是”这段内容曾经成立,但现在已失效或不再推荐”。它和直接删掉文字的区别在于:删除线保留了历史信息,读者能看到”这里原来写了什么”,同时立刻知道它已经不作数。
类比:删除线就像合同里的”划改”——把旧条款划掉但保留可辨认的原文,旁边写上新条款;直接删除则像把那一页撕掉,审阅者无从核对。
在 Markdown 生态里需要先建立一个认知:删除线不是 CommonMark 核心语法,而是 GFM 的扩展。这意味着在只实现 CommonMark 的渲染器里,~~文本~~ 会原样显示为两个波浪号加文本,不做任何转换。这一点决定了它的使用边界(详见第 5 节跨平台对照)。
1.1 基本语法
当前稳定版本为 v2.0.0,~~v1.9.0 已停止维护~~。
渲染结果(GFM 环境):当前稳定版本为 v2.0.0,v1.9.0 已停止维护。
解析器会把 ~~文本~~ 输出为 HTML 的 <del> 元素,这也是 GitHub 网页端源码里删除线对应的标签。不认识该扩展的渲染器则原样输出文本。
1.2 历史脉络
- 原始 Markdown(John Gruber,2004)没有删除线语法;各实现在此后十余年各自扩展,
~~逐渐成为事实标准。 - 2017 年 GitHub 发布 GFM 规范(基于 cmark-gfm),删除线被正式写入规范文本,规则从此稳定。
- 如今 GitHub、GitLab、Obsidian、Typora、VS Code 预览等主流工具普遍支持
~~;理解”它是扩展而非核心”,就能解释为什么同一段 Markdown 在不同平台渲染结果不同。
2. 语法规则与解析行为
本节是准确使用删除线的关键,逐条给出规则与正误对照。
2.1 必须成对且紧贴内容
| 写法 | 结果 | 原因 |
|---|---|---|
~~文本~~ | 渲染为删除线 | 正确写法 |
~文本~ | 通常原样显示(见 2.2) | 单波浪号在 GitHub 端不生效 |
~~文本 | 原样显示 | 只有开标记没有闭标记 |
~~ 文本 ~~ | 原样显示 | 定界符内侧有空格,无法闭合 |
与强调语法一样,定界符必须紧贴内容:开定界符后、闭定界符前不能是空白字符。~~ 内容 ~~ 在 GFM 渲染器中不会生成删除线,这是新手最常见的失误。
2.2 波浪号数量的细节
GFM 规范的定义是”由一对匹配的一个或两个波浪号包裹的文本”——即规范本身允许单波浪号 ~文本~(cmark-gfm 默认行为)。但要注意:GitHub 网页端实践中只有恰好两个波浪号 ~~ 会渲染,单个波浪号会原样显示;GitHub 官方语法文档也只收录 ~~。
结论:写作时一律使用 ~~,把”单波浪号也能删”当作个别渲染器的私有行为,不要依赖。
三个波浪号 ~~~ 则另有身份:出现在行首时它是围栏代码块的定界符,不是删除线。这也是讲解删除线语法本身时容易踩的坑(见 6.4 节)。
2.3 不跨段落
删除线是行内(inline)结构,块级结构优先于行内结构:
~~第一段
第二段~~
两段之间被空行隔开,解析器先切分出两个段落,波浪号无法跨越,最终全部原样显示。删除线只能作用于同一段落内的连续行内内容。
2.4 转义波浪号
波浪号是 ASCII 标点,可以被反斜杠转义。要原样展示两个波浪号,最稳妥的写法是把每个波浪号都转义:
\~\~不是删除线\~\~
渲染结果:~~不是删除线~~
只转义一侧(例如 \~~文本~~)的解析结果因实现而异,不要依赖;成对地转义所有波浪号是唯一可靠的做法。
3. 与其他行内元素组合
GFM 解析器用统一的定界符栈处理删除线与 *、_ 强调,因此它们可以自由嵌套,“先内层后外层”的直觉通常正确:
~~**删除且加粗**~~
~~*删除且斜体*~~
~~`删除的代码`~~
[~~被删除的链接文字~~](https://example.com)
逐个说明渲染结果(GFM 环境):
~~**删除且加粗**~~→<del><strong>删除且加粗</strong></del>,带横线的粗体。~~*删除且斜体*~~→ 带横线的斜体。~~`删除的代码`~~→ 行内代码先被反引号消费,删除线包裹整个代码跨度;GitHub 上代码内容同样显示横线。- 链接文字加删除线也合法,链接仍然可点击。
4. HTML 替代方案
Markdown 允许内嵌 HTML,因此 <del> 与 <s> 是删除线的”保底方案”,在纯 CommonMark 渲染器里也能生效。
| 标签 | HTML 标准 | 语义 | 推荐度 |
|---|---|---|---|
<del> | HTML5 | 修订中”被删除”的内容,可与 <ins> 配对 | 高 |
<s> | HTML5 | “不再准确/不再相关”的内容(如商品原价) | 中 |
<strike> | 已废弃 | 无语义,仅供旧文档兼容 | 低 |
<del>修订中被删除的内容</del>
<s>不再准确的内容</s>
<del> 支持两个可选属性,用于说明删除原因与时间:
<del datetime="2026-06-14" cite="https://example.com/reason">旧方案</del>
语义分工记忆法:<del> 面向”文档修订”(谁在什么时候把它删了),<s> 面向”内容时效”(它过时了但不是被编辑删除)。GFM 把 ~~ 渲染为 <del>,等于把 Markdown 删除线归入”修订”语义。
5. 跨平台支持对照
| 平台 / 渲染器 | ~~语法~~ | <del> / <s> | 说明 |
|---|---|---|---|
| GitHub | 支持 | 支持 | 规范内置扩展,单波浪号不生效 |
| GitLab | 支持 | 支持 | 兼容 GFM |
| Obsidian、Typora、VS Code 预览 | 支持 | 支持 | 主流编辑器均兼容 |
| Hugo(Goldmark 默认配置) | 支持 | 支持 | 默认启用 GFM 扩展集 |
| Jekyll(kramdown) | 支持 | 支持 | kramdown 内建删除线 |
| 纯 CommonMark 渲染器 | 不支持(原样输出) | 支持 | 如严格按规范实现的解析器 |
跨平台写作的最佳实践:面向 GitHub/GitLab 等平台的文档放心用 ~~;文档可能被任意渲染器消费(如作为库的分发包)时,关键位置改用 <del> 兜底,或约定目标渲染器。
6. 使用场景与工程实践
6.1 变更记录与废弃标记
发布说明中最典型的模式——废弃项一律附带替代方案:
### 2.0.0(2026-08-01)
- 废弃 `--old-flag` 参数,请使用 `--new-flag`
- ~~Node.js 16 支持~~,最低要求提升至 Node.js 18
工程文档的黄金法则:告诉读者”旧的不行”的同时,必须告诉”新的怎么用”。只划掉不给方案,读者仍然无法行动。
6.2 修订型笔记
保留旧结论、用删除线标记失效、补一行新事实,形成可读的时间线:
Python 3.9 的 dict 支持 `|` 合并运算符。
~~Python 3.9 是唯一支持该语法的版本。~~
Python 3.10 起 `match` 语句与 `|` 联合类型同时可用。
这种”旧结论不删除、只标失效”的写法,在需要审计、追溯的场景(决策记录、迁移指南、实验笔记)明显优于直接删改;但在追求干净成品的正式出版物里则显得杂乱,按读者对象取舍。
6.3 任务列表中标记取消
- [x] 完成登录模块
- [x] ~~完成支付模块~~(需求变更,已取消)
- [ ] 完成退款模块
删除线只作用于任务文本,复选框 [x] 本身不受影响。相比直接删除任务或关闭条目,这种写法保留了完整历史,后续检索时也能快速过滤。
6.4 讲解删除线语法本身
被 ```markdown 围栏包裹的内容会原样显示,这是讲解语法的第一选择。若内容本身包含三波浪号,注意行首的 ~~~ 会被解析为代码块围栏——把示例代码放进围栏代码块或改用四个空格缩进都可以避开。
6.5 决策记录(ADR)中的状态演变
# ADR-012:构建工具选型
状态:~~已接受~~ 已废弃(2026-07 更新,原因见 ADR-019)
状态字段用删除线表达决策生命周期,配合指向新决策的引用,既有历史又有去向。
7. 常见陷阱
- 内侧空格:
~~ 文本 ~~无法闭合,原样显示。始终写~~文本~~。 - 单波浪号:
~文本~在 GitHub 端不渲染;不要依赖个别渲染器的宽容行为。 - 与
~~~代码围栏冲突:行首三波浪号开启代码块;讲解语法或书写示例时注意区分。 - 滥用为语气强调:删除线表达”失效”。想弱化语气请改用括号补充说明,否则读者会误以为内容已废弃。
- 在标题中使用:
## ~~旧标题~~虽可解析,但目录与正文不一致、影响检索,应避免。 - 跨平台不一致:纯 CommonMark 渲染器会原样输出波浪号;对外分发前确认目标平台支持 GFM,或用
<del>兜底。 - 只标记不解释:重要的废弃项应同时给出替代内容或失效原因,纯删除线不传达”为什么”。
小结
- 初学者要点:删除线写法是
~~文本~~,必须成对、紧贴内容;它表达”已失效”,常用于变更记录、修订笔记与被取消的任务;GitHub、GitLab、主流编辑器均支持。 - 进阶注意:删除线是 GFM 扩展而非 CommonMark 核心,跨平台分发时改用
<del>/<s>兜底;GFM 把~~渲染为<del>(修订语义),<s>则表示”不再准确”;\~\~成对转义是显示字面波浪号的唯一可靠方式;单波浪号行为因渲染器而异,一律不要使用。