textlint v15.0.0をリリースしました!

textlint v15は、v12.3.0から非推奨としてマークされていた古いAPIをすべて削除するメジャーリリースです。

textlint v15.0.0の変更点

主要な変更点は次の通りです。

Breaking Changes

  • Node.js 20+のサポート(Node.js 16,18はサポート終了
  • TextLintEngineを削除 → createLinter()
  • TextFixEngineを削除 → createLinter()
  • TextLintCoreを削除 → createLinter()または@textlint/kernel
  • textlint(シングルトンインスタンス)を削除 → createLinter()
  • createFormatterを削除 → loadFormatter()

Node.js 20以上が必要

textlint v15では、Node.js 20.0.0以上が必要になりました。 Nodejs 18はEOL(End of Life)となっているため、Node.js 20以上を使用する必要があります。

非推奨APIの削除

textlintパッケージをNode.jsモジュールとして利用する場合のみ影響を受ける変更です。

textlint v15では、非推奨となっていた次のAPIが完全に削除されました。

移行ガイドは次のページに用意しています。

TextLintEnginecreateLinter()

変更前(v14以前):

const { TextLintEngine } = require("textlint");

const engine = new TextLintEngine({
    configFile: ".textlintrc.json"
});
const results = await engine.executeOnFiles(["*.md"]);
const output = engine.formatResults(results);
console.log(output);

変更後(v15以降):

import { createLinter, loadTextlintrc, loadLinterFormatter } from "textlint";

const descriptor = await loadTextlintrc({
    configFilePath: ".textlintrc.json"
});
const linter = createLinter({ descriptor });
const results = await linter.lintFiles(["*.md"]);
const formatter = await loadLinterFormatter({ formatterName: "stylish" });
const output = formatter.format(results);
console.log(output);

TextFixEnginecreateLinter()

変更前(v14以前):

const { TextFixEngine } = require("textlint");

const engine = new TextFixEngine();
const results = await engine.executeOnFiles(["*.md"]);

変更後(v15以降):

import { createLinter, loadTextlintrc } from "textlint";

const descriptor = await loadTextlintrc();
const linter = createLinter({ descriptor });
const results = await linter.fixFiles(["*.md"]);

TextLintCorecreateLinter()

変更前(v14以前):

const { TextLintCore } = require("textlint");

const textlint = new TextLintCore();
textlint.setupRules({
    "rule-name": require("./my-rule")
});
const result = await textlint.lintText("Hello world", "test.md");

変更後(v15以降):

import { createLinter } from "textlint";
import { TextlintKernelDescriptor } from "@textlint/kernel";
import { moduleInterop } from "@textlint/module-interop";

const descriptor = new TextlintKernelDescriptor({
    rules: [
        {
            ruleId: "rule-name",
            rule: moduleInterop((await import("./my-rule")).default)
        }
    ]
});
const linter = createLinter({ descriptor });
const result = await linter.lintText("Hello world", "test.md");

その他の改善

Exit Statusの改善

textlint v15では、ESLintの動作に合わせてExit Statusが改善されました。

  • Fatalエラー: Exit Status 2を返す(従来は1)
  • Lintエラー: Exit Status 1を返す(変更なし)
  • 成功: Exit Status 0を返す(変更なし)
# v15+ behavior
textlint nonexistent-file.md     # Exit Status: 2 (file search error)
textlint file-with-errors.md     # Exit Status: 1 (lint errors)
textlint clean-file.md           # Exit Status: 0 (success)

絶対パスのファイルも.textlintignoreのパターンを尊重

textlint v15では、絶対パスのファイルが.textlintignoreパターンを正しく尊重しない問題が修正されました。

以前は、.textlintignoreで記載されたパターンがマッチしていても、絶対パスとして渡された場合は無視されていませんでした。 v15では、絶対パスのファイルも.textlintignoreのパターンを正しく尊重するようになりました。

# Before v15 (Bug)
textlint /absolute/path/to/ignored-file.md  # Lintされてしまっていた

# v15+ (Fixed)
textlint /absolute/path/to/ignored-file.md  # Lintの対象外となった

詳しくは、GitHub Issue #1412を参照してください。

Model Context Protocol (MCP)の統合強化

textlint v14.8.0から、textlint --mcpでtextlintをMCPサーバーとして起動できます。

textlint v15では、MCPのサポートを改善しています。 2025-06-18のKey Changes - Model Context Protocolに基づいて、次の変更が行われました。

  • Structured Content: 出力結果の構造を事前に定義することで、AIツールが結果をより正確に解釈できるようになりました
  • Output Schema: 出力結果のJSON Schemaを提供することで、AIツールが結果を正確に解釈できるようにしました
  • isError: trueの追加: エラーが発生した場合、isError: trueを設定することで、AIツールでエラー状態を認識できるようにしました

詳しくは、次のGitHub Issueを参照してください。

まとめ

textlint v15では、非推奨となっているものを削除したり、動作の一貫性を改善するような変更をしています。

またtextlintの内部的にも、pnpmVitestへ移行し、 CIの合計時間を21m 5s → 7m 20sに短縮しています。(Windowsでnpmのインストールが遅かったのがボトルネック)

他にもMerge Gatekeeperを入れてAuto Mergeをできるようにしたり、Netlifyのキャッシュがやたら不安定なのでDeploy PR Preview actionを使ってPRのプレビューを作成するなどの改善をしています。

この辺を整理したので、textlint自体の開発体験もだいぶ良くなっています。

まだやるべきことはたくさんあるので、興味あるひとは是非Contributorとして参加してください!

実験的なものとしてtextlint-rule-preset-ai-writingとか書きながら考えていましたが、Linterの役割はちょっと広がってきているのかなと思いました。 Biome v2で追加されたAssistもそうですが、ErrorやWarningではなくSuggestionに近い部分も増えてきているように感じます。Suggestionに関してはLinterの役割なのかは微妙なところです。しかし、この辺りの機能はLinterの延長として実装されることも多くなっています。

特に自然言語はauto fixが難しいので、Suggestionのような形でHintを提供できる仕組みがあると、人間とAIにとっても使える感じのツールになるんじゃないかなーと思っています。

textlintでは、Contributionを歓迎しています。

また、GitHub Sponsorsでのサポートも歓迎しています。

関連リンク