😸

Zennの執筆環境を快適にする(DevContainer + WSL2 + Docker)

2024/01/21に公開

はじめに

今回の記事は、以下で構築した環境を快適にするための修正内容です。
https://zenn.dev/mknsk0309/articles/20240116-7940d414bbaffc

現環境の課題

今回解決する課題は以下の3点です。

  • コンテナ開始後、いちいちプレビューを開始するのが面倒くさい。
  • 簡単に記事内に画像を貼り付けたい。
  • 今後記事が増えてきた時、自動生成されるslugだとわかりづらい。

それでは早速それぞれの課題について改善を行っていきましょう。

環境改善

Update.1 コンテナ起動時にプレビューを開始する

コンテナを起動した後、いちいち手動でnpx zenn previewをコマンド実行するのが面倒なので、コンテナにリモート接続するたびに自動実行されるように設定します。

.devcontainer/devcontainer.json
  /****** 前 略 ******/
  "mounts": [
    "source=${localEnv:HOME}${localEnv:USERPROFILE}/.gitconfig,target=/home/node/.gitconfig,type=bind"
  ],
+ "postStartCommand": "npx zenn preview",
  "customizations": {
    "vscode": {
      "extensions": [
  /****** 後 略 ******/

その他、devcontainer.jsonの各プロパティについては以下を参照。
https://containers.dev/implementors/json_reference/


Update.2 画像の貼り付けを簡単にする

ZennをGitHub連携して画像管理もする場合によくでてくるのが、VSCodeの拡張機能 Paste Image なんですが・・・。

困ったことにこれが、WSLのリモートコンテナ上だと動かない(Mac環境ならいける?)
詳しい説明は省きますが、色々試してみたり、他の拡張機能も触ってみたのですが、なかなかうまくいかない。

そんな時に見つけたのがこちら

2023年5月の VSCode(ver 1.79) で拡張機能なしでMarkdownに画像が貼り付けられるようになっていたみたいです。
画像の保存先も変更可能で、ワークスペース内の設定ファイルに以下を追加してみました。

.vscode/settings.json
{
  "markdown.copyFiles.destination": {
    "articles/*.md": "/images/articles/${documentBaseName}/",
    "books/*/*.md": "/images/books/${documentDirName}/${documentBaseName}/"
  }
}

articlesファイル内で画像貼り付けを行った場合は/images/articles/{記事ファイル名}/内に画像が配置されます。

しかし、この機能もなかなか曲者で、注意点が3つほど・・・。

注意① ${documentDirName}のバグ

設定ファイルではbooks用の設定も行っておりますが、変数${documentDirName}にバグがあり、うまく機能しません・・・。

注意② 画像ファイル名の設定ができない

現状、保存される画像ファイル名も変更ができないようで、image.pngまたはimage-{連番}.pngでしか出力されません。

注意③ Zenn CLI との相性の悪さ

この機能、使い方は簡単で、記事内でスクリーンショットを挿入箇所でCtrl + Vを十個するだけなんですが・・・。

![Alt text](../images/articles/20240121-8d1a31bcd83530/image-1.png)

挿入されるときのコードが相対パスなんです。
Zenn公式からもご丁寧に注意されている誤った指定方法なんです。

Alt text

なので貼り付けた後は手動で絶対パスにしてあげてください・・・。


Update.3 記事、本の作成を簡単にする

最後のアップデートとして、記事・本の作成を簡単に実装します。
Zenn CLI 標準のコマンドだと、ランダムなスラッグによるファイル名(またはディレクトリ名)の記事(または本)が生成されるじゃないですか。

あのslugだけだとわかりづらいので、生成されるファイルのフォーマットをyyyymmdd-{ランダムなslug}にしたいと思います。

Googleが開発しているJavaScriptで記述できるzxを使用してみます。

zxのインストール

Dockerfileにzxをインストールするよう記述を追加します。

.devcontainer/Dockerfile
###### 前 略 ######
RUN apk -no-catche add \
  git \
  bash\
  && yarn global add zenn-cli \
  && yarn global add zx
###### 後 略 ######

Dockerfileを修正後、コンテナをリビルドしておきます。

npmの初期化

リビルド後、コンテナのターミナルで以下のコマンドを実行。

npm init

コマンドを実行するとpackage.jsonというファイルが作成されます。
コマンド実行時に入力要求される項目はとりあえずすべてEnterでもいいでしょう。
詳しいプロパティの内容は以下を参照。
https://docs.npmjs.com/cli/v10/configuring-npm/package-json

JavaScriptファイルの作成

次に、zxコマンドで動作するスクリプトファイルを作成します。
scriptsフォルダを作成し、new-files.mjsファイルを作成します。

scripts/new-files.mjs
#!/usr/bin/env zx
$.verbose = false;
const path = require("path");

// 1,2番目はnodeとzxのパスのため、3番目の引数以降を取り出す
const args = process.argv.slice(3);

// 日付取得
const today = (await $`date "+%Y%m%d"`).stdout.trim();

// ファイルの作成
var filePath = "";
switch (args[0]) {
  case "article":
    // articleファイルの作成
    var result = (await $`zenn new:article`).stdout.trim();
    // 作成したファイル名の取得
    filePath = result.match(/articles\/.*\.md/)[0];
    break;

  case "book":
    // bookフォルダとファイルの作成
    var result = (await $`zenn new:book`).stdout.trim();
    // 作成したフォルダ名の取得
    filePath = result.match(/books\/.*(?=\/)/)[0];
    break;

  default:
    // 引数が不正の場合は例外をスロー
    throw "error: invalid arguments.";
}

// 日付付きslugの生成
let { dir, base: fileName } = path.parse(filePath);
let newPath = `${dir}/${today}-${fileName}`;

// ファイルのリネーム
$`mv ${filePath} ${newPath}`;

var green = '\x1B[32m';
var reset = '\x1B[39m';
console.log("created: " + green + newPath + reset);

package.jsonにコマンドの実装

スクリプトファイルが完成したら、package.jsonファイルを編集します。

package.json
/***** 前 略 *****/
  "scripts": {
    "new-article": "zx ./scripts/new-files.mjs article",
    "new-book": "zx ./scripts/new-files.mjs book"
  },
/***** 後 略 *****/

使い方

以上で、準備が整いました。
後は、コンテナのターミナルから

npm run new-article

と打てば、日付付きの記事ファイルが、

npm run new-book

と打てば、日付付きの本ディレクトリがそれぞれ生成されます。

まとめ

新しい知識も取り入れて、これでだいぶZennの執筆が楽になったのではないでしょうか。
画像の挿入など、まだまだ改善の余地はありますが、とりあえずはこれで運用してみたいと思います。

実際に私が運用しているリポジトリはこちら。
https://github.com/mknsk0309/zenn-public

GitHubで編集を提案

Discussion