@markuplint/ml-spec 5.0.0-rc.4 → 5.0.0-rc.6
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.
- package/CHANGELOG.md +14 -0
- package/README.md +0 -8
- package/lib/algorithm/aria/accname/aria-steps.d.ts +0 -24
- package/lib/algorithm/aria/accname/aria-steps.js +0 -24
- package/lib/algorithm/aria/accname/compute.d.ts +0 -10
- package/lib/algorithm/aria/accname/compute.js +0 -10
- package/lib/algorithm/aria/accname/element-names.d.ts +0 -23
- package/lib/algorithm/aria/accname/element-names.js +0 -23
- package/lib/algorithm/aria/accname/helpers.d.ts +2 -64
- package/lib/algorithm/aria/accname/helpers.js +2 -72
- package/lib/algorithm/aria/accname/label-steps.d.ts +2 -18
- package/lib/algorithm/aria/accname/label-steps.js +5 -21
- package/lib/algorithm/aria/accname/types.d.ts +0 -3
- package/lib/algorithm/aria/get-explicit-role.d.ts +1 -8
- package/lib/algorithm/aria/get-explicit-role.js +1 -8
- package/lib/algorithm/aria/get-non-presentational-ancestor.d.ts +2 -10
- package/lib/algorithm/aria/get-non-presentational-ancestor.js +2 -10
- package/lib/algorithm/aria/get-permitted-roles-spec.js +1 -0
- package/lib/algorithm/aria/matches-context-role.d.ts +3 -10
- package/lib/algorithm/aria/matches-context-role.js +3 -10
- package/lib/algorithm/html/content-model-category-to-tag-names.d.ts +5 -0
- package/lib/algorithm/html/content-model-category-to-tag-names.js +5 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.js +28 -0
- package/lib/types/index.d.ts +35 -4
- package/lib/utils/schema-to-spec.d.ts +10 -0
- package/lib/utils/schema-to-spec.js +10 -0
- package/package.json +6 -6
- package/ARCHITECTURE.ja.md +0 -267
- package/ARCHITECTURE.md +0 -267
- package/SKILL.md +0 -116
- package/docs/aria-algorithms.ja.md +0 -802
- package/docs/aria-algorithms.md +0 -804
- package/docs/html-algorithms.ja.md +0 -469
- package/docs/html-algorithms.md +0 -469
- package/docs/maintenance.ja.md +0 -359
- package/docs/maintenance.md +0 -359
- package/docs/spec-resolution.ja.md +0 -575
- package/docs/spec-resolution.md +0 -588
- package/docs/type-definitions.ja.md +0 -584
- package/docs/type-definitions.md +0 -584
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { isTransparentForOwnership } from './is-presentational.js';
|
|
2
2
|
import { getComputedRole } from './get-computed-role.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* ownership traversal (via `isTransparentForOwnership`).
|
|
7
|
-
*
|
|
8
|
-
* In ARIA 1.3, `generic` role elements are additionally transparent.
|
|
9
|
-
*
|
|
10
|
-
* @param el - The DOM element whose ancestors to traverse
|
|
11
|
-
* @param specs - The full markup language specification
|
|
12
|
-
* @param version - The ARIA specification version to use
|
|
13
|
-
* @returns The nearest non-presentational ancestor's `ComputedRole`, or `{ el: null, role: null }` if none exists
|
|
4
|
+
* In ARIA 1.3, `generic` role elements are additionally transparent for
|
|
5
|
+
* ownership traversal.
|
|
14
6
|
*/
|
|
15
7
|
export function getNonPresentationalAncestor(
|
|
16
8
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -64,6 +64,7 @@ export function getPermittedRoles(specs, localName, namespace, version, matches)
|
|
|
64
64
|
// allowed at all per ARIA in HTML — even a value matching the implicit role.
|
|
65
65
|
// e.g. `<img alt="">`: implicit role is `presentation`, but "No role permitted"
|
|
66
66
|
// means `role="presentation"` and `role="none"` are both disallowed.
|
|
67
|
+
// See https://github.com/markuplint/markuplint/issues/3641 for background.
|
|
67
68
|
if (permittedRoles === false) {
|
|
68
69
|
return permittedRoleList;
|
|
69
70
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { ARIAVersion, MLMLSpec } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* ` > ` (e.g., `"list > group"`).
|
|
3
|
+
* Implements the ARIA "Required Accessibility Parent Role" (called "Required
|
|
4
|
+
* Context Role" in ARIA 1.2). Each condition string describes a chain of
|
|
5
|
+
* ancestor roles separated by ` > ` (e.g., `"list > group"`).
|
|
7
6
|
*
|
|
8
7
|
* TODO: This function only walks the DOM `parentElement` chain and does not
|
|
9
8
|
* consider `aria-owns` relationships. An element referenced by `aria-owns` on
|
|
@@ -11,11 +10,5 @@ import type { ARIAVersion, MLMLSpec } from '../../types/index.js';
|
|
|
11
10
|
* that ancestor. Implementing this requires a document-wide reverse lookup of
|
|
12
11
|
* `aria-owns` attributes, which is a separate architectural concern.
|
|
13
12
|
* See also: `has-required-owned-elements.ts` has a similar limitation.
|
|
14
|
-
*
|
|
15
|
-
* @param conditions - An array of required accessibility parent role condition strings to match against
|
|
16
|
-
* @param ownedEl - The owned DOM element whose parent context is being validated
|
|
17
|
-
* @param specs - The full markup language specification
|
|
18
|
-
* @param version - The ARIA specification version to use
|
|
19
|
-
* @returns `true` if any of the context role conditions are satisfied by the element's ancestors
|
|
20
13
|
*/
|
|
21
14
|
export declare function matchesContextRole(conditions: readonly string[], ownedEl: Element, specs: MLMLSpec, version: ARIAVersion): boolean;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { isTransparentForOwnership } from './is-presentational.js';
|
|
2
2
|
import { getComputedRole } from './get-computed-role.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* ` > ` (e.g., `"list > group"`).
|
|
4
|
+
* Implements the ARIA "Required Accessibility Parent Role" (called "Required
|
|
5
|
+
* Context Role" in ARIA 1.2). Each condition string describes a chain of
|
|
6
|
+
* ancestor roles separated by ` > ` (e.g., `"list > group"`).
|
|
8
7
|
*
|
|
9
8
|
* TODO: This function only walks the DOM `parentElement` chain and does not
|
|
10
9
|
* consider `aria-owns` relationships. An element referenced by `aria-owns` on
|
|
@@ -12,12 +11,6 @@ import { getComputedRole } from './get-computed-role.js';
|
|
|
12
11
|
* that ancestor. Implementing this requires a document-wide reverse lookup of
|
|
13
12
|
* `aria-owns` attributes, which is a separate architectural concern.
|
|
14
13
|
* See also: `has-required-owned-elements.ts` has a similar limitation.
|
|
15
|
-
*
|
|
16
|
-
* @param conditions - An array of required accessibility parent role condition strings to match against
|
|
17
|
-
* @param ownedEl - The owned DOM element whose parent context is being validated
|
|
18
|
-
* @param specs - The full markup language specification
|
|
19
|
-
* @param version - The ARIA specification version to use
|
|
20
|
-
* @returns `true` if any of the context role conditions are satisfied by the element's ancestors
|
|
21
14
|
*/
|
|
22
15
|
export function matchesContextRole(conditions,
|
|
23
16
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -5,6 +5,11 @@ import type { Category } from '../../types/permitted-structures.js';
|
|
|
5
5
|
* frozen array of HTML/SVG tag names that belong to that category.
|
|
6
6
|
* Results are cached for repeated lookups.
|
|
7
7
|
*
|
|
8
|
+
* Note: entries are returned as stored in the spec's `#contentModels` map
|
|
9
|
+
* without CSS selector parsing — they are expected to be bare tag names or
|
|
10
|
+
* tag-with-attribute selectors (e.g. `a[href]`); complex selectors are not
|
|
11
|
+
* decomposed into tag names.
|
|
12
|
+
*
|
|
8
13
|
* @param contentModel - The content model category identifier
|
|
9
14
|
* @param def - The specification definitions containing content model mappings
|
|
10
15
|
* @returns A frozen, sorted array of tag name strings belonging to the category
|
|
@@ -4,6 +4,11 @@ const cache = new Map();
|
|
|
4
4
|
* frozen array of HTML/SVG tag names that belong to that category.
|
|
5
5
|
* Results are cached for repeated lookups.
|
|
6
6
|
*
|
|
7
|
+
* Note: entries are returned as stored in the spec's `#contentModels` map
|
|
8
|
+
* without CSS selector parsing — they are expected to be bare tag names or
|
|
9
|
+
* tag-with-attribute selectors (e.g. `a[href]`); complex selectors are not
|
|
10
|
+
* decomposed into tag names.
|
|
11
|
+
*
|
|
7
12
|
* @param contentModel - The content model category identifier
|
|
8
13
|
* @param def - The specification definitions containing content model mappings
|
|
9
14
|
* @returns A frozen, sorted array of tag name strings belonging to the category
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Specification foundation layer for markuplint.
|
|
3
|
+
*
|
|
4
|
+
* Type definitions, W3C specification algorithms (WAI-ARIA, HTML-AAM, AccName,
|
|
5
|
+
* HTML content models), and JSON schemas live together in this single package
|
|
6
|
+
* by design. Separating the "static schemas" from the "computing algorithms"
|
|
7
|
+
* was considered and rejected: the algorithms are integral parts of the
|
|
8
|
+
* specifications themselves — HTML elements define implicit ARIA roles, the
|
|
9
|
+
* ARIA algorithms reference HTML semantics, and test cases validate
|
|
10
|
+
* cross-specification behavior — so a split would create an artificial
|
|
11
|
+
* boundary with no runtime benefit.
|
|
12
|
+
*
|
|
13
|
+
* The accessible name computation (`getAccname`) is implemented in-house with
|
|
14
|
+
* no external dependency; this is intentional.
|
|
15
|
+
*
|
|
16
|
+
* Versioning policy: the schemas and spec data structures are not part of
|
|
17
|
+
* markuplint's public API surface. Changes to schemas, generated types, or
|
|
18
|
+
* algorithm behavior are released as minor versions.
|
|
19
|
+
*
|
|
20
|
+
* Several module-level caches (element spec lookup, namespace resolution,
|
|
21
|
+
* version-resolved ARIA, content-model category tables) are intentionally
|
|
22
|
+
* never invalidated: spec data is immutable after merging and a lint run uses
|
|
23
|
+
* a single configuration. Long-running embedders (e.g. language servers)
|
|
24
|
+
* should be aware that spec data is cached at first access for the process
|
|
25
|
+
* lifetime.
|
|
26
|
+
*
|
|
27
|
+
* @module @markuplint/ml-spec
|
|
28
|
+
*/
|
|
1
29
|
export { getAttrSpecs as getAttrSpecsByNames } from './utils/get-attr-specs-spec.js';
|
|
2
30
|
export * from './utils/aria-version.js';
|
|
3
31
|
export { EMBEDDED_CONTROL_ROLES, isNativeEmbeddedControl } from './const/index.js';
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Specification foundation layer for markuplint.
|
|
3
|
+
*
|
|
4
|
+
* Type definitions, W3C specification algorithms (WAI-ARIA, HTML-AAM, AccName,
|
|
5
|
+
* HTML content models), and JSON schemas live together in this single package
|
|
6
|
+
* by design. Separating the "static schemas" from the "computing algorithms"
|
|
7
|
+
* was considered and rejected: the algorithms are integral parts of the
|
|
8
|
+
* specifications themselves — HTML elements define implicit ARIA roles, the
|
|
9
|
+
* ARIA algorithms reference HTML semantics, and test cases validate
|
|
10
|
+
* cross-specification behavior — so a split would create an artificial
|
|
11
|
+
* boundary with no runtime benefit.
|
|
12
|
+
*
|
|
13
|
+
* The accessible name computation (`getAccname`) is implemented in-house with
|
|
14
|
+
* no external dependency; this is intentional.
|
|
15
|
+
*
|
|
16
|
+
* Versioning policy: the schemas and spec data structures are not part of
|
|
17
|
+
* markuplint's public API surface. Changes to schemas, generated types, or
|
|
18
|
+
* algorithm behavior are released as minor versions.
|
|
19
|
+
*
|
|
20
|
+
* Several module-level caches (element spec lookup, namespace resolution,
|
|
21
|
+
* version-resolved ARIA, content-model category tables) are intentionally
|
|
22
|
+
* never invalidated: spec data is immutable after merging and a lint run uses
|
|
23
|
+
* a single configuration. Long-running embedders (e.g. language servers)
|
|
24
|
+
* should be aware that spec data is cached at first access for the process
|
|
25
|
+
* lifetime.
|
|
26
|
+
*
|
|
27
|
+
* @module @markuplint/ml-spec
|
|
28
|
+
*/
|
|
1
29
|
export { getAttrSpecs as getAttrSpecsByNames } from './utils/get-attr-specs-spec.js';
|
|
2
30
|
export * from './utils/aria-version.js';
|
|
3
31
|
// Constants
|
package/lib/types/index.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ export interface MLMLSpec {
|
|
|
12
12
|
readonly def: SpecDefs;
|
|
13
13
|
readonly specs: readonly ElementSpec[];
|
|
14
14
|
readonly directivePatterns?: readonly DirectivePattern[];
|
|
15
|
+
/**
|
|
16
|
+
* Controls how `@markuplint/ml-core`'s `MLAttr` resolves attribute names.
|
|
17
|
+
*
|
|
18
|
+
* - `'idl'`: enables IDL-to-content attribute name resolution (e.g.
|
|
19
|
+
* `className` → `class`) and suggests the IDL name as a candidate when the
|
|
20
|
+
* content attribute name is used (e.g. `tabindex` → "Did you mean
|
|
21
|
+
* `tabIndex`?"). Used by React, which accepts only IDL property names.
|
|
22
|
+
* - `'both'`: enables the same resolution but accepts both content attribute
|
|
23
|
+
* names and IDL property names without suggesting either. Used by Svelte.
|
|
24
|
+
*/
|
|
15
25
|
readonly acceptedAttrNames?: 'idl' | 'both';
|
|
16
26
|
}
|
|
17
27
|
/**
|
|
@@ -32,6 +42,10 @@ export type ExtendedSpec = {
|
|
|
32
42
|
readonly def?: Partial<SpecDefs>;
|
|
33
43
|
readonly specs?: readonly ExtendedElementSpec[];
|
|
34
44
|
readonly directivePatterns?: readonly DirectivePattern[];
|
|
45
|
+
/**
|
|
46
|
+
* See {@link MLMLSpec.acceptedAttrNames}. Last-write-wins across merged
|
|
47
|
+
* specs; omitting the property does not reset a previously set value.
|
|
48
|
+
*/
|
|
35
49
|
readonly acceptedAttrNames?: 'idl' | 'both';
|
|
36
50
|
};
|
|
37
51
|
/**
|
|
@@ -41,6 +55,10 @@ export type ExtendedSpec = {
|
|
|
41
55
|
*
|
|
42
56
|
* The `pattern` is a regex string matched against the raw attribute name.
|
|
43
57
|
* Capture groups can be referenced in `potentialName` using `$1`, `$2`, etc.
|
|
58
|
+
*
|
|
59
|
+
* Patterns are evaluated in order and the first match wins. Merging specs
|
|
60
|
+
* (`schemaToSpec`) concatenates pattern arrays, so spec authors should define
|
|
61
|
+
* patterns from most specific to most general.
|
|
44
62
|
*/
|
|
45
63
|
export type DirectivePattern = {
|
|
46
64
|
/**
|
|
@@ -131,21 +149,26 @@ export type ElementSpec = {
|
|
|
131
149
|
*/
|
|
132
150
|
readonly description?: string;
|
|
133
151
|
/**
|
|
134
|
-
* Experimental technology
|
|
152
|
+
* Experimental technology: not yet standardized (proposed or draft;
|
|
153
|
+
* subject to change or removal).
|
|
135
154
|
*/
|
|
136
155
|
readonly experimental?: true;
|
|
137
156
|
/**
|
|
138
|
-
* Obsolete or alternative elements
|
|
157
|
+
* Obsolete or alternative elements: removed from the spec entirely
|
|
158
|
+
* (browsers may no longer recognize it). Optionally points to an
|
|
159
|
+
* alternative element via `alt`.
|
|
139
160
|
*/
|
|
140
161
|
readonly obsolete?: true | {
|
|
141
162
|
readonly alt: string;
|
|
142
163
|
};
|
|
143
164
|
/**
|
|
144
|
-
* Deprecated
|
|
165
|
+
* Deprecated: still defined by the spec but its use is discouraged
|
|
166
|
+
* (usually still works in browsers).
|
|
145
167
|
*/
|
|
146
168
|
readonly deprecated?: true;
|
|
147
169
|
/**
|
|
148
|
-
* Non-standard
|
|
170
|
+
* Non-standard: never part of any standard (vendor-specific or
|
|
171
|
+
* proprietary).
|
|
149
172
|
*/
|
|
150
173
|
readonly nonStandard?: true;
|
|
151
174
|
/**
|
|
@@ -246,11 +269,19 @@ export type ARIARoleInSchema = Partial<ARIARole & {
|
|
|
246
269
|
/**
|
|
247
270
|
* Describes a property owned by an ARIA role, including whether it is inherited,
|
|
248
271
|
* required, or deprecated.
|
|
272
|
+
*
|
|
273
|
+
* `requiredCondition` qualifies `required: true` so that the property is only
|
|
274
|
+
* required when the condition holds. The W3C ARIA source markup does not encode
|
|
275
|
+
* such conditions; values are populated by manual overrides in
|
|
276
|
+
* `@markuplint/html-spec/generator/aria.ts`. Currently the only value is
|
|
277
|
+
* `'focusable'` (applied to `separator`'s `aria-valuenow`); the `wai-aria`
|
|
278
|
+
* checker resolves this through `mayBeFocusable` from `@markuplint/ml-spec`.
|
|
249
279
|
*/
|
|
250
280
|
export type ARIARoleOwnedProperties = {
|
|
251
281
|
readonly name: string;
|
|
252
282
|
readonly inherited?: true;
|
|
253
283
|
readonly required?: true;
|
|
284
|
+
readonly requiredCondition?: 'focusable';
|
|
254
285
|
readonly deprecated?: true;
|
|
255
286
|
};
|
|
256
287
|
/**
|
|
@@ -6,6 +6,16 @@ import type { ElementSpec, ExtendedSpec, MLMLSpec } from '../types/index.js';
|
|
|
6
6
|
*
|
|
7
7
|
* Ex: `@markuplint/html-spec` + `{ specs: { "\\.vue$": "@markuplint/vue-spec" } }` in configure files.
|
|
8
8
|
*
|
|
9
|
+
* The merge is an additive overlay with silent, unconditional override: later
|
|
10
|
+
* specs win, and there is deliberately no conflict detection and no provenance
|
|
11
|
+
* tracking in the merged result. Framework specs exist precisely to relax or
|
|
12
|
+
* extend base HTML constraints (e.g. React's `dangerouslySetInnerHTML`, Vue's
|
|
13
|
+
* `v-if`), so every key collision with the base spec is treated as a
|
|
14
|
+
* deliberate decision by the `ExtendedSpec` author — an extension that
|
|
15
|
+
* unintentionally weakens a base constraint is not flagged anywhere.
|
|
16
|
+
*
|
|
17
|
+
* @see https://github.com/markuplint/markuplint/issues/3893
|
|
18
|
+
*
|
|
9
19
|
* @param schemas - A tuple where the first element is the base `MLMLSpec` and subsequent elements are extended specs to merge
|
|
10
20
|
* @returns The merged specification combining the base spec with all extensions
|
|
11
21
|
*/
|
|
@@ -6,6 +6,16 @@ import { mergeArray } from './merge-array.js';
|
|
|
6
6
|
*
|
|
7
7
|
* Ex: `@markuplint/html-spec` + `{ specs: { "\\.vue$": "@markuplint/vue-spec" } }` in configure files.
|
|
8
8
|
*
|
|
9
|
+
* The merge is an additive overlay with silent, unconditional override: later
|
|
10
|
+
* specs win, and there is deliberately no conflict detection and no provenance
|
|
11
|
+
* tracking in the merged result. Framework specs exist precisely to relax or
|
|
12
|
+
* extend base HTML constraints (e.g. React's `dangerouslySetInnerHTML`, Vue's
|
|
13
|
+
* `v-if`), so every key collision with the base spec is treated as a
|
|
14
|
+
* deliberate decision by the `ExtendedSpec` author — an extension that
|
|
15
|
+
* unintentionally weakens a base constraint is not flagged anywhere.
|
|
16
|
+
*
|
|
17
|
+
* @see https://github.com/markuplint/markuplint/issues/3893
|
|
18
|
+
*
|
|
9
19
|
* @param schemas - A tuple where the first element is the base `MLMLSpec` and subsequent elements are extended specs to merge
|
|
10
20
|
* @returns The merged specification combining the base spec with all extensions
|
|
11
21
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-spec",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.6",
|
|
4
4
|
"description": "Types and schema that specs of the Markup languages for markuplint",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=24"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"schema:aria": "npx json2ts ./schemas/aria.schema.json --cwd ./schemas > ./src/types/aria.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@markuplint/ml-ast": "5.0.0-rc.
|
|
40
|
-
"@markuplint/types": "5.0.0-rc.
|
|
39
|
+
"@markuplint/ml-ast": "5.0.0-rc.6",
|
|
40
|
+
"@markuplint/types": "5.0.0-rc.6",
|
|
41
41
|
"is-plain-object": "5.0.0",
|
|
42
42
|
"type-fest": "5.6.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@markuplint/test-tools": "5.0.0-rc.
|
|
45
|
+
"@markuplint/test-tools": "5.0.0-rc.6",
|
|
46
46
|
"json-schema-to-typescript": "15.0.4"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "c02c3a0783eac6b2fb4707be2dc00b88f6219641"
|
|
49
49
|
}
|
package/ARCHITECTURE.ja.md
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
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`, `ConditionalAttributeType`, `GlobalAttributes`, `AttributeJSON`, `List`, `Enum`, `Number`, `Directive` |
|
|
154
|
-
| `types/permitted-structures.ts` | 生成型: `PermittedContentPattern`, `ContentModel`, `Category`(HTML 13 + SVG 19 + MathML 3 カテゴリ) |
|
|
155
|
-
|
|
156
|
-
### 2. ARIA アルゴリズム
|
|
157
|
-
|
|
158
|
-
ARIA アルゴリズムは WAI-ARIA, HTML-AAM, SVG-AAM, MathML-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/MathML/露出可能要素拡張付きパルパブルコンテンツ検出 |
|
|
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) -- スキーマ生成、依存関係管理、レシピ、トラブルシューティング
|