Zenn 記事の目次をターミナル内でプレビュー
作成した Zenn 記事を実環境にデプロイしてみたところ「目次(章)のバランスがよくなかったかな」ということがありました。
本来ならばエディターのアウトラインなどで確認しておけばよいのですが、現在は CMS 上で編集しているのでそれも少し難しい。
エディターのアウトライン表示
そのようなわけで簡単な目次のプレビュー機能を作ってみました。
対応案
2 つほど思いついた案があったのですが、最終的には「記事を CMS からローカルへ保存するスクリプトの表示の中に目次も含める」という方法になりました。
実装方法
FrontMatter + Markdown を扱うので本来ならば gray-matter
+ remark
などを使うのが固いのですが、今回は grep
などを組み合わせることにしました。
見出しの抽出
grep
で先頭の #
を検索することで対応します。
以下のような懸念点はありますが、今回はとりあえず保留にしておきます。
- FrontMatter 中のコメント
- コードブロック内の
#
形式のコメント - コードブロック内の Markdown
-
---
を使った見出し
追記: remark-cli
を使う方法も試してみたので問題が多いようなら切り替えることにします。
見出しの整形
sed
と Bash の文字列操作で対応します。
$ grep -e '^##\{1,2\} ' -- tmp/articles/native-esm-with-typescript-jest.md | sed -e 's/^## /+ /' -e 's/^### /| /'
+ モジュールの native ESM 対応
+ ts-jest の ESM 対応設定
+ Jest の native ESM 対応設定
+ native ESM での jest モックモジュール
+ VSCode 関連
| 構文チェック
| デバッグ
| コード補完と動的インポート
+ とりあえず
表示幅の確認
これは以下のように「実環境での表示で折り返される」行を検出したいというものです。
環境によって表示は異なるので、それほど気にするものではありませんが「長すぎる見出しもよくないかな」ということで。
折り返されている項目
この部分はターミナル上だと難しいので(Puppeteer でいけるかもですがそこまでは)、Fullwidth などを考慮した値を wc --max-line-length
で取得し簡易的に使います[1] 。
$ echo '👀 Preview:'| wc --max-line-length
11
作ってみた
上記の内容を組み合わせて作ったのもが以下になります。
script(toc.sh)
#!/bin/bash
set -e
WARN_LEN="33"
COLOR_RESET='\e[0m'
COLOR_DEPTH2='\e[0m'
COLOR_DEPTH3='\e[2m'
COLOR_WARN='\e[33m'
grep -e '^\(##\|###\) ' -- | sed -e 's/^## /+ /' -e 's/^### /| /' | while read -r LINE
do
HEADDING="${LINE::1}"
TITLE="${LINE:2}"
LEN="$(echo "${TITLE}" | wc --max-line-length)"
# ヘッディング文字
echo -n "${HEADDING} "
# 装飾
if test "${LEN}" -gt "${WARN_LEN}" ; then
echo -n -e "${COLOR_WARN}"
elif test "${HEADDING}" = "+" ;then
echo -n -e "${COLOR_DEPTH2}"
else
echo -n -e "${COLOR_DEPTH3}"
fi
# タイトル
echo -n "${TITLE}"
# 装飾リセット
echo -n -e "${COLOR_RESET}"
echo ""
done
$ bash scripts/toc.sh < articles/native-esm-with-typescript-jest.md
実行結果
簡単な装飾と長い行は警告色で表示されるようになっています。
おわりに
とりあえず動作するようになったので CMS からローカルへ保存するスクリプトにも組み込んで記事作成時に利用しています。
CMS からの保存時に目次プレビュー
やはり目次を事前に確認できるのは良い感じです。
ちなみに
本筋とは関係ないのですが、現在スクラップの使い方の練習もしています。
その一環として、この記事は以下のスクラップを作成してからそれを元に記述しています。
Discussion