Zennと連携したリポジトリにprettierとtextlintをいれてフォーマットと文章校正を自動で実行する
数多あるブログシステムの中で、Zennで記事を書くようになったのはGitHubと連携できるのが大きいです。Gitで履歴を管理したり、PRでの運用はとても快適です。
その中でも、prettierでマークダウン形式のフォーマットをしたり、textlintで文章の統一感や言葉の揺れチェックできるのは助かります。
今回は、このあたりを自動化した内容を記事にまとめます。
prettierをセットアップ
prettier本体をインストールします。
npm install --save-dev prettier
対象としないファイルを指定します。
.git
node_modules
package.json
package-lock.json
デフォルトのままだと、半角英数字と全角文字の間にスペースが入るようになってしまうので、それを回避するプラグインをいれます。
npm install --save-dev prettier-plugin-md-nocjsp
設定ファイルを.prettierrc
というファイル名で作成します。
overrides:
- files:
- "*.md"
- README
options:
parser: markdown-nocjsp
npm run
で実行できるようにします。
"scripts": {
+ "format": "prettier -w articles/**/*.md"
},
"keywords": [],
"author": "",
次のコマンドを実行することで、マークダウン形式のファイルをフォーマットします。
npm run format
textlintをセットアップ
文章校正をするため、textlintをセットアップします。
インストール
textlint本体をインストールします。
npm install --save-dev textlint
続いて、ルールをインストールします。
npm install --save-dev textlint-rule-preset-ja-technical-writing textlint-rule-preset-jtf-style
技術文章向けのプリセットルールと「JTF日本語標準スタイルガイド(翻訳用)」に対応したルールを追加しています。特に別に翻訳をするわけではなくても、技術系の文章を書く際に適したルールがあるのでいれるようにしています。
設定ファイルを下記の通りにします。
module.exports = {
plugins: {
"@textlint/markdown": {
extensions: [".md"],
},
},
rules: {
"preset-ja-technical-writing": true,
"preset-jtf-style": {
"2.1.6.カタカナの長音": true,
"2.2.1.ひらがなと漢字の使い分け": true,
},
},
};
preset-jtf-style
のいくつかがデフォルトでオフになっているので、ルールをオンにします。
実行
scripts
にtextlintを実行するためのコマンドを追加します。
記事を追加するたびに毎回全部の記事を対象にして非効率なので、ステージされたファイルを対象にしたり、textlintのオプションにあわせて、いくつか追加します。
"scripts": {
"format": "prettier -w articles/**/*.md",
+ "lint:text": "textlint --cache $(git diff main --name-only) -f pretty-error",
+ "lint:text:fix": "textlint --cache $(git diff main --name-only) --fix",
+ "lint:text:full": "textlint --cache README.md \"articles/**/*.md\" -f pretty-error",
+ "lint:text:full:fix": "textlint --cache README.md \"articles/**/*.md\" --fix"
},
"keywords": [],
"author": "",
エラーの箇所が特定しやすいように-f pretty-error
をオプションに追加しています。
ステージのファイルを対象にチェックする場合は以下を実行します。自動で修正するにはfixを付加します。
npm run lint:text
npm run lint:text:fix
コミット済みのファイルも対象にチェックをかけたい場合はそれぞれ下記を実行します。
npm run lint:text:full
npm run lint:text:full:fix
スクリプトを実行すると、キャッシュが生成されます。キャッシュはリポジトリーに含まなくてもいいので、.gitignore
に追加します。
+.textlintcache
便利なルールを追加
基本的なルールだけでもいいのですが、さらにいくつかルールを追加します。
prh
表記揺れなどを防ぐために、prhというツールのtextlintのプラグインをインストールします。
npm install --save-dev textlint-rule-prh
設定ファイルにルールの設定を追加します。
rules: {
"preset-ja-technical-writing": true,
"preset-jtf-style": {
"2.1.6.カタカナの長音": true,
"2.2.1.ひらがなと漢字の使い分け": true,
},
+ prh: { rulePaths: ["./prh.yml"] },
},
下記の様な内容でprh.yml
というファイルを作成します。
version: 1
rules:
- expected: Next.js
pattern:
- nextjs
- next.js
- expected: Zenn
pattern:
- zenn
詳しい書き方は次のサイトを参考にしてください。
textlint-filter-rule-comments
特定の文章ではチェックをオフにしたい場合があります。その時のためのルールを追加します。
npm install --save-dev textlint-filter-rule-comments
設定に追加します。
},
prh: { rulePaths: ["./prh.yml"] },
},
+ filters: {
+ comments: true,
+ },
};
Zennの場合、アコーディオン(トグル)があるのですが、その記述が以下のようになっています。
:::details タイトル
これだと、日本語と半角アルファベットの間にスペースをいれないというルールに引っかかってしまいます。
下記の記述にしておくと処理対象から除外できます。
<!-- textlint-disable -->
:::details ファイル全体
<!-- textlint-enable -->
コミット時に自動実行
prettierとtextlintが実行できるようになってので、コミットした際に自動で実行するようにします。huskyとlint-stagedを使います。
必要なパッケージをインストールします。
npm install --save-dev husky lint-staged
Git hooksを有効にします。
npx husky install
npm install
をした後、Git hooksを自動で有効化するために、package.jsonのscripts
に先ほどのコマンドを追加します。
あわせて、lint-stagedも実行できるように追加します。
"scripts": {
"format": "prettier -w articles/**/*.md",
"lint:text": "textlint --cache $(git diff main --name-only) -f pretty-error",
"lint:text:fix": "textlint --cache $(git diff main --name-only) --fix",
"lint:text:full": "textlint --cache README.md \"articles/**/*.md\" -f pretty-error",
"lint:text:full:fix": "textlint --cache README.md \"articles/**/*.md\" --fix",
+ "prepare": "husky install",
+ "lint-staged": "lint-staged"
},
"keywords": [],
"author": "",
コミット時に実行するスクリプトを作成します。
npx husky add .husky/pre-commit "npm run lint-staged"
.husky/pre-commit
というファイル名でスクリプトが生成されます。
内容は下記のようになります。
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run lint-staged
lint-stagedを実行する内容をpackage.json
に記述します。
+ "lint-staged": {
+ "*.md": [
+ "prettier -w",
+ "textlint --cache --fix",
+ "textlint --cache"
+ ]
+ },
textlintを2回実行しています。最初のtextlintの呼び出しで、自動で直せる箇所は修正します。2回目の呼び出しで、エラーがあった場合はコミットできないようにします。
GitHubアクションを追加
以上で普段Zennの記事を更新していくには十分なのですが、最後にGitHubでプルリクが作成されてたら、チェックが走るようにします。
下記のファイルを作成します。
name: Lint
on:
- pull_request
jobs:
textlint:
strategy:
matrix:
os:
- ubuntu-latest
node-version:
- 14.x
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2.3.0
with:
node-version: ${{ matrix.node-version }}
- name: Get the number of processors currently available
id: processors
run: echo "::set-output name=number::$(getconf _NPROCESSORS_ONLN)"
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Setup reviewdog
run: |
mkdir -p $HOME/bin && curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s -- -b $HOME/bin
echo "$HOME/bin" >> $GITHUB_PATH
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH # for Go projects
- name: Install dependencies
run: npm install
env:
CHILD_CONCURRENCY: ${{ steps.processors.outputs.number }}
NETWORK_CONCURRENCY: ${{ steps.processors.outputs.number }}
- name: textlint
run: npm run lint:text:full -- ${FILES} -f checkstyle --experimental --parallel --max-concurrency ${{ steps.processors.outputs.number }} | reviewdog -f=checkstyle -name="textlint" -reporter=github-pr-review -level=${LEVEL}
env:
FILES: README.md articles/**/*.md
LEVEL: error
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
このファイルをコミットしてプルリクを作成すると、チェックが走っているのを確認できます。
もし、何かエラーがあれば、reviewdogでプルリクにコメントがつくようになります。
おわりに
ZennがGitリポジトリーと連携しくれるお陰で、こういう仕組みができてすごく助かります。
がんばって記事をあげていきます。
Discussion