【スペルミスを許さない】社内単語・PJの単語を辞書パッケージ化して快適にtypoを破壊しよう【ユビキタス言語】

ChatGPTの話題で「これからのプログラミング言語は英語」なんて話はよく聞きます。
しかし毎日母語でもない英語の単語をふんだんに使ってプログラミングをしている皆様、英語のスペルに自信はありますか？

- **reslt** （正:result）
- **adress** （正:address）
- **atrribute** （正：attribute）

「**あ～**」と声を漏らす方は想像より多いのでしょう。
何度かスペルミスを絶対許さない民が執筆した記事が人気になっていた記憶があります。

- [VSCode に Code Spell Checker を導入して typo と戦う](https://qiita.com/diescake/items/98c5a099e85775cd917d)
- [【全人類へ】お前らはスペルミスが多すぎるッッ！！絶対に入れて欲しい拡張機能！【VisualStudioCode】](https://qiita.com/f0lst/items/400b01e430d06f0be690)

こちらで紹介されているのはVSCodeの拡張機能である「[Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)」です。
入れておけば圧倒的にタイプミスを減らすことが出来ます。

![image.png](https://raw.githubusercontent.com/streetsidesoftware/vscode-spell-checker/main/images/suggestions.gif)


https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker

これは間違いなく正義です。
最も手軽にスペルミスを減らすことが出来る手段と言えるでしょう。

**しかし、これでは足りないのです。**

# Code Spell Checker（CSpell）の辞書は汎用的

Code Spell Checker は、CSpellという解析ツールを利用したプロダクトの一つです。

CSpellは各プログラミング言語の単語及び言語特有の用語について特化した、ソースコード専門のtext linterのようなものです。

英語を始めとする単語辞書を基準としたホワイトリスト方式で稼働します。
つまり以下のものには圧倒的に弱いのです。

- 社内用語
- PJ特有の用語
- ニッチなドメイン知識の単語
- 日本語をローマ字にしたもの

（そもそもローマ字を含むことを許さないという過激派は一旦見ないこととする）

## 単語登録

標準の辞書に収録されていないものに関しては、

![image.png](https://github.com/kbkn3/cspell-dict-riichi-mahjong/raw/develop/images/vscode_fix.png)

クイックフィックスから修正もしくは`user settings`や`workspace settings`に対して辞書登録が出来ます。

![image.png](https://github.com/kbkn3/cspell-dict-riichi-mahjong/raw/develop/images/vscode_select.png)

## チーム開発・複数リポジトリの開発では力不足

私は麻雀に関わるアプリを複数開発しています。
その中で麻雀の用語はどうしても CSpell には弾かれます。

- 立直（リーチ）： `riichi`
- 門前清自摸和（ツモ）: `tsumo`
- etc...

毎度 VSCode の `workspace` や `user settings`に保存しても良いのですが、複数人・複数リポジトリで開発しているのであれば単語の基準は揃えたいところです。そこで辞書パッケージを作成する方法を紹介します。

# 辞書パッケージを作成する方法

構成はこのような形になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215371/a4a86c74-ea25-2202-eb93-c0fa88292dff.png)

npm packageを装いつつも、実質的な中身は辞書である `txt` と設定を書いた `json` のみ。

## 辞書ファイル

```.cspell/yaku.txt
# WRC 役一覧より
# From the WRC Yaku List

# 1han （1飜）
riichi #立直
menzen #門前
tsumo #自摸
menzentsumo #門前清自摸和
ippatsu # 一発
︙
```
辞書登録についてはこのように`txt`ファイルに並べるだけで可能です。
また禁止単語の設定や接頭辞としての登録など、ある程度の柔軟性がありますので、詳細はドキュメントを参照してください。

https://cspell.org/docs/dictionaries-custom/#words-list-syntax

## 設定ファイル

cspell の設定ファイル `cspell.yaml` で
```cspell.yaml
{
  version: "0.2",
  language: "en",
  ignorePaths: ["node_modules/**"],
  dictionaries: ["en_US","softwareTerms","typescript","node","php","go","html","css","bash","fonts","filetypes","npm"],
  languageSettings: [
    {
        # VSCode languageId. i.e. typescript, java, go, cpp, javascript, markdown, latex
        # * will match against any file type.
        languageId: "*",
        # Language locale. i.e. en-US, de-AT, or ru. * will match all locales.
        # Multiple locales can be specified like: "en, en-US" to match both English and English US.
        locale: "en,en-US",
        # List of dictionaries to enable by name in `dictionaryDefinitions`
        dictionaries: ["game","pro","rule","yaku"],
        # Dictionary definitions can also be supplied here. They are only used if "languageId" and "locale" match.
        dictionaryDefinitions: [
          {
            # The name of the dictionary is used to look it up.
            name: "game",
            # Path to the custom word file. Relative to this `cspell.json` file.
            path: "./.cspell/game.txt",
            addWords: false
          },
          {
            name: "pro",
            path: "./.cspell/pro.txt",
            addWords: false
          },
          {
            name: "rule",
            path: "./.cspell/rule.txt",
            addWords: false
          },
          {
            name: "yaku",
            path: "./.cspell/yaku.txt",
            addWords: false
          }
        ]
    }
  ]
}

```

設定ファイルの詳細については [Configulation - CSpell](https://cspell.org/configuration/#configuration) を御覧ください。

## 配布

npmパッケージとして配布する方法についてはGitサービスや採用するCIによって変わりますので、それぞれご確認ください。

- [Node.jsパッケージの公開 - Github Docs](https://docs.github.com/ja/actions/publishing-packages/publishing-nodejs-packages)
- [GitHub Packages の npm レジストリを使って、社内 org 用のプライベートパッケージを公開する手順とインストールする手順 - Zenn](https://zenn.dev/moneyforward/articles/20230620-github-packages)

今回私は例としてGithub Packageで公開しています。

https://github.com/kbkn3/cspell-dict-riichi-mahjong

## 利用

```bash
npm install -D @kbkn3/cspell-dict-riichi-mahjong
```

あなたのリポジトリに合わせて`cspell.json` / `cspell.yaml`を作成します。
`import`は`node_modules`にインストールされたディレクトリ構成に合わせてPathを書くイメージです。

```cspell.yaml
{
  version: "0.2",
  language: "en",
  import: ["@kbkn3/cspell-dict-riichi-mahjong/cspell.yaml"],
  # リポジトリ固有の用語を追加する。
  words: [
    "chii-nya!",
  ],
  ignorePaths: ["node_modules/**"],
  minWordLength: 4
}
```

このようにパッケージ化して共有することで、**社内・チーム内言語の統一に繋がり、typoを破壊し、幸せな世界に一歩近づくことができるでしょう**。

# まとめ

社内共通辞書を作ることは実はユビキタス言語策定とも重なるものになります。
社内用語の表記ゆれなんて最悪としか言いようがありません。
御社のAPIのパラメータやレスポンスのkeyにtypoはありませんか？

全てのtypoを撲滅し、エラーを未然に防ぐ社会を（過激派）

https://zenn.dev/leaner_dev/articles/20210922-ubiquitous-language

もう少し緩く、リポジトリごとにきれいに辞書を策定したい人に向けて同志を紹介して締めとします。

https://zenn.dev/75asa/articles/vanish-typo-by-github-action-and-vscode

# おまけ：CSpellツールの使い分け

Code Spell Checker は CSpell （https://cspell.org/） プロジェクトのプロダクトの一つです。
CSpellのプロダクトはいくつかあるのでご紹介します。

## Code Spell Checker （VScode 拡張機能）

### 長所

- VSCode に拡張機能をインストールするだけで利用できる。
- エディタ上に `INFO` の下線が表示される

### 短所

- 編集中のコードのみスペルチェックされ、リポジトリ全体はチェックされない。

## CSpell CLI

### 長所

- 動作が速い
- huskyなどを利用して`commit`時にチェックできる。

### 短所

- コーディング中にスペルミスに気づかない。

## CSpell-ESLint

### 長所

- エディタ上に `WARN` の下線が表示される
- 既存の eslint の設定に追記すれば利用可能
- エディタの下線部クイックフィックスからリポジトリごとの辞書への追加が可能

### 短所

- CSpell 系の設定を変更したあとのpnpm run lintは時間がかかる

## Github Actions

- CIの一貫に組み込むことができる

## 推奨する使い分け

**VSCode 拡張機能 と CSpell-CLI は併用することを推奨します**。 CSpell-CLI と CSpell-ESLint の併用は役割が被るため非推奨です。

# おまけ：CSpellツールごとの使い方

## Code Spell Checker（VScode 拡張機能）

1. [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)をインストールする。
2. ウィンドウをリロードする `cmd + Shift + P`

[How to Use with VSCode Extension](https://github.com/kbkn3/cspell-dict-riichi-mahjong/blob/master/HowToUseWithVSCodeExt.md)

## CSpell CLI

1. `npm install -g cspell` or `npm install cspell`
2. npm-scriptを登録する。
    ```package.json
    ︙
      "scripts": {
          "spellcheck": "pnpm cspell ./src --cache --no-progress --config ./cspell.json || exit 0",
          "spellcheck-all": "pnpm cspell ./src --no-progress --config ./cspell.json || exit 0"
      }
    ︙
    ```

3. (オプション)  コミットごとに自動スペルチェックをしたい場合は、[husky](https://github.com/typicode/husky)などのインストールを検討してください。

https://zenn.dev/luvmini511/articles/ade1f0e4b64770

## CSpell-ESLint

1. `@cspell/eslint-plugin`をインストールする。
    ```bash
    npm install --save-dev @cspell/eslint-plugin
    ```
2. `.eslintrc.json`に追記する。
    ```.eslintrc.json
    "extends": ["plugin:@cspell/recommended"]
    ```
3. Example:
   ```json
   {
    "plugins": ["@cspell"],
    "rules": {
      "@cspell/spellchecker": ["warn", { "checkComments": false, "autoFix": false }]
      }
    }
    ```