@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.
- package/ARCHITECTURE.ja.md +267 -0
- package/ARCHITECTURE.md +267 -0
- package/CHANGELOG.md +20 -2
- package/README.md +6 -188
- package/SKILL.md +116 -0
- package/docs/aria-algorithms.ja.md +798 -0
- package/docs/aria-algorithms.md +800 -0
- package/docs/html-algorithms.ja.md +469 -0
- package/docs/html-algorithms.md +469 -0
- package/docs/maintenance.ja.md +331 -0
- package/docs/maintenance.md +331 -0
- package/docs/spec-resolution.ja.md +568 -0
- package/docs/spec-resolution.md +580 -0
- package/docs/type-definitions.ja.md +565 -0
- package/docs/type-definitions.md +565 -0
- package/lib/algorithm/aria/accname/__tests__/test-helpers.d.ts +45 -0
- package/lib/algorithm/aria/accname/__tests__/test-helpers.js +120 -0
- package/lib/algorithm/aria/accname/aria-steps.d.ts +51 -0
- package/lib/algorithm/aria/accname/aria-steps.js +104 -0
- package/lib/algorithm/aria/accname/compute.d.ts +51 -0
- package/lib/algorithm/aria/accname/compute.js +101 -0
- package/lib/algorithm/aria/accname/element-names.d.ts +36 -0
- package/lib/algorithm/aria/accname/element-names.js +342 -0
- package/lib/algorithm/aria/accname/helpers.d.ts +98 -0
- package/lib/algorithm/aria/accname/helpers.js +330 -0
- package/lib/algorithm/aria/accname/index.d.ts +4 -0
- package/lib/algorithm/aria/accname/index.js +3 -0
- package/lib/algorithm/aria/accname/label-steps.d.ts +25 -0
- package/lib/algorithm/aria/accname/label-steps.js +66 -0
- package/lib/algorithm/aria/accname/svg-helpers.d.ts +17 -0
- package/lib/algorithm/aria/accname/svg-helpers.js +30 -0
- package/lib/algorithm/aria/accname/types.d.ts +70 -0
- package/lib/algorithm/aria/accname/types.js +2 -0
- package/lib/algorithm/aria/accname-computation.d.ts +19 -1
- package/lib/algorithm/aria/accname-computation.js +136 -6
- package/lib/algorithm/aria/aria-specs.d.ts +8 -0
- package/lib/algorithm/aria/aria-specs.js +7 -0
- package/lib/algorithm/aria/get-aria.d.ts +12 -0
- package/lib/algorithm/aria/get-aria.js +42 -4
- package/lib/algorithm/aria/get-computed-aria-props.d.ts +22 -0
- package/lib/algorithm/aria/get-computed-aria-props.js +10 -0
- package/lib/algorithm/aria/get-computed-role.d.ts +12 -0
- package/lib/algorithm/aria/get-computed-role.js +118 -26
- package/lib/algorithm/aria/get-explicit-role.d.ts +12 -0
- package/lib/algorithm/aria/get-explicit-role.js +12 -0
- package/lib/algorithm/aria/get-implicit-role.d.ts +18 -0
- package/lib/algorithm/aria/get-implicit-role.js +18 -0
- package/lib/algorithm/aria/get-non-presentational-ancestor.d.ts +12 -0
- package/lib/algorithm/aria/get-non-presentational-ancestor.js +14 -2
- package/lib/algorithm/aria/get-permitted-roles-spec.d.ts +8 -4
- package/lib/algorithm/aria/get-permitted-roles-spec.js +19 -6
- package/lib/algorithm/aria/get-permitted-roles.d.ts +9 -0
- package/lib/algorithm/aria/get-permitted-roles.js +9 -0
- package/lib/algorithm/aria/get-role-spec.d.ts +11 -0
- package/lib/algorithm/aria/get-role-spec.js +21 -3
- package/lib/algorithm/aria/has-required-owned-elements.d.ts +24 -0
- package/lib/algorithm/aria/has-required-owned-elements.js +40 -14
- package/lib/algorithm/aria/is-exposed.d.ts +7 -4
- package/lib/algorithm/aria/is-exposed.js +7 -4
- package/lib/algorithm/aria/is-presentational.d.ts +32 -0
- package/lib/algorithm/aria/is-presentational.js +39 -0
- package/lib/algorithm/aria/matches-context-role.d.ts +19 -0
- package/lib/algorithm/aria/matches-context-role.js +46 -2
- package/lib/algorithm/html/content-model-category-to-tag-names.d.ts +9 -0
- package/lib/algorithm/html/content-model-category-to-tag-names.js +10 -1
- package/lib/algorithm/html/get-content-model.d.ts +12 -1
- package/lib/algorithm/html/get-content-model.js +14 -6
- package/lib/algorithm/html/get-selectors-by-content-model-category.d.ts +8 -0
- package/lib/algorithm/html/get-selectors-by-content-model-category.js +8 -0
- package/lib/algorithm/html/is-nothing-content-model.d.ts +7 -0
- package/lib/algorithm/html/is-nothing-content-model.js +7 -0
- package/lib/algorithm/html/is-palpable-elements.d.ts +13 -0
- package/lib/algorithm/html/is-palpable-elements.js +13 -0
- package/lib/algorithm/html/is-void-element.d.ts +9 -0
- package/lib/algorithm/html/is-void-element.js +9 -0
- package/lib/algorithm/html/may-be-focusable.d.ts +10 -0
- package/lib/algorithm/html/may-be-focusable.js +10 -0
- package/lib/const/accname.d.ts +29 -0
- package/lib/const/accname.js +76 -0
- package/lib/const/dom.d.ts +8 -0
- package/lib/const/dom.js +8 -0
- package/lib/const/index.d.ts +2 -0
- package/lib/const/index.js +2 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +4 -0
- package/lib/types/index.d.ts +119 -0
- package/lib/utils/aria-version.d.ts +6 -0
- package/lib/utils/aria-version.js +6 -0
- package/lib/utils/directive-resolver.d.ts +23 -0
- package/lib/utils/directive-resolver.js +50 -0
- package/lib/utils/get-attr-specs-spec.d.ts +18 -0
- package/lib/utils/get-attr-specs-spec.js +22 -3
- package/lib/utils/get-attr-specs.d.ts +9 -0
- package/lib/utils/get-attr-specs.js +9 -0
- package/lib/utils/get-ns.d.ts +7 -0
- package/lib/utils/get-ns.js +7 -0
- package/lib/utils/get-spec-by-tag-name.d.ts +12 -1
- package/lib/utils/get-spec-by-tag-name.js +11 -0
- package/lib/utils/get-spec.d.ts +11 -1
- package/lib/utils/get-spec.js +10 -0
- package/lib/utils/merge-array.d.ts +10 -0
- package/lib/utils/merge-array.js +10 -0
- package/lib/utils/resolve-namespace.d.ts +13 -0
- package/lib/utils/resolve-namespace.js +10 -0
- package/lib/utils/resolve-version.d.ts +11 -0
- package/lib/utils/resolve-version.js +11 -0
- package/lib/utils/schema-to-spec.d.ts +7 -2
- package/lib/utils/schema-to-spec.js +20 -6
- package/lib/utils/validate-aria-version.d.ts +7 -0
- package/lib/utils/validate-aria-version.js +7 -0
- package/package.json +9 -7
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the CSS selectors associated with a content model category from the spec definitions.
|
|
3
|
+
* These selectors can be used to match elements that belong to the given category.
|
|
4
|
+
*
|
|
5
|
+
* @param specs - The full markup language specification
|
|
6
|
+
* @param category - The content model category identifier (e.g., `#flow`, `#interactive`)
|
|
7
|
+
* @returns A readonly array of CSS selector strings for the category, or an empty array if the category is not defined
|
|
8
|
+
*/
|
|
1
9
|
export function getSelectorsByContentModelCategory(specs, category) {
|
|
2
10
|
const selectors = specs.def['#contentModels'][category];
|
|
3
11
|
return selectors ?? [];
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Determines whether an element uses the "nothing" content model, meaning it
|
|
3
|
+
* must not contain any content. This includes void elements as well as
|
|
4
|
+
* `<iframe>` and `<template>` elements.
|
|
5
|
+
*
|
|
2
6
|
* @see https://html.spec.whatwg.org/multipage/dom.html#the-nothing-content-model
|
|
3
7
|
* @see https://html.spec.whatwg.org/multipage/indices.html#elements-3
|
|
8
|
+
*
|
|
9
|
+
* @param el - The DOM element to check
|
|
10
|
+
* @returns `true` if the element has the "nothing" content model
|
|
4
11
|
*/
|
|
5
12
|
export declare function isNothingContentModel(el: Element): boolean;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { isVoidElement } from './is-void-element.js';
|
|
2
2
|
/**
|
|
3
|
+
* Determines whether an element uses the "nothing" content model, meaning it
|
|
4
|
+
* must not contain any content. This includes void elements as well as
|
|
5
|
+
* `<iframe>` and `<template>` elements.
|
|
6
|
+
*
|
|
3
7
|
* @see https://html.spec.whatwg.org/multipage/dom.html#the-nothing-content-model
|
|
4
8
|
* @see https://html.spec.whatwg.org/multipage/indices.html#elements-3
|
|
9
|
+
*
|
|
10
|
+
* @param el - The DOM element to check
|
|
11
|
+
* @returns `true` if the element has the "nothing" content model
|
|
5
12
|
*/
|
|
6
13
|
export function isNothingContentModel(
|
|
7
14
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import type { MLMLSpec } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether an element is considered palpable content. Palpable elements
|
|
4
|
+
* are those that render something visible or meaningful to the user. Optionally
|
|
5
|
+
* extends the check to include SVG renderable elements and other exposable elements
|
|
6
|
+
* that do not belong to any standard content model category.
|
|
7
|
+
*
|
|
8
|
+
* @param el - The DOM element to check
|
|
9
|
+
* @param specs - The full markup language specification
|
|
10
|
+
* @param options - Optional flags to extend the palpable check
|
|
11
|
+
* @param options.extendsSvg - Whether to include SVG renderable elements (defaults to true)
|
|
12
|
+
* @param options.extendsExposableElements - Whether to include additional exposable elements like `<li>`, `<td>`, etc. (defaults to false)
|
|
13
|
+
* @returns `true` if the element is considered palpable content
|
|
14
|
+
*/
|
|
2
15
|
export declare function isPalpableElement(el: Element, specs: MLMLSpec, options?: {
|
|
3
16
|
readonly extendsSvg?: boolean;
|
|
4
17
|
readonly extendsExposableElements?: boolean;
|
|
@@ -28,6 +28,19 @@ const exposableElementsThatAreNoBelongingAModel = [
|
|
|
28
28
|
'thead',
|
|
29
29
|
'tr',
|
|
30
30
|
];
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether an element is considered palpable content. Palpable elements
|
|
33
|
+
* are those that render something visible or meaningful to the user. Optionally
|
|
34
|
+
* extends the check to include SVG renderable elements and other exposable elements
|
|
35
|
+
* that do not belong to any standard content model category.
|
|
36
|
+
*
|
|
37
|
+
* @param el - The DOM element to check
|
|
38
|
+
* @param specs - The full markup language specification
|
|
39
|
+
* @param options - Optional flags to extend the palpable check
|
|
40
|
+
* @param options.extendsSvg - Whether to include SVG renderable elements (defaults to true)
|
|
41
|
+
* @param options.extendsExposableElements - Whether to include additional exposable elements like `<li>`, `<td>`, etc. (defaults to false)
|
|
42
|
+
* @returns `true` if the element is considered palpable content
|
|
43
|
+
*/
|
|
31
44
|
export function isPalpableElement(
|
|
32
45
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
33
46
|
el, specs, options) {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether an element is a void element as defined by the HTML specification.
|
|
3
|
+
* Void elements cannot have any contents (e.g., `<br>`, `<img>`, `<input>`).
|
|
4
|
+
*
|
|
5
|
+
* @see https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
6
|
+
*
|
|
7
|
+
* @param el - An object with a `localName` property representing the element's tag name
|
|
8
|
+
* @returns `true` if the element is a void element
|
|
9
|
+
*/
|
|
1
10
|
export declare function isVoidElement(el: {
|
|
2
11
|
readonly localName: string;
|
|
3
12
|
}): boolean;
|
|
@@ -16,6 +16,15 @@ const voidElements = new Set([
|
|
|
16
16
|
'track',
|
|
17
17
|
'wbr',
|
|
18
18
|
]);
|
|
19
|
+
/**
|
|
20
|
+
* Determines whether an element is a void element as defined by the HTML specification.
|
|
21
|
+
* Void elements cannot have any contents (e.g., `<br>`, `<img>`, `<input>`).
|
|
22
|
+
*
|
|
23
|
+
* @see https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
24
|
+
*
|
|
25
|
+
* @param el - An object with a `localName` property representing the element's tag name
|
|
26
|
+
* @returns `true` if the element is a void element
|
|
27
|
+
*/
|
|
19
28
|
export function isVoidElement(el) {
|
|
20
29
|
return voidElements.has(el.localName);
|
|
21
30
|
}
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import type { MLMLSpec } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether an element may potentially be focusable, based on whether it matches
|
|
4
|
+
* interactive content selectors, has a `tabindex` attribute, or has a `contenteditable`
|
|
5
|
+
* attribute. This is a heuristic check that does not account for runtime state such as
|
|
6
|
+
* `disabled` or `inert` attributes.
|
|
7
|
+
*
|
|
8
|
+
* @param el - The DOM element to check
|
|
9
|
+
* @param specs - The full markup language specification containing interactive content definitions
|
|
10
|
+
* @returns `true` if the element may be focusable
|
|
11
|
+
*/
|
|
2
12
|
export declare function mayBeFocusable(el: Element, specs: MLMLSpec): boolean;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { getSelectorsByContentModelCategory } from './get-selectors-by-content-model-category.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether an element may potentially be focusable, based on whether it matches
|
|
4
|
+
* interactive content selectors, has a `tabindex` attribute, or has a `contenteditable`
|
|
5
|
+
* attribute. This is a heuristic check that does not account for runtime state such as
|
|
6
|
+
* `disabled` or `inert` attributes.
|
|
7
|
+
*
|
|
8
|
+
* @param el - The DOM element to check
|
|
9
|
+
* @param specs - The full markup language specification containing interactive content definitions
|
|
10
|
+
* @returns `true` if the element may be focusable
|
|
11
|
+
*/
|
|
2
12
|
export function mayBeFocusable(
|
|
3
13
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
4
14
|
el, specs) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AccnameElement } from '../algorithm/aria/accname/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* ARIA roles that are embedded controls per AccName Step 2C.
|
|
4
|
+
* @see https://www.w3.org/TR/accname-1.2/#comp_embedded_control
|
|
5
|
+
*/
|
|
6
|
+
export declare const EMBEDDED_CONTROL_ROLES: ReadonlySet<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Input types using label → title → placeholder name computation (HTML-AAM §4.1).
|
|
9
|
+
*/
|
|
10
|
+
export declare const TEXT_INPUT_TYPES: ReadonlySet<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Input types that behave as text-like controls (value attr → textContent).
|
|
13
|
+
* Subset of TEXT_INPUT_TYPES used for embedded control value extraction.
|
|
14
|
+
*/
|
|
15
|
+
export declare const TEXT_LIKE_INPUT_TYPES: ReadonlySet<string>;
|
|
16
|
+
/** Default accessible name for input[type=submit] per HTML-AAM §4.1 */
|
|
17
|
+
export declare const DEFAULT_SUBMIT_LABEL = "Submit";
|
|
18
|
+
/** Default accessible name for input[type=reset] per HTML-AAM §4.1 */
|
|
19
|
+
export declare const DEFAULT_RESET_LABEL = "Reset";
|
|
20
|
+
/** Default accessible name for input[type=image] per HTML-AAM §4.1 */
|
|
21
|
+
export declare const DEFAULT_IMAGE_LABEL = "Submit Query";
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a native HTML element is an embedded control (without role resolution).
|
|
24
|
+
* Centralizes the logic duplicated across accname-computation.ts, ml-core/accname.ts, test-helpers.ts.
|
|
25
|
+
*
|
|
26
|
+
* @param el - The element to check
|
|
27
|
+
* @returns True if the element is a native embedded control (textarea, select, or input with a value-producing type)
|
|
28
|
+
*/
|
|
29
|
+
export declare function isNativeEmbeddedControl(el: AccnameElement): boolean;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARIA roles that are embedded controls per AccName Step 2C.
|
|
3
|
+
* @see https://www.w3.org/TR/accname-1.2/#comp_embedded_control
|
|
4
|
+
*/
|
|
5
|
+
export const EMBEDDED_CONTROL_ROLES = new Set([
|
|
6
|
+
'textbox',
|
|
7
|
+
'combobox',
|
|
8
|
+
'listbox',
|
|
9
|
+
'spinbutton',
|
|
10
|
+
'slider',
|
|
11
|
+
'searchbox',
|
|
12
|
+
]);
|
|
13
|
+
/**
|
|
14
|
+
* Input types using label → title → placeholder name computation (HTML-AAM §4.1).
|
|
15
|
+
*/
|
|
16
|
+
export const TEXT_INPUT_TYPES = new Set([
|
|
17
|
+
'text',
|
|
18
|
+
'password',
|
|
19
|
+
'search',
|
|
20
|
+
'tel',
|
|
21
|
+
'url',
|
|
22
|
+
'email',
|
|
23
|
+
'number',
|
|
24
|
+
'date',
|
|
25
|
+
'month',
|
|
26
|
+
'week',
|
|
27
|
+
'time',
|
|
28
|
+
'datetime-local',
|
|
29
|
+
'color',
|
|
30
|
+
'range',
|
|
31
|
+
'file',
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* Input types that behave as text-like controls (value attr → textContent).
|
|
35
|
+
* Subset of TEXT_INPUT_TYPES used for embedded control value extraction.
|
|
36
|
+
*/
|
|
37
|
+
export const TEXT_LIKE_INPUT_TYPES = new Set([
|
|
38
|
+
'text',
|
|
39
|
+
'search',
|
|
40
|
+
'tel',
|
|
41
|
+
'url',
|
|
42
|
+
'email',
|
|
43
|
+
'password',
|
|
44
|
+
'number',
|
|
45
|
+
]);
|
|
46
|
+
/** Default accessible name for input[type=submit] per HTML-AAM §4.1 */
|
|
47
|
+
export const DEFAULT_SUBMIT_LABEL = 'Submit';
|
|
48
|
+
/** Default accessible name for input[type=reset] per HTML-AAM §4.1 */
|
|
49
|
+
export const DEFAULT_RESET_LABEL = 'Reset';
|
|
50
|
+
/** Default accessible name for input[type=image] per HTML-AAM §4.1 */
|
|
51
|
+
export const DEFAULT_IMAGE_LABEL = 'Submit Query';
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a native HTML element is an embedded control (without role resolution).
|
|
54
|
+
* Centralizes the logic duplicated across accname-computation.ts, ml-core/accname.ts, test-helpers.ts.
|
|
55
|
+
*
|
|
56
|
+
* @param el - The element to check
|
|
57
|
+
* @returns True if the element is a native embedded control (textarea, select, or input with a value-producing type)
|
|
58
|
+
*/
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
60
|
+
export function isNativeEmbeddedControl(el) {
|
|
61
|
+
const { localName } = el;
|
|
62
|
+
if (localName === 'textarea' || localName === 'select') {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (localName === 'input') {
|
|
66
|
+
const type = (el.getAttribute('type') ?? 'text').toLowerCase();
|
|
67
|
+
return (type !== 'hidden' &&
|
|
68
|
+
type !== 'button' &&
|
|
69
|
+
type !== 'submit' &&
|
|
70
|
+
type !== 'reset' &&
|
|
71
|
+
type !== 'image' &&
|
|
72
|
+
type !== 'checkbox' &&
|
|
73
|
+
type !== 'radio');
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** DOM Node.ELEMENT_NODE */
|
|
2
|
+
export declare const ELEMENT_NODE = 1;
|
|
3
|
+
/** DOM Node.TEXT_NODE */
|
|
4
|
+
export declare const TEXT_NODE = 3;
|
|
5
|
+
/** SVG namespace URI */
|
|
6
|
+
export declare const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
7
|
+
/** XHTML namespace URI */
|
|
8
|
+
export declare const XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
package/lib/const/dom.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** DOM Node.ELEMENT_NODE */
|
|
2
|
+
export const ELEMENT_NODE = 1;
|
|
3
|
+
/** DOM Node.TEXT_NODE */
|
|
4
|
+
export const TEXT_NODE = 3;
|
|
5
|
+
/** SVG namespace URI */
|
|
6
|
+
export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
7
|
+
/** XHTML namespace URI */
|
|
8
|
+
export const XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { getAttrSpecs as getAttrSpecsByNames } from './utils/get-attr-specs-spec.js';
|
|
2
2
|
export * from './utils/aria-version.js';
|
|
3
|
+
export { EMBEDDED_CONTROL_ROLES, isNativeEmbeddedControl } from './const/index.js';
|
|
4
|
+
export * from './algorithm/aria/accname/index.js';
|
|
3
5
|
export * from './algorithm/aria/accname-computation.js';
|
|
4
6
|
export * from './algorithm/aria/get-computed-aria-props.js';
|
|
5
7
|
export * from './algorithm/aria/get-computed-role.js';
|
|
@@ -24,6 +26,7 @@ export * from './utils/get-spec-by-tag-name.js';
|
|
|
24
26
|
export * from './utils/schema-to-spec.js';
|
|
25
27
|
export * from './utils/resolve-namespace.js';
|
|
26
28
|
export * from './utils/validate-aria-version.js';
|
|
29
|
+
export * from './utils/directive-resolver.js';
|
|
27
30
|
export * from './types/index.js';
|
|
28
31
|
export * from './types/aria.js';
|
|
29
32
|
export * from './types/attributes.js';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { getAttrSpecs as getAttrSpecsByNames } from './utils/get-attr-specs-spec.js';
|
|
2
2
|
export * from './utils/aria-version.js';
|
|
3
|
+
// Constants
|
|
4
|
+
export { EMBEDDED_CONTROL_ROLES, isNativeEmbeddedControl } from './const/index.js';
|
|
3
5
|
// ARIA algorithms
|
|
6
|
+
export * from './algorithm/aria/accname/index.js';
|
|
4
7
|
export * from './algorithm/aria/accname-computation.js';
|
|
5
8
|
export * from './algorithm/aria/get-computed-aria-props.js';
|
|
6
9
|
export * from './algorithm/aria/get-computed-role.js';
|
|
@@ -27,6 +30,7 @@ export * from './utils/get-spec-by-tag-name.js';
|
|
|
27
30
|
export * from './utils/schema-to-spec.js';
|
|
28
31
|
export * from './utils/resolve-namespace.js';
|
|
29
32
|
export * from './utils/validate-aria-version.js';
|
|
33
|
+
export * from './utils/directive-resolver.js';
|
|
30
34
|
// Type definitions
|
|
31
35
|
export * from './types/index.js';
|
|
32
36
|
export * from './types/aria.js';
|
package/lib/types/index.d.ts
CHANGED
|
@@ -11,20 +11,85 @@ export interface MLMLSpec {
|
|
|
11
11
|
readonly cites: Cites;
|
|
12
12
|
readonly def: SpecDefs;
|
|
13
13
|
readonly specs: readonly ElementSpec[];
|
|
14
|
+
readonly directivePatterns?: readonly DirectivePattern[];
|
|
15
|
+
readonly useIDLAttributeNames?: boolean;
|
|
14
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* An element specification for extending or overriding parts of the base spec.
|
|
19
|
+
* Only the `name` property is required; all other properties are optional partial overrides.
|
|
20
|
+
* Attributes use `Partial<Attribute>` to allow specifying only changed fields.
|
|
21
|
+
*/
|
|
15
22
|
export type ExtendedElementSpec = Partial<Omit<ElementSpec, 'name' | 'attributes'>> & {
|
|
16
23
|
readonly name: ElementSpec['name'];
|
|
17
24
|
readonly attributes?: Readonly<Record<string, Partial<Attribute>>>;
|
|
18
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* A partial specification used for extending or customizing the base markup language spec.
|
|
28
|
+
* Typically provided by parser plugins or framework-specific spec packages (e.g., `@markuplint/vue-spec`).
|
|
29
|
+
*/
|
|
19
30
|
export type ExtendedSpec = {
|
|
20
31
|
readonly cites?: Cites;
|
|
21
32
|
readonly def?: Partial<SpecDefs>;
|
|
22
33
|
readonly specs?: readonly ExtendedElementSpec[];
|
|
34
|
+
readonly directivePatterns?: readonly DirectivePattern[];
|
|
35
|
+
readonly useIDLAttributeNames?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* A declarative pattern for resolving framework-specific directive
|
|
39
|
+
* attributes to their canonical names and metadata. Stored as part
|
|
40
|
+
* of the spec, enabling "parser-less" framework support.
|
|
41
|
+
*
|
|
42
|
+
* The `pattern` is a regex string matched against the raw attribute name.
|
|
43
|
+
* Capture groups can be referenced in `potentialName` using `$1`, `$2`, etc.
|
|
44
|
+
*/
|
|
45
|
+
export type DirectivePattern = {
|
|
46
|
+
/**
|
|
47
|
+
* A regex string (without delimiters) matched against the raw attribute name.
|
|
48
|
+
* Must be a valid JavaScript RegExp pattern. Capture groups can be used
|
|
49
|
+
* for potentialName templates.
|
|
50
|
+
* @example "^(?:x-bind:|:)([^.]+)(?:\\.[^.]+)?$"
|
|
51
|
+
*/
|
|
52
|
+
readonly pattern: string;
|
|
53
|
+
/**
|
|
54
|
+
* Optional regex flags (e.g., "i" for case-insensitive).
|
|
55
|
+
* @default "i"
|
|
56
|
+
*/
|
|
57
|
+
readonly flags?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Template for the resolved potentialName. References capture groups
|
|
60
|
+
* with $1, $2, etc. If omitted, the attribute is treated as a directive
|
|
61
|
+
* with no potentialName change.
|
|
62
|
+
* @example "on$1" -- for `@click` -> `onclick`
|
|
63
|
+
* @example "$1" -- for `:href` -> `href`
|
|
64
|
+
*/
|
|
65
|
+
readonly potentialName?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether this attribute is a framework directive.
|
|
68
|
+
*/
|
|
69
|
+
readonly isDirective?: true;
|
|
70
|
+
/**
|
|
71
|
+
* Whether this attribute has a dynamic value.
|
|
72
|
+
*/
|
|
73
|
+
readonly isDynamicValue?: true;
|
|
74
|
+
/**
|
|
75
|
+
* The semantic value type for matched attributes.
|
|
76
|
+
*/
|
|
77
|
+
readonly valueType?: 'string' | 'number' | 'boolean' | 'code';
|
|
78
|
+
/**
|
|
79
|
+
* If true, the attribute can appear multiple times on the same element.
|
|
80
|
+
* Can also be a string array of potentialName values for which
|
|
81
|
+
* duplication is allowed (e.g., ['class', 'style']).
|
|
82
|
+
*/
|
|
83
|
+
readonly isDuplicatable?: true | readonly string[];
|
|
23
84
|
};
|
|
24
85
|
/**
|
|
25
86
|
* Reference URLs
|
|
26
87
|
*/
|
|
27
88
|
export type Cites = readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* Internal definition data within a markup language spec, containing global attributes,
|
|
91
|
+
* ARIA role/property definitions for each version, and content model category mappings.
|
|
92
|
+
*/
|
|
28
93
|
export type SpecDefs = {
|
|
29
94
|
readonly '#globalAttrs': {
|
|
30
95
|
readonly [category: string]: Readonly<Record<string, Partial<Attribute>>>;
|
|
@@ -41,6 +106,7 @@ export type SpecDefs = {
|
|
|
41
106
|
type ARIASpec = {
|
|
42
107
|
readonly roles: readonly ARIARoleInSchema[];
|
|
43
108
|
readonly graphicsRoles: readonly ARIARoleInSchema[];
|
|
109
|
+
readonly dpubRoles: readonly ARIARoleInSchema[];
|
|
44
110
|
readonly props: readonly ARIAProperty[];
|
|
45
111
|
};
|
|
46
112
|
/**
|
|
@@ -124,6 +190,9 @@ type ElementSpecOmissionTags = {
|
|
|
124
190
|
type ElementCondition = {
|
|
125
191
|
readonly __WIP__: 'WORK_IN_PROGRESS';
|
|
126
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* Describes a single HTML/SVG attribute with its type, description, and status flags.
|
|
195
|
+
*/
|
|
127
196
|
export type Attribute = {
|
|
128
197
|
readonly name: string;
|
|
129
198
|
readonly type: ReadonlyDeep<AttributeType> | readonly ReadonlyDeep<AttributeType>[];
|
|
@@ -135,11 +204,26 @@ export type Attribute = {
|
|
|
135
204
|
readonly nonStandard?: true;
|
|
136
205
|
} & ExtendableAttributeSpec;
|
|
137
206
|
type ExtendableAttributeSpec = Omit<ReadonlyDeep<AttributeJSON>, 'type'>;
|
|
207
|
+
/**
|
|
208
|
+
* A fully resolved ARIA role with all its properties, requirements, and naming constraints.
|
|
209
|
+
*/
|
|
138
210
|
export type ARIARole = {
|
|
139
211
|
readonly name: string;
|
|
140
212
|
readonly isAbstract: boolean;
|
|
141
213
|
readonly deprecated: boolean;
|
|
214
|
+
/** Required Accessibility Parent Role (ARIA 1.3 name) */
|
|
215
|
+
readonly requiredAccessibilityParentRole: readonly string[];
|
|
216
|
+
/** Allowed Accessibility Child Roles (ARIA 1.3 name) */
|
|
217
|
+
readonly allowedAccessibilityChildRoles: readonly string[];
|
|
218
|
+
/**
|
|
219
|
+
* @deprecated Use {@link ARIARole.requiredAccessibilityParentRole} instead.
|
|
220
|
+
* Retained for ARIA 1.2 backward compatibility.
|
|
221
|
+
*/
|
|
142
222
|
readonly requiredContextRole: readonly string[];
|
|
223
|
+
/**
|
|
224
|
+
* @deprecated Use {@link ARIARole.allowedAccessibilityChildRoles} instead.
|
|
225
|
+
* Retained for ARIA 1.2 backward compatibility.
|
|
226
|
+
*/
|
|
143
227
|
readonly requiredOwnedElements: readonly string[];
|
|
144
228
|
readonly accessibleNameRequired: boolean;
|
|
145
229
|
readonly accessibleNameFromAuthor: boolean;
|
|
@@ -149,18 +233,30 @@ export type ARIARole = {
|
|
|
149
233
|
readonly ownedProperties: readonly ARIARoleOwnedProperties[];
|
|
150
234
|
readonly prohibitedProperties: readonly string[];
|
|
151
235
|
};
|
|
236
|
+
/**
|
|
237
|
+
* An ARIA role as defined in the raw schema data. All properties are optional
|
|
238
|
+
* except `name`, since the schema may provide only partial role information.
|
|
239
|
+
*/
|
|
152
240
|
export type ARIARoleInSchema = Partial<ARIARole & {
|
|
153
241
|
readonly description: string;
|
|
154
242
|
readonly generalization: readonly string[];
|
|
155
243
|
}> & {
|
|
156
244
|
readonly name: string;
|
|
157
245
|
};
|
|
246
|
+
/**
|
|
247
|
+
* Describes a property owned by an ARIA role, including whether it is inherited,
|
|
248
|
+
* required, or deprecated.
|
|
249
|
+
*/
|
|
158
250
|
export type ARIARoleOwnedProperties = {
|
|
159
251
|
readonly name: string;
|
|
160
252
|
readonly inherited?: true;
|
|
161
253
|
readonly required?: true;
|
|
162
254
|
readonly deprecated?: true;
|
|
163
255
|
};
|
|
256
|
+
/**
|
|
257
|
+
* Describes an ARIA property or state, including its value type, enumeration values,
|
|
258
|
+
* global status, default value, conditional values per role, and equivalent HTML attributes.
|
|
259
|
+
*/
|
|
164
260
|
export type ARIAProperty = {
|
|
165
261
|
readonly name: string;
|
|
166
262
|
readonly type: 'property' | 'state';
|
|
@@ -176,14 +272,33 @@ export type ARIAProperty = {
|
|
|
176
272
|
readonly equivalentHtmlAttrs?: readonly EquivalentHtmlAttr[];
|
|
177
273
|
readonly valueDescriptions?: Readonly<Record<string, string>>;
|
|
178
274
|
};
|
|
275
|
+
/**
|
|
276
|
+
* The possible value types for ARIA attributes, as defined by the WAI-ARIA specification.
|
|
277
|
+
*/
|
|
179
278
|
export type ARIAAttributeValue = 'true/false' | 'tristate' | 'true/false/undefined' | 'ID reference' | 'ID reference list' | 'integer' | 'number' | 'string' | 'token' | 'token list' | 'URI';
|
|
279
|
+
/**
|
|
280
|
+
* A union type of supported ARIA specification version strings, derived from the `ariaVersions` tuple.
|
|
281
|
+
*/
|
|
180
282
|
export type ARIAVersion = (typeof ariaVersions)[number];
|
|
283
|
+
/**
|
|
284
|
+
* Describes an HTML attribute that is semantically equivalent to an ARIA property,
|
|
285
|
+
* enabling automatic mapping from HTML attributes to ARIA states/properties.
|
|
286
|
+
*/
|
|
181
287
|
export type EquivalentHtmlAttr = {
|
|
182
288
|
readonly htmlAttrName: string;
|
|
183
289
|
readonly isNotStrictEquivalent?: true;
|
|
184
290
|
readonly value: string | null;
|
|
185
291
|
};
|
|
292
|
+
/**
|
|
293
|
+
* A function that tests whether an element matches a given CSS selector string.
|
|
294
|
+
* Typically bound to `Element.prototype.matches`.
|
|
295
|
+
*/
|
|
186
296
|
export type Matches = (selector: string) => boolean;
|
|
297
|
+
/**
|
|
298
|
+
* The result of computing an element's ARIA role, containing the element reference,
|
|
299
|
+
* the resolved role specification (or null if no role applies), and an optional
|
|
300
|
+
* error type indicating issues during role computation.
|
|
301
|
+
*/
|
|
187
302
|
export type ComputedRole = {
|
|
188
303
|
readonly el: Element;
|
|
189
304
|
readonly role: (ARIARole & {
|
|
@@ -192,5 +307,9 @@ export type ComputedRole = {
|
|
|
192
307
|
}) | null;
|
|
193
308
|
readonly errorType?: RoleComputationError;
|
|
194
309
|
};
|
|
310
|
+
/**
|
|
311
|
+
* Error codes that may arise during ARIA role computation, indicating specific
|
|
312
|
+
* issues such as abstract roles, invalid context, or presentational conflicts.
|
|
313
|
+
*/
|
|
195
314
|
export type RoleComputationError = 'ABSTRACT' | 'GLOBAL_PROP_MUST_NOT_BE_PRESENTATIONAL' | 'IMPLICIT_ROLE_NAMESPACE_ERROR' | 'INTERACTIVE_ELEMENT_MUST_NOT_BE_PRESENTATIONAL' | 'INVALID_LANDMARK' | 'INVALID_REQUIRED_CONTEXT_ROLE' | 'NO_EXPLICIT' | 'NO_OWNER' | 'NO_PERMITTED' | 'REQUIRED_OWNED_ELEMENT_MUST_NOT_BE_PRESENTATIONAL' | 'ROLE_NO_EXISTS';
|
|
196
315
|
export {};
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The supported ARIA specification versions as a readonly tuple.
|
|
3
|
+
*/
|
|
1
4
|
export declare const ariaVersions: readonly ["1.1", "1.2", "1.3"];
|
|
5
|
+
/**
|
|
6
|
+
* The recommended default ARIA specification version to use when none is explicitly specified.
|
|
7
|
+
*/
|
|
2
8
|
export declare const ARIA_RECOMMENDED_VERSION = "1.2";
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The supported ARIA specification versions as a readonly tuple.
|
|
3
|
+
*/
|
|
1
4
|
export const ariaVersions = ['1.1', '1.2', '1.3'];
|
|
5
|
+
/**
|
|
6
|
+
* The recommended default ARIA specification version to use when none is explicitly specified.
|
|
7
|
+
*/
|
|
2
8
|
export const ARIA_RECOMMENDED_VERSION = '1.2';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DirectivePattern } from '../types/index.js';
|
|
2
|
+
type CompiledDirectivePattern = {
|
|
3
|
+
readonly regex: RegExp;
|
|
4
|
+
readonly pattern: DirectivePattern;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Compiles directive patterns into RegExp objects, caching them
|
|
8
|
+
* by the patterns array reference for efficiency.
|
|
9
|
+
*/
|
|
10
|
+
export declare function compileDirectivePatterns(patterns: readonly DirectivePattern[]): readonly CompiledDirectivePattern[];
|
|
11
|
+
export type DirectiveResolution = {
|
|
12
|
+
readonly potentialName?: string;
|
|
13
|
+
readonly isDirective?: true;
|
|
14
|
+
readonly isDynamicValue?: true;
|
|
15
|
+
readonly valueType?: 'string' | 'number' | 'boolean' | 'code';
|
|
16
|
+
readonly isDuplicatable?: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Resolves an attribute name against a list of compiled directive patterns.
|
|
20
|
+
* Returns the first match's resolution, or null if no pattern matches.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveDirective(attrName: string, compiledPatterns: readonly CompiledDirectivePattern[]): DirectiveResolution | null;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const cache = new WeakMap();
|
|
2
|
+
/**
|
|
3
|
+
* Compiles directive patterns into RegExp objects, caching them
|
|
4
|
+
* by the patterns array reference for efficiency.
|
|
5
|
+
*/
|
|
6
|
+
export function compileDirectivePatterns(patterns) {
|
|
7
|
+
let compiled = cache.get(patterns);
|
|
8
|
+
if (!compiled) {
|
|
9
|
+
compiled = patterns.map(p => ({
|
|
10
|
+
regex: new RegExp(p.pattern, p.flags ?? 'i'),
|
|
11
|
+
pattern: p,
|
|
12
|
+
}));
|
|
13
|
+
cache.set(patterns, compiled);
|
|
14
|
+
}
|
|
15
|
+
return compiled;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves an attribute name against a list of compiled directive patterns.
|
|
19
|
+
* Returns the first match's resolution, or null if no pattern matches.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveDirective(attrName,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
23
|
+
compiledPatterns) {
|
|
24
|
+
for (const { regex, pattern } of compiledPatterns) {
|
|
25
|
+
regex.lastIndex = 0;
|
|
26
|
+
const match = regex.exec(attrName);
|
|
27
|
+
if (!match) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
let potentialName;
|
|
31
|
+
if (pattern.potentialName != null) {
|
|
32
|
+
potentialName = pattern.potentialName.replaceAll(/\$(\d+)/g, (_, idx) => (match[Number(idx)] ?? '').toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
let isDuplicatable;
|
|
35
|
+
if (pattern.isDuplicatable === true) {
|
|
36
|
+
isDuplicatable = true;
|
|
37
|
+
}
|
|
38
|
+
else if (Array.isArray(pattern.isDuplicatable) && potentialName) {
|
|
39
|
+
isDuplicatable = pattern.isDuplicatable.includes(potentialName);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
potentialName,
|
|
43
|
+
isDirective: pattern.isDirective,
|
|
44
|
+
isDynamicValue: pattern.isDynamicValue,
|
|
45
|
+
valueType: pattern.valueType,
|
|
46
|
+
isDuplicatable,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import type { MLMLSpec, Attribute } from '../types/index.js';
|
|
2
2
|
import type { NamespaceURI } from '@markuplint/ml-ast';
|
|
3
|
+
/**
|
|
4
|
+
* Retrieves the merged attribute specifications for an element identified by its local name
|
|
5
|
+
* and namespace. Combines global attributes from the relevant categories with the element's
|
|
6
|
+
* own attribute definitions. Results are cached by the namespace-qualified element name.
|
|
7
|
+
*
|
|
8
|
+
* @param localName - The local tag name of the element
|
|
9
|
+
* @param namespace - The namespace URI of the element, or null for HTML namespace
|
|
10
|
+
* @param schema - The full markup language specification containing attribute definitions
|
|
11
|
+
* @returns A sorted array of attribute specifications for the element, or null if the element is not found in the schema
|
|
12
|
+
*/
|
|
3
13
|
export declare function getAttrSpecs(localName: string, namespace: NamespaceURI | null, schema: MLMLSpec): readonly Attribute[] | null;
|
|
4
14
|
type HasName = {
|
|
5
15
|
readonly name: string;
|
|
6
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Compares two items by name in a case-insensitive manner, suitable for use as
|
|
19
|
+
* a sort comparator. Accepts either objects with a `name` property or plain strings.
|
|
20
|
+
*
|
|
21
|
+
* @param a - The first item to compare (object with `name` property or a string)
|
|
22
|
+
* @param b - The second item to compare (object with `name` property or a string)
|
|
23
|
+
* @returns A negative number if `a` comes before `b`, positive if after, or 0 if equal
|
|
24
|
+
*/
|
|
7
25
|
export declare function nameCompare(a: HasName | string, b: HasName | string): 1 | -1 | 0;
|
|
8
26
|
export {};
|