From bf12f7d4ab0bffef3e07a230dd8c63adb70e60aa Mon Sep 17 00:00:00 2001 From: Yusuke Hirao Date: Tue, 20 Jan 2026 17:35:57 +0900 Subject: [PATCH 1/2] feat(markuplint): require command attribute on button elements Add rule to enforce Invoker Commands API usage on button elements with type="button". Two separate rules are added: 1. Require command attribute on button[type=button] elements - Exceptions: buttons with role attribute, form buttons (submit/reset/no type) 2. Encourage migration from popovertarget to Invoker Commands API - Display dedicated message for buttons with popovertarget attribute Update README to document all included rules in the config. Co-Authored-By: Claude Sonnet 4.5 --- packages/@d-zero/markuplint-config/README.md | 39 ++++++++++++++++++++ packages/@d-zero/markuplint-config/base.js | 21 +++++++++++ 2 files changed, 60 insertions(+) diff --git a/packages/@d-zero/markuplint-config/README.md b/packages/@d-zero/markuplint-config/README.md index 79f70a2e..d0df68fa 100644 --- a/packages/@d-zero/markuplint-config/README.md +++ b/packages/@d-zero/markuplint-config/README.md @@ -1,5 +1,7 @@ # `@d-zero/markuplint-config` +D-ZERO用のMarkuplint設定です。アクセシブルで保守性の高いHTML実装を促進するためのルールセットを提供します。 + ## 個別インストール ```sh @@ -16,6 +18,43 @@ npm install -D @d-zero/markuplint-config } ``` +## 含まれるルール + +このconfigには以下のD-ZERO独自ルールが含まれています: + +### 1. 要素の禁止・必須化 + +- **`br`要素の禁止**: CSSでスタイル調整を推奨 +- **`img`要素のalt属性必須**: アクセシビリティ確保のため +- **`a`要素のhref属性必須**: リンクの明確化 + +### 2. button要素のInvoker Commands API使用の強制 + +- **`type="button"`のbutton要素**: `command`属性が必須 + - Invoker Commands APIを使用した宣言的なUI実装を推奨 + - 例外: `role`属性を持つボタン、フォーム送信ボタン(`type="submit"`/`type="reset"`/typeなし) + +- **`popovertarget`属性を持つボタン**: Invoker Commands APIへの移行を推奨 + - `commandfor`/`command`属性の使用を推奨 + - `popovertarget`は将来的に非推奨となる予定 + +詳細は[CODING_GUIDELINES_NO_CLICK_EVENT.md](../../CODING_GUIDELINES_NO_CLICK_EVENT.md)を参照してください。 + +### 3. ファイル名の命名規則 + +- **画像/メディアファイル**: 小文字のケバブケース(ハイフン区切り)を強制 + - 対象: `img`, `video`, `audio`, `source`要素の`src`/`poster`属性 + - 大文字、スペース、アンダースコアは使用不可 + +### 4. 無効な属性 + +- **`a`要素のhref属性**: `javascript:`スキームを禁止 + - 代わりに`button`要素の使用を推奨 + +### 5. 特殊な属性の許可 + +- **`html`要素の`prefix`属性**: Open Graph Protocolのため許可 + ### 拡張 プロジェクトに合わせて設定を追加します。 diff --git a/packages/@d-zero/markuplint-config/base.js b/packages/@d-zero/markuplint-config/base.js index f2705663..dc0973eb 100644 --- a/packages/@d-zero/markuplint-config/base.js +++ b/packages/@d-zero/markuplint-config/base.js @@ -106,5 +106,26 @@ export default { }, }, }, + { + selector: 'button[type=button]:not([role]):not([popovertarget])', + rules: { + 'required-attr': { + value: 'command', + reason: + 'button要素には原則としてcommand属性が必要です。Invoker Commands APIを使用してアクセシブルなUIを実装してください。role属性を持つボタン(role="tab"など)やtype="submit"/type="reset"/typeなしのボタンは例外として許可されます。(D-ZERO独自ルール)', + }, + }, + }, + { + selector: + 'button[popovertarget]:not([command]):not([role]):not([type=submit]):not([type=reset])', + rules: { + 'required-attr': { + value: 'command', + reason: + 'popovertarget属性の代わりにInvoker Commands API(commandfor/command属性)の使用を推奨します。commandfor属性とshow-popover/hide-popover/toggle-popoverコマンドを使用してください。popovertargetは将来的に非推奨となる予定です。(D-ZERO独自ルール)', + }, + }, + }, ], }; From 2c3148ddc167bda7d71d58115be18280c3b0f88b Mon Sep 17 00:00:00 2001 From: Yusuke Hirao Date: Tue, 20 Jan 2026 17:36:25 +0900 Subject: [PATCH 2/2] test(markuplint): add tests for button command attribute rule Add comprehensive test cases for the new button command attribute validation: - Test type="button" buttons requiring command attribute - Test exceptions: role attributes, form buttons (submit/reset/no type) - Test popovertarget migration warning - Test edge cases and multiple attribute combinations Co-Authored-By: Claude Sonnet 4.5 --- test/cli.spec.mjs | 21 +++ test/fixtures/markuplint/button-command.html | 130 +++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 test/fixtures/markuplint/button-command.html diff --git a/test/cli.spec.mjs b/test/cli.spec.mjs index 522e4837..8cdf61f8 100644 --- a/test/cli.spec.mjs +++ b/test/cli.spec.mjs @@ -183,6 +183,27 @@ describe('markuplint', () => { ); expect(validNaming).toStrictEqual([]); }); + + test('Button Command Attribute', async () => { + const violations = await markuplint( + 'test/fixtures/markuplint/button-command.html', + 'packages/@d-zero/markuplint-config/base.js', + ); + expect(violations).toStrictEqual([ + 'test/fixtures/markuplint/button-command.html:27:17 The "btn" class name is unmatched with the below patterns: "/^c-(?[a-z][a-z0-9]*(?:-[a-z0-9]+)*)$/"', + 'test/fixtures/markuplint/button-command.html:45:58 The "btn" class name is unmatched with the below patterns: "/^c-(?[a-z][a-z0-9]*(?:-[a-z0-9]+)*)$/"', + 'test/fixtures/markuplint/button-command.html:42:40 The "command" attribute expects either "toggle-popover", "show-popover", "hide-popover", "close", "show-modal". Or, the "command" attribute expects the custom command format. Did you mean "--toggle"? (https://html.spec.whatwg.org/multipage/form-elements.html#valid-custom-command)', + 'test/fixtures/markuplint/button-command.html:102:2 Detected perceptible nodes between the trigger and corresponding target', + 'test/fixtures/markuplint/button-command.html:109:6 Detected perceptible nodes between the trigger and corresponding target', + 'test/fixtures/markuplint/button-command.html:108:2 Require accessible name', + 'test/fixtures/markuplint/button-command.html:127:3 Require accessible name', + 'test/fixtures/markuplint/button-command.html:18:2 The "button" element expects the "command" attribute', + 'test/fixtures/markuplint/button-command.html:101:2 The "button" element expects the "command" attribute', + 'test/fixtures/markuplint/button-command.html:102:2 The "button" element expects the "command" attribute', + 'test/fixtures/markuplint/button-command.html:55:21 The "aria-selected" ARIA state is not global state', + 'test/fixtures/markuplint/button-command.html:63:16 The "button" role is the implicit role of the "button" element', + ]); + }); }); describe('stylelint', () => { diff --git a/test/fixtures/markuplint/button-command.html b/test/fixtures/markuplint/button-command.html new file mode 100644 index 00000000..5c245dbf --- /dev/null +++ b/test/fixtures/markuplint/button-command.html @@ -0,0 +1,130 @@ + + + + + Button Command Test + + +

Button Command Attribute Tests

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Dialog content

+ +
+ +
+

Popover content

+
+ +
+ Summary +

Details content

+
+ +
+

Popover for popovertarget

+
+ +
+ +
+ +