@markuplint/ml-spec 4.10.1 → 4.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ARCHITECTURE.ja.md +253 -0
  2. package/ARCHITECTURE.md +253 -0
  3. package/CHANGELOG.md +3 -3
  4. package/README.md +4 -186
  5. package/SKILL.md +116 -0
  6. package/docs/aria-algorithms.ja.md +651 -0
  7. package/docs/aria-algorithms.md +651 -0
  8. package/docs/html-algorithms.ja.md +469 -0
  9. package/docs/html-algorithms.md +469 -0
  10. package/docs/maintenance.ja.md +340 -0
  11. package/docs/maintenance.md +340 -0
  12. package/docs/spec-resolution.ja.md +540 -0
  13. package/docs/spec-resolution.md +551 -0
  14. package/docs/type-definitions.ja.md +561 -0
  15. package/docs/type-definitions.md +561 -0
  16. package/lib/algorithm/aria/accname-computation.d.ts +7 -0
  17. package/lib/algorithm/aria/accname-computation.js +7 -0
  18. package/lib/algorithm/aria/aria-specs.d.ts +7 -0
  19. package/lib/algorithm/aria/aria-specs.js +7 -0
  20. package/lib/algorithm/aria/get-aria.d.ts +12 -0
  21. package/lib/algorithm/aria/get-aria.js +12 -0
  22. package/lib/algorithm/aria/get-computed-aria-props.d.ts +22 -0
  23. package/lib/algorithm/aria/get-computed-aria-props.js +10 -0
  24. package/lib/algorithm/aria/get-computed-role.d.ts +12 -0
  25. package/lib/algorithm/aria/get-computed-role.js +12 -0
  26. package/lib/algorithm/aria/get-implicit-role.d.ts +18 -0
  27. package/lib/algorithm/aria/get-implicit-role.js +18 -0
  28. package/lib/algorithm/aria/get-permitted-roles.d.ts +9 -0
  29. package/lib/algorithm/aria/get-permitted-roles.js +9 -0
  30. package/lib/algorithm/aria/get-role-spec.d.ts +11 -0
  31. package/lib/algorithm/aria/get-role-spec.js +11 -0
  32. package/lib/algorithm/aria/has-required-owned-elements.d.ts +23 -0
  33. package/lib/algorithm/aria/has-required-owned-elements.js +23 -0
  34. package/lib/algorithm/aria/is-exposed.d.ts +7 -4
  35. package/lib/algorithm/aria/is-exposed.js +7 -4
  36. package/lib/algorithm/aria/is-presentational.d.ts +8 -0
  37. package/lib/algorithm/aria/is-presentational.js +8 -0
  38. package/lib/algorithm/aria/matches-context-role.d.ts +11 -0
  39. package/lib/algorithm/aria/matches-context-role.js +11 -0
  40. package/lib/algorithm/html/content-model-category-to-tag-names.d.ts +9 -0
  41. package/lib/algorithm/html/content-model-category-to-tag-names.js +9 -0
  42. package/lib/algorithm/html/get-content-model.d.ts +9 -0
  43. package/lib/algorithm/html/get-content-model.js +9 -0
  44. package/lib/algorithm/html/get-selectors-by-content-model-category.d.ts +8 -0
  45. package/lib/algorithm/html/get-selectors-by-content-model-category.js +8 -0
  46. package/lib/algorithm/html/is-nothing-content-model.d.ts +7 -0
  47. package/lib/algorithm/html/is-nothing-content-model.js +7 -0
  48. package/lib/algorithm/html/is-palpable-elements.d.ts +13 -0
  49. package/lib/algorithm/html/is-palpable-elements.js +13 -0
  50. package/lib/algorithm/html/is-void-element.d.ts +9 -0
  51. package/lib/algorithm/html/is-void-element.js +9 -0
  52. package/lib/algorithm/html/may-be-focusable.d.ts +10 -0
  53. package/lib/algorithm/html/may-be-focusable.js +10 -0
  54. package/lib/types/index.d.ts +54 -0
  55. package/lib/utils/aria-version.d.ts +6 -0
  56. package/lib/utils/aria-version.js +6 -0
  57. package/lib/utils/get-attr-specs-spec.d.ts +18 -0
  58. package/lib/utils/get-attr-specs-spec.js +18 -0
  59. package/lib/utils/get-attr-specs.d.ts +9 -0
  60. package/lib/utils/get-attr-specs.js +9 -0
  61. package/lib/utils/get-spec-by-tag-name.d.ts +11 -0
  62. package/lib/utils/get-spec-by-tag-name.js +11 -0
  63. package/lib/utils/get-spec.d.ts +11 -1
  64. package/lib/utils/get-spec.js +10 -0
  65. package/lib/utils/resolve-namespace.d.ts +13 -0
  66. package/lib/utils/resolve-namespace.js +10 -0
  67. package/lib/utils/schema-to-spec.d.ts +5 -2
  68. package/lib/utils/schema-to-spec.js +5 -2
  69. package/lib/utils/validate-aria-version.d.ts +7 -0
  70. package/lib/utils/validate-aria-version.js +7 -0
  71. package/package.json +6 -6
