markdown-itでリンクを開く際にtarget="_blank" rel="noopener"を自動付与する
js製Markdown parserのmarkdown-itを利用する際にaタグをカスタマイズしたかったので対応方法をメモしておく。
公式ドキュメントを参考にrenderer.rulesを書き換える。
import MarkdownIt from "markdown-it";
class Markdown {
constructor() {
this.md = new MarkdownIt();
// https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
const defaultRender =
this.md.renderer.rules.link_open ||
function(tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
this.md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
const targetIndex = tokens[idx].attrIndex("target");
if (targetIndex < 0) {
tokens[idx].attrPush(["target", "_blank"]);
} else {
tokens[idx].attrs[targetIndex][1] = "_blank";
}
const relIndex = tokens[idx].attrIndex("rel");
if (relIndex < 0) {
tokens[idx].attrPush(["rel", "noopener"]);
} else {
tokens[idx].attrs[relIndex][1] = "noopener";
}
return defaultRender(tokens, idx, options, env, self);
};
}
render(text) {
return this.md.render(text);
}
}
const md = new Markdown();
export default md
renderer.rules.link_openのルールを書き換え、リンクを開く際はtarget="_blank" rel="noopener"を自動付与するようにした。
rel="noopener"をつけないとリンク先のページで親のwindowの操作ができてしまうためセキュリティ上の脆弱性がある。
一般的に、外部リンクを新しいウィンドウまたはタブで開く場合は、必ず rel="noopener" を追加してください。
Google Developersにもtarget="_blank" を使う際はrel="noopener"も必須と書かれている。