2018年 12月の投稿を表示しています

WordPressでプラグイン無しmarkdownを使って記事を書けるようにする

以前やろうとしたときはうまく動かなかった記憶がある。ので諦めて自分で用意した話。

記事を書くときに Markdown で書き、何かしらの手段を講じて、実際に見えるときに HTML である状態を作ります。
それにはいくつかのアプローチが考えられます。

入力画面で Markdown を使い WordPress へ保存するデータも Markdown にする

この場合 Post のメタデータとして Markdown であることを伝えて、テンプレートを表示する際に Markdown であった場合に PHP あるいは Javascript で Markdown から HTML に変換します。

PHP でやる場合 Composer でテーマ開発をする路線に乗り parsedown などを使うのがお手軽でしょう。
erusev/parsedown: Markdown Parser in PHP

そのほかにも Packagist を探すといくつかのライブラリが見つかります。
Packagist

Javascript でやる場合、テンプレートの出力を一度見えないようにしておいて HTML で整形できたら見せるようにすると綺麗です。
もちろんあえて Markdown を表示しておく、というのもアリかと。

ライブラリとしては marked があります。
markedjs/marked: A Markdown parser and compiler. Built for speed.

cdnjs を探すとほかにも見つかります。
cdnjs.com - The best FOSS CDN for web related libraries to speed up your websites!

PHP か Javascript かどちらを取るかというと、どっちでもよいと思います。
PHP の場合はサーバサイドの処理になるので、例えば nginx なり CDN なりで HTML にレンダリングしたものに対してキャッシュが利きます。
Javascript 上でやる場合、クライアントのリソースを使うので、大きなコンテンツであればあるほど HTML が表示されるまでに時間がかかってきます。
(ServiceWorker を使ってキャッシュを持つなどしてもよいかもしれません)

そしてこのパターンで PHP, Javascript 問わずに気を付けるべきは、もしも仮に第三者が記入できるエリアにも適用された場合に XSS などのバグおよび脆弱性につながりやすくことも挙げられます。
いやそもそもそういうことやりたいという事情はそんなにないか。

入力画面で Markdown を使い WordPress へ保存するデータを HTML にする

このアプローチは現在のごみばこいんでも扱っています。
WordPress 管理画面上の入力画面において Markdown で書いたものを HTML に変換するボタンを作っています。

具体的には以下のようなコードを functions.php に書いています。

// add media area buttons for admin
function hook_media_buttons() {
?>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.5.2/marked.min.js" integrity="sha256-zFUosuESzULu5P+SZdjRRtBZR8+1u5RZDlbt3Q5KL8U=" crossorigin="anonymous"></script>
    <button type="button" class="button Markdown-to-html">
        <span class="dashicons dashicons-thumbs-up"></span>
        Markdown to HTML
    </button>
    <script type="text/javascript">
        document.querySelector('.Markdown-to-html').addEventListener('click', () => {
            if (marked === null || marked === undefined) {
                alert("marked not loaded...");
                return;
            }

            let text = $('#content').val();

            // Markdown to html
            text = marked(text, {
                headerIds: false,
            });

            // More newline
            text = text
                .replace(
                    /(<\/(p|table|h\d|pre|ul|ol)>)\n?/g,
                    (_, a) => {
                        return `${a}\n\n`;
                    }
                )
                .replace(
                    /\n\n+/g,
                    '\n\n'
                );

            // Replace value
            $('#content').val(text);

            return false;
        });
    </script>
<?php
}
add_action('media_buttons', 'hook_media_buttons');

若干おまけもついていますが、これで Markdown を HTML にするボタンを記事編集ページに追加できます。
下書きを WordPress 上なり、別の場所なりで書いてから、実際に記事公開する前にポチっとやって様子を見てから公開するようにしています。公開アクションにフックして自動で変換されるようにすることもできると思います、今そうしていない理由は特にないです。

入力画面で Markdown を使わない

要は別の Markdown なエディタを使って、整形された HTML を WordPress にぶっこめば良いという話です。パッと思いつくのはこのあたり。

