JavaScriptで
ちゃんとマークアップする
環境を作る
夏のJavascript祭り Online
Webアクセシビリティエンジニア/開発者体験デザイナー: 平尾ゆうてん
https://markuplint.dev ©markuplint under the MIT license.
自己紹介
平尾ゆうてん
https://markuplint.dev ©markuplint under the MIT license.
今日話すこと
https://markuplint.dev ©markuplint under the MIT license.
マークアップは大切です
https://markuplint.dev ©markuplint under the MIT license.
マークアップは大切です
https://markuplint.dev ©markuplint under the MIT license.
マークアップを機械的にチェックする方法
| markuplint | eslint-plugin-jsx-a11y | axe | Nu Html Checker | acot | pa11y | miChecker | WAVE | A11yc |
エディタ・ アドオン | ✔ | ✔ | | | | | | | |
CLI (Web API) | ✔ | ✔ | ✔ | ✔ (Validator) | ✔ | ✔ | | ✔ | |
ブラウザ・ アドオン | | | ✔ | | | | | ✔ | |
SasS | | | ✔ (Lighthouse) | ✔ | | ✔ | | ✔ | ✔ |
アプリ | | | | | | ✔ (Koa11y) | ✔ Windows専用 | | |
エディタ→CLI→API→ブラウザ→SaaS→アプリになるにつれて『コーディング』から遠くなる
https://markuplint.dev ©markuplint under the MIT license.
マークアップを機械的にチェックする方法
| markuplint | eslint-plugin-jsx-a11y | axe | Nu Html Checker | acot | pa11y | miChecker | WAVE | A11yc |
エディタ・ アドオン | ✔ | ✔ | | | | | | | |
CLI (Web API) | ✔ | ✔ | ✔ | ✔ (Validator) | ✔ | ✔ | | ✔ | |
ブラウザ・ アドオン | | | ✔ | | | | | ✔ | |
SasS | | | ✔ (Lighthouse) | ✔ | | ✔ | | ✔ | ✔ |
アプリ | | | | | | ✔ (Koa11y) | ✔ ※Windows | | |
エディタ・CLIまわりのチェック環境を強化したい
https://markuplint.dev ©markuplint under the MIT license.
マークアップを機械的にチェックする方法
markuplintを開発することにしました
https://markuplint.dev ©markuplint under the MIT license.
マークアップを機械的にチェックする方法
https://markuplint.dev ©markuplint under the MIT license.
markuplintの特徴
https://markuplint.dev ©markuplint under the MIT license.
markuplintの特徴
https://markuplint.dev ©markuplint under the MIT license.
markuplintの特徴
https://markuplint.dev ©markuplint under the MIT license.
markuplintの使い方
https://markuplint.dev ©markuplint under the MIT license.
markuplintの設定をいじる
https://markuplint.dev ©markuplint under the MIT license.
markuplintの設定をいじる
「class-naming」ルールを利用してCSS設計の命名規則チェック
(もっと厳密に設定できるように、セレクタを正規表現に対応できるようにしようかな、と考えてたり考えていなかったり…)
<div class="Block">
<div class="Block__Element"></div>
<div class="Block__Element --modifier"></div>
</div>
<!-- Blockにはmodifierを与えない、という運用にしたいとき -->
<div class="Block --modifier">
<div class="Block__Element"></div>
<div class="Block__Element --modifier"></div>
</div>
{
"rules": {
"class-naming": "/^[A-Z][a-z]*$/"
},
"nodeRules": [
{
"selector": "[class*='__']",
"rules": {
"class-naming": [
"/^[A-Z][a-z]*__[A-Z][a-z]*$/",
"/^--[a-z]*$/"
]
}
}
]
}
https://markuplint.dev ©markuplint under the MIT license.
markuplintの設定をいじる
<x-tabs>
<x-tablist>
<x-tab>Tab 1</x-tab>
<x-tab>Tab 2</x-tab>
<x-tab>Tab 3</x-tab>
<x-tab>Tab 4</x-tab>
<x-tab>Tab 5</x-tab>
</x-tablist>
<x-tabpanel>Content 1</x-tabpanel>
<x-tabpanel>Content 2</x-tabpanel>
<x-tabpanel>Content 3</x-tabpanel>
<x-tabpanel>Content 4</x-tabpanel>
<x-tabpanel>Content 5</x-tabpanel>
</x-tabs>
「permitted-contents」ルールを利用して、カスタム要素にルールを設定
"rules": {
"permitted-contents": [
{
"tag": "x-tabs",
"contents": [
{
"require": "x-tablist"
},
{
"oneOrMore": "x-tabpanel"
}
]
},
{
"tag": "x-tablist",
"contents": [
{
"oneOrMore": "x-tab"
}
]
}
]
}
https://markuplint.dev ©markuplint under the MIT license.
markuplintの設定をいじる
「permitted-contents」ルールを利用して、カスタム要素にルールを設定
const Component = () => {
return (
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
<Tab>Tab 4</Tab>
<Tab>Tab 5</Tab>
</TabList>
<TabPanel>Content 1</TabPanel>
<TabPanel>Content 2</TabPanel>
<TabPanel>Content 3</TabPanel>
<TabPanel>Content 4</TabPanel>
<TabPanel>Content 5</TabPanel>
</Tabs>
);
};
"rules": {
"permitted-contents": [
{
"tag": "Tabs",
"contents": [
{
"require": "TabList"
},
{
"oneOrMore": "TabPanel"
}
]
},
{
"tag": "TabList",
"contents": [
{
"oneOrMore": "Tab"
}
]
}
]
}
https://markuplint.dev ©markuplint under the MIT license.
markuplintの設定をいじる
https://markuplint.dev ©markuplint under the MIT license.
markuplintのプラグインの書き方
https://markuplint.dev ©markuplint under the MIT license.
markuplintのプラグインの書き方
const { createRule } = require('@markuplint/ml-core');
module.exports = createRule({
defaultLevel: 'warning',
name: 'anyRuleName',
defaultValue: 'defaultValue',
defaultOptions: null,
async verify(document) {
const reports = [];
// ノード(テキストノード含めた要素など)ごとに探索
document.walk(node => {
// .markuplintrcで設定された値もしくはデフォルト値
// nodeから参照するのは、既にセレクタの上書きルール解決済みだから
const value = node.rule.value;
const result = doSomething(node, value);
if (!result) {
reports.push({
severity: node.rule.severity,
message: `${node.name} is bad`,
line: node.startLine,
col: node.startCol,
raw: node.raw,
});
}
});
return reports;
},
});
https://markuplint.dev ©markuplint under the MIT license.
markuplintのプラグインの書き方
document.walkOn('Element', element => {});
document.walkOn('ElementCloseTag', closeTag => {});
document.walkOn('Comment', comment => {});
document.walkOn('Text', text => {});
https://markuplint.dev ©markuplint under the MIT license.
markuplintのプラグインの書き方
element.attributes; // 属性の参照
element.childNodes; // 子要素の参照
element.classList; // クラスの参照
element.closeTag; // 閉じタグノードの参照
element.isForeignElement; // 外来要素かどうか
element.isCustomElement; // カスタム要素かどうか
element.ownModels; // 自身の所属するコンテントモデル
element.matches('SELECTOR'); // セレクタにマッチするか
element.closest('SELECTOR'); // セレクタにマッチする先祖の参照
https://markuplint.dev ©markuplint under the MIT license.
markuplintのプラグインの書き方
https://markuplint.dev ©markuplint under the MIT license.
JavaScriptで
ちゃんとマークアップする
環境を作る
夏のJavascript祭り Online
Webアクセシビリティエンジニア/開発者体験デザイナー: 平尾ゆうてん
https://markuplint.dev ©markuplint under the MIT license.