@mdit/plugin-anchor
为标题添加 id 属性,可附带永久链接的插件。
使用
import MarkdownIt from "markdown-it";
import { anchor } from "@mdit/plugin-anchor";
const mdIt = new MarkdownIt().use(anchor);
mdIt.render("# 标题");使用自定义 slugify:
import MarkdownIt from "markdown-it";
import { anchor } from "@mdit/plugin-anchor";
const mdIt = new MarkdownIt().use(anchor, {
slugify: (s) =>
s
.trim()
.toLowerCase()
.replace(/[^\w\u4e00-\u9fff-]+/g, "-")
.replace(/-+/g, "-"),
});
mdIt.render("# 你好 世界");语法
所有匹配 level 选项的标题将自动添加 id 和 tabindex 属性。
示例
选项
level
- 类型:
number | number[] - 默认值:
1 - 详情:要添加锚点的标题级别。数字表示「该级别及更深的级别(例如
2表示 h2–h6)」,数组表示「精确匹配的级别」。
slugify
- 类型:
(str: string) => string - 详情:自定义 slug 化函数,将标题文本转换为 URL 友好的 slug。
默认会转小写 ASCII 字母、保留非 ASCII 字符(如中文)、将空白与连字符折叠为单个连字符,并剥离其余 ASCII 标点。如果你想要严格百分号编码的 slug,可使用导出的 legacySlugify:
import MarkdownIt from "markdown-it";
import { anchor, legacySlugify } from "@mdit/plugin-anchor";
const mdIt = new MarkdownIt().use(anchor, { slugify: legacySlugify });slugifyWithState
- 类型:
(str: string, state: StateCore) => string - 详情:类似
slugify,但可访问 markdown-it 状态,例如使用state.env。
getTokensText
- 类型:
(tokens: Token[]) => string - 详情:自定义从标题 token 中提取文本内容的函数。默认包含
text和code_inlinetoken。
uniqueSlugStartIndex
- 类型:
number - 默认值:
1 - 详情:重复 slug 编号的起始索引。设为
2可得到title、title-2、title-3。
defaultPlaceHolder
- 类型:
string - 默认值:
"heading" - 详情:当标题没有文本内容、生成的 slug 为空时(如纯图片标题)使用的占位 slug。
permalink
- 类型:
PermalinkGenerator - 详情:渲染永久链接的函数。见下方永久链接。使用提供的预设之一或自行编写。
callback
- 类型:
(token: Token, info: AnchorInfo) => void - 详情:在渲染每个标题后调用,传入
token和包含slug、title的info对象。
tabIndex
- 类型:
string | number | false - 默认值:
"-1" - 详情:标题上
tabindex属性的值。默认-1使标题可被聚焦但不可通过键盘导航到达——屏幕阅读器会在跳转时朗读标题内容。设为false可移除该属性。
你可以通过 @mdit/plugin-attrs 手动设置标题 ID。确保 attrs 在 anchor 之前加载:
import MarkdownIt from "markdown-it";
import { attrs } from "@mdit/plugin-attrs";
import { anchor } from "@mdit/plugin-anchor";
const mdIt = new MarkdownIt().use(attrs, { allowed: ["id"] }).use(anchor);
mdIt.render("# 我的标题 {#custom-id}");Anchor 插件会复用已有的 id。
永久链接
插件提供了四种永久链接预设。根据无障碍需求选择合适的方案。
所有渲染器共享以下通用选项:
| 名称 | 描述 | 默认值 |
|---|---|---|
class | 永久链接锚点的 CSS 类。 | header-anchor |
symbol | 永久链接锚点中的符号。 | # |
renderHref | 自定义永久链接 href 渲染函数。 | (slug) => \#$`` |
renderAttrs | 自定义永久链接属性渲染函数。 | () => ({}) |
headerLink
将整个标题内容包裹在永久链接锚点中。
简单且开箱即用的无障碍方案。若标题内已包含链接(markdown 链接,或在 html 开启时的原始 <a> 标签),则不会包裹,以避免产生非法的嵌套锚点。
import { headerLink } from "@mdit/plugin-anchor";输出: <h2 id="title" tabindex="-1"><a class="header-anchor" href="#title">标题</a></h2>
| 名称 | 描述 | 默认值 |
|---|---|---|
safariReaderFix | 在链接内添加 <span> 使 Safari 阅读器视图正确显示标题。 | false |
| 见通用选项。 |
linkInsideHeader
在标题内部插入永久链接锚点,位于文本之后或之前。
import { linkInsideHeader } from "@mdit/plugin-anchor";输出: <h2 id="title" tabindex="-1">标题 <a class="header-anchor" href="#title">#</a></h2>
| 名称 | 描述 | 默认值 |
|---|---|---|
space | 在标题文本和永久链接之间添加空格。可传入字符串自定义(如 )。 | true |
placement | 永久链接的位置,before 或 after。 | after |
ariaHidden | 是否添加 aria-hidden="true" 到永久链接。 | false |
| 见通用选项。 |
如果使用 # 这样的符号,屏幕阅读器会将其作为每个标题的一部分朗读。 建议使用 ariaHidden() 或传入可访问的 HTML 作为 symbol。
ariaHidden
linkInsideHeader 的别名,默认 ariaHidden: true。
import { ariaHidden } from "@mdit/plugin-anchor";输出: <h2 id="title" tabindex="-1">标题 <a class="header-anchor" href="#title" aria-hidden="true">#</a></h2>
linkAfterHeader
在标题块之后放置永久链接锚点。提供最灵活的屏幕阅读器无障碍体验。
与其他预设不同,linkAfterHeader 没有默认选项 —— 使用默认的 visually-hidden 样式时至少需要传入 assistiveText 和 visuallyHiddenClass:
import MarkdownIt from "markdown-it";
import { anchor, linkAfterHeader } from "@mdit/plugin-anchor";
const mdIt = new MarkdownIt().use(anchor, {
permalink: linkAfterHeader({
assistiveText: (title) => `永久链接:${title}`,
visuallyHiddenClass: "sr-only",
}),
});输出: <h2 id="title" tabindex="-1">标题</h2><a class="header-anchor" href="#title"><span class="sr-only">永久链接:标题</span> <span aria-hidden="true">#</span></a>
| 名称 | 描述 | 默认值 |
|---|---|---|
style | 样式:visually-hidden、aria-label、aria-describedby 或 aria-labelledby。 | visually-hidden |
assistiveText | 接收标题返回辅助文本的函数。visually-hidden 和 aria-label 样式必须提供。 | undefined |
visuallyHiddenClass | 使元素视觉隐藏的 CSS 类。visually-hidden 样式必须提供。 | undefined |
space | 在辅助文本和永久链接符号之间添加空格。 | true |
placement | 永久链接符号相对于辅助文本的位置(before / after)。 | after |
wrapper | 可选的 [开始标签, 结束标签] HTML 包装器,包裹标题与永久链接。 | null |
| 见通用选项。 |
自定义永久链接
如果预设不满足需求,可以提供自己的渲染器:
function customPermalink(slug, opts, state, idx) {
// 修改 state.tokens 中 idx 周围的 token 来构建永久链接
}
mdIt.use(anchor, { permalink: customPermalink });其中 state 是 markdown-it 的 StateCore 实例,idx 是 heading_open token 的索引。heading_open 之后紧跟着一个包含标题文本的 inline token,最后是 heading_close。