remark-gfm
[![构建][build-badge]][build] [![覆盖率][coverage-badge]][coverage] ![下载量][downloads-badge]
remark 插件,用于支持 GFM(自动链接、脚注、删除线、表格、任务列表)。
目录
这是什么?
这个包是一个 unified (remark) 插件,用于启用 GitHub 通过 GFM 添加的 Markdown 扩展:自动链接(www.x.com
)、脚注([^1]
)、删除线(~~stuff~~
)、表格(| cell |…
)和任务列表(* [x]
)。你可以使用这个插件来添加对解析和序列化这些扩展的支持。这些由 GitHub 对 CommonMark 的扩展被称为 GFM(GitHub Flavored Markdown)。
这个插件不处理 Markdown 如何转换为 HTML。那是由 remark-rehype
完成的。如果你的内容不是英文且使用了脚注,你应该配置该插件。在生成 HTML 时,你可能还想启用 rehype-slug
来为标题添加 id
。
另一个插件 remark-frontmatter
添加了对前置元数据的支持。GitHub 支持仓库和 Gist 中文件的 YAML 前置元数据,但它们并不将其视为 GFM 的一部分。
另一个插件 remark-github
添加了对 Markdown 在特定 GitHub 仓库的评论、问题、PR 和发布中如何工作的支持,通过链接引用提交、问题和用户。
还有一个插件 remark-breaks
将软换行(回车)转换为硬换行(<br>
)。GitHub 在一些地方(评论、问题、PR 和发布)执行这种操作。
我应该在什么时候使用它?
当你想要支持 GitHub 在仓库文件、Gist 和其他几个地方所支持的相同功能时,这个项目很有用。用户经常认为其中一些扩展,特别是自动链接和表格,是普通 Markdown 的一部分,所以使用 remark-gfm
将有助于使你的实现与他们对 Markdown 的理解相匹配。在一些边缘情况下,GitHub 的实现以意想不到的方式工作,甚至与他们的规范描述不同,所以编写 GFM 并不总是最佳选择。
如果你只是想将 Markdown 转换为 HTML(可能带有一些扩展,如 GFM),我们推荐使用 micromark
和 micromark-extension-gfm
。如果你不使用插件并且想访问语法树,你可以使用 mdast-util-from-markdown
和 mdast-util-gfm
。
安装
这个包只支持 ESM。在 Node.js(16+ 版本)中,使用 npm 安装:
npm install remark-gfm
在 Deno 中使用 esm.sh
:
import remarkGfm from 'https://esm.sh/remark-gfm@4'
在浏览器中使用 esm.sh
:
<script type="module">
import remarkGfm from 'https://esm.sh/remark-gfm@4?bundle'
</script>
使用
假设我们的文档 example.md
包含:
# GFM
## 自动链接
www.example.com, https://example.com, 和 contact@example.com。
## 脚注
一个注释[^1]
[^1]: 大注释。
## 删除线
~一个~ 或 ~~两个~~ 波浪线。
## 表格
| a | b | c | d |
| - | :- | -: | :-: |
## 任务列表
* [ ] 待办
* [x] 已完成
...而我们的模块 example.js
包含:
import rehypeStringify from 'rehype-stringify'
import remarkGfm from 'remark-gfm'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {read} from 'to-vfile'
import {unified} from 'unified'
const file = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(await read('example.md'))
console.log(String(file))
...那么运行 node example.js
将产生:
<h1>GFM</h1>
<h2>自动链接</h2>
<p><a href="http://www.example.com">www.example.com</a>, <a href="https://example.com">https://example.com</a>, 和 <a href="mailto:contact@example.com">contact@example.com</a>。</p>
<h2>脚注</h2>
<p>一个注释<sup><a href="#user-content-fn-1" id="user-content-fnref-1" data-footnote-ref aria-describedby="footnote-label">1</a></sup></p>
<h2>删除线</h2>
<p><del>一个</del> 或 <del>两个</del> 波浪线。</p>
<h2>表格</h2>
<table>
<thead>
<tr>
<th>a</th>
<th align="left">b</th>
<th align="right">c</th>
<th align="center">d</th>
</tr>
</thead>
</table>
<h2>任务列表</h2>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" disabled> 待办</li>
<li class="task-list-item"><input type="checkbox" checked disabled> 已完成</li>
</ul>
<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">脚注</h2>
<ol>
<li id="user-content-fn-1">
<p>大注释。 <a href="#user-content-fnref-1" data-footnote-backref class="data-footnote-backref" aria-label="返回内容">↩</a></p>
</li>
</ol>
</section>
API
这个包不导出任何标识符。默认导出是 remarkGfm
。
unified().use(remarkGfm[, options])
添加对 GFM(自动链接、脚注、删除线、表格、任务列表)的支持。
参数
options
(Options
, 可选) — 配置
返回值
无 (undefined
)。
Options
配置(TypeScript 类型)。
字段
stringLength
(((value: string) => number)
, 默认值:d => d.length
) — 检测表格单元格的大小,用于对齐单元格singleTilde
(boolean
, 默认值:true
) — 是否支持单个波浪线的删除线; 单个波浪线在 github.com 上有效,但在技术上被 GFM 禁止; 你始终可以使用 2 个或更多波浪线进行删除线tablePipeAlign
(boolean
, 默认值:true
) — 是否对齐表格管道符tableCellPadding
(boolean
, 默认值:true
) — 是否在表格管道符和单元格之间添加一个空格作为填充
示例
示例:singleTilde
要关闭对单波浪线解析删除线的支持,传入 singleTilde: false
:
// …
const file = await unified()
.use(remarkParse)
.use(remarkGfm, {singleTilde: false})
.use(remarkRehype)
.use(rehypeStringify)
.process('~one~ and ~~two~~')
console.log(String(file))
生成结果:
<p>~one~ and <del>two</del></p>
示例:stringLength
可以根据单元格的视觉宽度对表格进行对齐。 首先,让我们展示问题所在:
import {remark} from 'remark'
import remarkGfm from 'remark-gfm'
const input = `| Alpha | Bravo |
| - | - |
| 中文 | Charlie |
| 👩❤️👩 | Delta |`
const file = await remark().use(remarkGfm).process(input)
console.log(String(file))
上面的代码展示了如何使用 remark 来格式化 markdown。 输出结果如下:
| Alpha | Bravo |
| -------- | ------- |
| 中文 | Charlie |
| 👩❤️👩 | Delta |
为了改善这些全角字符和表情符号的对齐,传入一个计算单元格视觉宽度的 stringLength
函数。
一种这样的算法是 string-width
。
它可以这样使用:
@@ -1,5 +1,6 @@
import {remark} from 'remark'
import remarkGfm from 'remark-gfm'
+import stringWidth from 'string-width'
@@ -10,7 +11,7 @@ async function main() {
| 👩❤️👩 | Delta |`
-const file = await remark().use(remarkGfm).process(input)
+const file = await remark()
+ .use(remarkGfm, {stringLength: stringWidth})
+ .process(input)
console.log(String(file))
进行这些更改后,我们代码的输出如下:
| Alpha | Bravo |
| ----- | ------- |
| 中文 | Charlie |
| 👩❤️👩 | Delta |
错误
关于 GFM 中存在但这里不存在的错误,或其他支持的特殊情况,请参阅每个相应的自述文件:
编写
关于如何编写 GFM 的建议,请参阅每个相应的自述文件:
HTML
此插件不处理 markdown 如何转换为 HTML。
关于如何实现以及如何更改,请参阅 remark-rehype
。
CSS
关于 GitHub 如何对这些功能进行样式设置的信息,请参阅每个相应的自述文件:
语法
关于这些功能的语法信息,请参阅每个相应的自述文件:
语法树
关于这些功能的语法树信息,请参阅每个相应的自述文件:
类型
此包使用 TypeScript 进行完全类型化。
它导出了额外的类型 Options
。
默认情况下,@types/mdast
支持节点类型。
兼容性
unified 集体维护的项目与维护版本的 Node.js 兼容。
当我们发布新的主要版本时,我们会放弃对不再维护的 Node.js 版本的支持。
这意味着我们尽量保持当前发布线 remark-gfm@^4
与 Node.js 16 兼容。
此插件适用于 remark-parse
11+ 版本(remark
15+ 版本)。
之前的版本(v3)适用于 remark-parse
10 版本(remark
14 版本)。
在此之前,v2 适用于 remark-parse
9 版本(remark
13 版本)。
remark-parse
和 remark
的早期版本有一个默认为 true 的 gfm
选项,启用了此功能。
安全
使用 remark-frontmatter
不涉及 rehype(hast)或用户内容,因此不存在 跨站脚本攻击(XSS) 的漏洞。
相关
remark-github
— 链接引用提交、问题、PR 和用户remark-breaks
— 支持不需要空格或转义的换行(回车转换为<br>
)remark-frontmatter
— 支持前置元数据(YAML、TOML 等)remark-directive
— 支持指令remark-math
— 支持数学公式remark-mdx
— 支持 MDX(ESM、JSX、表达式)
贡献
查看 remarkjs/.github
中的 contributing.md
以了解参与方式。
查看 support.md
以获取帮助的方法。
本项目有一个 行为准则。 通过与此仓库、组织或社区进行交互,您同意遵守其条款。
许可证
MIT © Titus Wormer [downloads-badge]: https://img.shields.io/npm/dm/remark-gfm.svg