Zenn の自作執筆/プレビュー環境 (2022/Q4)
Zenn の自作執筆/プレビュー環境 (2022/Q4)
Zenn は、記事や書籍の公開や販売には非常に強力なプラットフォームで、 UI も見やすく洗練されており非常に気に入っています。
ただ、それなりに大きめの量の本を書くとなると、自分の場合は満たされてない要件がありました。一部は Issue を立てて解決してもらったり、 PR を投げてマージされたりしましたが、それは全てではありません。かといって、要望が個人的すぎるので Zenn のチームがフォーカスしたいこととは違うと思い、自粛している部分もあります。
結果、自分が欲しい環境は自分で作ることで解決しています。それをなんとなく紹介します。
プレビューに求めること
記事は基本 VSCode で書いています。執筆/編集に必要な全ての機能は VSCode 上で解決しているので、「書く」上で必要なものを Zenn に求める部分はありません。
従って、 Zenn に期待するのは「読む」つまり Preview による確認です。 Markdown を HTML に変換するツールはいくらでもありますが、 Zenn には独自の記法もあるため、完全な再現はできません。
現状、「これが Zenn 上でどう表示されるか」を知るには Zenn に表示して確認するのが一番でしょう。
実際 Github に Push すれば本体サイトで、ローカルなら Zenn CLI で Preview できます。ブラウザで表示を確認するだけなら、それでもあまり問題ありません。
問題は、「レビュアーの招待」と「印刷」です。
レビューアーの招待
書いてる途中で誰かに見てもらいたくなる時があります。
できれば、 Zenn の表示で見てもらいたいですが、非公開のまま誰かに共有する機能は Zenn にはありません。
GitHub に入ってもらって、ローカルで zenn-cli を叩いてもらうか、 PDF にして送るか、リアルタイムなら画面を共有するかといった方法になります。
できれば、トークン付き URL を送ったら一定時間見られるとか、 Zenn のアカウントを指定して Reviewer として追加するといった、何かしらの機能が欲しいところです。
以前は、自分のサーバに zenn-cli をデプロイし、それを Basic 認証で共有するといったことをしたりもしてました。
zenn-cli は localhost で動かす前提で作られているため、ドメイン付き HTTPS でデプロイされると想定されておらず、デプロイした時におこる一部不具合を直してもらったりもしました。
zenn-cli をデプロイしようとするのは筆者くらいな気がするため、こういう変更依頼は少し躊躇われるところがあります。
印刷プレビュー
筆者は、下書きが終わったら、一度紙に印刷して確認します。
不思議なことに客観的に見られるのか、紙にすると画面で見ていた雰囲気とは全く変わり、画面では気づかなかった部分に気づけたりします。
また、ちょっとしたメモや指示を書き込んだりする上でも、紙の方が自由度が高いため、移動中などは紙で確認することが多いです。
ちなみに、長い時間読んでいるとその間にペン先が乾くため、いろいろなペンを試した結果絶対に乾かないペン(シル)を見つけて愛用しています。
ところが、紙に印刷しようとした瞬間 Zenn だといろいろな問題が出ます。この印刷された原稿にたどり着くまでに色々やりました。
サイドバー
Zenn で表示するとサイドバーが隠せません。印刷しなくてもフォーカスリーディングのためにシングルカラムで画面一杯に表示するといったこともできません。
拡大すると消えますが、印刷するとやはりサイドバーが出てきます。画面の半分以上を潰すため、 DOM を消したりしないとうまく印刷できません。
ToC
ある程度の分量になると ToC がグチャグチャになったりするので、それも確認したいのですが、 Zenn CLI は ToC を浅い階層しか表示してくれません。
VSCode 上では Markdown の ToC を Outline に表示できますが、画面上でも表示して確認したい場合があります。単純にそこをリンクにしてページ内ジャンプもしたいし、 Deep Link にもしたい。
そして、 Zenn 本体の表示ではサイドバーにあるため、サイドバーを消すと ToC が消えるため、印刷には残りません。
メタデータ
これはかなり汎用性の無い話かもしれませんが、印刷している記事の情報も一緒に表示したいところです。
- 行数と文字数
- 最終更新時刻
- コミットハッシュ
- タイトル/emoji/topics などの Frontmatter の内容
特に、何度も印刷していると、いつ印刷したどのバージョンなのかがわからなくなることもあるし、画面上でも GitHub 側でビルドがコケてる場合もあるので、「これってどのコミットまで反映された表示だ?」と確認したい時もあります。
Zenn の表示にはこうした書籍のメタデータが一切表示されません。
コードハイライト
Zenn のコードハイライトは基本的には黒背景です。
これは、印刷すると潰れて少し読みにくくなります。
印刷には白背景の方が向いていますし、ハイライトも白黒印刷でも読めるものにしたいです。
<details>
が閉じる
Zenn では、 :::details
ディレクティブで <details>
内にコンテンツを書き、表示をトグルする機能があります。
これをコラムのように使っているのですが、 <details>
が印刷時も Close のままなので、印刷できません。
印刷時には全て Open にしたいところです。
alt
が隠れる
画像の 画像に付与した alt
が内容と一致しているかも確認したいですが、もちろん印刷されません。
alt
の誤字を確認したいのもそうですが、エディタで間違えて別の画像のパスを書き、 alt
とまったく整合してなかったりすることがあるので、印刷でも確認したいところです。
自作 Preview 環境
こういう細かいところを全部まるっと解決するために、 Zenn の Preview 環境を自作しました。
Markdown のパーサは自分で書いたものがあるため、それを使って Zenn 用の .md
が全部読めるようにし、 HTML で表示する Web アプリを Next.js で作りました。
出来上がりはこんな感じです(ブラウザから印刷で PDF にしたところ)。
レイアウト
まずヘッダ部分に
- 必要なメタデータ全て
- ToC 全階層
を付与しました。
本文は、ほぼ余白なしシングルカラムです。
ToC はヘッダへのリンクにしてるので、そのリンクを原稿にメモに残したりもできます。
スタイル
基本的に全部 Zenn の CSS のパクリです。
その上で、細かい部分を印刷用に修正しています。
例えば、コードのハイライトは白バックにし、白黒で印刷しても読めるように最小限の変更を入れてます。
details
は、印刷に限らず常に open
にしています。(Preview 中、閉じる理由がないことに気づいた)
また、画像は <figure>
で囲むようにし alt
の中身を <figcaption>
にして画像の下に表示するようにしています。
![代替テキスト]("path-to-image.webp")
<figure>
<img src="path-to-image.webp">
<figcaption>代替テキスト</figcaption>
</figure>
画像の、おまけで <table>
も <figure>
で囲んで <figcaption>
を付けられるようにしました。
Caption: テーブルのキャプション
| Head | Head | Head |
| ---- | ---- | ---- |
| Text | Text | Text |
| Text | Text | Text |
こういうインライン用のディレクティブは迷いますが、「表の直前に "Caption:" で始まるもの」というパースの定義にして、エディタ上も不自然じゃ無いようにしてます。
論文指導で仕込まれたトラウマで、図と表にはキャプションが無いとゾワゾワしますよね。あと、「図のキャプションは下」と「表はキャプションは上」みたいな謎ルールや、「図 1:」「表 1:」みたいな連番プレフィックスも欲しくなります。
精神衛生を保つために全部再現できるようになってます。
この機能が Zenn にもあると嬉しいけど、嬉しいのは自分だけでしょう。。
画像のサイズ指定
画像のサイズの指定は Zenn では URL の後ろに半角スペースを開ける(image.png =300x
)指定ですが、これは一般的な Markdown のプレビューで URL を壊すので、ちょっと、というかすごく困ります。
![alt](https://path-to-image.png =250x)
自分の自作 Markdown パーサでは、昔から fragment で縦横を指定できるようにしていたので、これを使って執筆し、公開前に一括変換かなぁと考えています。
![alt](https://path-to-image.png#300x100)
SSR リアルタイムレビュー
PC で執筆するときは、デプロイしたディレクトリにある記事のコードを直接 SSH で入って編集しています。
それを Next で常に SSR しているので、書きながら常に最新の文書がプレレビューできます。Zenn 本体のようにビルドを待たず、 zenn-cli のように書いてすぐ画面を確認できる良いところどりです。
GitHub に Push したものは Action で同期してるので、 iPhone での執筆も、 "Working Copy" とブラウザだけで(zenn-cli 無しで)完結します。
毎回レンダリングしているので、古いものが表示されている危惧もありません。
デプロイ
そうして作ったものを、自分のドメインに Basic 認証付きでデプロイしています。
レビュアーとして招待したい人にはゲストアカウント(guest/password)を送って、そちらを見てもらうことでレビューができるようになりました。
終わったら消せばいいし、複数人入れるのも楽だし、 Basic 認証は今でもやっぱり便利です。
執筆スタイル
これにより執筆と Preview のフローがかなり変わりました。
執筆は基本的にベッドの中か通勤中にしているので
- ベッドの中で iPhone の Working Copy で編集し、 Push したら Safari で確認
- 通勤中に iPhone で書き、乗り換えのコンビニで印刷し、その後紙と赤青ペンで校正
- まとまった量書いたら、 Basic 認証を渡した人にレビューしてもらう
まとめ
これを作ってから、 Zenn 本体のプレビューも、 Zenn CLI も使わなくなりました。
完全に「俺が楽」なだけのコードで、そのコードも Zenn プロジェクトの中にベタ書きで全部入ってます。
今のところ切り出して公開といったことは考えてません。
こういうフローが一般的とも思わないため、 Zenn がカバーすべきとも思いません。究極的には自分が欲しいものは自分で用意するしかないでしょう。
ただ、こういうフローで執筆しているユーザもいるというのが、 Zenn チームの参考になればと思います。
Discussion
貴重なフィードバックをありがとうございます!
印刷レイアウトに関する機能リクエストを何度か頂いていましたが、紙にプリントして確認するためだったのですね。実際のユースケースを提示していただいたことで、本には本のレビュー機能が必要ということがよく分かりました。
Zennはこれまで執筆体験の向上に力を入れてきましたが、本のレビューという部分に関してはまだできることが多く残っていると考えていますので、今後改善していきたいと思います。
VSCodeでのプレビューについては、昨日リリースした拡張機能によりリアルタイムにプレビューを反映できるようになりました。ご活用いただければ幸いです。