@markuplint/ml-spec 4.10.1 → 5.0.0-alpha.0

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 (111) hide show
  1. package/ARCHITECTURE.ja.md +267 -0
  2. package/ARCHITECTURE.md +267 -0
  3. package/CHANGELOG.md +20 -2
  4. package/README.md +6 -188
  5. package/SKILL.md +116 -0
  6. package/docs/aria-algorithms.ja.md +798 -0
  7. package/docs/aria-algorithms.md +800 -0
  8. package/docs/html-algorithms.ja.md +469 -0
  9. package/docs/html-algorithms.md +469 -0
  10. package/docs/maintenance.ja.md +331 -0
  11. package/docs/maintenance.md +331 -0
  12. package/docs/spec-resolution.ja.md +568 -0
  13. package/docs/spec-resolution.md +580 -0
  14. package/docs/type-definitions.ja.md +565 -0
  15. package/docs/type-definitions.md +565 -0
  16. package/lib/algorithm/aria/accname/__tests__/test-helpers.d.ts +45 -0
  17. package/lib/algorithm/aria/accname/__tests__/test-helpers.js +120 -0
  18. package/lib/algorithm/aria/accname/aria-steps.d.ts +51 -0
  19. package/lib/algorithm/aria/accname/aria-steps.js +104 -0
  20. package/lib/algorithm/aria/accname/compute.d.ts +51 -0
  21. package/lib/algorithm/aria/accname/compute.js +101 -0
  22. package/lib/algorithm/aria/accname/element-names.d.ts +36 -0
  23. package/lib/algorithm/aria/accname/element-names.js +342 -0
  24. package/lib/algorithm/aria/accname/helpers.d.ts +98 -0
  25. package/lib/algorithm/aria/accname/helpers.js +330 -0
  26. package/lib/algorithm/aria/accname/index.d.ts +4 -0
  27. package/lib/algorithm/aria/accname/index.js +3 -0
  28. package/lib/algorithm/aria/accname/label-steps.d.ts +25 -0
  29. package/lib/algorithm/aria/accname/label-steps.js +66 -0
  30. package/lib/algorithm/aria/accname/svg-helpers.d.ts +17 -0
  31. package/lib/algorithm/aria/accname/svg-helpers.js +30 -0
  32. package/lib/algorithm/aria/accname/types.d.ts +70 -0
  33. package/lib/algorithm/aria/accname/types.js +2 -0
  34. package/lib/algorithm/aria/accname-computation.d.ts +19 -1
  35. package/lib/algorithm/aria/accname-computation.js +136 -6
  36. package/lib/algorithm/aria/aria-specs.d.ts +8 -0
  37. package/lib/algorithm/aria/aria-specs.js +7 -0
  38. package/lib/algorithm/aria/get-aria.d.ts +12 -0
  39. package/lib/algorithm/aria/get-aria.js +42 -4
  40. package/lib/algorithm/aria/get-computed-aria-props.d.ts +22 -0
  41. package/lib/algorithm/aria/get-computed-aria-props.js +10 -0
  42. package/lib/algorithm/aria/get-computed-role.d.ts +12 -0
  43. package/lib/algorithm/aria/get-computed-role.js +118 -26
  44. package/lib/algorithm/aria/get-explicit-role.d.ts +12 -0
  45. package/lib/algorithm/aria/get-explicit-role.js +12 -0
  46. package/lib/algorithm/aria/get-implicit-role.d.ts +18 -0
  47. package/lib/algorithm/aria/get-implicit-role.js +18 -0
  48. package/lib/algorithm/aria/get-non-presentational-ancestor.d.ts +12 -0
  49. package/lib/algorithm/aria/get-non-presentational-ancestor.js +14 -2
  50. package/lib/algorithm/aria/get-permitted-roles-spec.d.ts +8 -4
  51. package/lib/algorithm/aria/get-permitted-roles-spec.js +19 -6
  52. package/lib/algorithm/aria/get-permitted-roles.d.ts +9 -0
  53. package/lib/algorithm/aria/get-permitted-roles.js +9 -0
  54. package/lib/algorithm/aria/get-role-spec.d.ts +11 -0
  55. package/lib/algorithm/aria/get-role-spec.js +21 -3
  56. package/lib/algorithm/aria/has-required-owned-elements.d.ts +24 -0
  57. package/lib/algorithm/aria/has-required-owned-elements.js +40 -14
  58. package/lib/algorithm/aria/is-exposed.d.ts +7 -4
  59. package/lib/algorithm/aria/is-exposed.js +7 -4
  60. package/lib/algorithm/aria/is-presentational.d.ts +32 -0
  61. package/lib/algorithm/aria/is-presentational.js +39 -0
  62. package/lib/algorithm/aria/matches-context-role.d.ts +19 -0
  63. package/lib/algorithm/aria/matches-context-role.js +46 -2
  64. package/lib/algorithm/html/content-model-category-to-tag-names.d.ts +9 -0
  65. package/lib/algorithm/html/content-model-category-to-tag-names.js +10 -1
  66. package/lib/algorithm/html/get-content-model.d.ts +12 -1
  67. package/lib/algorithm/html/get-content-model.js +14 -6
  68. package/lib/algorithm/html/get-selectors-by-content-model-category.d.ts +8 -0
  69. package/lib/algorithm/html/get-selectors-by-content-model-category.js +8 -0
  70. package/lib/algorithm/html/is-nothing-content-model.d.ts +7 -0
  71. package/lib/algorithm/html/is-nothing-content-model.js +7 -0
  72. package/lib/algorithm/html/is-palpable-elements.d.ts +13 -0
  73. package/lib/algorithm/html/is-palpable-elements.js +13 -0
  74. package/lib/algorithm/html/is-void-element.d.ts +9 -0
  75. package/lib/algorithm/html/is-void-element.js +9 -0
  76. package/lib/algorithm/html/may-be-focusable.d.ts +10 -0
  77. package/lib/algorithm/html/may-be-focusable.js +10 -0
  78. package/lib/const/accname.d.ts +29 -0
  79. package/lib/const/accname.js +76 -0
  80. package/lib/const/dom.d.ts +8 -0
  81. package/lib/const/dom.js +8 -0
  82. package/lib/const/index.d.ts +2 -0
  83. package/lib/const/index.js +2 -0
  84. package/lib/index.d.ts +3 -0
  85. package/lib/index.js +4 -0
  86. package/lib/types/index.d.ts +119 -0
  87. package/lib/utils/aria-version.d.ts +6 -0
  88. package/lib/utils/aria-version.js +6 -0
  89. package/lib/utils/directive-resolver.d.ts +23 -0
  90. package/lib/utils/directive-resolver.js +50 -0
  91. package/lib/utils/get-attr-specs-spec.d.ts +18 -0
  92. package/lib/utils/get-attr-specs-spec.js +22 -3
  93. package/lib/utils/get-attr-specs.d.ts +9 -0
  94. package/lib/utils/get-attr-specs.js +9 -0
  95. package/lib/utils/get-ns.d.ts +7 -0
  96. package/lib/utils/get-ns.js +7 -0
  97. package/lib/utils/get-spec-by-tag-name.d.ts +12 -1
  98. package/lib/utils/get-spec-by-tag-name.js +11 -0
  99. package/lib/utils/get-spec.d.ts +11 -1
  100. package/lib/utils/get-spec.js +10 -0
  101. package/lib/utils/merge-array.d.ts +10 -0
  102. package/lib/utils/merge-array.js +10 -0
  103. package/lib/utils/resolve-namespace.d.ts +13 -0
  104. package/lib/utils/resolve-namespace.js +10 -0
  105. package/lib/utils/resolve-version.d.ts +11 -0
  106. package/lib/utils/resolve-version.js +11 -0
  107. package/lib/utils/schema-to-spec.d.ts +7 -2
  108. package/lib/utils/schema-to-spec.js +20 -6
  109. package/lib/utils/validate-aria-version.d.ts +7 -0
  110. package/lib/utils/validate-aria-version.js +7 -0
  111. package/package.json +9 -7
