メインコンテンツまでスキップ

ルール修正関数

新機能

v5 の新機能です。v4 に対応する機能はありません。既存のルールは変更なしで動作します。このページでは、カスタムルールに自動修正を追加する方法を説明します。

対象読者

  • 自動修正機能を追加したいカスタムルール作成者
  • サードパーティの Markuplint ルールを開発するプラグイン開発者

概要

v5 では ESLint のフィクサーに着想を得た自動修正システムが導入されました。context.report()fix コールバックを追加します。ユーザーが fix=true で Markuplint を実行すると、コールバックが編集を生成してソースに適用します。

fix コールバックの追加

report()fix プロパティを追加します。IRuleFixer を受け取り、1つ以上の TextEdit オブジェクトを返します:

context.report({
scope: node,
message: 'タグ名は小文字にすべきです',
fix: fixer => fixer.replaceText({ startOffset: nameOffset, raw: node.rawName }, node.rawName.toLowerCase()),
});
注記

fix コールバックはリント中には実行されません。MLCore.verify()fix=true が渡された場合のみ実行されます。

IRuleFixer API

IRuleFixer インターフェースは 6 つのメソッドを提供します:

メソッド動作
replaceText(token, text)トークンのテキストを置換
replaceRange(range, text)[start, end) レンジを置換
insertBefore(token, text)トークンの前にテキストを挿入
insertAfter(token, text)トークンの後にテキストを挿入
remove(token)トークンを削除
removeRange(range)[start, end) レンジを削除

FixToken

token を受け取るメソッドは FixToken 型を使用します:

type FixToken = {
readonly startOffset: number;
readonly raw: string;
};

すべての MLDOM トークン(MLTokenMLAttrnameNodevalueNode など)はこの型を満たします。手動でトークンを作成することもできます:

fix: fixer => fixer.replaceText(
{ startOffset: 42, raw: 'old-text' },
'new-text',
),

複数の編集を返す

TextEdit の配列を返すと、アトミックな複数編集になります。グループ内のいずれかの編集が他のルールの fix と重複すると、グループ全体がスキップされます:

fix: fixer => [
fixer.remove(attr.spacesBeforeEqual),
fixer.remove(attr.equal),
fixer.remove(attr.valueNode),
],

実装例

テキストの置換

タグ名を小文字に変換:

fix: fixer => fixer.replaceText(
{ startOffset: nameOffset, raw: el.rawName },
el.rawName.toLowerCase(),
),

トークンの削除

孤立した終了タグを削除:

fix: fixer => fixer.remove(
{ startOffset: text.startOffset, raw: text.raw },
),

レンジによる削除

属性全体を削除(先頭の空白から閉じ引用符まで):

fix: fixer => fixer.removeRange([
firstToken.startOffset,
lastToken.startOffset + lastToken.raw.length,
]),

ヘルパー関数

@markuplint/rules に属性削除パターン用の共有ヘルパーが用意されています:

ヘルパー動作
removeAttr(fixer, attr)属性全体を削除(属性名 + 値 + 空白)
removeAttrValue(fixer, attr)値部分のみ削除(等号、引用符、値)、属性名は残す

null/空トークンは自動的に処理されます。

マルチパス fix の動作

複数のルールが重複する fix を生成した場合、エンジンが解決します:

  1. すべての fix を収集し、1パスで適用
  2. 重複する fix はスキップ
  3. スキップがあった場合、ソースを再パースしてルールを再実行
  4. スキップがなくなるまで繰り返す(最大10パス)
ヒント

ルール作成者が重複する fix を処理する必要はありません。エンジンが自動的に管理します。

自動修正をサポートする組み込みルール

v5 で自動修正をサポートする組み込みルール:

ルール修正内容
case-sensitive-tag-name設定されたケースにタグ名を変換
case-sensitive-attr-name設定されたケースに属性名を変換
attr-value-quotes設定されたスタイルに引用符を変換
no-boolean-attr-value真偽値属性から値を削除
no-default-valueデフォルト値を持つ属性を削除
attr-duplication重複属性を削除
ineffective-attr無効な属性を削除
no-orphaned-end-tag孤立した終了タグを削除
no-consecutive-br連続する <br> 要素を削除
attr-order設定された順序に属性を並べ替え
head-element-orderhead 内の子要素を並べ替え

型のインポート

import type { IRuleFixer, TextEdit, FixToken } from '@markuplint/ml-config';

IRuleFixer はコールバックに渡されます。自分でインスタンス化する必要はありません。