如何为v-md-editor渲染的a标签添加rel属性?

博客 Markdown 里外链默认只有 href,没有 rel="nofollow noopener"。一方面 SEO 上希望外链不传递权重,另一方面 target="_blank" 时加 noopener 能减轻 window.opener 风险。v-md-editor 底层是 markdown-it,渲染链路和 XSS 过滤各管一段,只改插件不够,白名单也要动。

当时环境:Vue 2 + @kangc/v-md-editor(v-md-editor),主题用的 GitHub 预览样式。

yarn add markdown-it-external-links --dev

npm 同理:npm i markdown-it-external-links -D。插件会在生成 token 时区分站内/站外链接,给 <a> 加上 class 和 rel

拓展markdown-it

拓展是为了改变markdown-it的tokens,进而改变渲染后的文本

在创建编辑器时通过 extend(md) 挂插件(具体挂在 VueMarkdownEditor 还是 VMdPreview,跟你是编辑态还是纯预览有关,以项目里初始化代码为准):

import externalLinks from 'markdown-it-external-links';

extend(md) {
  md.use(externalLinks, {
    externalClassName: 'custom-external-link',
    internalClassName: 'custom-internal-link',
    internalDomains: ['blog.thinkmoon.cn'],
    externalRel: 'nofollow noopener noreferrer',
  });
},
  • internalDomains:列成站内的域名,这些链走 internalClassName,不加 nofollow。
  • externalRel:站外链接的 rel 字符串,可按需删减,例如只要 nofollow noopener

改完后若查看页面源码仍没有 rel,多半是下一步 XSS 把属性剥了。

修改xss白名单

如果不修改白名单,会出现增加的属性,无法体现在最终渲染的html上。

v-md-editor 预览默认走 xss 过滤,<a> 标签允许的属性列表里若没有 rel,渲染结果里就看不到。

VMdPreview.xss.extend({
  // 扩展白名单
  whiteList: {
    a: ['target', 'href', 'title', 'rel'],
  },
});

若你还给 a 加了 class(插件会加),白名单里也要写上 class,否则 class 同样会被滤掉。改完刷新预览,站外链接应类似:

<a href="https://example.com" rel="nofollow noopener noreferrer" class="custom-external-link" target="_blank">...</a>

踩坑小结

  1. md.use 不 extend 白名单 → 源码有 token 但 DOM 没 rel
  2. internalDomains 漏写 www 或非 apex 域名 → 站内链被当成外链加了 nofollow。
  3. 编辑器和预览若各有一套 extend,两边要一致,否则编辑预览和发布页表现不同。

参考文档

扩展-markdown-it

markdown-it-external-links

版权声明: 本文首发于 指尖魔法屋-如何为v-md-editor渲染的a标签添加rel属性?https://blog.thinkmoon.cn/post/955-guide-md-editor-rel/) 转载或引用必须申明原指尖魔法屋来源及源地址!