そのほか考えるとよさそうなところ

超速 web 体験を目指すなら、可能な限り前処理を済ませたほうがよいと思うので、クライアントの手元で動かすことをなるべく減らす = JavaScript 側でやるという選択肢ははずれてくるのではないでしょうか。
ServerSideRendering 的な話と捉えてもよいっぽい。保存するデータはどっち?という話は編集ページの利便性によってなんでもいいかなーと。

常に Markdown で書きたいなら Markdown で保存できるようにしたほうが良いだろうし。まあ何も気にせずプラグインぶっこむのがお手軽簡単でいいんじゃないですかね~~(結論)

PHP を Go にするという話を mercari.go というイベントで喋りました

PHP を Go にするという話を mercari.go というイベントで喋りました(今更)

mercari.go #4 を開催しました - Mercari Engineering Blog

スライドに書いてある話がおおむねすべてです。

リポジトリはここ: sters/phptogo: Transpile PHP code to Go like something code.

今のメルカリの状況については、各所の web メディアにかかれている Mercari Tech Conf の話がいちばんまとまっていると思います。

この記事では後付けというか、いくつか補足できればと思いますー。

コードすべて変換して手直しはそう大変でもない

初期のもの(スライド中の v1)では、丸っと全コード変換はしていません。

Go でざっくりと書いたテンプレートファイルを作っておいて、そこに struct を書いていて、元の PHP コードから function 単位で、該当するテンプレートファイル上の関数へと埋めていく、といったことをやっていました。

Github で公開したものはその手続きを含んでいないので、大変そうに見えると思います。
(実際これでやれって話になったらチョットつらい)

加えて、各種 Go ヘルプするツール群を利用すれば
自動である程度整ってくれるので、マジつれーわーうわーみたいなことにはならないとおもっています。

型情報もう少しなんとかしたい

PHPDoc あるいは PHP の型宣言の情報を利用すれば、もっと埋めることができます。
そのとき、わからないやつは一旦全部 interface{}でゆるっと扱う、みたいなことになると思います。

関数においての PHPDoc からの補完はすでに書いています。
add function parameter type completion form phpdoc · sters/phptogo@b8e3d96

テストどうやる問題

確かにテストは本当に正しいのかどうかわからないというのもわかります、実際わからない。

一つのやり方として、生成物が Go のような何かのコードではなく、完全に Go の AST を作ってしまう、という手が考えられます。
テストとしては AST→AST ができることを確認すればよいので、今よりは信頼できる(?)テストになるんじゃないでしょうか。
当然そのまま持っていくことがムリな情報は落とさざるを得ないので、落とすか、それっぽい値で補完するかのどちらかになるのは今と変わらないです。

Githubで公開したものに色々追加したいねー

Github で公開したものは、セミコロンないよとか変数に$はつかないよとか、ごくごく基本的な構文の変換くらいしかやっていません。

もっと足を伸ばして PHP クラスを Go の構造体に落とすぞ!!!みたいなものはちょっとやりすぎで、そのとき、うまく出来るように一定のフォーマットであるとか、フレームワークのようなものを利用者に強いることになってくると思うのでそのフレームワークのようなものを理解しなければいけないのは微妙かなと。

ということで、必要なもの、なんとかしたいもの、はそれぞれで実装してくれ!ただ、それだと勝手が悪いところも多いと思うので、サンプルの文量を増やしていくかなあとはおもっています。
たとえば初期実装ではやっていたようなテンプレートファイルに落とし込むようなやつとか。

そもそもPHPをGoに変換する必要があるのか

いや、そんなにないんじゃないですかね……

複雑すぎないクラスやバッチがたくさんあって、何かしらの理由で Go に持っていきたい、という場合に需要がでてくると思います。
ただ PHP で今動いているものを Go で動かすことに対して、手間ひまがかかることは当然なので、効果というか色々と天秤にかけたうえでやったらいいんじゃないですかね~~~。

欲する人のそれぞれの状況によると思うので一概に答えはないと思います。
僕の状況ではだんだんつらくなってきて欲しくなったので作っていった、というだけです。