textlintで日本語の自動校正サービスを作ってみた!

ほりでー


textlintで日本語の自動校正サービスを作ってみた!

こんにちは。フロントエンドエンジニアのほりでーです。

Web関係のお仕事をされている方のなかには、業務のノウハウを自社のブログや個人のサイト、はてなやQiitaなどのブログサービスを通じて発信されている方も多いでしょう。私もLIGブログへ載せるには敷居の高いネタはQiitaへ投稿することが多いです。しかし、推敲が苦手なので自分のあまりの誤字脱字の多さに辟易してしまうことがあります。

エンジニアにとっての国語のライティングは、技術記事の執筆以外においても案外重要なスキルです。要件定義書、仕様書、環境構築手順書、Wiki、README、コミットログ、チケット、バグレポートなど、コード以外にもエンジニアが書くべきドキュメントはたくさんあります

こういった日本語のライティングを強力にサポートしてくれるのがtextlint(テキストリント)という校正支援ツールです。

今回はこのtextlintとTravisCIというツールを使い、GitHubリポジトリに連動する自動校正サービスの構築方法をご紹介します。

▼目次

サンプルコード

今回使用したコード一式をGitHubで公開しています。このリポジトリとGitHub/TravisCIアカウントがあれば、すぐに自動校正サービスを試せるようになっています。

hokkey/textlint-travis-demo: A demo project to run textlint in TravisCI

校正支援ツール・textlint(テキストリント)

lint(リント)とは

プログラマーを支援するツールとして、以前からlint(リント)と呼ばれる種類のアプリケーションがあります。lintはコードの内容を自動的に検査し、バグの温床となりそうな悪い書き方を指摘して、修正を促すユーティリティです。

JavaScript用のlintであれば、昔はjslint(ジェイ・エス・リント)やjshint(ジェイ・エス・ヒント)、最近であればeslintt(イー・エス・リント)などのツールが有名です。lintを導入すると、プログラミングの細かい実装のぶれをなくせるため、特にチームで開発しているときには有益です。

textlint(テキストリント)とは

このlintの考え方を、プログラミング言語ではなく自然言語(=日本語や英語など、人間が読んだり話したりする言語のこと)に応用したものがtextlint(テキストリント)です。

textlint/textlint: The pluggable natural language linter for text and markdown.

textlintはnode.js製のコマンドラインツールで、主にMarkdown形式のドキュメントに対応した校正機能を持っています。たとえば、技術文書を対象としたプリセット『textlint-rule-preset-ja-technical-writing』では、次のようなルールを適用できます。

  • ですます調とだである調を統一する
  • 二重否定は使用しない
  • ら抜き言葉を使用しない
  • 逆接の接続助詞「が」を連続して使用しない
  • 同じ接続詞を連続して使用しない
  • 同じ助詞を連続して使用しない
  • 半角カナを使用しない

※上記は一例です。詳細はGitHub上の説明をご覧ください。

textlint-ja/textlint-rule-preset-ja-technical-writing: 技術文書向けのtextlintルールプリセット

こういったプリセットルールがオープンソースで公開されているため、それらを組み合わせて自分のライティングスタイルに最適なlintを作れるようになっています。

textlintの場合、作者が日本人のため、日本語関係のルールやドキュメントが比較的充実しているのも特長です。

textlintの導入

node.jsの準備

textlintを使うにはnode.jsが必要になります。nodebrewやnvmなどの環境管理ツールを使い、バージョン7系に切り替えておきましょう。nodebrewでv7.4.0を導入する方法は次のとおりです。

$nodebrew install-binary v7.4.0
$nodebrew use v7.4.0
$node -v
v7.4.0

nodebrewとnvmのどちらもインストールしていない! という方は、まずはnode.jsの環境構築からスタートしましょう。

textlintのインストール

今回の構成では適当なディレクトリを作り、textlintをローカルインストールします。

$mkdir textlint-demo && cd $_
$npm init --yes
$npm install --save textlint

校正プリセットのインストール

初期状態のtextlintには何も校正ルールが入っていないため、さらにプリセットをインストールしましょう。今回は先程も紹介した『textlint-rule-preset-ja-technical-writing』と、技術用語の表記ぶれを整える『textlint-spellcheck-tech-word』を追加します。

$npm install --save textlint-rule-preset-ja-technical-writing textlint-spellcheck-tech-word

設定ファイルの追加

インストールしたプリセットは、設定ファイルで利用を宣言しないと利用できません。不可視ファイル「.textlintrc」を作成し、その中へJSON形式の設定を記述します。

$touch .textlintrc

 

適当なテキストエディタで「.textlintrc」へ次のJSONコードをペーストしてください。

{
    "rules": {
        "spellcheck-tech-word": true,
        "preset-ja-technical-writing": true
    }
}

 

校正ルールは、これ以外にも多数GitHub上で公開されています

  1. npm install –save textlint-○○○○ でインストールする
  2. .textlintrcの「rules」へ「”○○○○”: true」を追加する

