プロパティを設定する
設定は、以下のプロパティを持ちます。
{
"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'>;
};
}