HTML Best PracticesのREADME*.mdを生成する仕組み

Markdownを普通に書いて済ませていたHTML Best Practicesを、プラクティスごとにファイルに分割した。といっても一覧できないと読む気が起きないと思うので、簡単なスクリプトでREADME*.mdを生成している。主な目的は目次をちゃんと安定した形で作れるようにするためと、小さな文書群をがばっと生成する仕組みの実験のため。

data.jsonに、ローカライズ一覧(バリエーション)と目次(文書の構造)がくる。他には、ローカライズ不要な寄稿者や翻訳者のGitHub ID、ライセンスなどが含まれる。スクリプトが書きやすいように、この構造を決めた。

Node.jsで書くので、分割代入でオブジェクトをマージしていくと、Mustacheで扱うデータができあがるようにしたかった。オブジェクトの配列が含まれる場合、分割代入でうまく扱うのが難しくなるため、英語用データをデフォルトに(data.jsonに含めるように)はしなかった。

ファイル配置では、セクションごとにさらにディレクトリーを掘っても良さそうだったけど、そういうツリーの管理もdata.jsonだけで済ませれば楽かなと思ってやめた。なのでプラクティスIDのディレクトリーがズラッと並び、その配下にja.mdというようなファイル名で、ローカライズされたプラクティスが配置される。

テンプレートはMustacheだけど、生成するのはMarkdownなので、エスケープされないように{{{...}}}を駆使して書く。Mustacheセクションでインデントすると読みやすくなるけど、Markdown記法と競合しやすいので、インデントせず、ずらずらと書いていく。

スクリプトはPromise.allを濫用し、ローカライズごとに並行実行し、セクションごとに並行実行し、プラクティスごとに並行実行する。プラクティスは古の手法でタイトルと本文に分割し、うまいことしてデータとして格納するだけ。


GitHubの作る見出しIDは、それはそれは正しく機能するけど、目次は作ってくれない。今のNode.jsでは、正規表現でユニコード・プロパティー・エスケープが使えるので、完全な移植も可能だと思うし、実装もいくつか見つかる。けれど、ファイルを分けた場合、順序を管理する必要があるし、そのデータがあるなら、それを再利用した方が手っ取りばやいと思う。

目次は、自分で考えたIDにジャンプするよう、リスト記法で並べる。本文では、見出しの末尾に空のspan要素を追加し、それに考えたIDを振る(ここのIDはMarkdownレンダラーで処理されないので、Mustacheでエスケープされるように{{...}}で書く)。目次と本文で2回、同じセクションを回す。

{{#sections}}
- [{{{title}}}](#{{{id}}})
{{#practices}}
    - [{{{title}}}](#{{{id}}})
{{/practices}}
{{/sections}}


{{#sections}}
## {{{title}}}<span id="{{id}}"></span>

{{#practices}}
### {{{title}}}<span id="{{id}}"></span>

{{{body}}}
{{/practices}}
{{/sections}}

IDを振った要素で見出しを括ってしまってもいいけど、それだとMarkdownとして読みづらくなるので、空要素にした。HTMLにすることを前提とした、こういったMarkdownはよくないと思うものの、GitHubのためならエンヤコラという感じだ。同時に、GitHubの見出しIDに依存しない(共存できる)ので、どこでHTMLにされても多分機能するという利点もある。


MarkdownからMarkdownを生成していて、いったい何をやっているのか、ただつなげればいいんじゃないのかという感じだけど、ボチボチ遊んでいる。もうすぐスターが1500になりそうでうれしい。docsディレクトリーにHTMLファイルも生成して、GitHub Pagesとして公開されるようにもしたので、ディストラクション・フリーな形でも読める。

あわせて、普通のHTMLの書き方としてここで公開している長い方は、別のリポジトリーに分けた。こっちも似たような仕組みで生成するようになっていて、Markdownファイルも作るようになり、逆にGitHubでも一気に読めるようになった。