Go to this month’s calendar
2020 / 10 / 14

エディタページにマークダウンのプレビュー機能を実装した

今日もひたすら日記の開発をしていた。ちなみに昨日はすごく疲れてて夜の 21 時か 22 時くらいに寝てしまった。でも起きたのは 4 時くらいだった。

起きてから数時間は結構集中力もあったが、やっぱり睡眠時間的にはあんまり眠れていないのでぼんやりしたり眠くなったり集中力が途切れることが多かった。

でも今日もなんだかんだいって朝から夜までずっと開発をすることができた 💪

今日は主にエディタ (編集画面) の変更を行った。

最初はドラッグアンドドロップで画像をアップロードできる機能を実装しようとしていた。しかし、昨日、AWS S3 に対応して本番環境でも S3 を使うようにしたので、開発環境で S3 に画像をアップロードするわけにはいかない。となると開発環境では S3 の代わりにローカル環境に直接アップロードする (従来のアップロード) ようにしなければならない。つまり、従来のローカルへのアップロードと S3 へのアップロードを切り替えられるようにしないといけない。

それをしないことにはドラッグアンドドロップの実装もできない (画像アップロードを試すときに本番環境で使っている S3 バケットにアップロードするわけにはいかない) ので、まずはローカルと S3 の切り替えをできるようにした。

はじめは別々の実装にしようと思っていたのだが、画像をアップロードする、という点では共通していてコードを見た感じ、共通化するのはそんなに難しくはなさそうだったので、共通化した。

そのあといよいよドラッグアンドドロップの実装、と思ったが、ドラッグアンドドロップ以前にエディタを改良する必要があるなと思ったので今日はそっちをやることにした。具体的には、Qiita みたいにマークダウンのプレビューを表示できるようにした。こんな感じ!

スクリーンショット 2020-10-14 20.22.53.png

今までは中央にフォーム (文字入力するところ) があるだけだった。そのフォームを画面半分の大きさにして左に寄せた。そしてそれと同じ大きさ (画面半分の大きさ) の別の領域を新たに作ってそれを右に寄せた。

画面左のフォームで文字を入力すると、右にマークダウンをパースした HTML が表示されるというものだ。Qiita の記事投稿画面の UI に似せて作った。

実装としては、フォームに対して change イベントを作成して、フォーム内の変更を監視する。つまり、文字が入力されたり削除されたりするとイベントが発火する。

イベントが発火したらフォーム内の文字列を取得して非同期でサーバに投げる。サーバではその文字列 (マークダウン) をパースして HTML にしたものを返す。それを右側に表示する、というシンプルなものだ。

一文字一文字、入力するたびにサーバと通信して結果を表示させるので負荷とか問題ないかなと心配になったけど、今のところ特に問題はないようだ。文字列の取得や、パースした HTML の反映も非同期で行っているため入力がブロッキングされることはない。

ただし、なんとなく以前よりも入力しづらくなったような気がしなくもない。なんか入力が重くなったり、ときどき文字が欠落したりするような感じがするのだが、気のせいという気もする。非同期だから入力には影響を与えていないはずだし、まあそんなに致命的ではないのでこのまましばらく使っていく。

あと左側のエディタのほうをスクロールすると、それに合わせて右側のプレビューもスクロールするという実装にしてみた。これも Qiita のパクリみたいな感じの機能なんだけど、画像とかが入ると、エディタ側とプレビュー側でスクロール位置が大きくずれてしまうので、完全にスクロール位置をそろえることはできなさそう。でも画像を大量に入れない限りはおおむねちゃんとスクロール位置が整うし、たいていは一番下にどんどん文字を追加していく感じになるので問題ないかな。

マークダウンのプレビューを入れたことによって、エディタがかなりリッチな見た目になった。個人的には、マークダウンって、HTML と違って、パースしなくても直感的に記号が何を表しているのかわかりやすいので、プレビューなくても良いかなと思っていた。だから今まで実装もしていなかったんだけど、唯一不便なのは画像がプレビューできない点だ。画像ばかりは raw なマークダウンでは補完しようがないのでプレビューするしかないのだ。

今までは Dropzone を使っていたので、アップロードした画像がちっちゃい枠の中に表示されていたのでかろうじて使えていたが、今回 S3 への対応等で、Dropzone も使わなくなり、画像がエディタページでは全く確認できなくなってしまった。アップロードがちゃんとされたかもわからない。

スクリーンショット 2020-10-14 20.40.06.png
▲ Dropzone のフォーム。画像をアップロードすると小さい正方形の画像が並んで表示される

それでは困るので、ようやくプレビュー機能を入れたというわけだ。尤も、Dropzone を使っていたときもプレビューされる画像は小さかったし、複数の画像アップロードした場合はどの画像が文中のどの位置にあるものかもわからなかったし、何より日記投稿してから編集するときにはプレビューは表示されないので前々から不便だなとは思っていたんだよね。

あと決定的だったのは、テンプレート機能を実装してエディタページのスクロール量が多くなったことだ。Dropzone のフォームはページの一番下にあるから、画像をアップロードするたびにわざわざページ最下部までスクロールしなくちゃいけないのはかなりめんどくさかった。今はページ上部に画像アップロードボタンがついて、そのボタンのある親要素が position: sticky; で追従されるからだいぶ使いやすくなった。

そんな感じで、少しずつ改善されていっている。趣味の開発って、熱が出ると昨日や今日みたいに朝から晩までずっと開発するほどのめり込んだりするけど、熱が冷めると数ヶ月とか全然開発しなくなったりするんだよね。本当は、毎日じゃなくても良いから定期的に開発を続けていきたいんだけど、モチベーションをずっと保ち続けるのはなかなか難しい。でも、開発して、自分の使っているものが、少しずつ良くなっていったりするのはとても楽しい。開発自体もとても楽しい。

今日できなかったドラッグアンドドロップも実装しよう。