Qiita::Markdownを使ってMarkdown APIサーバを書いた
Markdownには様々な方言があり、記法の解釈にも微妙に差があったりする。 一つの言語で開発しているのであれば、同じライブラリを使えば問題にならないが、それぞれ別の言語で書いた複数のアプリケーションで全く同じレンダリング結果を得るのは難しい。 一番ベーシックな記法だけに絞れば差分を減らすことは可能だが、 Fenced code block や Table 記法はあるとないとでは大分使い勝手が変わるので出来れば使いたい。
と、実際に困ることがあったので、どの言語で開発しても統一した記法が使えるよう、Markdownをレンダリングするサーバを書いた。
https://github.com/nkwhr/qiita-markdown-server
デモ: https://qiita-markdown.herokuapp.com/
書いたと言ってもPOSTされた内容をQiita::Markdown
に投げて結果を返しているだけなので大したことはしていない。
むしろQiita::Markdown
がすごい。デフォルトでサニタイズもシンタックスハイライトもしてくれるし絵文字まで使える。
APIの仕様は基本的にGitHubのMarkdown APIに合わせているので、GitHubのMarkdown APIを使ったことがある人は違和感なく使うことが出来ると思う。
READMEに書いてある通り、提供しているAPIは/markdown
と/markdown/raw
だけ。
使い方
/markdown
はtext
フィールドにMarkdownテキストを入れたJSONをPOSTすれば変換された結果がtext/html
で戻ってくる。
$ curl -X POST -H 'Content-Type: application/json' -d ' { "text": "Hello my twitter ID is @_nao8 :smile:", "options": { "asset_root": "http://localhost:8080/images", "base_url": "https://twitter.com" } }' http://localhost:8080/markdown
< HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 262 < Access-Control-Allow-Origin: * <p>Hello my twitter ID is <a href="https://twitter.com/_nao8" class="user-mention" title="_nao8">@_nao8</a> <img class="emoji" title=":smile:" alt=":smile:" src="http://localhost:8080/images/emoji/unicode/1f604.png" height="20" width="20" align="absmiddle"></p>
(GitHubのMarkdown APIはなぜか/markdown/raw
の方しかContent-Typeをチェックしていなかったが、片方だけ何でもいいというのは気持ちが悪かったので、/markdown
の方もチェックするようにしている。)
オプション( qiita-markdownのcontext )は起動時に config/qiita-markdown.yml で指定するか、上の例のようにリクエスト毎に指定することができる。(ただし/markdown
のみ) この辺もQiita::Markdown
が.new
と#call
の両方で受け取ってくれる仕様だったので簡単に実装できた。ありがたい。
/markdown/raw
の方はもっとシンプルで、変換したいテキストをtext/plain
またはtext/x-markdown
でPOSTするだけ。
$ curl -X POST -H 'Content-Type: text/plain' -d ' # Task List - [x] task1 - [ ] task2 ' http://localhost:8080/markdown/raw
< HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 342 < Access-Control-Allow-Origin: * <h1> <span id="task-list" class="fragment"></span><a href="#task-list"><i class="fa fa-link"></i></a>Task List</h1> <ul> <li class="task-list-item"> <input type="checkbox" class="task-list-item-checkbox" checked disabled>task1</li> <li class="task-list-item"> <input type="checkbox" class="task-list-item-checkbox" disabled>task2</li> </ul>
Dockerで動かす
コンテナ一つ手元に転がしておけば開発が捗るかなと思い、Docker化した。
実行例
$ docker run \ --rm \ --env WEB_CONCURRENCY=$(nproc) \ --env ASSET_ROOT=http://example.com/images \ -p 8080:8080 \ nkwhr/qiita-markdown-server
highlight.jsなどシンタックスハイライトに対応したJS/CSSや、絵文字の画像データを一緒にパッケージできれば、コンテナを一台動かして、そこを参照するようにアプリケーションを書くことができて楽なのだが、調べた限りコンテナイメージ内に絵文字の画像データ含めるのは、ライセンス的にアウトなようなので諦めた。
Herokuで動かす
前々からHeroku Buttonを使ってみたかったというのもあり、2クリックでHerokuへデプロイ出来るようにした。
buildpack周りは以下のエントリを参考にさせて頂いた。
qiita-markdownを含んだGemfileをHerokuにpushするには
多分何も見ずにデプロイしていたらハマっていたと思う。ありがとうございます。