めろたんのアレ

色々書いてくやつ

PostHTMLのプラグインつくったぞーって話

どうも。

いろんなことに夢見て、そのたびに期待をアレされて悲しくなってるめろたんです。

最近はクリエイターズマーケットっていうイベントで購入したテラリウムを見て心を癒やしています。

はい。

今回はPostHTMLプラグインつくったぞーって話を書こうと思います。

PostHTMLって?

と本題に入る前にPostHTMLってなんぞって話なんですが、

github.com

PostHTMLとは、JSHTML/XMLを変換するツールで、HTMLをパースして、ノードツリーを操作するAPIを提供しています。

PostCSS*1HTML版ですね。

これ単体だと、特になにも起きません。

で、色々公開されている、プラグインを使うことで、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とかは共通につくっておきたいなー みたいなのにすごく便利では?って思ったり崎哲夫してました。

今回作ったの

で、今回作ったのはこちらですー

github.com

英語が苦手なフレンズなのでアレ。

それはさておき、何を作ったかというと、

<!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タグかつrelstylesheetで、expandtrueのときだけ展開する処理を行うようにしています。 全部展開されると困ることもあるでしょうし、任意のやつだけ展開したいことが多くあると思うので、専用の属性を設けました。 本当はdata-~~とかにすべきなのかなぁとかも思ったけど、まぁ変換された後のHTMLが正しければいいと思うし、まぁいいやってなりました。

②選択したファイルのよみこみ

まぁとくに説明することはないですね。hrefで指定されているファイルを読み込むようにしています。 それを展開するためにcontentに保持しています。

③styleで書き出す

で、その①でマッチした所をstyleタグに変換します。 中身は②で取ってきたやつですね。

テッテレ~

完成。

まとめ

もともとはすでにこういうのあるっしょ〜とか思ってたんだけど、無くて*2、期待をアレされて悲しくなってましたが、意外と簡単な作りだったので、自分でできて良かったです(小並感)。

後々になってposthtml-include使えばよかったのでは?とか思ったけど、なんか気持ち悪いし作ってよかったなと思ってます。

今後、これも盛り上がっていくといいなぁとおもいつつ、無いだろうなぁとおもっためろたんでした。

あ、今回作ったやつnpmで公開しているので、興味がある人は使ってみてくだされ〜

www.npmjs.com

チラ裏

ここからは、愚痴等。

で今、AMPのサイトつくろ〜っと思ってこれ無いやんってなったので作ったのですが、そこまでに至る経緯がクソだったので書いとく。

まず最初 Webpack3出たし、Webpackでやろ〜とおもってposthtml-loaderっていうの使おうと思ったんだけど、

github.com

これね

f:id:renyamizuno:20170702001855p:plain

f:id:renyamizuno:20170702001907p:plain

リリースに載ってないバージョンがリリースされてるんすよwwwwww

しかも壊れてるんすよwwwwwwwwwwww*3*4*5

これ特定するのにまじで精神と時間をすり減らしたから訴訟したい(暴挙)。

で諦めて、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)の文字列が入ってきちゃって、処理すること無く空を返すみたいな感じになってたっぽい。深くは見ていない。