🖋️

Zenn の執筆・校正環境をねばっと構築

2023/02/08に公開

しばらく技術を離れていたため、キャッチアップのためいろいろと調べ物をしています。
そんな中 Zenn に投稿された記事を目にすることが多かったことと、開発者の方のブログや、こちらの記事などを読んで、他の投稿サイトとは違った魅力を感じたので登録してみました。

みなさん有益な情報をいつもありがとうございます🙌

私も何か投稿をしてみようということで、先の記事で Zenn の特徴として紹介されていた Zenn CLI と、textlint を簡単に使える環境を構築する方法についてまとめてみました。

🏁 この記事の目標

この記事を読むことで、以下のことが得られることを目標とします。

  1. なるべく簡単かつ環境を汚さないで、以下のことをできる環境を作る
    • 実際に Zenn で表示されるようなデザインで記事をプレビューできる
    • 投稿する記事の日本語を自動で校正できる
  2. textlint の校正ルールについて概要を知る

⚠ 前提や対象など

この記事を読む上での注意点や、前提となる知識・経験は以下となります。

  • Visual Studio Code(以下 VS Code)や GitHub、Docker について触れた経験
    この記事では、インストールや基本的な操作については取扱いません。
  • VS Code の Dev Containers を利用できる環境があること
    基本的には、Docker Desktop と VS Code のインストールされた PC があれば大丈夫です。

🗺️ システム概要

今回想定している環境の全体概要です。この図の赤字の部分を構築していきます。

  • Zenn CLI と textlint はどちらも Node.js のモジュールです。Node.js はプロジェクトによってバージョンが指定されたり、モジュールの依存関係が問題となることがあるので、ホスト環境に影響しないコンテナ内へと隔離します。
  • コンテナに隔離することで、今度はコンテナの構築やホストとの連携が課題となります。今回は、校正やプレビューなど頻繁にエディタと連携する必要があることから、構築と連携がシームレスにできる VS Code と Dev Containers を使用します。
  • VS Code と GitHub の連携は単純に Push するだけなのでこの記事では取扱いません。同様に GitHub と Zenn の連携も公式のページに記載されていますので、そちらを参照してください。

💪やってみよう

とりあえずサクッと使ってみたいという方は、本記事の内容をテンプレートリポジトリとして公開しているので活用してみてください。

https://github.com/roppi/Zenn-template

以下は、構築の手順と内容の説明となります。

📦 Visual Studio Code Dev Containers の設定

まずは下記の手順で環境を整えていきましょう。

1. VS Code に Dev Containers をインストール

VS Code を開いたら、 Extensions のタブで「Dev Containers」を検索してインストールします。

2. Dev Containers の設定ファイルを作成

続いて、以下の手順で Dev Containers とコンテナの設定ファイルを作成します。

ⅰ. コマンドパレットを開いて、「Add Dev Containers Configuration Files」を選択

ⅱ. 設定のベースとして「Node.js」を選択

続いて、設定のベースを選択します。
今回使用する、Zenn CLI、textlint はどちらも、Node.js のパッケージなので「Node.js」を選択

ⅲ. 設定のベースとなる Node.js のバージョンに「18」を選択

特に指定はないのですが、現時点では「18」のみ選択可能なようですのでこちらを使用します。

ⅳ. 追加のパッケージを選択して「OK」ボタンを押下

今回は使用するものがないので、何も選択せずに「OK」ボタンを押下します。

以上でベースとなる設定ファイルが作成されました。

ファイルのツリーに、devcontainer.jsonDockerfile の2つのファイルが作成されたことを確認してください。

3. Dockerfile でコンテナを設定

次に先ほど作成された Dcokerfile を編集して、コンテナの中身を設定していきます。

ベースとなるイメージですでに、Node.js のパッケージマネージャーの npm が入っています。
ですので、npm コマンドを使用して Zenn CLI と textlint、それから textlint のプリセットルールをインストールします。

下記の内容を追加してください。

https://github.com/roppi/Zenn-template/blob/main/.devcontainer/Dockerfile#L11-L19

4. textlint の設定ファイルを作成

先ほどインストールコマンドを追加した textlint のプリセットルール。
実はそのままでは有効になりません。

ですので、textlint の設定ファイルを作成して、先ほどのルールが有効となるようにしましょう。

新規ファイル .textlintrc.jsonc を作成して下記の内容を追加してください。

.textlintrc.jsonc
{
  "filters": {},
  "rules": {
    "preset-ja-technical-writing": true,
    "preset-ja-spacing": true,
    "prh": {
      "rulePaths": ["/usr/local/lib/node_modules/textlint-rule-prh/node_modules/prh/prh-rules/media/techbooster.yml"]
    },
    "@proofdict/proofdict": {
      // URLはご自分のものに差し替えてください
      "dictURL": "https://roppi.github.io/proof-dictionary/"
    }
  }
}

5. Dev Containers.json で環境を設定

最後に、コンテナを操作する Dev Containers 側の設定を devcontainer.json を編集して行いましょう。

VS Code の textlint 拡張機能を導入する

拡張機能を導入することで、自動で検証・修正できるようにします。

