スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

markedでMarkdown→HTML変換時にIDを重複させない

markedは見出し文のテキストをそのままh1-5要素のid属性に変換するが、その際に既に作成した他のid属性値との重複確認を行わず、半角英数以外の文字が続いた場合は全て "-" に省略してしまう。よって見出しに同一文また半角英数以外の文字を使うと以下のようになってしまう。

# title
## hoge
## hoge
## ほげ
## ふが

<h1 id="title">titleh1>
<h2 id="hoge">hogeh2>
<h2 id="hoge">hogeh2>
<h2 id="-">ほげh2>
<h2 id="-">ふがh2>

id属性値が重複されては困るのでなんとかする。markedはsetOptionsメソッドに渡す設定オブジェクトからRendererの持つメソッドを上書きできるので、今回は見出し要素を出力しているRenderer#headingメソッドを書き換えて、id属性値が重複しそうな場合は適当に数字を振って回避することにした。
余談だが、最初はreadme.mdを読み飛ばしていて設定からRendererを上書きできることに気付かず、直接marked.Renderer.prototype.headingを書き換えて実装していた、いい迷惑である。説明書はよく読もう。

const marked = require('marked');
const renderer = new marked.Renderer();
const id_cache = {}

renderer.heading = function heading_new(text, level, raw){
let id = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w]+/g, '-');
if(id_cache[id]){
id_cache[id]++;
id += id_cache[id];
}else{
id_cache[id] = 1
}
return `<h${level} id="${id}">${text}</h${level}>\n`;
}

marked.setOptions({renderer});

<h1 id="title">titleh1>
<h2 id="hoge">hogeh2>
<h2 id="hoge2">hogeh2>
<h2 id="-">ほげh2>
<h2 id="-2">ふがh2>

単に属性値の末尾に数字を付与しただけのやっつけ仕様で見栄えは悪いが、まあ重複が避けられれば良しとしよう。おしまい。
関連記事

コメントの投稿

非公開コメント

すポンサードリンク
最新記事
カテゴリ
DN (57)
CSS (2)
いろいろ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。