ドットインストールのtextlint入門を見たあとにやること一覧

textlint入門を見たあとにやること

ドットインストールの新着レッスンにtextlint入門があったので見てみたのだが、これだけではtextlintの校正ルールの半分も使用できてない。

ドットインストール textlint入門

レッスンでは

  • textlint-rule-max-ten
  • textlint-rule-preset-japanese
  • textlint-rule-prh
  • linter-textlint

などがインストールされていたが、業務で使用する場合、これだけでは足りない。

さらにインストールしたほうが良い校正ルール

iwb.jpでは以下の校正ルールを使用している。

使用方法や校正ルールに関しては各GitHub参照

textlint-rule-alex
textlint-rule-common-misspellings
textlint-rule-date-weekday-mismatch
textlint-rule-general-novel-style-ja
textlint-rule-helper
textlint-rule-ja-hiragana-fukushi
textlint-rule-ja-hiragana-hojodoushi
textlint-rule-ja-hiragana-keishikimeishi
textlint-rule-ja-nakaguro-or-halfwidth-space-between-katakana
textlint-rule-ja-no-abusage
textlint-rule-ja-no-mixed-period
textlint-rule-ja-no-redundant-expression
textlint-rule-ja-no-space-around-parentheses
textlint-rule-ja-no-space-between-full-width
textlint-rule-ja-no-successive-word
textlint-rule-ja-no-weak-phrase
textlint-rule-ja-space-after-exclamation
textlint-rule-ja-space-after-question
textlint-rule-ja-space-around-code
textlint-rule-ja-space-between-half-and-full-width
textlint-rule-ja-unnatural-alphabet
textlint-rule-max-comma
textlint-rule-max-kanji-continuous-len
textlint-rule-max-ten
textlint-rule-no-dead-link
textlint-rule-no-double-negative-ja
textlint-rule-no-doubled-conjunction
textlint-rule-no-doubled-conjunctive-particle-ga
textlint-rule-no-doubled-joshi
textlint-rule-no-dropping-the-ra
textlint-rule-no-exclamation-question-mark
textlint-rule-no-hankaku-kana
textlint-rule-no-mix-dearu-desumasu
textlint-rule-no-mixed-zenkaku-and-hankaku-alphabet
textlint-rule-no-nfd
textlint-rule-no-surrogate-pair
textlint-rule-prefer-tari-tari
textlint-rule-preset-ja-spacing
textlint-rule-preset-ja-technical-writing
textlint-rule-preset-japanese
textlint-rule-preset-jtf-style
textlint-rule-prh
textlint-rule-rousseau
textlint-rule-sentence-length
textlint-rule-spellcheck-tech-word
textlint-rule-terminology
textlint-util-to-string

かなり多いが

  • textlint-rule-preset-japanese
  • textlint-rule-preset-ja-spacing
  • textlint-rule-preset-ja-technical-writing
  • textlint-rule-preset-jtf-style

の4つをインストールすれば8割はインストール完了だ。

実行時はnpx textlintかtextlint

ドットインストールでは./node_modules/.bin/textlint -v形式で実行しているが、npmのバージョン5.2以上ならnpx textlint -vで実行できる。

さらに--globalでインストールした場合はtextlint -vで実行可能。

npm install textlint --global

prh用YAMLをスプレッドシートで作成

GogleをGoogleにするなどのルールを作成する際にはYAML形式で作成するが、この形式は慣れていないと記述しづらい。

# prhサンプル
version: 1
rules:

  - patterns: Gogle
    expected: Google

  - patterns: /textlint/i
    expected: textlint

GoogleスプレッドシートとGoogle Apps Scriptを使用すればスプレッドシートに入力した内容をウェブアプリケーションとして導入を使用すればYAML形式で簡単に書き出すことができる。

この方法だとYAML形式に慣れていないエンジニアでない人でも校正ルール作成に参加しやすくなるメリットもある。
GoogleスプレッドシートとGoogle Apps Scriptを使用すればスプレッドシートに入力した内容をウェブアプリケーションとして導入を使用すればYAML形式で簡単に書き出すことができる。

// Output YAML code by Google Apps Script!
var cTitle = 'prhサンプル';
var version = 1;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();

function doGet(e) {
  var result;
  var cco = function(s) {
    return ContentService.createTextOutput(
      '# ' + cTitle + '\nversion: ' + version + '\nrules:\n' + s
    );
  };
  result = cco(JSON.stringify(toXSV(sheet))
    .replace(/,/g, '\n')
    .replace(/"(patterns|expected)":"(.+?)"/gm, '$1: $2')
    .replace(/^\[?{/gm, '')
    .replace(/}\]?$/gm, '')
    .replace(/^(patterns:)/gm, '\n  - $1')
    .replace(/^(expected:)/gm, '    $1')
    .replace(/\\\\/gm, '\\')
  );
  return result;
}

function toXSV(sheet) {
  var jIndex = 1;
  var colIndex = 0 + jIndex;
  var rowNum = 0 + jIndex;
  var firstRange = sheet.getRange(1, 1, 1, sheet.getLastColumn());
  var firstRowValues = firstRange.getValues();
  var titleColumns = firstRowValues[0];
  var lastRow = sheet.getLastRow();
  var rowValues = [];
  var jsonArray = [];
  for(var rowIndex=1+jIndex; rowIndex<=lastRow; rowIndex++) {
    var colIndex = 1;
    var rowNum = 1;
    var range = sheet.getRange(rowIndex, colIndex, rowNum, sheet.getLastColumn());
    var values = range.getValues();
    rowValues.push(values[0]);
  }
  for(var i=0; i<rowValues.length; i++) {
    var line = rowValues[i];
    var json = {};
    for(var j=0; j<titleColumns.length; j++) {
      json[titleColumns[j]] = line[j];
    }
    jsonArray.push(json);
  }
  return jsonArray;
}

