0
1

#01 marked.js + highlight.js でMarkdownをきれいにHTMLに変換

Posted at

概要

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から直接ダウンロードしました。

  1. marked.min.jsをダウンロード
  2. /assets/js ディレクトリに配置
  3. 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に変換するとこうなります。
image.png

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に変換してみます。
image.png

無事にファイル名が表示されるようになりました。
あとは、表示が不格好なので、CSSで整えれば完了です。

<style>
pre span.filename {
    color: #000;
    background-color: #eeede7;
    padding: 2px 8px;
    display: block;
    overflow: hidden;
}
</style>

image.png

いい感じの表示になりました。


コード以外も、rendererに設定すればHTML変換処理をカスタマイズ可能です。
詳細はmarked.jsのDocumentationを参照してください。


以上です。ご清覧ありがとうございます。

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1