プロパティを設定する
設定は、以下のプロパティを持ちます。
{
"extends": [],
"plugins": {},
"parser": {},
"parserOptions": {},
"specs": [],
"excludeFiles": [],
"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",
"\\.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[];
}
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
}
}
インターフェイス
interface Config {
rules?: {
[ruleName: string]: Rule<T, O>;
};
}
type Rule<T, O> =
| boolean
| T
| {
severity?: 'error' | 'warning' | 'info';
value?: T;
option?: O;
reason?: string;
};
nodeRules
特定の要素にのみルールを適用させたい場合、このプロパティを指定します。値が配列であることに注意してください。
selector
かregexSelector
のどちらかが必要です。rules
フィールドも必須です。rules
プロパティと同じ値を指定します。
{
"nodeRules": [
{
"selector": "main",
"rules": {
"class-naming": "/[a-z]+(__[a-z]+)?/"
}
}
]
}
rules
rules
プロパティと同じ値を受け取ります。必須です。
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;
rules: {
[ruleName: string]: Rule<T, O>;
};
}
| {
regexSelector: RegexSelector;
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;
rules: {
[ruleName: string]: Rule<T, O>;
};
}
| {
regexSelector: RegexSelector;
inheritance?: boolean;
rules: {
[ruleName: string]: Rule<T, O>;
};
}
)[];
}
pretenders
プリテンダー機能は、カスタムコンポーネントをネイティブのHTML要素のように見せかける機能です。いくつかのルールで、コンポーネントをレンダリングされた結果の要素として評価するために利用します。値が配列であることに注意してください。
selector
対象コンポーネントにマッチさせるためのセレクタを受け取ります。必須です。
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
属性値を受け取ります。省略可能です。
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>;
インターフェイス
interface Config {
pretenders?: {
selector: string;
as: string | OriginalNode;
}[];
}
type OriginalNode = {
element: string;
namespace?: 'svg';
inheritAttrs?: boolean;
attrs?: {
name: string;
value?:
| string
| {
fromAttr: string;
};
}[];
aria?: {
name?:
| boolean
| {
fromAttr: 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'>;
};
}