📝

textlintでMDXを校正するプラグインを作成した

2024/04/09に公開

はじめに

textlintという自然言語の文書校正(Lint)ができるツールでMDXを校正するためのプラグインを作成したので紹介いたします。

https://www.npmjs.com/package/textlint-plugin-mdx

https://github.com/textlint/textlint-plugin-mdx

使用する場合は以下のコマンドで依存関係に追加し、.textlintrcにMDXプラグインの設定を追加してください。

# npm
npm install textlint-plugin-mdx

# Yarn
yarn add textlint-plugin-mdx

# pnpm
pnpm add textlint-plugin-mdx

# Bun
bun add textlint-plugin-mdx
.textlintrc
{
  "plugins": {
    "mdx": true
  }
}

MDXについて

MDXとはMarkdownでJSXを扱えるようにした拡張構文です。拡張子は.mdxです。

https://mdxjs.com/

MDXは近年話題のAstroDocusaurusでサポートされているなど現在も知名度が上がりつつあります。詳細や使用例は他の記事をご参照ください。

https://zenn.dev/topics/mdx

textlintでMDXをLintするときの課題

textlintではテキストファイルをASTに変換してLintを行うため、構文に対応するプラグインが必要になります。Markdownについては公式にプラグインが提供されていますが、MDXについてはプラグインが存在しなかったため、Markdownのプラグインの設定で.mdxをLintの対象に追加し、MDXファイルをMarkdownとして処理させることが一般的でした。

https://www.npmjs.com/package/@textlint/textlint-plugin-markdown

しかし、この方法ではMDXの独自構文が正しくパースされないため、JSXがLint対象となってしまったり、textlint-filter-rule-commentsのようなMDXでサポートされていないMarkdownの構文を前提とした機能が利用できない課題がありました。

MDXの独自構文の対応

MDX v2以降で導入されているmdastノードは以下の通りです。これらのノードの処理をMarkdownのプラグインに追加しました。textlintのASTについては公式ドキュメントのTxtAST Interfaceをご覧ください。

https://textlint.github.io/docs/txtnode.html

mdast-util-mdx-expression

https://github.com/syntax-tree/mdast-util-mdx-expression#syntax-tree

MdxFlowExpression

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxFlowExpression/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxFlowExpression/output.json

MdxTextExpression

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxTextExpression/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxTextExpression/output.json

mdast-util-mdx-jsx

https://github.com/syntax-tree/mdast-util-mdx-jsx?tab=readme-ov-file#syntax-tree

MdxJsxFlowElement

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxJsxFlowElement/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxJsxFlowElement/output.json

MdxJsxTextElement

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxJsxTextElement/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxJsxTextElement/output.json

mdast-util-mdxjs-esm

https://github.com/syntax-tree/mdast-util-mdxjs-esm?tab=readme-ov-file#syntax-tree

MdxjsEsm

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxjsEsm/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxjsEsm/output.json

コメントの例外処理

HTMLのコメント表現<!-- -->をサポートしていないMDXでtextlint-filter-rule-commentsを使用するために、{/* */}をCommentノードとして扱うようにしました。

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxFlowExpressionComment/input.mdx

https://github.com/textlint/textlint-plugin-mdx/blob/main/test/fixtures/mdxFlowExpressionComment/output.json

使用例は以下の通りです。

This is error text.

{/* textlint-disable */}

This is ignored text by rule.
Disables all rules between comments

{/* textlint-enable */}

This is error text.

textlint-filter-rule-commentsでは、以下のコードの通りHTMLノードの<!-- -->の内部またはCommentノードをコメントとして扱うようになっているため、{/* <!-- textlint-disable --> */}のように記述している方が多かったと思われます。MDXプラグインでは{/* */}がCommentノードとして解釈されるため、回避策を行わずに正常に利用できるようになっています。

https://github.com/textlint/textlint-filter-rule-comments/blob/b96db71f32a291154b1e572bcfffecb9ca618655/src/textlint-filter-rule-comments.js

おわりに

バグ報告や機能の提案、Pull Requestなど、皆様のContributionをお待ちしております。

Discussion