PostHTMLのプラグインつくったぞーって話
どうも。
いろんなことに夢見て、そのたびに期待をアレされて悲しくなってるめろたんです。
最近はクリエイターズマーケットっていうイベントで購入したテラリウムを見て心を癒やしています。
そういえば、クリマでこれ買ったわ。 pic.twitter.com/RSv6XXTN0n
— わかり亭めろたん。 (@renyamizuno_) 2017年6月17日
はい。
今回はPostHTML
のプラグインつくったぞーって話を書こうと思います。
PostHTML
って?
と本題に入る前にPostHTML
ってなんぞって話なんですが、
PostHTML
とは、JS
でHTML/XML
を変換するツールで、HTML
をパースして、ノードツリーを操作するAPIを提供しています。
PostCSS
*1のHTML
版ですね。
これ単体だと、特になにも起きません。
で、色々公開されている、プラグインを使うことで、HTML
を良い感じに変換したりできます。
そのままのっけるけど、
import posthtml from 'posthtml' const html = ` <component> <title>Super Title</title> <text>Awesome Text</text> </component> ` const result = posthtml() .use(require('posthtml-custom-elements')()) .process(html, { sync: true }) .html console.log(result)
みたいにすると、
<div class="component"> <div class="title">Super Title</div> <div class="text">Awesome Text</div> </div>
と変換されてHTML
が返ってくるっていうやつです。
(このposthtml-custom-elements
っていうプラグイン筋悪くね…ってちょっとおもったゾ…)
静的なページを作るんだけど、複数ページつくらないといけなくて、header
とかは共通につくっておきたいなー
みたいなのにすごく便利では?って思ったり崎哲夫してました。
今回作ったの
で、今回作ったのはこちらですー
英語が苦手なフレンズなのでアレ。
それはさておき、何を作ったかというと、
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="~~~~" > </head> </html>
みたいに書いたときにstylesheet
を中に良い感じに展開してほしい、っていうのを作りました。
なんでいるの?とは思うかもしれませんが、HTMLメールとか?あと、AMPで中に書く必要があったりするじゃん?みたいなので、どうしても中に書きたい場合があるんすよ。
っていうので作りました。
実装はどうなってる?
非常に簡単な作りになっているのでぎっよはっぶでみてくれ、みたいなところはあるけど、まぁ軽く。
github.com これを参考にしてつくりました。
const parser = require('posthtml-parser'); const fs = require('fs'); const path = require('path'); module.exports = function(options) { const root = options.root || './'; const encoding = options.encoding || 'utf-8'; return function posthtmlInclude(tree) { tree.match({ tag: 'link', attrs: { expand: 'true', rel: 'stylesheet' } }, function(node) { // ① const href = node.attrs.href; let content; if (href) { const src = path.resolve(root, href); content = parser(fs.readFileSync(src, encoding)); // ② } return { // ③ tag: 'style', content: content }; }); return tree; }; };
これが全コードですね。簡単な作りです。
① ノードのマッチ
ここでlink
タグかつrel
がstylesheet
で、expand
がtrue
のときだけ展開する処理を行うようにしています。
全部展開されると困ることもあるでしょうし、任意のやつだけ展開したいことが多くあると思うので、専用の属性を設けました。
本当はdata-~~
とかにすべきなのかなぁとかも思ったけど、まぁ変換された後のHTML
が正しければいいと思うし、まぁいいやってなりました。
②選択したファイルのよみこみ
まぁとくに説明することはないですね。href
で指定されているファイルを読み込むようにしています。
それを展開するためにcontent
に保持しています。
③styleで書き出す
で、その①でマッチした所をstyle
タグに変換します。
中身は②で取ってきたやつですね。
テッテレ~
完成。
まとめ
もともとはすでにこういうのあるっしょ〜とか思ってたんだけど、無くて*2、期待をアレされて悲しくなってましたが、意外と簡単な作りだったので、自分でできて良かったです(小並感)。
後々になってposthtml-include
使えばよかったのでは?とか思ったけど、なんか気持ち悪いし作ってよかったなと思ってます。
今後、これも盛り上がっていくといいなぁとおもいつつ、無いだろうなぁとおもっためろたんでした。
あ、今回作ったやつnpmで公開しているので、興味がある人は使ってみてくだされ〜
チラ裏
ここからは、愚痴等。
で今、AMPのサイトつくろ〜っと思ってこれ無いやんってなったので作ったのですが、そこまでに至る経緯がクソだったので書いとく。
まず最初 Webpack3
出たし、Webpack
でやろ〜とおもってposthtml-loader
っていうの使おうと思ったんだけど、
これね
リリースに載ってないバージョンがリリースされてるんすよwwwwww
これ特定するのにまじで精神と時間をすり減らしたから訴訟したい(暴挙)。
で諦めて、cli
をつかってみようと思ったら、そっちもうまく動かなくて、精神と時間を溶かした人の顔になってた。
結局posthtml
を叩くjs
を書いた。
この時の僕の気持ちは最高にアレだった。
頼むから壊れたままにするのはやめてほしい。
そんなアレでした。
とりあえずnpm界隈はこれだから〜みたいな感じになった。
*1:CSSをパースしてASTを吐いてそれを操作するAPIを提供しているJSのやつ。めっちゃ好き。ロゴがイカしてる。 github.com
*2:ちゃんと探せていないだけかもしれない
*3:もしかしたら使い方が違うかもしれないとかそういうやつかもしれないけど、4時間近く色々試したし、loaderのコードに色々差し込んで確認したりしたから確固たる意志をもって書く。僕は間違っていない。
*4:parserを指定できるので、pug(jadeって言われてたやつ)をつかってみよーと思ったら、だけ出力されてキレてた。
*5:どうも、parserにoptionを渡す前提で作られていないので、optionを受け取る前提で作られているparserにはoptionを受け取るところで、html(というかpug)の文字列が入ってきちゃって、処理すること無く空を返すみたいな感じになってたっぽい。深くは見ていない。