Markdown に関する投稿を表示しています

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

Go 言語の練習に markdown のテーブルだけいい感じに調整するやつを作ってみた

作ったよ

sters/markdown-table-formatter: markdown-table-formatter

|hoge            |huga|
|--------------|------|
|its|confusing              |markdown|
|table   |so|crazy|table|.|

みたいなガタガタテーブルが書かれているテキストをキレイに揃えてくれるやつ。

|hoge |huga     |        |     | |
|-----|---------|--------|-----|-|
|its  |confusing|markdown|     | |
|table|so       |crazy   |table|.|

 

何も考えずにこんな要素が必要では?とテストを書いていって、それに合わせて実装をしていったので、同じことを何度もやっているような部分もあって、
アーキテクチャ的には再考の余地あり。

struct に中間データ的なものを閉じ込めてバケツリレーするのが簡単かなあ。
テストがいるので、ここからリファクタしがいありますね、って感じで。

 

書いてみて、ポインタとかまったく気にしなくて良いってことがわかってきた。
出番はほぼないのと、あっても波線出たときにどうにかする、ということだけを、とりあえず、それでよさそう。

リリースの配布

タグを設定すると Circle CI が動いてリリースが作られるようにしてみた。
(go get に必要なのかな?と思ったけどそういうわけではなかったみたい)

goreleaser を使ったリリースというタスクを作って、ワークフローで制御している。

goreleaser/goreleaser: Deliver Go binaries as fast and easily as possible

設定はここみて。

markdown-table-formatter/config.yml at master · sters/markdown-table-formatter

詰まったポイント

テスト時の assert を見やすくするために gopwt を使ってみたんですが、-cover したときにカバレッジが出なくなる問題があり、そこで無駄に詰まった。
gopwt のソースを調査するのはまたの機会にして、カバレッジ測定では gopwt を無効にした。

markdown-table-formatter/Makefile at master · sters/markdown-table-formatter

あと go get したときにそのままバイナリができる方法がわからなかった。ググってもそれっぽい回答が見つからない。。公式ドキュメントのどこかにいるのかなあ…

わからなかったので、リリースを作ってみたが違った ./main.go にして見たらバイナリが作られるようになった。
ディレクトリ切るとだめなんかな。いや、./formatter.go がいたからダメだったのかな、、
ドキュメントどこーー

そのほか

カバレッジ出ると楽しい。
100%にするのが完璧なテストというわけではないけど、そもそもココのテストできてなくね?とかが可視化されるの便利。