マークダウン形式のファイルをPDFファイルに変換する(mermaid・emoji・toc対応)

アプリケーション

概要

マークダウン形式のファイルをPDFファイルに変換したいという要望に応えるための簡易的なドキュメント管理ツールを作った。

bmf-san/docs-md-to-pdf-example

特に深く考えることなくあり物のライブラリを活用して作ったので、あまりサステナビリティを感じない構成になっている。

モチベーション

単にマークダウン形式のファイルをPDFファイルに変換するだけであれば、md-to-pdfというライブラリを使うだけで良い。

このライブラリは、レジュメで管理でもお世話になっている。 cf. Githubでレジュメを管理するようにした

mermaid記法の対応やunicodeに登録されている絵文字以外の絵文字を使いたかったりという希望があったので、それに対応する形のものを作りたかった。

vscodeの拡張であるvscode-markdown-pdfを使えば簡単に解決することができるのだが、vscodeが必要になるので、人によってはvscodeのインストールが必要になってしまう。

変換のためだけにvscodeを使うというのはナンセンスだと思ったので実装してみた。

設計

md-to-pdfというライブラリは使いやすく素晴らしいライブラリなのだが、現状以下の機能が標準でサポートされていない。

  • mermaid記法
  • emoji(unicodeに登録されているもの以外)
  • TOCの生成

md-to-pdfmarkedjs/markedの設定拡張が可能であるため、どれもmd-to-pdfをカスタマイズすることで実現可能そうではある。

TOCについてはサポートされる予定があるらしい。 Generate TOC (table of contents) #74

md-to-pdfを使うでも良かったが、やや手間がかかりそうだったので、なるべくハッカソンのような感じで手短に実装したかったので、md-to-pdf-ngというライブラリを使うことにした。

これはmd-to-pdfを拡張してmermaid記法に対応させたライブラリで、あまりメンテナンスされていないようではあるが、一応問題なく使用できる。

md-to-pdf-ngをベースに、emoji対応はnode-emojifyを、TOC生成はdoctocというライブラリを使って実現する形とした。

実装

以下をnpmでインストール。

※おまけでtextlintを入れているがそのへんは割愛。

emoji対応はmarkedを拡張するような形で対応するので、次のような設定ファイルを用意。

const marked = require('marked');
const { emojify } = require('node-emoji');

const renderer = new marked.Renderer();

renderer.text = emojify;

module.exports = {
    marked_options: { renderer },
};

package.jsonのscriptsに次のようなコマンドを定義。

doctoc --notitle md/ && md-to-pdf md/*.md --config-file config.js && mv md/*.pdf pdf/

まずdoctocでTOCを生成、次にマークダウンをPDFに変換、最後にディレクトリを移動といった感じ。

md-to-pdfの生成したpdfのアウトプット先をディレクトリ単位で指定できると良いのだがそういうオプションはなさそうだったので、mv md/*.pdf pdf/という安直な方法で対応している。

所感

この手のものを作ろうとするとやはり結構外部のライブラリに依存しがちになってしまう。 できれば自分で全て実装したいがかなり大変そうに思う。 そのうち機会があればPDFのデータ構造を学んだり、Goで似たようなCLIツールを作ったりしてみたい。