#01 marked.js + highlight.js でMarkdownをきれいにHTMLに変換
概要
Markdownで書いたページをHTMLに変換する際に、
marked.js と highlight.js のライブラリの組み合わせが使いやすかったのでご紹介です。
- marked.js (Markdown→HTML変換用)
- highlight.js (コードを書いてる部分をきれいにする用)
準備
marked.js
Documentation: https://marked.js.org/
Github: https://github.com/markedjs/marked
NPMで適用することもできますが、今回はgithubから直接ダウンロードしました。
- marked.min.jsをダウンロード
- /assets/js ディレクトリに配置
- HTMLファイルに以下を追記
<script src="/assets/js/marked.min.js"></script>
highlight.js
配布ページ: https://highlightjs.org/
GitHub: https://github.com/highlightjs/highlight.js
こちらは、NPMで適用するか、ファイルをダウンロードするか、CDNで適用するかですが、
今回は表示したい言語が決まっていなかったのでCDNで適用しました。
どの言語のコードを表示したいかあらかじめ決まっていた場合は、
その言語用のファイルだけダウンロードしたほうが軽量化になると思います。
1.HTMLファイルに以下を追記
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
2.デモページで、表示テーマを選択
3.HTMLファイルに以下を追記
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/{テーマ名}.min.css">
今回は、Monokai Sublime を選択したのでテーマ名部分はmonokai-sublime
となります。
実装
ライブラリを適用したので、コードに組み込んでいきます。
var markdown_text = '~~~';
// Markdown→HTMLに変換
var html = marked.parse(markdown);
// HTML要素にセット
document.getElementById('markdown').innerHTML = html;
// コードハイライト
hljs.highlightAll();
あとは、出力されたHTMLを見て、好みに合わせてCSSスタイルを調整すれば完成です。
カスタマイズ
ここから先は必須ではありません。
コード部分にファイル名を表示する
コードを記載しているところに、ファイル名も一緒に表示したかったのですが、
marked.jsのデフォルトの設定だと表示してくれないようです。
↓これが問題のMarkdownです。
1. 言語名だけ
```javascript
console.log('Hello World');
```
2. 言語名+ファイル名
```javascript:hogehoge.js
console.log('Hello World');
```
3. ファイル名だけ
```hogehoge.js
console.log('Hello World');
```
↓上のMarkdownをHTMLに変換するとこうなります。
1はファイル名を指定していないので期待通りの動作です。
2はファイル名が表示されない。。。
3はそもそもハイライトされない。。。
そこで、以下のように修正します。
<script>
var highlight = function(code, lang, callback){
if (lang) {
return hljs.highlight(code, {language: lang, ignoreIllegals: true}).value;
} else {
return hljs.highlightAuto(code).value;
}
}
var renderer = new marked.Renderer();
renderer.code = function(code, fileInfo, escaped) {
if (!fileInfo) {
fileInfo = '';
}
var info = fileInfo.split(':');
langs = hljs.listLanguages();
// hljsの対応言語に含まれていなければファイル名とする
if (!langs.includes(info[0])) {
var fileName = info[0];
} else {
var lang = info[0];
var fileName = info[1];
}
var fileTag = '';
if (fileName) {
fileTag = '<span class="filename">'+fileName+'</span>'
}
if (this.options.highlight) {
var out = this.options.highlight(code, lang);
if (out != null && out !== code) {
escaped = true;
code = out;
}
}
if (!lang) {
return '<pre>'+fileTag+'<code>'
+ (escaped === false ? escape(code, true) : code)
+ '\n</code></pre>';
}
return '<pre>'+fileTag+'<code class="'
+ this.options.langPrefix
+ escape(lang, true)
+ '">'
+ (escaped === false ? escape(code, true) : code)
+ '\n</code></pre>\n';
};
marked.setOptions({
renderer: renderer,
highlight: highlight
});
</script>
コード部分のHTML→Markdown処理を上書きし、
ファイル名が<span class="filename">ファイル名</span>
で表示されるようにしました。
↓改めて、HTMLに変換してみます。
無事にファイル名が表示されるようになりました。
あとは、表示が不格好なので、CSSで整えれば完了です。
<style>
pre span.filename {
color: #000;
background-color: #eeede7;
padding: 2px 8px;
display: block;
overflow: hidden;
}
</style>
いい感じの表示になりました。
コード以外も、rendererに設定すればHTML変換処理をカスタマイズ可能です。
詳細はmarked.jsのDocumentationを参照してください。
以上です。ご清覧ありがとうございます。
Discussion