devcontainer.json に下記の内容を追加してください。

devcontainer.json
  "customizations": {
    "vscode": {
      // コンテナ内で使用する Extension を指定
      "extensions": [
        "taichi.vscode-textlint"
      ],

      // コンテナ内での追加設定
      "settings": {
        //---------- taichi.vscode-textlint ----------
        "textlint": {
          // 設定ファイルパス
          "configPath": ".textlintrc.jsonc",
          // 保存時に校正エラーを自動修正する
          "autoFixOnSave": true,
          // 構成チェックの実行タイミング("onSave":保存時、"onType":入力時)
          "run": "onType",
          // 校正対象のファイル言語モード
          "languages": ["markdown", "plaintext"]
        }
      }
    }
  }

textlint-rule-prh のルールを直接編集できるようにする。

コンテナ作成時(インストール時)にワークスペースへルールファイルをコピーして、校正時はワークスペースを使用するようにします。

devcontainer.json に下記の内容を追加してください。
https://github.com/roppi/Zenn-template/blob/main/.devcontainer/devcontainer.json#L9-L10

また、textlint の設定ファイルも以下のようにします。

.textlintrc.jsonc
+ "rulePaths": ["./prh-rules/media/techbooster.yml"]
- "rulePaths": ["/usr/local/lib/node_modules/textlint-rule-prh/node_modules/prh/prh-rules/media/techbooster.yml"]

6. コンテナを起動

設定を終えたら、コンテナを起動してみましょう。

コマンドパレットを開いて、「Rebuild and Reopen in Container」を選択しましょう。

VS Code の画面左下の緑の部分に「Dev Containers:(コンテナ名)」と表示されれば成功です。
これで、コンテナ上の環境とつながることができました。

さっそく、ターミナルを開いて、Zenn CLI のコマンドを実行してみましょう。

zenn --version:Zenn CLI のバージョンが表示されます。
zenn init:記事連携用のフォルダが自動生成されます。

最後に zenn と実行することで、プレビューサーバが起動します。
init 未実行の場合はその旨のメッセージが表示されます)

このような画面になれば成功です。

📝 textlint の構成ルールについて

続いて、先ほどの環境構築で導入した textlint について紹介します。

今回は汎用的な環境を構築するため、textlint の構築記事でよく使用されている次の4本を導入しています。

  • textlint-rule-preset-ja-technical-writing
  • textlint-rule-preset-ja-spacing
  • textlint-rule-prh
  • @proofdict/textlint-rule-proofdict

その他の校正ルールは、GitHub 上で textlint-rule と検索すれば見つかります。

https://github.com/search?q=textlint-rule

それでは、導入した4本のルールについて見ていきましょう。

textlint-rule-preset-ja-technical-writing

https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing

技術文書向けのtextlintルールプリセットです。

一文の長さや、ですます調とである調の混在チェック、連続する助詞など表記全般に関するルールが定義されています。
ルールもかなり細かく設定できるため、まずはこちらのルールを使い始めるのが良さそうです。

設定項目

textlint-rule-preset-ja-spacing

https://github.com/textlint-ja/textlint-rule-preset-ja-spacing

日本語周りにおけるスペースの有無を決定する textlint ルールプリセット。

上記の「textlint」の前後のように全角文字と半角文字の間に自動でスペースを入れる。
半角文字の前が読点だったらスペースを入れないなどスペース関連のルールを設定できます。

設定項目

textlint-rule-prh

https://github.com/textlint-rule/textlint-rule-prh

WEB+DB PRESS と、techboosterの2つのメディアで使用されている(?)ルールが定義されています。

ルールの中身はどちらも、漢字とかなの表記についてが主のようですが、前者のルールではさらに、語尾の伸ばしの有無、技術用語やソフトウェア名のカナと英語表記に関するルールも定義されています。

矛盾しているルールが一部あるため、両者を有効にする場合はルールの統制を取る必要があります。

ルールの統制を取るには、フィルタルールというものを定義すれば元のファイルを編集する必要はないのですが、定義するのが少し面倒なため、今回はコピーを取得して直接編集できるようにしています。

設定項目

@proofdict/textlint-rule-proofdict

https://github.com/proofdict/proofdict

3つ目に紹介した textlint-rule-prh のような表記揺れのチェックルールを簡単に定義・使用できる機能拡張です。
GitHub のリポジトリをフォークすることで、GitHub Pages を使用したオンラインエディタを使用できます。

自動でルールファイルの再取得をしてくれる機能もあります。
ただ、再取得の際に作成するキャッシュディレクトリが、パーミッションエラーとなる場合があるようです。

今回の例では、コンテナ起動時のユーザーの node ではエラーとなるため、Dockerfile 内でディレクトリの生成とパーミッション設定をしています。

設定項目

🍵終わりに

欲張りすぎて、記事が長くなってしまいました💦
ここまでお読みいただいてありがとうございます。

以上で、VS Code を開くだけで Zenn に執筆しやすい環境ができました。
よりよいルールやプラグインなど、記事やコメントで共有いただけるとうれしいです。

それではどうぞ、良い Zenn ライフを👋

Discussion