この手順でいくつでも適用したいルールを増やせるので、ひととおり慣れたら他のルールも追加してみるのもよいでしょう!

npmスクリプトの追加

package.jsonの「scripts」オブジェクトの中へ、textlintを実行するコードを挿入してください。これもJSONなのでカンマに気をつけてくださいね!

"lint": "textlint ./*.md",
"lintfix": "textlint --fix ./*.md",

package.jsonの確認

デフォルトの「package.json」にこれまでの変更を加えると次のようになっているはずです(dependenciesのバージョン番号は、今後の変更によって変わる場合があります)。

{
  "name": "textlint-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "lint": "textlint ./*.md",
    "lintfix": "textlint --fix ./*.md",
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "textlint": "^7.2.2",
    "textlint-rule-preset-ja-technical-writing": "^0.1.3"
  }
}

Markdownファイルの追加

これで準備ができましたが、校正対象となるMarkdownの原稿がまだありません。今回は、サンプルとして私がQiitaで書いた記事を「demo.md」として保存してみることにします。

LPなどの視覚的なデザインを売りとしたサイトの場合、高い水準でカンプ通りの実装が求められる。自分では狂いなく再現したつもりでも、どこかでずれていてデザイナーから指摘されることもしばしばある。この記事では、[^1]デザインカンプの徹底再現([^2] ピクセルパーフェクト)の必要性と、そのための便利なMacOSXアプリケーションを紹介する。

**要約**

* 他人の作ったデザインを高いレベルで再現するには、ピクセルパーフェクトを狙うくらいの意気込みが必要
* その為には、ブラウザへカンプを重ね合わせるチェックが有効
* Helium/Mapture/LayxerXは、フローティングと透過機能を持った非常に便利なアプリケーション

<!-- 長いので以下略 -->

textlintを実行する

ここまでくれば準備完了です。「npm run -s lint」を実行してlintの結果を見てみましょう!

$npm run -s lint

/Users/Shared/Documents/working/textlint-demo/demo.md
    1:150  ✓ error  MacOSX => Mac OS X                             spellcheck-tech-word
   14:1    error    Line 14 exceeds the maximum line length of 90  preset-ja-technical-writing/sentence-length
   14:55   error    一つの文で"、"を3つ以上使用しています          preset-ja-technical-writing/max-ten
   22:1    ✓ error  Webブラウザ => ブラウザ                        spellcheck-tech-word
   26:31   ✓ error  文末が"。"で終わっていません。                 preset-ja-technical-writing/ja-no-mixed-period
   30:33   error    弱い表現: "かも" が使われています。            preset-ja-technical-writing/ja-no-weak-phrase
   34:66   error    一つの文で"、"を3つ以上使用しています          preset-ja-technical-writing/max-ten
   34:76   ✓ error  文末が"。"で終わっていません。                 preset-ja-technical-writing/ja-no-mixed-period
   77:3    ✓ error  Webブラウザ => ブラウザ                        spellcheck-tech-word
   88:1    error    Line 88 exceeds the maximum line length of 90  preset-ja-technical-writing/sentence-length
   88:47   ✓ error  Webブラウザ => ブラウザ                        spellcheck-tech-word
   94:39   ✓ error  Webブラウザ => ブラウザ                        spellcheck-tech-word
   94:128  error    弱い表現: "思う" が使われています。            preset-ja-technical-writing/ja-no-weak-phrase
  150:1    ✓ error  node.js => Node.js                             spellcheck-tech-word
  152:32   ✓ error  node.js => Node.js                             spellcheck-tech-word

✖ 15 problems (15 errors, 0 warnings)
✓ 9 fixable problems.
Try to run: $ textlint --fix [file]

 

結構色々でてきますね……。でも、検査結果が日本語で出てくるのが分かりやすい! この指示にしたがって原稿を修正していきます。

ここで「✓」マークが付いているエラーは自動で修正可能です。修正するには「npm run -s lintfix」を実行してください。

$npm run -s lintfix

/Users/Shared/Documents/working/textlint-demo/demo.md
    1:150  ✔   MacOSX => Mac OS X              spellcheck-tech-word
   22:1    ✔   Webブラウザ => ブラウザ         spellcheck-tech-word
   77:3    ✔   Webブラウザ => ブラウザ         spellcheck-tech-word
   88:47   ✔   Webブラウザ => ブラウザ         spellcheck-tech-word
   94:39   ✔   Webブラウザ => ブラウザ         spellcheck-tech-word
  150:1    ✔   node.js => Node.js              spellcheck-tech-word
  152:32   ✔   node.js => Node.js              spellcheck-tech-word
   26:31   ✔   文末が"。"で終わっていません。  preset-ja-technical-writing/ja-no-mixed-period
   34:76   ✔   文末が"。"で終わっていません。  preset-ja-technical-writing/ja-no-mixed-period

✔ Fixed 9 problems

 

表記ルールにしたがって文言ファイルが修正されました!

無視フィルターの追加

とはいえ、中にはあえて修正したくないlint結果も報告されてくることでしょう。これを無視するためには『textlint-filter-rule-comments』というパッケージを追加します。

$npm install --save textlint-filter-rule-comments

 

次に「.textlintrc」を次の状態に書き換えます。

{
    "rules": {
        "spellcheck-tech-word": true,
        "preset-ja-technical-writing": true
    },
    "filters": {
        "comments": true
    }
}

 

この設定により、「demo.md」で次のような<!– textlint-disable –>と<!– textlint-enable –>コメントで挟まれた部分を、textlintから無視する範囲として指定できます。

# なぜピクセルパーフェクトを目指すのか

<!-- textlint-disable -->

Webサイトという技術の特性上、フォントが違ったり、組版の仕様が違ったり、文字サイズのデフォルト値が違ったり、モニタの色見が周辺環境や端末スペックによって違ったりとするため、**ピクセルパーフェクトにこだわる理由は本来的には無い**。

<!-- textlint-enable -->

 

上記箇所にはtextlintの警告が出ていましたが、コメントで囲み、警告を無視させられるようになりました(前後の改行がこのとおりでないと効かないので注意)。

今後継続的にこのフォルダの中へ校正対象となる原稿を足していった場合、修正しない部分をコメントで除外しないとエラーの数が膨大になってしまいます。

TravisCIで自動校正サービスを作る

これでtextlintをローカルで実行できるようになりました。次は、この仕組みをGitHubとTravisCIを使い、クラウド上で自動実行できるようにしてみましょう。

TravisCI(トラビス・シー・アイ)とは

TravisCI(トラビス・シー・アイ)とは「継続的インテグレーション」のためのWebサービスで、GitHub上のオープンソースプロジェクトからは無料で利用できます。

継続的インテグレーションとは

「継続的インテグレーション」とは、ソフトウェア開発方法の1つです。専用のサーバを用意してコードの状態を頻繁に監視しながら、ビルドや自動テストが失敗しないかを自動的にチェックしたり、問題がなければ自動的にそのコードを公開するなど、色々なルーチンワークを自動化して開発効率と品質をアップさせることを目的とします。この「継続的インテグレーション」を簡単に導入できるWebサービスの1つがTravisCIです。

今回は、この継続的インテグレーションの仕組みをソフトウェアの品質管理ではなく、原稿の品質管理へ応用します。

TravisCIへのtextlint導入方法

TravisCIのアカウント作成とGitHub公開リポジトリとの連携

GitHubアカウントがあればTravisCIのアカウントもすぐに作成できます。まだGitHubアカウントをお持ちでない方は、この機会に両方作成してしまいましょう!

次に、GitHubへ適当な公開リポジトリを作成します。今回は「textlint-travis-demo」という名称にしました。

その後、TravisCI上でそのリポジトリとの連携を有効化します。

歯車アイコンをクリックすると、その連携の設定を確認できます。

設定では、図のように「Build only if .travis.yml is present」をONにしておきます。

.travis.ymlの作成

これまでのデモで作成したtravis-demoディレクトリへ移動し、新しい不可視ファイル.travis.ymlを作成します。この.travis.ymlは、TravisCIで実行してほしい命令を記述する設定ファイルです。

sudo: false
language: node_js
node_js:
  - '7.4.0'
before_script:
  - npm install
script:
  - npm run lint -s

ローカルリポジトリの作成とリモートリポジトリの設定

最後に、git initとgit commitをしてから、先程作成したGitHub上のリポジトリをリモートに登録&pushしましょう。

$git init
$git add . -m "Initial commit"
$git remote add origin # ここに自分のGitHubリポジトリURLをセット #
$git push -u origin master

TravisCIでtextlintの結果を表示

pushが完了したら、TravisCIにアクセスしてみましょう。数秒後にはTravisCIの処理がスタートしているはずです。

TravisCI内にある仮想マシン上では、nodejsのインストールとnpmパッケージのインストールが自動的に行われ、最終的にtextlintのコマンドが実行されます。

今回はわざと修正部分を残しているので、CIの実行結果はエラーっぽい雰囲気になりました。

実行ログの末尾にtextlintの結果が出力されています。成功ですね!

未来の出版ワークフロー?

今回はこれで終了ですが、CIと連動して文書校正をかけられるようになると、以下のようなワークフローを思い浮かべることもできます。

intellij-16

  • 校正ルールのプリセットをよくカスタマイズし、その媒体の独自ルールに最適化する
  • GitHubで原稿を管理し、CIを通じて自動校正をかける
  • 自動校正の結果をSlackなどへ配信し、編集者に通知する
  • GitHub上のツールを使い、赤字校正や素材の手配をする

このワークフローでメリットの大きい業界があるとすれば、それは出版業界ではないでしょうか。

前回の記事でも触れたとおり、私は前職でエディトリアルデザイナーをしていました。締め切り直前のあのバタバタとした原稿のやりとりがシステム化でスムーズになれば、大幅に業務の効率化ができるかもしれませんね!

ほりでー
この記事を書いた人
ほりでー

フロントエンドエンジニア

関連記事