プロパティを設定する
クイックリファレンス
ほとんどのプロジェクトでは、いくつかのプロパティだけで十分です。やりたいことに応じて使うプロパティを選んでください:
| やりたいこと | プロパティ |
|---|---|
| プリセットを使う | extends |
| ルールを有効化・カスタマイズする | rules |
| フレームワーク(React、Vueなど)で使う | parser + specs |
| 特定の要素にルールを適用する | nodeRules or childNodeRules |
| カスタムコンポーネントを検証する | pretenders |
| ファイルをリント対象から除外する | excludeFiles |
| ディレクトリごとに設定を上書きする | overrides |
すべてのプロパティ
{
"extends": [],
"plugins": {},
"parser": {},
"parserOptions": {},
"specs": [],
"excludeFiles": [],
"severity": {},
"rules": {},
"nodeRules": [],
"childNodeRules": [],
"pretenders": [],
"overrideMode": "reset",
"overrides": {}
}
パスの解決
extends、plugins、parser、specs、excludeFilesはパスを指定できます。そのうちextends、plugins、parser、specsの4つでは、パスの代わりにnpmパッケージを指定できます。
まず、パッケージとしてインポートします。パッケージが存在しない、文字列がパッケージでないなど、失敗した場合は、文字列を単なるパスとして解決します。相対パスは、設定ファイルのあるディレクトリが基準となります。
各プロパティの詳細
extends
他の設定ファイルへのパスを指定した場合、その設定をマージします。
{
"extends": [
// ローカルファイルとして読み込む
"../../.markuplintrc",
// パッケージとして読み込む
"third-party-config"
]
}
markuplint:というプレフィックスがついた名前は、Markuplintから提供されたpresetを読み込みます。
{
"extends": ["markuplint:recommended"]
}
plugin:というプレフィックスがついた名前は、プラグインから提供された設定を読み込みます。スラッシュの前はプラグインがもつ名前空間です。スラッシュの後ろは、そのプラグイン固有の設定名です。
{
"extends": ["plugin:third-party-plugin-name/config-name"],
"plugins": ["third-party-plugin"]
}
インターフェイス
interface Config {
extends?: string[];
}
plugins
任意のプラグインを読み込むことができます。パッケージ名またはパスを指定します。プラグインが設定をもつ場合はsettingsに指定できます。
{
"plugins": [
"third-party-plugin",
"@third-party/markuplint-plugin",
{
"name": "third-party-plugin2",
"settings": {
"foo": "bar"
}
},
"./path/to/local-plugin.js",
{
"name": "./path/to/local-plugin.js2",
"settings": {
"foo": "bar"
}
}
]
}
インターフェイス
interface Config {
plugins?: (
| string
| {
name: string;
settings?: Record<string, string | number | boolean | Object>;
}
)[];
}
parser
キーに正規表現を、値にパーサのファイルパスまたはパッケージ名を指定します。正規表現は、対象ファイルにマッチするものを指定します(例は拡張子を示しています)。
{
"parser": {
"\\.pug$": "@markuplint/pug-parser",
"\\.[jt]sx?$": "@markuplint/jsx-parser",
"\\.vue$": "@markuplint/vue-parser",
"\\.svelte$": "@markuplint/svelte-parser",
"\\.ts$": "@markuplint/tagged-template-literal-parser",
"\\.ext$": "./path/to/custom-parser/any-lang.js"
}
}
インターフェイス
interface Config {
parser?: {
[regex: string]: string;
};
}
parserOptions
{
"parserOptions": {
"ignoreFrontMatter": true,
"authoredElementName": ["AuthoredElement"]
}
}
ignoreFrontMatter
trueを設定すると、パーサはソースコードのFront Matterフォーマット部分を無視します。デフォルトはfalseです。
---
prop: value
---
<html>
...
</html>
authoredElementName
ReactやVueなどを使っている場合、Markuplintのパーサーはコンポーネントに小文字の名前を付けると、ネイティブのHTML要素として検出します。ほとんどの場合、コンポーネントは大文字から命名する必要がありますが、パーサプラグインごとに特定のパターンがあります(例:Vue: Built-in Special Elements)。もし、異なる命名パターンが必要な場合は、authoredElementNameオプションを指定することで解決できます。デフォルトはundefinedです。
{
"parserOptions": {
"authoredElementName": ["custom", "mine"]
}
}
<template>
<custom><!-- 指定がない場合はネイティブのHTML要素として検出されます。 --></custom>
<mine><!-- 指定がない場合はネイティブのHTML要素として検出されます。 --></mine>
</template>
インターフェイス
interface Config {
parserOptions?: {
ignoreFrontMatter?: boolean;
authoredElementName?: string | RegExp | Function | (string | RegExp | Function)[];
};
}
specs
キーに正規表現を、値にスペックファイルのパスまたはパッケージ名を指定します。正規表現は、対象ファイルにマッチするものを指定します(例は拡張子を示しています)。
{
"specs": {
"\\.vue$": "@markuplint/vue-spec",
"\\.ext$": "./path/to/custom-specs/any-lang.js"
}
}
インターフェイス
interface Config {
specs?: {
[regex: string]: string;
};
}
v1.xまで非推奨の構文
配列または文字列で指定可能ですが、非推奨です。
{
// 非推奨
"specs": ["@markuplint/vue-spec", "./path/to/custom-specs/any-lang"]
}
{
// 非推奨
"specs": "@markuplint/vue-spec"
}
excludeFiles
必要であれば、ファイルを除外できます。値は設定ファイルからの相対パスか絶対パスが必要です。パスはglob形式も可能です。否定を表す!シンボルを使うこともできます。後から指定したものが優先されます。パターンは.gitignoreの仕様に従って動作します。(node-ignoreを用いて解決されます)
{
"excludeFiles": ["./ignore.html", "./ignore/*.html", "!./ignore/no-ignore.html"]
}
インターフェイス
interface Config {
excludeFiles?: string[];
}
severity
診断カテゴリごとにデフォルトの深刻度を制御します。
parseError
パースエラーの深刻度を制御します。"off" または false を設定するとパースエラーの報告を抑制できます。
{
"severity": {
"parseError": "warning"
}
}
deprecation
非推奨のルール名に関する通知(v5 のルール体系再設計より前の名前で、現在も解決はできるが v6 で削除される予定のもの)の深刻度を制御します。デフォルトは "warning" です。"off" または false を設定するとこの通知を抑制できます。
{
"severity": {
"deprecation": "off"
}
}
インターフェイス
interface Config {
severity?: {
parseError?: 'error' | 'warning' | 'info' | 'off' | boolean;
deprecation?: 'error' | 'warning' | 'info' | 'off' | boolean;
};
}
rules
ルールを有効にしたり、詳細を設定します。各ルールの値は、文字列、数値、および配列のいずれかです。
falseを指定した場合、ルールは無効になります。trueを指定すると、各ルールが持つデフォルト値として適用されます。
{
"rules": {
"rule-name": "value" // ここにルール名と値を設定します
}
}
もしくは、Objectで詳細を指定します。
{
"rules": {
"rule-name": {
"value": "any-value",
"severity": "error",
"options": {
"any-option": "any-optional-value"
}
}
}
}
value
省略可能です。省略した場合は、各ルールが持つデフォルト値として評価されます。
severity
"error"または"warning"を受け取ります。省略可能です。省略した場合は、各ルールが持つデフォルトの深刻度で評価されます。
options
ルールが定義するObjectを受け取ります。省略可能です。フィールドの一部がデフォルト値を持つ場合があります。
非推奨のoptionフィールド
optionフィールドは、v3.0.0からoptionsに置き換えられました。互換性のためにoptionを通しても適用できますが、非推奨です。代わりにoptionsを使用してください。
ルール名について
ルール名はスラッシュを含む場合があります。その場合、そのルールがプラグインによるものであることを示します。スラッシュの前はプラグインがもつ名前空間です。スラッシュの後ろは、そのプラグイン固有の一意なルール名です。
{
"plugins": ["third-party-plugin", "./path/to/local-plugin.js"],
"rules": {
"core-rule-name": true,
"third-party-plugin/rule-name": true,
"named-plugin-imported-form-local/rule-name": true
}
}
プリセットの名前付きルール
プリセットは namespace/rule-name 形式の名前付きルールを定義します。名前付きルールは違反レポートに表示され、rules プロパティで個別にカスタマイズ可能です。
{
"extends": ["markuplint:recommended"],
"rules": {
// プリセットの特定の名前付きルールを無効化
"a11y/html-lang": false,
// 名前付きルールの深刻度を変更
"html-standard/head-charset-utf8": { "severity": "warning" },
// ワイルドカードで名前空間内のすべての名前付きルールを無効化
"a11y/*": false,
// ベースルール名で無効化(詳細は下記参照)
"no-duplicate-id": false
}
}
ベースルール名による無効化
ベースルール名をfalseに設定すると、そのベースルールをラップしている名前付きルールグループ内の該当エントリが無効化されます。例えば、プリセットが以下のように定義されているとします:
{
"rules": {
"my-checks/validation": {
"rules": {
"no-duplicate-id": true,
"no-invalid-attr-value": true
}
}
}
}
設定に"no-duplicate-id": falseを追加すると、グループ内の該当ベースルールだけが無効化されます:
{
"rules": {
"my-checks/validation": {
"rules": {
"no-duplicate-id": false,
"no-invalid-attr-value": true
}
}
}
}
同グループ内のno-invalid-attr-valueは影響を受けずに有効のままです。これは全グループに適用されます — a11y/id-duplicationとhtml-standard/id-duplicationの両方がno-duplicate-idベースルールをラップしている場合、両方とも無効化されます。この機能は後方互換性のために提供されています。
一覧はプリセット内の名前付きルールを参照してください。
名前付きルールグループ
/ を含むキーと rules フィールドを持つ値を使って、独自の名前付きルールグループを定義できます。1つ以上のベースルールを名前空間でラップし、個別制御やメタデータの付与が可能になります。
{
"rules": {
"my-project/no-accesskey": {
"specConformance": "non-normative",
"rules": {
"no-restricted-attr": {
"options": { "disallowAttrs": ["accesskey"] }
}
}
}
}
}
specConformance
'normative' または 'non-normative' を受け取ります。省略可能です。チェックがHTML仕様の規範的要件に関するものか非規範的要件に関するものかを示すメタデータで、違反レポートに含まれますが、深刻度には影響しません。
'normative': MUST や REQUIRED の要件に対応するチェック。'non-normative': SHOULD や RECOMMENDED の要件に対応するチェック。
MarkuplintのHTML仕様に基づく組み込みプリセットルールにはこの値が自動的に設定されます。ユーザーが独自に設定することも可能です — 例えば、MarkuplintがHTML仕様の更新にまだ対応していない場合や、Markuplintのバージョンアップがやむを得ずできない場合に利用できます。
このフィールドはHTML仕様に基づくチェックのみを対象としています。独自ルールやハウスルールに対して使用しないでください。乱用すると、違反レポートに表示される準拠レベルを見たユーザーが、HTML仕様上の要件だと誤解する恐れがあります。
severity
'error'、'warning'、または 'info' を受け取ります。省略可能です。指定すると、グループ内の全ルールのデフォルト深刻度を上書きします。
rules
rulesプロパティと同じ個別ルール設定を受け取りますが、名前付きルールグループのネストは受け付けません。必須です。ラップするベースルールを1つ以上含みます。
複数エントリの命名規則
名前付きルールグループに1つのエントリがある場合、グループキーがそのままルール名になります。2つ以上のエントリがある場合、各エントリにグループキー/ベースルール名形式の派生名が付与され、グループキーはグループ名になります。
{
"rules": {
// 単一エントリ: ルール名は "my-project/no-accesskey"
"my-project/no-accesskey": {
"rules": { "no-restricted-attr": { "options": { "disallowAttrs": ["accesskey"] } } }
},
// 複数エントリ: ルール名は "my-project/checks/no-duplicate-attr"
// と "my-project/checks/class-naming"
"my-project/checks": {
"rules": {
"no-duplicate-attr": true,
"class-naming": "/[a-z]+/"
}
}
}
}
グループ名を使って複数エントリのグループを一括で無効化できます:
{
"rules": {
"my-project/checks": false
}
}
積み上げ動作
複数の名前付きルールグループが同じベースルールをラップしている場合(例: a11y/id-duplication と html-standard/id-duplication)、それぞれ独立して実行され、両方が違反を報告します。各名前付きルールは独立して制御できます:
{
"extends": ["markuplint:a11y", "markuplint:html-standard"],
"rules": {
// a11y の観点のみ無効化。html-standard の観点は有効のまま
"a11y/id-duplication": false
}
}
インターフェイス
interface Config {
rules?: {
[ruleName: string]: Rule<T, O> | NamedRuleGroup;
};
}
type Rule<T, O> =
| boolean
| T
| {
severity?: 'error' | 'warning' | 'info';
value?: T;
option?: O;
reason?: string;
};
type NamedRuleGroup = {
specConformance?: 'normative' | 'non-normative';
severity?: 'error' | 'warning' | 'info';
rules: {
[ruleName: string]: Rule<T, O>;
};
};
nodeRules
特定の要素にのみルールを適用させたい場合、このプロパティを指定します。値が配列であることに注意してください。
selectorかregexSelectorのどちらかが必要です。rulesフィールドも必須です。個別のルール設定(rulesプロパティのエントリと同じ形式)を受け取りますが、名前付きルールグループの定義(新しいグループの作成)は受け取れません。
ただし、プリセットが作成した仮想ルールをベースルール名や名前空間ワイルドカードで制御できます:
- ベースルール名:
"no-unknown-role": falseは仮想ルールa11y/wai-aria/non-existent-role(およびno-unknown-roleをラップする他のすべての仮想ルール)を無効化します - 名前空間ワイルドカード:
"a11y/*": falseはa11y/名前空間内のすべての仮想ルールを無効化します - オプション上書き:
"no-unknown-role": { "options": { ... } }はno-unknown-roleをラップする仮想ルールにオプションを伝播します
名前空間ワイルドカードは false のみ受け付けます。オプションを指定するには、具体的なルール名(ベースまたは仮想)を使用してください。
{
"nodeRules": [
{
"selector": "main",
"rules": {
"class-naming": "/[a-z]+(__[a-z]+)?/"
}
}
]
}
name
/ を含む文字列(例: a11y/html-lang)を受け取ります。省略可能です。指定すると、rules プロパティで個別に設定可能な名前付きルールを作成します。主にプリセットで使用されます。
rules フィールドに1つのエントリがある場合、この名前がそのままルール名になります。2つ以上のエントリがある場合、各エントリに name/ベースルール名 形式の派生名が付与され、この名前はグループ名になります。グループは rules["グループ名"]: false で一括無効化できます。
specConformance
Named Rule GroupsのspecConformanceと同じです。
rules
個別のルール設定(rulesプロパティのエントリと同じ形式)を受け取りますが、名前付きルールグループの定義は受け取れません。必須です。ベースルール名と名前空間ワイルドカードに対応しています — 詳細は nodeRules を参照してください。
selector
ターゲットにマッチさせるためのセレクタを受け取ります。regexSelectorを使用しない場合は必須です。
regexSelector
ターゲットにマッチさせるための正規表現を受け取ります。selectorを使用しない場合は必須。
このフィールドには、nodeName、attrName、attrValueの各フィールドがあり、任意に正規表現を受け取ります。そのため、それぞれ省略が可能です。組み合わせる場合はAND条件となります。
正規表現はスラッシュで挟む必要があります。そうでない場合は、単なる文字列として適用されます。
{
"nodeRules": [
{
"regexSelector": {
"nodeName": "/^[a-z]+$/",
"attrName": "/^[a-z]+$/",
"attrValue": "/^[a-z]+$/"
},
"rules": {
"any-rule": "any-value"
}
}
]
}
正規表現で文字列をキャプチャし、rulesプロパティの値に展開する強力な機能を備えています。先頭に$マークを付けたキャプチャ番号を変数として展開します。値はMustache形式で指定します。
{
"nodeRules": [
{
"regexSelector": {
"attrName": "/^data-([a-z]+)$/"
},
"rules": {
"any-rule": "It is {{ $1 }} data attribute",
"any-rule2": {
"value": "It is {{ $1 }} data attribute",
"severity": "error"
}
}
}
]
}
もちろん、名前付きキャプチャグループを使うことも可能です。名前を変数として展開します。
{
"nodeRules": [
{
"regexSelector": {
"attrName": "/^data-(?<dataName>[a-z]+)$/"
},
"rules": {
"any-rule": "It is {{ dataName }} data attribute"
}
}
]
}
名前付きキャプチャの使用を推奨します。番号付きキャプチャは衝突して上書きされる可能性があります。
{
"nodeRules": [
{
"regexSelector": {
"attrName": "/^data-([a-z]+)$/", // `$1`になります
"attrValue": "/^(.+)$/" // ここも`$1`になり、`$1`は上書きされます
},
"rules": {
"any-rule": "It is {{ $1 }} data attribute, and value is {{ $1 }}"
}
},
{
"regexSelector": {
"attrName": "/^data-(?<dataName>[a-z]+)$/", // `dataName`になります
"attrValue": "/^(?<dataValue>.+)$/" // `dataValue`になります
},
"rules": {
"any-rule": "It is {{ dataName }} data attribute, and value is {{ dataValue }}"
}
}
]
}
combinationフィールドを使えば、複雑な条件でも要素を選択できます。
{
"nodeRules": [
{
"regexSelector": {
"attrName": "img",
"combination": {
"combinator": ":has(~)",
"nodeName": "source"
}
}
}
]
}
上記はCSSのセレクタimg:has(~ source)と同等です。
combinatorは以下をサポートします。
" ": 子孫結合子">": 子結合子"+": 後方隣接兄弟結合子":has(+)": 前方隣接兄弟結合子"~": 後方兄弟結合子":has(~)": 前方兄弟結合子
ノードは無制限に深く定義できます。
{
"nodeRules": [
{
"regexSelector": {
"nodeName": "el1",
"combination": {
"combinator": " ",
"nodeName": "el2",
"combination": {
"combinator": ">",
"nodeName": "el3",
"combination": {
"combinator": "+",
"nodeName": "el4",
"combination": {
"combinator": "~",
"nodeName": "el5"
}
}
}
}
}
}
]
}
上記はCSSのセレクタel1 el2 > el3 + el4 ~ el5と同等です。
インターフェイス
interface Config {
nodeRules?: (
| {
selector: string;
name?: string;
specConformance?: 'normative' | 'non-normative';
rules: {
[ruleName: string]: Rule<T, O>;
};
}
| {
regexSelector: RegexSelector;
name?: string;
specConformance?: 'normative' | 'non-normative';
rules: {
[ruleName: string]: Rule<T, O>;
};
}
)[];
}
type RegexSelector = {
nodeName?: string;
attrName?: string;
attrValue?: string;
combination?: RegexSelector & {
combinator: ' ' | '>' | '+' | '~' | ':has(+)' | ':has(~)';
};
};
childNodeRules
特定の要素の子孫に何らかのルールを適用させたい場合、このプロパティで指定します。inheritanceフィールドにtrueを指定すると、対象要素のすべての子孫ノードに適用され、指定しなければ子ノードのみに適用されます。値が配列であることに注意してください。
このプロパティはinheritanceフィールドを持つこと以外は、nodeRulesプロパティと同じフィールドを受け取ります。
inheritance
論理値を受け取ります。省略可能で、デフォルトはfalseです。
インターフェイス
interface Config {
childNodeRules?: (
| {
selector: string;
inheritance?: boolean;
name?: string;
specConformance?: 'normative' | 'non-normative';
rules: {
[ruleName: string]: Rule<T, O>;
};
}
| {
regexSelector: RegexSelector;
inheritance?: boolean;
name?: string;
specConformance?: 'normative' | 'non-normative';
rules: {
[ruleName: string]: Rule<T, O>;
};
}
)[];
}
pretenders
プリテンダー機能は、カスタムコンポーネントをネイティブのHTML要素のように見せかける機能です。いくつかのルールで、コンポーネントをレンダリングされた結果の要素として評価するために利用します。
値はプリテンダー定義の配列、またはdata、scanなどのフィールドを持つオブジェクトのいずれかです。
selector
対象コンポーネントにマッチさせるためのセレクタを受け取ります。必須です。
セレクタが標準 HTML / SVG 要素にマッチする pretender エントリは暗黙的に無視されます。pretender は custom component(Web Components、JSX/Vue/Svelte 等の authored component、または HTML パースで spec エントリがない不明な名前)のみが対象です。<button> や <marquee> を指定しても何も起きません(移行ガイドを参照)。
as
要素名もしくは要素のプロパティを受け取ります。必須です。
{
"pretenders": [
{
"selector": "MyComponent",
"as": "div"
}
]
}
{
"pretenders": [
{
"selector": "MyComponent",
"as": {
"element": "div",
"inheritAttrs": true,
"attrs": [
{
"name": "role",
"value": "region"
}
]
}
}
]
}
as.element
要素名を受け取ります。必須です。
as.inheritAttrs
レンダリングされた要素が、コンポーネントで定義された属性を公開するかどうかを論理値を受け取ります。省略可能です。省略した場合のデフォルト値はfalseです。
const MyComponent = props => {
return <div {...props}>{props.children}</div>;
};
{
"pretenders": [
{
"selector": "MyComponent",
"as": {
"element": "div",
"inheritAttrs": true
}
}
]
}
<div>
{/* レンダリングされたdiv要素がaria-live="polite"を持つものとして評価します。 */}
<MyComponent aria-live="polite">Lorem Ipsam</MyComponent>
</div>
as.attrs
配列を受け取ります。レンダリングされた要素に指定した属性を持っているものとして評価されます。省略可能です。
const MyPicture = () => {
return <img src="path/to/file.png" alt="Lorem ipsam" />;
};
{
"pretenders": [
{
"selector": "MyPicture",
"as": {
"element": "img",
"attrs": [
{
"name": "src"
},
{
"name": "alt",
"value": "Lorem ipsam"
}
]
}
}
]
}
<div>
{/* レンダリングされたimg要素がsrc属性とalt="Lorem ipsam"を持つものとして評価されます。*/}
<MyComponent />
</div>
as.attrs[].name
属性名を受け取ります。必須です。
as.attrs[].value
属性値を受け取ります。省略可能です。省略した場合、その属性は真偽値属性になります。
- 文字列: 静的な値です。
{ "fromAttr": "name" }: コンポーネントが持つ属性の値です。その属性が式(<MyButton kind={kind} />)であれば、値も動的になります。コンポーネントがその属性を持たない場合、要素はその属性を空の値で持ちます。{ "fromAttr": "name", "omitIfMissing": true }: 同上ですが、コンポーネントがその属性を持たない場合、要素もその属性を持ちません。省略可能なpropをそのまま渡すコンポーネントが描画する結果です(<button type={kind}>はkindがundefinedのときtypeを持ちません)。{ "dynamic": true }: 属性は存在しますが、値はコンポーネントがレンダリングされるまで分からない場合(例:tabIndex={selected ? 0 : -1})に指定します。ルールは動的な値として扱い、検証しません。
as.aria
ARIAのプロパティをObjectで受け取ります。現在段階ではnameフィールドしかありません。省略可能です。
as.aria.name
アクセシブルな名前を論理値もしくはObjectで受け取ります。コンポーネントが名前を明確に持っている場合はtrueを指定する。そうでなければ、その名前を参照する属性名をfromAttrに設定する。
const MyIcon = ({ label }) => {
return (
<svg role="img" aria-label={label}>
<rect />
</svg>
);
};
{
"pretenders": [
{
"selector": "MyIcon",
"as": {
"element": "svg",
"aria": {
"name": {
"fromAttr": "label"
}
}
}
}
]
}
<div>
{/* アクセシブルな名前が「my icon name」であるとして評価します。 */}
<MyIcon label="my icon name" />
</div>
as.slots
このプロパティは実験的であり、将来のリリースで変更される可能性があります。
コンポーネントが子要素を受け入れるか、スロットを持つかどうかを指定します。省略可能です。
null: コンポーネントは子要素を受け入れない、またはスロットを持ちません。例えば、<img>(void要素)としてレンダリングされるコンポーネントです。true: コンポーネントは子要素を受け入れ、ラッパー要素が最も外側の要素です。- 配列: 子要素を包む要素が最も外側の要素ではない場合に、その要素を要素仕様として記述します。コンポーネントに渡された子要素は、最も外側の要素ではなくこの要素に対して評価されます。配列に2つ以上の仕様がある場合、子要素がどの仕様に属するかが分からないため、子要素は検証されません。
// このコンポーネントは子要素を受け入れる — slotsはtrueにすべき
const Wrapper = ({ children }) => <div>{children}</div>;
// このコンポーネントは子要素を受け入れない — slotsはnullにすべき
const Icon = props => <img src={props.src} />;
{
"pretenders": [
{
"selector": "Wrapper",
"as": {
"element": "div",
"slots": true
}
},
{
"selector": "Icon",
"as": {
"element": "img",
"slots": null
}
}
]
}
子要素が内側の要素に包まれている場合は、その要素を指定します。
const Card = ({ children }) => (
<div>
<h2>lorem ipsum</h2>
<p>{children}</p>
</div>
);
{
"pretenders": [
{
"selector": "Card",
"as": {
"element": "div",
"slots": [{ "element": "p" }]
}
}
]
}
<Card><div></div></Card> は、div要素がp要素の中では許可されないため報告されます。
as.contents
このプロパティは実験的であり、将来のリリースで変更される可能性があります。
コンポーネントが、スロットを包む要素の直下にレンダリングするものを順番に指定します。省略可能です。スロットを包む要素とは、最も外側の要素、またはslots配列の各仕様の要素です。
{ "element": "img", "attrs": [...] }: コンポーネントが常にその位置にレンダリングするネイティブ要素です。{ "slot": true }: コンポーネントに渡された子要素が置かれる位置です。{ "dynamic": true }: その位置にレンダリングされるものの内容が分からない場合(式、条件分岐、別のコンポーネントなど)に指定します。必須の子要素が欠けていることの検査はスキップされます。
permitted-contentsなどのコンテンツを検査するルールは、ラッパー要素の子をこのリストとして評価し、{ "slot": true }の位置に渡された子要素を置きます。リストに{ "slot": true }がない場合、渡された子要素はリストの後ろに置かれます。省略した場合、渡された子要素がコンテンツのすべてです。
const Picture = () => (
<picture>
<img src="example.gif" alt="Example" />
</picture>
);
const Details = ({ children }) => <details>{children}</details>;
{
"pretenders": [
{
"selector": "Picture",
"as": {
"element": "picture",
"slots": null,
"contents": [
{
"element": "img",
"attrs": [
{ "name": "src", "value": "example.gif" },
{ "name": "alt", "value": "Example" }
]
}
]
}
},
{
"selector": "Details",
"as": {
"element": "details",
"slots": true,
"contents": [{ "slot": true }]
}
}
]
}
<Picture />は、コンポーネント自身がimg要素をレンダリングするため、img要素の欠如は報告されません。<Details></Details>は、summary要素を用意できるのは使用側だけなので、summary要素の欠如が報告されます。
現在、contentsを利用するのはpermitted-contents、require-owned-elementsと、アクセシブルな名前の算出(require-accessible-nameなどが利用)だけです。名前の算出では、{ "dynamic": true }は名前の出どころになりません(ただし、それ以外に名前の出どころがないコンポーネントは、その内容が名前かもしれないためrequire-accessible-nameは報告しません)。またslotsがnullのコンポーネントに渡された子要素は使われません。要素の子を参照するほかのルールには、コンポーネントに渡された子要素だけが見えます。
コンポーネントがルートに複数の要素をレンダリングする場合は、elementに"#fragment"を指定します。コンポーネント自身は要素ではなく、そのcontentsが親の中でコンポーネントの位置に置かれます。
scan
このプロパティは実験的であり、将来のリリースで変更される可能性があります。
pretendersのオブジェクト形式を使用する場合、scanフィールドで動的コンポーネントスキャンを有効にできます。すべてのコンポーネントを手動でリストアップする代わりに、markuplintがコンポーネントファイルをスキャンしてプリテンダーマッピングを自動的に発見します。
ファイルの拡張子によってスキャナーが決定されます:
.js,.jsx,.ts,.tsx→ JSXスキャナー.vue,.svelte,.astro→ テンプレートスキャナー
{
"pretenders": {
"scan": [
{
"files": "./src/components/**/*.tsx"
},
{
"files": "./src/components/**/*.vue",
"ignoreComponentNames": ["BaseLayout"]
}
]
}
}
scan[].files
スキャンするコンポーネントファイルのglobパターン(またはglobパターンの配列)。必須です。
scan[].ignoreComponentNames
スキャン結果から除外するコンポーネント名の配列。省略可能です。
data(オブジェクト形式)
オブジェクト形式を使用する場合、インラインのプリテンダー定義はdataフィールドに記述します:
{
"pretenders": {
"data": [
{
"selector": "MyComponent",
"as": "div"
}
],
"scan": [
{
"files": "./src/components/**/*.vue"
}
]
}
}
auto(オブジェクト形式)
このプロパティは実験的機能であり、将来のリリースで変更される可能性があります。
オブジェクト形式を使用する場合、auto: trueを指定すると、data/scanをあらかじめ設定しなくても、リント対象ファイル自身のimportグラフをスキャンしてプリテンダーを解決します:
{
"pretenders": {
"auto": true
}
}
importをたどる段数は、lint対象ファイルから最大8段です。JS/TSファイル(lint対象ファイル自身がMDXの場合はそのファイルも)の再エクスポート(export ... from)もimportと同じようにたどるため、バレルファイル経由でimportしたコンポーネントも見つかります。バレルファイルを経由する分も1段に数えます。オブジェクト形式で変更できます。0を指定するとlint対象ファイル自身だけが対象になります。extendsで設定をマージする場合、後の設定のautoが前の設定のautoを丸ごと置き換えるため、{}を指定すると上限は8に戻ります:
{
"pretenders": {
"auto": { "depth": 3 }
}
}
設定済みのファイル集合を一度だけ事前スキャンするscanとは異なり、autoはリント対象ごとに実行され、リント対象ファイルが実際に(推移的に)importしているコンポーネントのみを対象とします。そのため、無関係なファイルにある同名コンポーネントが衝突することは構造的にありません。ただし、次のトレードオフがあります:
- watchモードやエディタセッションでは、
auto(とscan)が読み込んだコンポーネントファイルも設定ファイルとあわせて監視されるため、いずれかを編集すると、それを使っているファイルが再lintされます。監視されないため、設定を変更するまで反映されないのは、まだ存在しないコンポーネントファイル(scanのglobに新しく一致したファイル、削除後に戻ってきたファイルを含みます)、node_modules配下のファイル、filesとimportsのファイルです。lint対象のファイル自身の編集(importの追加・削除・変更)は、そのファイルの次回のlintに反映されます。 autoを指定できるのはpretendersのオブジェクト形式のみです。配列形式の省略記法では指定できません。
同じセレクターに対しては、files・imports・data・scanなど他のプリテンダー解決元が先に解決されるため、autoよりも優先されます。
インターフェイス
interface Config {
pretenders?:
| Pretender[]
| {
data?: Pretender[];
scan?: PretenderScanConfig[]; // @experimental
auto?: boolean | { depth?: number }; // @experimental
};
}
type Pretender = {
selector: string;
as: string | OriginalNode;
};
type OriginalNode = {
element: string;
slots?: null | true | Slot[]; // @experimental
contents?: Content[]; // @experimental
namespace?: 'svg';
inheritAttrs?: boolean;
attrs?: {
name: string;
value?:
| string
| {
fromAttr: string;
omitIfMissing?: true;
}
| {
dynamic: true;
};
}[];
aria?: {
name?:
| boolean
| {
fromAttr: string;
};
};
};
type Slot = Omit<OriginalNode, 'slots'>; // @experimental
type Content = // @experimental
{ element: string; attrs?: OriginalNode['attrs'] } | { slot: true } | { dynamic: true };
type PretenderScanConfig = {
files: string | string[];
ignoreComponentNames?: string[];
};
overrideMode
このオプションは、overrides セクションの振る舞いを制御します。このオプションを設定することで、プロジェクトの特定の部分に適用する異なるLintルールの設定の扱い方を指定できます。
reset
リセットモードでは、overrides セクションの設定は全く新しい設定として扱われ、既存の設定は無視されます。このモードは、特定のファイルやディレクトリに完全に新しいLintルールを適用したい場合に役立ちます。overrides セクションに指定された設定のみが使用され、他の設定は適用されません。
merge
このモードを選択すると、overrides セクションで指定された設定が既存の全体設定とマージされます。具体的には、overrides セクションに記載されたルールが追加されたり、既存のものを上書きしますが、他の設定は保持されます。このモードは、既存の設定に対して部分的な変更や追加を行いたい場合に適しています。
overrideMode の既定値は、互換性を保つために reset に設定されています。この設定は、デフォルトで overrides セクションが既存の設定を完全に置き換え、特定のファイルやディレクトリに特化したクリーンな状態を提供することを保証します。
既存のルールと新しいルールを融合させるより一般的な振る舞いを期待する場合は、overrideMode を merge に明示的に設定するべきです。これにより、overrides の設定がグローバル設定とシームレスに統合され、指定された変更のみが適用される一方で、既存のルールも維持されます。
インターフェイス
interface Config {
overrideMode?: 'reset' | 'merge';
}
overrides
overridesオプションを指定すると、特定のファイルに対して設定を上書きできます。キーに指定されたglob形式のパスに適用します。(minimatchを用いて解決されます)
{
"rules": {
"any-rule": true
},
"overrides": {
"./path/to/**/*": {
"rules": {
"any-rule": false
}
}
}
}
以下のプロパティを上書きできます。
インターフェイス
interface Config {
overrides?: {
[path: string]: Omit<Config, 'extends' | 'overrideMode' | 'overrides'>;
};
}