.textlintrcの設定

ドットインストールでは.textlintrcの作成を手動で行っていたが、npx textlint --initを実行すれば現在インストールされているものをすべてtrueにした初期設定.textlintrcファイルが書き出される。

npx textlint --init

しかし最初の内は学習も兼ねて.textlintrcの設定を手動で追加するのも悪くない。

// .textlintrc設定例
{
  "rules": {
    "preset-japanese": {
      "sentence-length": false,
      "max-comma": false,
      "max-ten": false,
      "no-doubled-joshi": false,
    },
    "preset-ja-technical-writing": {
      "sentence-length": false,
      "max-comma": false,
      "max-ten": false,
      "max-kanji-continuous-len": false,
      "no-doubled-joshi": false,
      "no-exclamation-question-mark": false,
      "ja-no-mixed-period": false,
    },
    "preset-ja-spacing": {
      "ja-no-space-between-full-width": false,
    },
    "prh": {
      "rulePaths": [
        "rules/prh.yml"
      ]
    },
    "ja-unnatural-alphabet": true,
    "ja-no-redundant-expression": true,
    "ja-hiragana-keishikimeishi": true,
    "textlint-rule-ja-hiragana-fukushi": true,
    "textlint-rule-ja-hiragana-hojodoushi": true,
    "no-surrogate-pair": true,
    "no-mixed-zenkaku-and-hankaku-alphabet": true,
    "prefer-tari-tari": true,
    "spellcheck-tech-word": true,
    "@textlint-ja/textlint-rule-no-insert-dropping-sa": true,
    "rousseau": {
      "showLevels": ["warning", "error"],
      "ignoreTypes": [
        "sentence:uppercase",
        "sentence:start"
      ]
    },
    "date-weekday-mismatch": {
      "lang": "ja"
    },
    "no-dead-link": {
      "checkRelative": true,
      "baseURI": null,
      "ignore": [],
      "preferGET": []
    },
    "alex": {
      "allow": []
    },
    "common-misspellings": {
      "ignore": []
    },
    "general-novel-style-ja": {

      // 各段落の先頭に許可する文字 (false: チェックしない)
      "chars_leading_paragraph": false,

      // 閉じ括弧の手前に句読点(。、)を置かない
      "no_punctuation_at_closing_quote": true,

      // 疑問符(?)と感嘆符(!)の直後にスペースを置く
      "space_after_marks": true,

      // 連続した三点リーダー(…)の数は偶数にする
      "even_number_ellipsises": false,

      // 連続したダッシュ(―)の数は偶数にする
      "even_number_dashes": true,

      // 連続した句読点(。、)を許可しない
      "appropriate_use_of_punctuation": true,

      // 連続した中黒(・)を許可しない
      "appropriate_use_of_interpunct": true,

      // 連続した長音符(ー)を許可しない
      "appropriate_use_of_choonpu": true,

      // マイナス記号(−)は数字の前にしか許可しない
      "appropriate_use_of_minus_sign": true,

      // アラビア数字の桁数は2桁まで (false: チェックしない)
      "max_arabic_numeral_digits": false
    },
  }
}

技術文書向けのtextlintルールプリセットtextlint-rule-preset-ja-technical-writingをインストールしているため、これだけでも多くの用語の間違えを検出してくれるが、検出されない用語はprhのprh.ymlにルールを自分で記述する。

例えばJavaScriptはpreset-ja-technical-writingに含まれているため検出されるが、TypeScriptは含まれていないため自分で校正ルールを追加する必要がある。

また、放送禁止用語の校正ルールがないため、独自にprh.ymlに追加してある。

prh.yml

PuppeteerでWebサイトのテキストファイル作成

textlintはテキストファイルの文章校正に使用するものなのでWebサイトの文章校正には直接使用できない。

Webサイトの文章校正を行う場合はPuppeteerでWebサイトのチェックしたい箇所のテキストを取得してテキストファイルを作成するとチェックしやすくなる。

例えばiwb.jpの以下の3ページの投稿記事の文書校正をしたい場合は.entry-content内のテキストを取得してfsでテキストファイルを作成する。(ファイル名はURLの一部を使用)

コード(.syntaxhighlighter)部分は文章校正の対象外にしたいため、innerHTML = ''で削除した。

この方法なら不要な箇所を除いて特定の部分のテキストだけチェックできるため効率的だ。

サンプルなので簡素な作りにしたが、実作業の際はテキスト内のURLなども取り除くと良いだろう。(大文字・小文字のチェックで引っかかるため)

const puppeteer = require('puppeteer');
const fs = require('fs');
const urls = [
  'https://iwb.jp/puppeteer-headless-chrome-evaluate/',
  'https://iwb.jp/google-gmap-embed-apisite-invisible/',
  'https://iwb.jp/minimum-dom-exec-jquery-javascript/'
];

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  for (const url of urls) {
    await page.goto(url);
    console.log(url);
    if (await page.$('.syntaxhighlighter') !== null) {
      await page.$$eval('.syntaxhighlighter', c => c.map(e => e.innerHTML = ''));
    }
    const fileName = url.replace(/https:\/\/iwb.jp\/(.+?)\//g, '$1');
    const text = await page.$eval('.entry-content', e => e.innerText);
    fs.writeFileSync(`docs/${fileName}.txt`, text);
  }
  browser.close();
});

Puppeteerで作成されたテキストファイル

1ページの一部分だけならChromeのConsoleからcopy($0.innerText)でテキストをコピーしてテキストファイルを作成するという方法もある。
1ページの一部分だけならChromeのConsoleからcopy($0.innerText)でテキストをコピーしてテキストファイルを作成