prettierで整形できて、minifyして書き出せる、MTML

  • 投稿日:
  • by
  • カテゴリ:

こんにちは、天野と申します。Movable Typeの開発に参加しています。

今日はMTML(Movable Type Markup Language)の話です。

MTMLを気持ちよく編集したい

公開される記事の典型的なMTMLは以下のようなものになります。

HTMLの属性の中にMTタグが入っていますが、「カスタム要素の入ったHTML」と思ってみれば特別見にくいものでもないと思います。VSCodeにMTMLの拡張を入れれば、属性の中にも色がついて見やすくなります。

ただMTMLはやはり独自のマークアップ言語で一般的なツールではパースできないので「自動整形ができない」「対応するタグで閉じられているか編集時に検証できない」という問題があります。上のGistの内容だと「</titl>」となっていてHTMLが壊れていますし、「encde_html」となっている箇所もあります。また「<mt:EntryTitle>」というのは「encode_html」を付け忘れていると思われます。

とういところで、「JSXで書ければ整形も検証も一般的なツールでできるのになぁ」というのを思ったのです。

MTMLとJSXの関係については以前もmt-data-api-react としてPoC的なことをやったことがあります。これは「既存のMTMLをそのままで、DataAPIから取得したデータでフロントエンドでレンダリングする」というテーマでした。今回はそれとは異なり「JSXを書いて、それをMTが処理できるMTMLに変換する」というものです。

JSXに馴染みのない方はここまで読んでnot for meだなと感じるかもしれませんが、この話はそうでもないのでもう少し読み進めてください。以下は前出のMTMLを書き換えたものですが、ほぼほぼXMLとして違和感はないだろうと思います。(ないということで話を進めます。)またこれはJSXとしてもValidであり、これを処理することができます。

Reactを書いている方は「JSXとしてもValid」というところで「Validかもしれないけど(TSXでは)型のエラーが出るよね」という話になってくると思いますが、JSXをReactでないJSXの処理系で型を付ければこれもいけます。

説明が長くなってきたので結果を見てみると、今回作ったmt-jsx-templateというコマンドで処理すると以下のような結果になります。

JSXで整形やバリデーションができる上に、つまるところJSXからMTMLへのトランスパイルになるので、その過程でMTMLをminifyして書き出すことができるのです。

実装部分は、honoというOSSのプロジェクトでJSXの処理系を実装したことがあったので、そこから一部をコピーしつつひとまず形にしました。

ちなみにTypeScriptで型も付けられるので、「encoee_html」もちゃんとエラーにできます。またトランスパイルのついでに「<$mt:EntryTitle$>」に自動で(デフォルトで)encode_htmlをつけることもできます。これは、結構いいんじゃないでしょうか。

JSXになればできること

JSXになると、自分でパースの努力をしなくてよくなるので「使われているCSSのクラス名を収集する」ということもやりやすくなります。(今までのテンプレートでも正規表現で収集すれば実用上十分な精度でできたと思いますが。)「JSXで書いてトランスパイルする」という処理が作業フローに組み込まれるのであれば、そのついでに「CSSのフレームワークから必要なCSSを抽出して最小限のCSSを作成する」というのもやろうかという話になってくると思います。

以下が、MasterCSSを使ったサイトのJSXテンプレートからクラス名を抽出して、使われているCSSのみを出力するイメージです。

このMTMLのclassを解析して、MasterCSSを使って以下のCSSを出力することができます。

フロントエンドに関しては、2023年においてはウェブサイトを運用する際には何らかのビルド作業が入っていることが多いと思いますが、MTMLや(MTMLの内容を踏まえた上での)CSSもビルドするようになってもいいのかもしれません。MTのプラグイン(主にPerl)でビルドできればよいようにも思いますが、プラグインだとサーバー上で動作させることになり制限があることも多いので、作業環境の方が自由に環境を作れるというのもあり、これはこれでよいアプローチだと思います。

「ここまでやるならJamstackで生成した方が素直じゃないか?」という指摘があっても否めない気もします。とはいえまあ、上と同じ理由で運用環境は自由にならないこともあるのでMTを使ううえではMTMLの開発効率が上がるのはよいことだと思います。

プレビューもしたい

「JSXでパースできる」ということは、mt:Entriesやmt:EntryTtileのモックを作ってあげれば、JSXを直接文字列化してテンプレートの出力結果も確認できそうです。これになってくると上で出たmt-data-api-reactとも近い話になってくるのですが。これをやるには時間が足りなかったのでやっていませんが、後はモックを頑張って作りさえすれば、プレビューできるというところまで来ていると思います。

今回作成したもの

mt-jsx-templateです。

$ npx mt-jsx-template ファイル名

だけですぐに動かせます。また標準入力からも読み込めますので、動くことだけ確認したい場合には以下のコマンドを実行すれば変換された結果を見ることができます。

$ curl https://gist.githubusercontent.com/usualoma/e3d68e800bd264e9cdb0f2b7b1b19a64/raw/7c0b05a92e95f01f4e317d8c7ab46cb118296b66/entry.mtml.tsx | npx mt-jsx-template

TSXを書いて実際に型の付くことを確認したい場合には以下のようにプロジェクトにインストールして、tsconfig.jsonを設定してもらえば好きなエディタで動作させることができます。

$ npm install --save-dev mt-jsx-template

属性値の型も定義されているので、補完が効いたり、マニュアルを参照できたりします。

これは、結構いいんじゃないでしょうか!

この記事について

この記事は Movable Type Advent Calendar 2023 の25日目の記事です。皆様お疲れさまでした。それでは良いお年を!