@@ -0,0 +1,267 @@
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 リゾルバ + 再入防止ガード)
22
+ │ │ ├── accname/ # AccName 純粋アルゴリズム(HTML-AAM §4.1)
23
+ │ │ │ ├── types.ts # AccnameElement/AccnameResolver インターフェース
24
+ │ │ │ ├── compute.ts # コアアルゴリズム: Steps 2A-2I
25
+ │ │ │ ├── aria-steps.ts # Steps 2B (aria-labelledby), 2D (aria-label)
26
+ │ │ │ ├── element-names.ts # Step 2E: 要素固有の名前(HTML-AAM §4.1)
27
+ │ │ │ ├── helpers.ts # 共有ユーティリティ(埋め込みコントロール、name-from-content)
28
+ │ │ │ ├── label-steps.ts # Step 2E: ラベル関連付け(labelable 要素)
29
+ │ │ │ ├── svg-helpers.ts # SVG アクセシブル名ソース判定
30
+ │ │ │ └── index.ts # 公開 API 再エクスポート
31
+ │ │ ├── aria-specs.ts # バージョン別 ARIA 仕様データの取得
32
+ │ │ ├── get-aria.ts # 要素レベルの ARIA 仕様解決(条件付き)
33
+ │ │ ├── get-computed-aria-props.ts # ARIA プロパティ解決(明示 → HTML → デフォルト)
34
+ │ │ ├── get-computed-role.ts # 中核:最終ロール計算と競合解決
35
+ │ │ ├── get-explicit-role.ts # role 属性からの明示ロール(著者エラー処理)
36
+ │ │ ├── get-implicit-role.ts # HTML-AAM による暗黙ロール
37
+ │ │ ├── get-implicit-role-spec.ts # 暗黙ロール名の低レベル検索
38
+ │ │ ├── get-non-presentational-ancestor.ts # プレゼンテーショナルロールをスキップする祖先探索
39
+ │ │ ├── get-permitted-roles.ts # DOM 要素の許可ロール
40
+ │ │ ├── get-permitted-roles-spec.ts # タグ名/名前空間による許可ロール(低レベル)
41
+ │ │ ├── get-role-spec.ts # スーパークラスチェーン付きロール仕様
42
+ │ │ ├── has-required-owned-elements.ts # 必須所有要素の検証
43
+ │ │ ├── is-exposed.ts # アクセシビリティツリー包含/除外
44
+ │ │ ├── is-presentational.ts # プレゼンテーショナルロール判定(presentation/none)
45
+ │ │ └── matches-context-role.ts # 必須コンテキストロールの検証
46
+ │ └── html/
47
+ │ ├── content-model-category-to-tag-names.ts # カテゴリ → タグ名配列(キャッシュ付き)
48
+ │ ├── get-content-model.ts # 条件付きコンテンツモデル評価
49
+ │ ├── get-selectors-by-content-model-category.ts # カテゴリ → CSS セレクタ配列
50
+ │ ├── is-nothing-content-model.ts # 「Nothing」コンテンツモデル判定
51
+ │ ├── is-palpable-elements.ts # パルパブルコンテンツ検出
52
+ │ ├── is-void-element.ts # ボイド要素判定(13 要素)
53
+ │ └── may-be-focusable.ts # フォーカス可能性ヒューリスティック
54
+ ├── const/
55
+ │ ├── index.ts # 全定数の再エクスポート
56
+ │ ├── dom.ts # DOM 定数(ELEMENT_NODE, TEXT_NODE, 名前空間 URI)
57
+ │ └── accname.ts # AccName 定数(埋め込みコントロールロール、入力型、デフォルト値)
58
+ └── utils/
59
+ ├── aria-version.ts # ARIA バージョン定数('1.1', '1.2', '1.3')
60
+ ├── get-attr-specs.ts # DOM 要素の属性仕様(ラッパー)
61
+ ├── get-attr-specs-spec.ts # タグ名/名前空間による属性仕様(コア)
62
+ ├── get-ns.ts # 名前空間 URI → 短縮名マッピング
63
+ ├── get-spec.ts # DOM 要素の要素仕様(ラッパー)
64
+ ├── get-spec-by-tag-name.ts # タグ名/名前空間による要素仕様(キャッシュ付き)
65
+ ├── merge-array.ts # 名前ベースの配列マージユーティリティ
66
+ ├── resolve-namespace.ts # 名前空間解決とプレフィックス正規化
67
+ ├── resolve-version.ts # ARIA バージョン固有プロパティの解決
68
+ ├── schema-to-spec.ts # スキーママージパイプライン(ベース + 拡張)
69
+ └── validate-aria-version.ts # ARIA バージョン文字列の型ガード
70
+
71
+ schemas/
72
+ ├── element.schema.json # トップレベル要素仕様スキーマ(11 行)
73
+ ├── aria.schema.json # ARIA ロール/プロパティスキーマ(291 行)
74
+ ├── attributes.schema.json # 属性型スキーマ(190 行)
75
+ ├── content-models.schema.json # コンテンツモデルパターンスキーマ(215 行)
76
+ └── global-attributes.schema.json # グローバル属性カテゴリスキーマ(787 行)
77
+
78
+ gen/
79
+ ├── gen.ts # global-attributes.schema.json のスキーマジェネレータ
80
+ └── global-attribute.data.ts # グローバル属性カテゴリ定義
81
+ ```
82
+
83
+ ## アーキテクチャ図
84
+
85
+ ```mermaid
86
+ flowchart TD
87
+ subgraph input ["入力レイヤー"]
88
+ htmlSpec["@markuplint/html-spec\n(MLMLSpec JSON)"]
89
+ fwSpec["フレームワーク仕様\n(ExtendedSpec)"]
90
+ end
91
+
92
+ subgraph merge ["仕様解決"]
93
+ schemaToSpec["schemaToSpec()"]
94
+ getSpec["getSpec() / getSpecByTagName()"]
95
+ getAttrSpecs["getAttrSpecs()"]
96
+ resolveNS["resolveNamespace()"]
97
+ end
98
+
99
+ subgraph aria ["ARIA アルゴリズム"]
100
+ getComputedRole["getComputedRole()"]
101
+ getExplicitRole["getExplicitRole()"]
102
+ getImplicitRole["getImplicitRole()"]
103
+ getPermittedRoles["getPermittedRoles()"]
104
+ getRoleSpec["getRoleSpec()"]
105
+ getARIA["getARIA()"]
106
+ getComputedAriaProps["getComputedAriaProps()"]
107
+ isExposed["isExposed()"]
108
+ getAccname["getAccname()"]
109
+ end
110
+
111
+ subgraph html ["HTML アルゴリズム"]
112
+ getContentModel["getContentModel()"]
113
+ isPalpable["isPalpableElement()"]
114
+ isVoid["isVoidElement()"]
115
+ mayBeFocusable["mayBeFocusable()"]
116
+ end
117
+
118
+ subgraph types ["型定義"]
119
+ handWritten["MLMLSpec, ElementSpec\nARIARole, ComputedRole"]
120
+ generated["ARIA, PermittedRoles\nContentModel, Category"]
121
+ end
122
+
123
+ htmlSpec --> schemaToSpec
124
+ fwSpec --> schemaToSpec
125
+ schemaToSpec --> getSpec
126
+ getSpec --> getAttrSpecs
127
+ getSpec --> getARIA
128
+ resolveNS --> getSpec
129
+
130
+ getARIA --> getComputedRole
131
+ getExplicitRole --> getComputedRole
132
+ getImplicitRole --> getComputedRole
133
+ getPermittedRoles --> getExplicitRole
134
+ getRoleSpec --> getImplicitRole
135
+ getRoleSpec --> getExplicitRole
136
+ getComputedRole --> getComputedAriaProps
137
+ getComputedRole --> isExposed
138
+
139
+ getSpec --> getContentModel
140
+ getSpec --> isPalpable
141
+ ```
142
+
143
+ ## 主要コンポーネント
144
+
145
+ ### 1. 型定義
146
+
147
+ 型システムは、マークアップ言語仕様・要素仕様・ARIA ロール・属性の構造を定義します。
148
+
149
+ | ファイル | 役割 |
150
+ | ------------------------------- | ------------------------------------------------------------------------------------------------- |
151
+ | `types/index.ts` | 手書き型: `MLMLSpec`, `ElementSpec`, `ExtendedSpec`, `ARIARole`, `ComputedRole` 等 |
152
+ | `types/aria.ts` | 生成型: `ARIA`, `PermittedRoles`, `ImplicitRole`, `PermittedARIAProperties`, `ImplicitProperties` |
153
+ | `types/attributes.ts` | 生成型: `AttributeType`, `GlobalAttributes`, `AttributeJSON`, `List`, `Enum`, `Number` |
154
+ | `types/permitted-structures.ts` | 生成型: `PermittedContentPattern`, `ContentModel`, `Category`(HTML 13 + SVG 19 カテゴリ) |
155
+
156
+ ### 2. ARIA アルゴリズム
157
+
158
+ ARIA アルゴリズムは WAI-ARIA, HTML-AAM, SVG-AAM, AccName 1.2 仕様に基づくロール計算とアクセシビリティツリー管理を実装します。
159
+
160
+ | ファイル | 役割 |
161
+ | -------------------------------- | ------------------------------------------------------------------------------- |
162
+ | `get-computed-role.ts` | 中核アルゴリズム: Presentational Roles Conflict Resolution による最終ロール計算 |
163
+ | `get-explicit-role.ts` | `role` 属性からの明示ロール解決(著者エラー処理付き) |
164
+ | `get-implicit-role.ts` | HTML-AAM に基づく暗黙(ネイティブ)ARIA ロールの決定 |
165
+ | `get-computed-aria-props.ts` | ARIA プロパティ解決: 明示 `aria-*` → HTML 等価属性 → 仕様デフォルト |
166
+ | `is-exposed.ts` | WAI-ARIA ルールに基づくアクセシビリティツリーの包含/除外判定 |
167
+ | `get-permitted-roles.ts` | 要素の許可ロール一覧(Any/No/具体的リスト) |
168
+ | `get-role-spec.ts` | スーパークラスロールチェーン付き完全ロール仕様の取得 |
169
+ | `has-required-owned-elements.ts` | 必須所有要素制約の検証 |
170
+ | `matches-context-role.ts` | 祖先チェーンにおける必須コンテキストロール条件の検証 |
171
+ | `accname-computation.ts` | アクセシブルネーム計算ファサード(DOM リゾルバ + 再入防止ガード) |
172
+ | `accname/compute.ts` | 純粋 AccName アルゴリズム: HTML-AAM §4.1 の Steps 2A-2I |
173
+ | `accname/element-names.ts` | Step 2E: 要素固有の名前計算(HTML-AAM §4.1) |
174
+ | `get-aria.ts` | バージョンと条件の解決を含む要素レベル ARIA 仕様 |
175
+ | `is-presentational.ts` | ロールが `presentation` または `none` かどうかの判定 |
176
+
177
+ ### 3. HTML アルゴリズム
178
+
179
+ HTML アルゴリズムは HTML Living Standard に基づくコンテンツモデル評価と要素分類を実装します。
180
+
181
+ | ファイル | 役割 |
182
+ | -------------------------------------------- | ------------------------------------------------------------------------------ |
183
+ | `get-content-model.ts` | 条件付きパターン評価を含むコンテンツモデルの取得 |
184
+ | `content-model-category-to-tag-names.ts` | コンテンツモデルカテゴリをソート済みタグ名配列に変換 |
185
+ | `get-selectors-by-content-model-category.ts` | コンテンツモデルカテゴリを CSS セレクタにマッピング |
186
+ | `is-palpable-elements.ts` | SVG/露出可能要素拡張付きパルパブルコンテンツ検出 |
187
+ | `is-void-element.ts` | ボイド要素判定(13 の HTML ボイド要素) |
188
+ | `is-nothing-content-model.ts` | 「Nothing」コンテンツモデル判定(void + iframe + template) |
189
+ | `may-be-focusable.ts` | フォーカス可能性ヒューリスティック(interactive + tabindex + contenteditable) |
190
+
191
+ ### 4. 仕様解決ユーティリティ
192
+
193
+ 仕様のマージ・解決・キャッシュのためのユーティリティです。
194
+
195
+ | ファイル | 役割 |
196
+ | -------------------------- | ---------------------------------------------------------------------------- |
197
+ | `schema-to-spec.ts` | ベース `MLMLSpec` と `ExtendedSpec[]` のマージ(グローバル属性, ARIA, 要素) |
198
+ | `get-spec-by-tag-name.ts` | タグ名 + 名前空間による要素仕様の検索(キャッシュ付き) |
199
+ | `get-attr-specs-spec.ts` | マージ済み属性仕様の取得(グローバル + 要素固有) |
200
+ | `resolve-namespace.ts` | 名前空間プレフィックスを含む要素名の正規化 |
201
+ | `resolve-version.ts` | ARIA バージョン固有のオーバーライドをフォールバック付きで解決 |
202
+ | `merge-array.ts` | 名前ベースの配列マージ(`name` プロパティによる追加/上書き) |
203
+ | `validate-aria-version.ts` | 有効な ARIA バージョン文字列の型ガード |
204
+
205
+ ## 外部依存パッケージ
206
+
207
+ | パッケージ | 用途 | 使用箇所 |
208
+ | -------------------- | -------------------------------------------------- | ----------------------------- |
209
+ | `@markuplint/ml-ast` | XML 名前空間処理のための `NamespaceURI` 型 | `types/index.ts`, utils |
210
+ | `@markuplint/types` | 属性値の型定義のための `Type` 共用体 | `types/attributes.ts` 経由 |
211
+ | `is-plain-object` | AAM 情報のプレーンオブジェクト検出 | `get-permitted-roles-spec.ts` |
212
+ | `type-fest` | 深い不変性のための `ReadonlyDeep` ユーティリティ型 | 複数ファイル |
213
+
214
+ ## 他パッケージとの連携
215
+
216
+ ```mermaid
217
+ flowchart LR
218
+ subgraph upstream ["上流パッケージ"]
219
+ htmlSpec["@markuplint/html-spec"]
220
+ vueSpec["@markuplint/vue-spec"]
221
+ reactSpec["@markuplint/react-spec"]
222
+ otherSpec["その他フレームワーク仕様"]
223
+ end
224
+
225
+ subgraph pkg ["@markuplint/ml-spec"]
226
+ types["型定義"]
227
+ ariaAlgo["ARIA アルゴリズム"]
228
+ htmlAlgo["HTML アルゴリズム"]
229
+ specRes["仕様解決"]
230
+ end
231
+
232
+ subgraph downstream ["下流パッケージ"]
233
+ mlCore["@markuplint/ml-core"]
234
+ rules["@markuplint/rules"]
235
+ selector["@markuplint/selector"]
236
+ end
237
+
238
+ htmlSpec -->|"MLMLSpec JSON"| specRes
239
+ vueSpec -->|"ExtendedSpec"| specRes
240
+ reactSpec -->|"ExtendedSpec"| specRes
241
+ otherSpec -->|"ExtendedSpec"| specRes
242
+
243
+ specRes --> ariaAlgo
244
+ specRes --> htmlAlgo
245
+ types --> mlCore
246
+ ariaAlgo -->|"ロール計算\nアクセシビリティツリー"| rules
247
+ htmlAlgo -->|"コンテンツモデル\n要素分類"| rules
248
+ types --> selector
249
+ ```
250
+
251
+ ### 上流
252
+
253
+ `@markuplint/html-spec` は、全 HTML 要素仕様・ARIA 定義・コンテンツモデルデータを含むベース `MLMLSpec` JSON を提供します。フレームワーク固有パッケージ(`@markuplint/vue-spec`, `@markuplint/react-spec` 等)は、要素・属性・ARIA マッピングを追加またはオーバーライドする `ExtendedSpec` オブジェクトを提供します。
254
+
255
+ ### 下流
256
+
257
+ - **`@markuplint/ml-core`** は型定義を使用して、仕様認識を持つパース済みドキュメント要素を表現します。
258
+ - **`@markuplint/rules`** は ARIA および HTML アルゴリズムを呼び出して、リントルール(ロール検証、コンテンツモデルチェック、アクセシビリティチェック)を実装します。
259
+ - **`@markuplint/selector`** は要素マッチングのために型定義を使用します。
260
+
261
+ ## ドキュメントマップ
262
+
263
+ - [ARIA アルゴリズム](docs/aria-algorithms.ja.md) -- ロール計算、アクセシビリティツリー、ARIA プロパティ解決
264
+ - [HTML アルゴリズム](docs/html-algorithms.ja.md) -- コンテンツモデル、要素分類、ボイド要素
265
+ - [型定義](docs/type-definitions.ja.md) -- コア型、生成型、JSON スキーマ
266
+ - [仕様解決](docs/spec-resolution.ja.md) -- スキーママージ、名前空間解決、キャッシュ
267
+ - [メンテナンスガイド](docs/maintenance.ja.md) -- スキーマ生成、依存関係管理、レシピ、トラブルシューティング
@@ -0,0 +1,267 @@
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 facade (DOM resolver + reentrant guard)
22
+ │ │ ├── accname/ # AccName pure algorithm (HTML-AAM §4.1)
23
+ │ │ │ ├── types.ts # AccnameElement/AccnameResolver interfaces
24
+ │ │ │ ├── compute.ts # Core algorithm: Steps 2A-2I
25
+ │ │ │ ├── aria-steps.ts # Steps 2B (aria-labelledby) and 2D (aria-label)
26
+ │ │ │ ├── element-names.ts # Step 2E: element-specific name (HTML-AAM §4.1)
27
+ │ │ │ ├── helpers.ts # Shared utilities (embedded controls, name-from-content)
28
+ │ │ │ ├── label-steps.ts # Step 2E: label association for labelable elements
29
+ │ │ │ ├── svg-helpers.ts # SVG accessible name source check
30
+ │ │ │ └── index.ts # Re-exports public API
31
+ │ │ ├── aria-specs.ts # Version-specific ARIA spec data retrieval
32
+ │ │ ├── get-aria.ts # Element-level ARIA spec resolution with conditions
33
+ │ │ ├── get-computed-aria-props.ts # ARIA property resolution (explicit → HTML → default)
34
+ │ │ ├── get-computed-role.ts # Core: final role computation with conflict resolution
35
+ │ │ ├── get-explicit-role.ts # Explicit role from role attribute with author error handling
36
+ │ │ ├── get-implicit-role.ts # Implicit (native) role from HTML-AAM
37
+ │ │ ├── get-implicit-role-spec.ts # Low-level implicit role name lookup
38
+ │ │ ├── get-non-presentational-ancestor.ts # Ancestor traversal skipping presentational roles
39
+ │ │ ├── get-permitted-roles.ts # Permitted roles for a DOM element
40
+ │ │ ├── get-permitted-roles-spec.ts # Permitted roles from tag name/namespace (low-level)
41
+ │ │ ├── get-role-spec.ts # Full role spec with super-class chain
42
+ │ │ ├── has-required-owned-elements.ts # Required owned elements validation
43
+ │ │ ├── is-exposed.ts # Accessibility tree inclusion/exclusion
44
+ │ │ ├── is-presentational.ts # Presentational role check (presentation/none)
45
+ │ │ └── matches-context-role.ts # Required context role validation
46
+ │ └── html/
47
+ │ ├── content-model-category-to-tag-names.ts # Category → tag name array (cached)
48
+ │ ├── get-content-model.ts # Content model with conditional evaluation
49
+ │ ├── get-selectors-by-content-model-category.ts # Category → CSS selector array
50
+ │ ├── is-nothing-content-model.ts # "Nothing" content model check
51
+ │ ├── is-palpable-elements.ts # Palpable content detection
52
+ │ ├── is-void-element.ts # Void element check (13 elements)
53
+ │ └── may-be-focusable.ts # Focusability heuristic
54
+ ├── const/
55
+ │ ├── index.ts # Re-exports all constants
56
+ │ ├── dom.ts # DOM constants (ELEMENT_NODE, TEXT_NODE, namespace URIs)
57
+ │ └── accname.ts # AccName constants (embedded control roles, input types, defaults)
58
+ └── utils/
59
+ ├── aria-version.ts # ARIA version constants ('1.1', '1.2', '1.3')
60
+ ├── get-attr-specs.ts # Attribute specs for a DOM element (wrapper)
61
+ ├── get-attr-specs-spec.ts # Attribute specs by tag name/namespace (core)
62
+ ├── get-ns.ts # Namespace URI → shorthand mapping
63
+ ├── get-spec.ts # Element spec for a DOM element (wrapper)
64
+ ├── get-spec-by-tag-name.ts # Element spec by tag name/namespace (cached)
65
+ ├── merge-array.ts # Name-based array merge utility
66
+ ├── resolve-namespace.ts # Namespace resolution and prefix normalization
67
+ ├── resolve-version.ts # ARIA version-specific property resolution
68
+ ├── schema-to-spec.ts # Schema merge pipeline (base + extensions)
69
+ └── validate-aria-version.ts # ARIA version string type guard
70
+
71
+ schemas/
72
+ ├── element.schema.json # Top-level element spec schema (11 lines)
73
+ ├── aria.schema.json # ARIA role/property schema (291 lines)
74
+ ├── attributes.schema.json # Attribute type schema (190 lines)
75
+ ├── content-models.schema.json # Content model pattern schema (215 lines)
76
+ └── global-attributes.schema.json # Global attribute categories schema (787 lines)
77
+
78
+ gen/
79
+ ├── gen.ts # Schema generator for global-attributes.schema.json
80
+ └── global-attribute.data.ts # Global attribute category definitions
81
+ ```
82
+
83
+ ## Architecture Diagram
84
+
85
+ ```mermaid
86
+ flowchart TD
87
+ subgraph input ["Input Layer"]
88
+ htmlSpec["@markuplint/html-spec\n(MLMLSpec JSON)"]
89
+ fwSpec["Framework specs\n(ExtendedSpec)"]
90
+ end
91
+
92
+ subgraph merge ["Spec Resolution"]
93
+ schemaToSpec["schemaToSpec()"]
94
+ getSpec["getSpec() / getSpecByTagName()"]
95
+ getAttrSpecs["getAttrSpecs()"]
96
+ resolveNS["resolveNamespace()"]
97
+ end
98
+
99
+ subgraph aria ["ARIA Algorithms"]
100
+ getComputedRole["getComputedRole()"]
101
+ getExplicitRole["getExplicitRole()"]
102
+ getImplicitRole["getImplicitRole()"]
103
+ getPermittedRoles["getPermittedRoles()"]
104
+ getRoleSpec["getRoleSpec()"]
105
+ getARIA["getARIA()"]
106
+ getComputedAriaProps["getComputedAriaProps()"]
107
+ isExposed["isExposed()"]
108
+ getAccname["getAccname()"]
109
+ end
110
+
111
+ subgraph html ["HTML Algorithms"]
112
+ getContentModel["getContentModel()"]
113
+ isPalpable["isPalpableElement()"]
114
+ isVoid["isVoidElement()"]
115
+ mayBeFocusable["mayBeFocusable()"]
116
+ end
117
+
118
+ subgraph types ["Type Definitions"]
119
+ handWritten["MLMLSpec, ElementSpec\nARIARole, ComputedRole"]
120
+ generated["ARIA, PermittedRoles\nContentModel, Category"]
121
+ end
122
+
123
+ htmlSpec --> schemaToSpec
124
+ fwSpec --> schemaToSpec
125
+ schemaToSpec --> getSpec
126
+ getSpec --> getAttrSpecs
127
+ getSpec --> getARIA
128
+ resolveNS --> getSpec
129
+
130
+ getARIA --> getComputedRole
131
+ getExplicitRole --> getComputedRole
132
+ getImplicitRole --> getComputedRole
133
+ getPermittedRoles --> getExplicitRole
134
+ getRoleSpec --> getImplicitRole
135
+ getRoleSpec --> getExplicitRole
136
+ getComputedRole --> getComputedAriaProps
137
+ getComputedRole --> isExposed
138
+
139
+ getSpec --> getContentModel
140
+ getSpec --> isPalpable
141
+ ```
142
+
143
+ ## Core Components
144
+
145
+ ### 1. Type Definitions
146
+
147
+ The type system defines the structure of markup language specifications, element specs, ARIA roles, and attributes.
148
+
149
+ | File | Purpose |
150
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------- |
151
+ | `types/index.ts` | Hand-written types: `MLMLSpec`, `ElementSpec`, `ExtendedSpec`, `ARIARole`, `ComputedRole`, etc. |
152
+ | `types/aria.ts` | Generated: `ARIA`, `PermittedRoles`, `ImplicitRole`, `PermittedARIAProperties`, `ImplicitProperties` |
153
+ | `types/attributes.ts` | Generated: `AttributeType`, `GlobalAttributes`, `AttributeJSON`, `List`, `Enum`, `Number` |
154
+ | `types/permitted-structures.ts` | Generated: `PermittedContentPattern`, `ContentModel`, `Category` (HTML 13 + SVG 19 categories) |
155
+
156
+ ### 2. ARIA Algorithms
157
+
158
+ ARIA algorithms implement WAI-ARIA, HTML-AAM, SVG-AAM, and AccName 1.2 specifications for role computation and accessibility tree management.
159
+
160
+ | File | Purpose |
161
+ | -------------------------------- | --------------------------------------------------------------------------------- |
162
+ | `get-computed-role.ts` | Core algorithm: computes final role with Presentational Roles Conflict Resolution |
163
+ | `get-explicit-role.ts` | Resolves explicit roles from `role` attribute with author error handling |
164
+ | `get-implicit-role.ts` | Determines implicit (native) ARIA role from HTML-AAM |
165
+ | `get-computed-aria-props.ts` | Resolves ARIA properties: explicit `aria-*` → HTML equivalent → spec defaults |
166
+ | `is-exposed.ts` | Determines accessibility tree inclusion/exclusion per WAI-ARIA rules |
167
+ | `get-permitted-roles.ts` | Lists permitted roles for an element (Any/No/specific list) |
168
+ | `get-role-spec.ts` | Retrieves full role spec with super-class role chain |
169
+ | `has-required-owned-elements.ts` | Validates required owned element constraints |
170
+ | `matches-context-role.ts` | Validates required context role conditions in ancestor chain |
171
+ | `accname-computation.ts` | Accessible name computation facade (DOM resolver + reentrant guard) |
172
+ | `accname/compute.ts` | Pure AccName algorithm: Steps 2A-2I per HTML-AAM §4.1 |
173
+ | `accname/element-names.ts` | Step 2E: Element-specific name computation (HTML-AAM §4.1) |
174
+ | `get-aria.ts` | Element-level ARIA spec with version and condition resolution |
175
+ | `is-presentational.ts` | Checks if a role is `presentation` or `none` |
176
+
177
+ ### 3. HTML Algorithms
178
+
179
+ HTML algorithms implement content model evaluation and element classification from the HTML Living Standard.
180
+
181
+ | File | Purpose |
182
+ | -------------------------------------------- | ----------------------------------------------------------------- |
183
+ | `get-content-model.ts` | Retrieves content model with conditional pattern evaluation |
184
+ | `content-model-category-to-tag-names.ts` | Converts content model category to sorted tag name array |
185
+ | `get-selectors-by-content-model-category.ts` | Maps content model category to CSS selectors |
186
+ | `is-palpable-elements.ts` | Palpable content detection with SVG/exposable extensions |
187
+ | `is-void-element.ts` | Void element check (13 HTML void elements) |
188
+ | `is-nothing-content-model.ts` | "Nothing" content model check (void + iframe + template) |
189
+ | `may-be-focusable.ts` | Focusability heuristic (interactive + tabindex + contenteditable) |
190
+
191
+ ### 4. Spec Resolution Utilities
192
+
193
+ Utilities for merging, resolving, and caching specifications.
194
+
195
+ | File | Purpose |
196
+ | -------------------------- | --------------------------------------------------------------------------- |
197
+ | `schema-to-spec.ts` | Merges base `MLMLSpec` with `ExtendedSpec[]` (global attrs, ARIA, elements) |
198
+ | `get-spec-by-tag-name.ts` | Looks up element spec by tag name + namespace (cached) |
199
+ | `get-attr-specs-spec.ts` | Retrieves merged attribute specs (global + element-specific) |
200
+ | `resolve-namespace.ts` | Normalizes element names with namespace prefixes |
201
+ | `resolve-version.ts` | Resolves ARIA version-specific overrides with fallback |
202
+ | `merge-array.ts` | Name-based array merging (add/override by `name` property) |
203
+ | `validate-aria-version.ts` | Type guard for valid ARIA version strings |
204
+
205
+ ## External Dependencies
206
+
207
+ | Dependency | Purpose | Where Used |
208
+ | -------------------- | ------------------------------------------------- | ----------------------------- |
209
+ | `@markuplint/ml-ast` | `NamespaceURI` type for XML namespace handling | `types/index.ts`, utils |
210
+ | `@markuplint/types` | `Type` union for attribute value type definitions | via `types/attributes.ts` |
211
+ | `is-plain-object` | Plain object detection for AAM info | `get-permitted-roles-spec.ts` |
212
+ | `type-fest` | `ReadonlyDeep` utility type for deep immutability | Multiple files |
213
+
214
+ ## Integration Points
215
+
216
+ ```mermaid
217
+ flowchart LR
218
+ subgraph upstream ["Upstream"]
219
+ htmlSpec["@markuplint/html-spec"]
220
+ vueSpec["@markuplint/vue-spec"]
221
+ reactSpec["@markuplint/react-spec"]
222
+ otherSpec["Other framework specs"]
223
+ end
224
+
225
+ subgraph pkg ["@markuplint/ml-spec"]
226
+ types["Type definitions"]
227
+ ariaAlgo["ARIA algorithms"]
228
+ htmlAlgo["HTML algorithms"]
229
+ specRes["Spec resolution"]
230
+ end
231
+
232
+ subgraph downstream ["Downstream"]
233
+ mlCore["@markuplint/ml-core"]
234
+ rules["@markuplint/rules"]
235
+ selector["@markuplint/selector"]
236
+ end
237
+
238
+ htmlSpec -->|"MLMLSpec JSON"| specRes
239
+ vueSpec -->|"ExtendedSpec"| specRes
240
+ reactSpec -->|"ExtendedSpec"| specRes
241
+ otherSpec -->|"ExtendedSpec"| specRes
242
+
243
+ specRes --> ariaAlgo
244
+ specRes --> htmlAlgo
245
+ types --> mlCore
246
+ ariaAlgo -->|"role computation\naccessibility tree"| rules
247
+ htmlAlgo -->|"content model\nelement classification"| rules
248
+ types --> selector
249
+ ```
250
+
251
+ ### Upstream
252
+
253
+ `@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.
254
+
255
+ ### Downstream
256
+
257
+ - **`@markuplint/ml-core`** uses the type definitions to represent parsed document elements with spec awareness.
258
+ - **`@markuplint/rules`** calls ARIA and HTML algorithms to implement lint rules (role validation, content model checking, accessibility checks).
259
+ - **`@markuplint/selector`** uses type definitions for element matching.
260
+
261
+ ## Documentation Map
262
+
263
+ - [ARIA Algorithms](docs/aria-algorithms.md) -- Role computation, accessibility tree, ARIA property resolution
264
+ - [HTML Algorithms](docs/html-algorithms.md) -- Content models, element classification, void elements
265
+ - [Type Definitions](docs/type-definitions.md) -- Core types, generated types, JSON schemas
266
+ - [Spec Resolution](docs/spec-resolution.md) -- Schema merging, namespace resolution, caching
267
+ - [Maintenance Guide](docs/maintenance.md) -- Schema generation, dependency management, recipes, troubleshooting
package/CHANGELOG.md CHANGED
@@ -3,13 +3,31 @@
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
+ # [5.0.0-alpha.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v5.0.0-alpha.0) (2026-02-20)
7
7
 
8
- **Note:** Version bump only for package @markuplint/ml-spec
8
+ ### Bug Fixes
9
+
10
+ - **ml-spec:** add explicit return type to getContentModel to fix d.ts output ([52724e5](https://github.com/markuplint/markuplint/commit/52724e5f40813b7637862bfe5c7d40f3908113b3))
11
+ - **ml-spec:** fix broken getContentModel cache using WeakMap ([4074caa](https://github.com/markuplint/markuplint/commit/4074caa002fed6fd5a8b63da88ea356b544d1f57)), closes [#1022](https://github.com/markuplint/markuplint/issues/1022)
12
+ - **ml-spec:** gate context role transparency to ARIA 1.3 only ([0535787](https://github.com/markuplint/markuplint/commit/053578760013f308e6135fb4c482e90e0d983643))
13
+ - resolve additional eslint-plugin-unicorn v63 errors ([e58a72c](https://github.com/markuplint/markuplint/commit/e58a72c17c97bbec522f9513b99777fac6904d64))
14
+
15
+ ### Features
9
16
 
17
+ - **ml-spec,rules:** adopt ARIA 1.3 property names with 1.2 compat ([4f7e54d](https://github.com/markuplint/markuplint/commit/4f7e54d21593495d36e48fbe8ad27f8be85ab5ef))
18
+ - **ml-spec:** add ARIA 1.3 generic role transparency and image/img synonym ([58172f0](https://github.com/markuplint/markuplint/commit/58172f0ed3925bc3d68f5573ff0ba9b158db588b)), closes [#1265](https://github.com/markuplint/markuplint/issues/1265) [#2364](https://github.com/markuplint/markuplint/issues/2364)
19
+ - **ml-spec:** add context role validation with caching and transparency ([7a27e0d](https://github.com/markuplint/markuplint/commit/7a27e0d729256919c926b03a11daeeebfd513e4b))
20
+ - **ml-spec:** add declarative directivePatterns for parser-less framework support ([ceb9aa6](https://github.com/markuplint/markuplint/commit/ceb9aa67048e3a058b40a9e4d91eb903c8ff1861))
21
+ - **ml-spec:** add dpubRoles to ARIASpec type and algorithms ([f88fe77](https://github.com/markuplint/markuplint/commit/f88fe778594e032e003c09396e53e9f64d4772c8)), closes [#1490](https://github.com/markuplint/markuplint/issues/1490)
22
+ - **ml-spec:** add useIDLAttributeNames to ExtendedSpec type and merge logic ([ad4f563](https://github.com/markuplint/markuplint/commit/ad4f563a417e3a706f04882252aed2e89fb109c3))
10
23
 
24
+ ## [4.10.2](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.10.1...@markuplint/ml-spec@4.10.2) (2026-02-10)
11
25
 
26
+ **Note:** Version bump only for package @markuplint/ml-spec
12
27
 
28
+ ## [4.10.1](https://github.com/markuplint/markuplint/compare/@markuplint/ml-spec@4.10.0...@markuplint/ml-spec@4.10.1) (2025-11-05)
29
+
30
+ **Note:** Version bump only for package @markuplint/ml-spec
13
31
 
14
32
  # [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
33