@@ -0,0 +1,253 @@
1
+ # @markuplint/ml-spec
2
+
3
+ ## 概要
4
+
5
+ `@markuplint/ml-spec` は markuplint の仕様基盤レイヤーです。型定義、W3C 仕様アルゴリズム(ARIA/HTML)、JSON スキーマ、ランタイムユーティリティを提供し、Web 標準の生データと markuplint のリントルールを橋渡しします。
6
+
7
+ `@markuplint/html-spec`(およびフレームワーク固有の仕様パッケージ)から要素仕様・ARIA ロール/プロパティ定義・コンテンツモデルデータを読み込み、ARIA ロール計算・要素仕様の解決・コンテンツモデル評価・アクセシビリティツリー包含判定のアルゴリズムを公開します。15 以上の下流パッケージが依存しています。
8
+
9
+ ## ディレクトリ構成
10
+
11
+ ```
12
+ src/
13
+ ├── index.ts # エントリーポイント。全公開 API を再エクスポート
14
+ ├── types/
15
+ │ ├── index.ts # 手書きのコア型(MLMLSpec, ElementSpec, ARIARole 等)
16
+ │ ├── aria.ts # aria.schema.json から生成(ARIA, PermittedRoles, ImplicitRole)
17
+ │ ├── attributes.ts # attributes.schema.json から生成(AttributeType, GlobalAttributes)
18
+ │ └── permitted-structures.ts # content-models.schema.json から生成(ContentModel, Category)
19
+ ├── algorithm/
20
+ │ ├── aria/
21
+ │ │ ├── accname-computation.ts # dom-accessibility-api によるアクセシブルネーム計算
22
+ │ │ ├── aria-specs.ts # バージョン別 ARIA 仕様データの取得
23
+ │ │ ├── get-aria.ts # 要素レベルの ARIA 仕様解決(条件付き)
24
+ │ │ ├── get-computed-aria-props.ts # ARIA プロパティ解決(明示 → HTML → デフォルト)
25
+ │ │ ├── get-computed-role.ts # 中核:最終ロール計算と競合解決
26
+ │ │ ├── get-explicit-role.ts # role 属性からの明示ロール(著者エラー処理)
27
+ │ │ ├── get-implicit-role.ts # HTML-AAM による暗黙ロール
28
+ │ │ ├── get-implicit-role-spec.ts # 暗黙ロール名の低レベル検索
29
+ │ │ ├── get-non-presentational-ancestor.ts # プレゼンテーショナルロールをスキップする祖先探索
30
+ │ │ ├── get-permitted-roles.ts # DOM 要素の許可ロール
31
+ │ │ ├── get-permitted-roles-spec.ts # タグ名/名前空間による許可ロール(低レベル)
32
+ │ │ ├── get-role-spec.ts # スーパークラスチェーン付きロール仕様
33
+ │ │ ├── has-required-owned-elements.ts # 必須所有要素の検証
34
+ │ │ ├── is-exposed.ts # アクセシビリティツリー包含/除外
35
+ │ │ ├── is-presentational.ts # プレゼンテーショナルロール判定(presentation/none)
36
+ │ │ └── matches-context-role.ts # 必須コンテキストロールの検証
37
+ │ └── html/
38
+ │ ├── content-model-category-to-tag-names.ts # カテゴリ → タグ名配列(キャッシュ付き)
39
+ │ ├── get-content-model.ts # 条件付きコンテンツモデル評価
40
+ │ ├── get-selectors-by-content-model-category.ts # カテゴリ → CSS セレクタ配列
41
+ │ ├── is-nothing-content-model.ts # 「Nothing」コンテンツモデル判定
42
+ │ ├── is-palpable-elements.ts # パルパブルコンテンツ検出
43
+ │ ├── is-void-element.ts # ボイド要素判定(13 要素)
44
+ │ └── may-be-focusable.ts # フォーカス可能性ヒューリスティック
45
+ └── utils/
46
+ ├── aria-version.ts # ARIA バージョン定数('1.1', '1.2', '1.3')
47
+ ├── get-attr-specs.ts # DOM 要素の属性仕様(ラッパー)
48
+ ├── get-attr-specs-spec.ts # タグ名/名前空間による属性仕様(コア)
49
+ ├── get-ns.ts # 名前空間 URI → 短縮名マッピング
50
+ ├── get-spec.ts # DOM 要素の要素仕様(ラッパー)
51
+ ├── get-spec-by-tag-name.ts # タグ名/名前空間による要素仕様(キャッシュ付き)
52
+ ├── merge-array.ts # 名前ベースの配列マージユーティリティ
53
+ ├── resolve-namespace.ts # 名前空間解決とプレフィックス正規化
54
+ ├── resolve-version.ts # ARIA バージョン固有プロパティの解決
55
+ ├── schema-to-spec.ts # スキーママージパイプライン(ベース + 拡張)
56
+ └── validate-aria-version.ts # ARIA バージョン文字列の型ガード
57
+
58
+ schemas/
59
+ ├── element.schema.json # トップレベル要素仕様スキーマ(11 行)
60
+ ├── aria.schema.json # ARIA ロール/プロパティスキーマ(291 行)
61
+ ├── attributes.schema.json # 属性型スキーマ(190 行)
62
+ ├── content-models.schema.json # コンテンツモデルパターンスキーマ(215 行)
63
+ └── global-attributes.schema.json # グローバル属性カテゴリスキーマ(787 行)
64
+
65
+ gen/
66
+ ├── gen.ts # global-attributes.schema.json のスキーマジェネレータ
67
+ └── global-attribute.data.ts # グローバル属性カテゴリ定義
68
+ ```
69
+
70
+ ## アーキテクチャ図
71
+
72
+ ```mermaid
73
+ flowchart TD
74
+ subgraph input ["入力レイヤー"]
75
+ htmlSpec["@markuplint/html-spec\n(MLMLSpec JSON)"]
76
+ fwSpec["フレームワーク仕様\n(ExtendedSpec)"]
77
+ end
78
+
79
+ subgraph merge ["仕様解決"]
80
+ schemaToSpec["schemaToSpec()"]
81
+ getSpec["getSpec() / getSpecByTagName()"]
82
+ getAttrSpecs["getAttrSpecs()"]
83
+ resolveNS["resolveNamespace()"]
84
+ end
85
+
86
+ subgraph aria ["ARIA アルゴリズム"]
87
+ getComputedRole["getComputedRole()"]
88
+ getExplicitRole["getExplicitRole()"]
89
+ getImplicitRole["getImplicitRole()"]
90
+ getPermittedRoles["getPermittedRoles()"]
91
+ getRoleSpec["getRoleSpec()"]
92
+ getARIA["getARIA()"]
93
+ getComputedAriaProps["getComputedAriaProps()"]
94
+ isExposed["isExposed()"]
95
+ getAccname["getAccname()"]
96
+ end
97
+
98
+ subgraph html ["HTML アルゴリズム"]
99
+ getContentModel["getContentModel()"]
100
+ isPalpable["isPalpableElement()"]
101
+ isVoid["isVoidElement()"]
102
+ mayBeFocusable["mayBeFocusable()"]
103
+ end
104
+
105
+ subgraph types ["型定義"]
106
+ handWritten["MLMLSpec, ElementSpec\nARIARole, ComputedRole"]
107
+ generated["ARIA, PermittedRoles\nContentModel, Category"]
108
+ end
109
+
110
+ htmlSpec --> schemaToSpec
111
+ fwSpec --> schemaToSpec
112
+ schemaToSpec --> getSpec
113
+ getSpec --> getAttrSpecs
114
+ getSpec --> getARIA
115
+ resolveNS --> getSpec
116
+
117
+ getARIA --> getComputedRole
118
+ getExplicitRole --> getComputedRole
119
+ getImplicitRole --> getComputedRole
120
+ getPermittedRoles --> getExplicitRole
121
+ getRoleSpec --> getImplicitRole
122
+ getRoleSpec --> getExplicitRole
123
+ getComputedRole --> getComputedAriaProps
124
+ getComputedRole --> isExposed
125
+
126
+ getSpec --> getContentModel
127
+ getSpec --> isPalpable
128
+ ```
129
+
130
+ ## 主要コンポーネント
131
+
132
+ ### 1. 型定義
133
+
134
+ 型システムは、マークアップ言語仕様・要素仕様・ARIA ロール・属性の構造を定義します。
135
+
136
+ | ファイル | 役割 |
137
+ | ------------------------------- | ------------------------------------------------------------------------------------------------- |
138
+ | `types/index.ts` | 手書き型: `MLMLSpec`, `ElementSpec`, `ExtendedSpec`, `ARIARole`, `ComputedRole` 等 |
139
+ | `types/aria.ts` | 生成型: `ARIA`, `PermittedRoles`, `ImplicitRole`, `PermittedARIAProperties`, `ImplicitProperties` |
140
+ | `types/attributes.ts` | 生成型: `AttributeType`, `GlobalAttributes`, `AttributeJSON`, `List`, `Enum`, `Number` |
141
+ | `types/permitted-structures.ts` | 生成型: `PermittedContentPattern`, `ContentModel`, `Category`(HTML 13 + SVG 19 カテゴリ) |
142
+
143
+ ### 2. ARIA アルゴリズム
144
+
145
+ ARIA アルゴリズムは WAI-ARIA, HTML-AAM, SVG-AAM, AccName 1.1 仕様に基づくロール計算とアクセシビリティツリー管理を実装します。
146
+
147
+ | ファイル | 役割 |
148
+ | -------------------------------- | ------------------------------------------------------------------------------- |
149
+ | `get-computed-role.ts` | 中核アルゴリズム: Presentational Roles Conflict Resolution による最終ロール計算 |
150
+ | `get-explicit-role.ts` | `role` 属性からの明示ロール解決(著者エラー処理付き) |
151
+ | `get-implicit-role.ts` | HTML-AAM に基づく暗黙(ネイティブ)ARIA ロールの決定 |
152
+ | `get-computed-aria-props.ts` | ARIA プロパティ解決: 明示 `aria-*` → HTML 等価属性 → 仕様デフォルト |
153
+ | `is-exposed.ts` | WAI-ARIA ルールに基づくアクセシビリティツリーの包含/除外判定 |
154
+ | `get-permitted-roles.ts` | 要素の許可ロール一覧(Any/No/具体的リスト) |
155
+ | `get-role-spec.ts` | スーパークラスロールチェーン付き完全ロール仕様の取得 |
156
+ | `has-required-owned-elements.ts` | 必須所有要素制約の検証 |
157
+ | `matches-context-role.ts` | 祖先チェーンにおける必須コンテキストロール条件の検証 |
158
+ | `accname-computation.ts` | `dom-accessibility-api` によるアクセシブルネーム計算 |
159
+ | `get-aria.ts` | バージョンと条件の解決を含む要素レベル ARIA 仕様 |
160
+ | `is-presentational.ts` | ロールが `presentation` または `none` かどうかの判定 |
161
+
162
+ ### 3. HTML アルゴリズム
163
+
164
+ HTML アルゴリズムは HTML Living Standard に基づくコンテンツモデル評価と要素分類を実装します。
165
+
166
+ | ファイル | 役割 |
167
+ | -------------------------------------------- | ------------------------------------------------------------------------------ |
168
+ | `get-content-model.ts` | 条件付きパターン評価を含むコンテンツモデルの取得 |
169
+ | `content-model-category-to-tag-names.ts` | コンテンツモデルカテゴリをソート済みタグ名配列に変換 |
170
+ | `get-selectors-by-content-model-category.ts` | コンテンツモデルカテゴリを CSS セレクタにマッピング |
171
+ | `is-palpable-elements.ts` | SVG/露出可能要素拡張付きパルパブルコンテンツ検出 |
172
+ | `is-void-element.ts` | ボイド要素判定(13 の HTML ボイド要素) |
173
+ | `is-nothing-content-model.ts` | 「Nothing」コンテンツモデル判定(void + iframe + template) |
174
+ | `may-be-focusable.ts` | フォーカス可能性ヒューリスティック(interactive + tabindex + contenteditable) |
175
+
176
+ ### 4. 仕様解決ユーティリティ
177
+
178
+ 仕様のマージ・解決・キャッシュのためのユーティリティです。
179
+
180
+ | ファイル | 役割 |
181
+ | -------------------------- | ---------------------------------------------------------------------------- |
182
+ | `schema-to-spec.ts` | ベース `MLMLSpec` と `ExtendedSpec[]` のマージ(グローバル属性, ARIA, 要素) |
183
+ | `get-spec-by-tag-name.ts` | タグ名 + 名前空間による要素仕様の検索(キャッシュ付き) |
184
+ | `get-attr-specs-spec.ts` | マージ済み属性仕様の取得(グローバル + 要素固有) |
185
+ | `resolve-namespace.ts` | 名前空間プレフィックスを含む要素名の正規化 |
186
+ | `resolve-version.ts` | ARIA バージョン固有のオーバーライドをフォールバック付きで解決 |
187
+ | `merge-array.ts` | 名前ベースの配列マージ(`name` プロパティによる追加/上書き) |
188
+ | `validate-aria-version.ts` | 有効な ARIA バージョン文字列の型ガード |
189
+
190
+ ## 外部依存パッケージ
191
+
192
+ | パッケージ | 用途 | 使用箇所 |
193
+ | ----------------------- | -------------------------------------------------- | ----------------------------- |
194
+ | `@markuplint/ml-ast` | XML 名前空間処理のための `NamespaceURI` 型 | `types/index.ts`, utils |
195
+ | `@markuplint/types` | 属性値の型定義のための `Type` 共用体 | `types/attributes.ts` 経由 |
196
+ | `dom-accessibility-api` | AccName 計算(WAI-ARIA アルゴリズム) | `accname-computation.ts` |
197
+ | `is-plain-object` | AAM 情報のプレーンオブジェクト検出 | `get-permitted-roles-spec.ts` |
198
+ | `type-fest` | 深い不変性のための `ReadonlyDeep` ユーティリティ型 | 複数ファイル |
199
+
200
+ ## 他パッケージとの連携
201
+
202
+ ```mermaid
203
+ flowchart LR
204
+ subgraph upstream ["上流パッケージ"]
205
+ htmlSpec["@markuplint/html-spec"]
206
+ vueSpec["@markuplint/vue-spec"]
207
+ reactSpec["@markuplint/react-spec"]
208
+ otherSpec["その他フレームワーク仕様"]
209
+ end
210
+
211
+ subgraph pkg ["@markuplint/ml-spec"]
212
+ types["型定義"]
213
+ ariaAlgo["ARIA アルゴリズム"]
214
+ htmlAlgo["HTML アルゴリズム"]
215
+ specRes["仕様解決"]
216
+ end
217
+
218
+ subgraph downstream ["下流パッケージ"]
219
+ mlCore["@markuplint/ml-core"]
220
+ rules["@markuplint/rules"]
221
+ selector["@markuplint/selector"]
222
+ end
223
+
224
+ htmlSpec -->|"MLMLSpec JSON"| specRes
225
+ vueSpec -->|"ExtendedSpec"| specRes
226
+ reactSpec -->|"ExtendedSpec"| specRes
227
+ otherSpec -->|"ExtendedSpec"| specRes
228
+
229
+ specRes --> ariaAlgo
230
+ specRes --> htmlAlgo
231
+ types --> mlCore
232
+ ariaAlgo -->|"ロール計算\nアクセシビリティツリー"| rules
233
+ htmlAlgo -->|"コンテンツモデル\n要素分類"| rules
234
+ types --> selector
235
+ ```
236
+
237
+ ### 上流
238
+
239
+ `@markuplint/html-spec` は、全 HTML 要素仕様・ARIA 定義・コンテンツモデルデータを含むベース `MLMLSpec` JSON を提供します。フレームワーク固有パッケージ(`@markuplint/vue-spec`, `@markuplint/react-spec` 等)は、要素・属性・ARIA マッピングを追加またはオーバーライドする `ExtendedSpec` オブジェクトを提供します。
240
+
241
+ ### 下流
242
+
243
+ - **`@markuplint/ml-core`** は型定義を使用して、仕様認識を持つパース済みドキュメント要素を表現します。
244
+ - **`@markuplint/rules`** は ARIA および HTML アルゴリズムを呼び出して、リントルール(ロール検証、コンテンツモデルチェック、アクセシビリティチェック)を実装します。
245
+ - **`@markuplint/selector`** は要素マッチングのために型定義を使用します。
246
+
247
+ ## ドキュメントマップ
248
+
249
+ - [ARIA アルゴリズム](docs/aria-algorithms.ja.md) -- ロール計算、アクセシビリティツリー、ARIA プロパティ解決
250
+ - [HTML アルゴリズム](docs/html-algorithms.ja.md) -- コンテンツモデル、要素分類、ボイド要素
251
+ - [型定義](docs/type-definitions.ja.md) -- コア型、生成型、JSON スキーマ
252
+ - [仕様解決](docs/spec-resolution.ja.md) -- スキーママージ、名前空間解決、キャッシュ
253
+ - [メンテナンスガイド](docs/maintenance.ja.md) -- スキーマ生成、依存関係管理、レシピ、トラブルシューティング
@@ -0,0 +1,253 @@
1
+ # @markuplint/ml-spec
2
+
3
+ ## Overview
4
+
5
+ `@markuplint/ml-spec` is the specification foundation layer for markuplint. It provides type definitions, W3C specification algorithms (ARIA/HTML), JSON schemas, and runtime utilities that form the bridge between raw web standard data and markuplint's lint rules.
6
+
7
+ The package reads element specifications, ARIA role/property definitions, and content model data from `@markuplint/html-spec` (and framework-specific spec packages), then exposes algorithms for computing ARIA roles, resolving element specifications, evaluating content models, and determining accessibility tree inclusion. Over 15 downstream packages depend on `@markuplint/ml-spec`.
8
+
9
+ ## Directory Structure
10
+
11
+ ```
12
+ src/
13
+ ├── index.ts # Package entry point; re-exports all public APIs
14
+ ├── types/
15
+ │ ├── index.ts # Hand-written core types (MLMLSpec, ElementSpec, ARIARole, etc.)
16
+ │ ├── aria.ts # Generated types from aria.schema.json (ARIA, PermittedRoles, ImplicitRole)
17
+ │ ├── attributes.ts # Generated types from attributes.schema.json (AttributeType, GlobalAttributes)
18
+ │ └── permitted-structures.ts # Generated types from content-models.schema.json (ContentModel, Category)
19
+ ├── algorithm/
20
+ │ ├── aria/
21
+ │ │ ├── accname-computation.ts # Accessible name computation via dom-accessibility-api
22
+ │ │ ├── aria-specs.ts # Version-specific ARIA spec data retrieval
23
+ │ │ ├── get-aria.ts # Element-level ARIA spec resolution with conditions
24
+ │ │ ├── get-computed-aria-props.ts # ARIA property resolution (explicit → HTML → default)
25
+ │ │ ├── get-computed-role.ts # Core: final role computation with conflict resolution
26
+ │ │ ├── get-explicit-role.ts # Explicit role from role attribute with author error handling
27
+ │ │ ├── get-implicit-role.ts # Implicit (native) role from HTML-AAM
28
+ │ │ ├── get-implicit-role-spec.ts # Low-level implicit role name lookup
29
+ │ │ ├── get-non-presentational-ancestor.ts # Ancestor traversal skipping presentational roles
30
+ │ │ ├── get-permitted-roles.ts # Permitted roles for a DOM element
31
+ │ │ ├── get-permitted-roles-spec.ts # Permitted roles from tag name/namespace (low-level)
32
+ │ │ ├── get-role-spec.ts # Full role spec with super-class chain
33
+ │ │ ├── has-required-owned-elements.ts # Required owned elements validation
34
+ │ │ ├── is-exposed.ts # Accessibility tree inclusion/exclusion
35
+ │ │ ├── is-presentational.ts # Presentational role check (presentation/none)
36
+ │ │ └── matches-context-role.ts # Required context role validation
37
+ │ └── html/
38
+ │ ├── content-model-category-to-tag-names.ts # Category → tag name array (cached)
39
+ │ ├── get-content-model.ts # Content model with conditional evaluation
40
+ │ ├── get-selectors-by-content-model-category.ts # Category → CSS selector array
41
+ │ ├── is-nothing-content-model.ts # "Nothing" content model check
42
+ │ ├── is-palpable-elements.ts # Palpable content detection
43
+ │ ├── is-void-element.ts # Void element check (13 elements)
44
+ │ └── may-be-focusable.ts # Focusability heuristic
45
+ └── utils/
46
+ ├── aria-version.ts # ARIA version constants ('1.1', '1.2', '1.3')
47
+ ├── get-attr-specs.ts # Attribute specs for a DOM element (wrapper)
48
+ ├── get-attr-specs-spec.ts # Attribute specs by tag name/namespace (core)
49
+ ├── get-ns.ts # Namespace URI → shorthand mapping
50
+ ├── get-spec.ts # Element spec for a DOM element (wrapper)
51
+ ├── get-spec-by-tag-name.ts # Element spec by tag name/namespace (cached)
52
+ ├── merge-array.ts # Name-based array merge utility
53
+ ├── resolve-namespace.ts # Namespace resolution and prefix normalization
54
+ ├── resolve-version.ts # ARIA version-specific property resolution
55
+ ├── schema-to-spec.ts # Schema merge pipeline (base + extensions)
56
+ └── validate-aria-version.ts # ARIA version string type guard
57
+
58
+ schemas/
59
+ ├── element.schema.json # Top-level element spec schema (11 lines)
60
+ ├── aria.schema.json # ARIA role/property schema (291 lines)
61
+ ├── attributes.schema.json # Attribute type schema (190 lines)
62
+ ├── content-models.schema.json # Content model pattern schema (215 lines)
63
+ └── global-attributes.schema.json # Global attribute categories schema (787 lines)
64
+
65
+ gen/
66
+ ├── gen.ts # Schema generator for global-attributes.schema.json
67
+ └── global-attribute.data.ts # Global attribute category definitions
68
+ ```
69
+
70
+ ## Architecture Diagram
71
+
72
+ ```mermaid
73
+ flowchart TD
74
+ subgraph input ["Input Layer"]
75
+ htmlSpec["@markuplint/html-spec\n(MLMLSpec JSON)"]
76
+ fwSpec["Framework specs\n(ExtendedSpec)"]
77
+ end
78
+
79
+ subgraph merge ["Spec Resolution"]
80
+ schemaToSpec["schemaToSpec()"]
81
+ getSpec["getSpec() / getSpecByTagName()"]
82
+ getAttrSpecs["getAttrSpecs()"]
83
+ resolveNS["resolveNamespace()"]
84
+ end
85
+
86
+ subgraph aria ["ARIA Algorithms"]
87
+ getComputedRole["getComputedRole()"]
88
+ getExplicitRole["getExplicitRole()"]
89
+ getImplicitRole["getImplicitRole()"]
90
+ getPermittedRoles["getPermittedRoles()"]
91
+ getRoleSpec["getRoleSpec()"]
92
+ getARIA["getARIA()"]
93
+ getComputedAriaProps["getComputedAriaProps()"]
94
+ isExposed["isExposed()"]
95
+ getAccname["getAccname()"]
96
+ end
97
+
98
+ subgraph html ["HTML Algorithms"]
99
+ getContentModel["getContentModel()"]
100
+ isPalpable["isPalpableElement()"]
101
+ isVoid["isVoidElement()"]
102
+ mayBeFocusable["mayBeFocusable()"]
103
+ end
104
+
105
+ subgraph types ["Type Definitions"]
106
+ handWritten["MLMLSpec, ElementSpec\nARIARole, ComputedRole"]
107
+ generated["ARIA, PermittedRoles\nContentModel, Category"]
108
+ end
109
+
110
+ htmlSpec --> schemaToSpec
111
+ fwSpec --> schemaToSpec
112
+ schemaToSpec --> getSpec
113
+ getSpec --> getAttrSpecs
114
+ getSpec --> getARIA
115
+ resolveNS --> getSpec
116
+
117
+ getARIA --> getComputedRole
118
+ getExplicitRole --> getComputedRole
119
+ getImplicitRole --> getComputedRole
120
+ getPermittedRoles --> getExplicitRole
121
+ getRoleSpec --> getImplicitRole
122
+ getRoleSpec --> getExplicitRole
123
+ getComputedRole --> getComputedAriaProps
124
+ getComputedRole --> isExposed
125
+
126
+ getSpec --> getContentModel
127
+ getSpec --> isPalpable
128
+ ```
129
+
130
+ ## Core Components
131
+
132
+ ### 1. Type Definitions
133
+
134
+ The type system defines the structure of markup language specifications, element specs, ARIA roles, and attributes.
135
+
136
+ | File | Purpose |
137
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------- |
138
+ | `types/index.ts` | Hand-written types: `MLMLSpec`, `ElementSpec`, `ExtendedSpec`, `ARIARole`, `ComputedRole`, etc. |
139
+ | `types/aria.ts` | Generated: `ARIA`, `PermittedRoles`, `ImplicitRole`, `PermittedARIAProperties`, `ImplicitProperties` |
140
+ | `types/attributes.ts` | Generated: `AttributeType`, `GlobalAttributes`, `AttributeJSON`, `List`, `Enum`, `Number` |
141
+ | `types/permitted-structures.ts` | Generated: `PermittedContentPattern`, `ContentModel`, `Category` (HTML 13 + SVG 19 categories) |
142
+
143
+ ### 2. ARIA Algorithms
144
+
145
+ ARIA algorithms implement WAI-ARIA, HTML-AAM, SVG-AAM, and AccName 1.1 specifications for role computation and accessibility tree management.
146
+
147
+ | File | Purpose |
148
+ | -------------------------------- | --------------------------------------------------------------------------------- |
149
+ | `get-computed-role.ts` | Core algorithm: computes final role with Presentational Roles Conflict Resolution |
150
+ | `get-explicit-role.ts` | Resolves explicit roles from `role` attribute with author error handling |
151
+ | `get-implicit-role.ts` | Determines implicit (native) ARIA role from HTML-AAM |
152
+ | `get-computed-aria-props.ts` | Resolves ARIA properties: explicit `aria-*` → HTML equivalent → spec defaults |
153
+ | `is-exposed.ts` | Determines accessibility tree inclusion/exclusion per WAI-ARIA rules |
154
+ | `get-permitted-roles.ts` | Lists permitted roles for an element (Any/No/specific list) |
155
+ | `get-role-spec.ts` | Retrieves full role spec with super-class role chain |
156
+ | `has-required-owned-elements.ts` | Validates required owned element constraints |
157
+ | `matches-context-role.ts` | Validates required context role conditions in ancestor chain |
158
+ | `accname-computation.ts` | Accessible name computation via `dom-accessibility-api` |
159
+ | `get-aria.ts` | Element-level ARIA spec with version and condition resolution |
160
+ | `is-presentational.ts` | Checks if a role is `presentation` or `none` |
161
+
162
+ ### 3. HTML Algorithms
163
+
164
+ HTML algorithms implement content model evaluation and element classification from the HTML Living Standard.
165
+
166
+ | File | Purpose |
167
+ | -------------------------------------------- | ----------------------------------------------------------------- |
168
+ | `get-content-model.ts` | Retrieves content model with conditional pattern evaluation |
169
+ | `content-model-category-to-tag-names.ts` | Converts content model category to sorted tag name array |
170
+ | `get-selectors-by-content-model-category.ts` | Maps content model category to CSS selectors |
171
+ | `is-palpable-elements.ts` | Palpable content detection with SVG/exposable extensions |
172
+ | `is-void-element.ts` | Void element check (13 HTML void elements) |
173
+ | `is-nothing-content-model.ts` | "Nothing" content model check (void + iframe + template) |
174
+ | `may-be-focusable.ts` | Focusability heuristic (interactive + tabindex + contenteditable) |
175
+
176
+ ### 4. Spec Resolution Utilities
177
+
178
+ Utilities for merging, resolving, and caching specifications.
179
+
180
+ | File | Purpose |
181
+ | -------------------------- | --------------------------------------------------------------------------- |
182
+ | `schema-to-spec.ts` | Merges base `MLMLSpec` with `ExtendedSpec[]` (global attrs, ARIA, elements) |
183
+ | `get-spec-by-tag-name.ts` | Looks up element spec by tag name + namespace (cached) |
184
+ | `get-attr-specs-spec.ts` | Retrieves merged attribute specs (global + element-specific) |
185
+ | `resolve-namespace.ts` | Normalizes element names with namespace prefixes |
186
+ | `resolve-version.ts` | Resolves ARIA version-specific overrides with fallback |
187
+ | `merge-array.ts` | Name-based array merging (add/override by `name` property) |
188
+ | `validate-aria-version.ts` | Type guard for valid ARIA version strings |
189
+
190
+ ## External Dependencies
191
+
192
+ | Dependency | Purpose | Where Used |
193
+ | ----------------------- | ------------------------------------------------- | ----------------------------- |
194
+ | `@markuplint/ml-ast` | `NamespaceURI` type for XML namespace handling | `types/index.ts`, utils |
195
+ | `@markuplint/types` | `Type` union for attribute value type definitions | via `types/attributes.ts` |
196
+ | `dom-accessibility-api` | AccName computation (WAI-ARIA algorithm) | `accname-computation.ts` |
197
+ | `is-plain-object` | Plain object detection for AAM info | `get-permitted-roles-spec.ts` |
198
+ | `type-fest` | `ReadonlyDeep` utility type for deep immutability | Multiple files |
199
+
200
+ ## Integration Points
201
+
202
+ ```mermaid
203
+ flowchart LR
204
+ subgraph upstream ["Upstream"]
205
+ htmlSpec["@markuplint/html-spec"]
206
+ vueSpec["@markuplint/vue-spec"]
207
+ reactSpec["@markuplint/react-spec"]
208
+ otherSpec["Other framework specs"]
209
+ end
210
+
211
+ subgraph pkg ["@markuplint/ml-spec"]
212
+ types["Type definitions"]
213
+ ariaAlgo["ARIA algorithms"]
214
+ htmlAlgo["HTML algorithms"]
215
+ specRes["Spec resolution"]
216
+ end
217
+
218
+ subgraph downstream ["Downstream"]
219
+ mlCore["@markuplint/ml-core"]
220
+ rules["@markuplint/rules"]
221
+ selector["@markuplint/selector"]
222
+ end
223
+
224
+ htmlSpec -->|"MLMLSpec JSON"| specRes
225
+ vueSpec -->|"ExtendedSpec"| specRes
226
+ reactSpec -->|"ExtendedSpec"| specRes
227
+ otherSpec -->|"ExtendedSpec"| specRes
228
+
229
+ specRes --> ariaAlgo
230
+ specRes --> htmlAlgo
231
+ types --> mlCore
232
+ ariaAlgo -->|"role computation\naccessibility tree"| rules
233
+ htmlAlgo -->|"content model\nelement classification"| rules
234
+ types --> selector
235
+ ```
236
+
237
+ ### Upstream
238
+
239
+ `@markuplint/html-spec` provides the base `MLMLSpec` JSON containing all HTML element specifications, ARIA definitions, and content model data. Framework-specific packages (`@markuplint/vue-spec`, `@markuplint/react-spec`, etc.) provide `ExtendedSpec` objects that add or override elements, attributes, and ARIA mappings.
240
+
241
+ ### Downstream
242
+
243
+ - **`@markuplint/ml-core`** uses the type definitions to represent parsed document elements with spec awareness.
244
+ - **`@markuplint/rules`** calls ARIA and HTML algorithms to implement lint rules (role validation, content model checking, accessibility checks).
245
+ - **`@markuplint/selector`** uses type definitions for element matching.
246
+
247
+ ## Documentation Map
248
+
249
+ - [ARIA Algorithms](docs/aria-algorithms.md) -- Role computation, accessibility tree, ARIA property resolution
250
+ - [HTML Algorithms](docs/html-algorithms.md) -- Content models, element classification, void elements
251
+ - [Type Definitions](docs/type-definitions.md) -- Core types, generated types, JSON schemas
252
+ - [Spec Resolution](docs/spec-resolution.md) -- Schema merging, namespace resolution, caching
253
+ - [Maintenance Guide](docs/maintenance.md) -- Schema generation, dependency management, recipes, troubleshooting
package/CHANGELOG.md CHANGED
@@ -3,13 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [4.10.1](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.10.0...@markuplint/ml-spec@4.10.1) (2025-11-05)
6
+ ## [4.10.2](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.10.1...@markuplint/ml-spec@4.10.2) (2026-02-10)
7
7
 
8
8
  **Note:** Version bump only for package @markuplint/ml-spec
9
9
 
10
+ ## [4.10.1](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.10.0...@markuplint/ml-spec@4.10.1) (2025-11-05)
10
11
 
11
-
12
-
12
+ **Note:** Version bump only for package @markuplint/ml-spec
13
13
 
14
14
  # [4.10.0](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.9.7...@markuplint/ml-spec@4.10.0) (2025-08-24)
15
15