@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
@@ -1,6 +1,16 @@
1
1
  import { resolveNamespace } from './resolve-namespace.js';
2
2
  const cacheMap = new Map();
3
3
  const schemaCache = new WeakSet();
4
+ /**
5
+ * Retrieves the merged attribute specifications for an element identified by its local name
6
+ * and namespace. Combines global attributes from the relevant categories with the element's
7
+ * own attribute definitions. Results are cached by the namespace-qualified element name.
8
+ *
9
+ * @param localName - The local tag name of the element
10
+ * @param namespace - The namespace URI of the element, or null for HTML namespace
11
+ * @param schema - The full markup language specification containing attribute definitions
12
+ * @returns A sorted array of attribute specifications for the element, or null if the element is not found in the schema
13
+ */
4
14
  export function getAttrSpecs(localName, namespace, schema) {
5
15
  if (!schemaCache.has(schema)) {
6
16
  cacheMap.clear();
@@ -59,14 +69,23 @@ export function getAttrSpecs(localName, namespace, schema) {
59
69
  ...attr,
60
70
  };
61
71
  }
62
- const attrList = Object.keys(attrs).map(name => {
72
+ const attrList = Object.keys(attrs)
73
+ .map(name => {
63
74
  const attr = attrs[name];
64
75
  return { name, type: 'Any', ...attr };
65
- });
66
- attrList.sort(nameCompare);
76
+ })
77
+ .toSorted(nameCompare);
67
78
  cacheMap.set(localNameWithNS, attrList);
68
79
  return attrList;
69
80
  }
81
+ /**
82
+ * Compares two items by name in a case-insensitive manner, suitable for use as
83
+ * a sort comparator. Accepts either objects with a `name` property or plain strings.
84
+ *
85
+ * @param a - The first item to compare (object with `name` property or a string)
86
+ * @param b - The second item to compare (object with `name` property or a string)
87
+ * @returns A negative number if `a` comes before `b`, positive if after, or 0 if equal
88
+ */
70
89
  export function nameCompare(a, b) {
71
90
  const nameA = typeof a === 'string' ? a : a.name.toUpperCase();
72
91
  const nameB = typeof b === 'string' ? b : b.name.toUpperCase();
@@ -1,2 +1,11 @@
1
1
  import type { MLMLSpec } from '../types/index.js';
2
+ /**
3
+ * Retrieves the attribute specifications for a DOM element by resolving its
4
+ * local name and namespace URI from the provided schema. This is a convenience
5
+ * wrapper around the spec-based `getAttrSpecs` that accepts a DOM element directly.
6
+ *
7
+ * @param el - The DOM element whose attribute specifications to retrieve
8
+ * @param schema - The full markup language specification containing attribute definitions
9
+ * @returns The array of attribute specifications for the element, or null if no spec exists
10
+ */
2
11
  export declare function getAttrSpecs(el: Element, schema: MLMLSpec): readonly import("../types/index.js").Attribute[] | null;
@@ -1,4 +1,13 @@
1
1
  import { getAttrSpecs as _getAttrSpecs } from './get-attr-specs-spec.js';
2
+ /**
3
+ * Retrieves the attribute specifications for a DOM element by resolving its
4
+ * local name and namespace URI from the provided schema. This is a convenience
5
+ * wrapper around the spec-based `getAttrSpecs` that accepts a DOM element directly.
6
+ *
7
+ * @param el - The DOM element whose attribute specifications to retrieve
8
+ * @param schema - The full markup language specification containing attribute definitions
9
+ * @returns The array of attribute specifications for the element, or null if no spec exists
10
+ */
2
11
  export function getAttrSpecs(
3
12
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
4
13
  el, schema) {
@@ -1,2 +1,9 @@
1
1
  import type { Namespace } from '@markuplint/ml-ast';
2
+ /**
3
+ * Maps a full namespace URI string to its shorthand `Namespace` identifier.
4
+ * Returns `'html'` as the default for any unrecognized or null namespace.
5
+ *
6
+ * @param namespaceURI - The full namespace URI, or null
7
+ * @returns The shorthand namespace identifier (`'html'`, `'svg'`, `'mml'`, or `'xlink'`)
8
+ */
2
9
  export declare function getNS(namespaceURI: string | null): Namespace;
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Maps a full namespace URI string to its shorthand `Namespace` identifier.
3
+ * Returns `'html'` as the default for any unrecognized or null namespace.
4
+ *
5
+ * @param namespaceURI - The full namespace URI, or null
6
+ * @returns The shorthand namespace identifier (`'html'`, `'svg'`, `'mml'`, or `'xlink'`)
7
+ */
1
8
  export function getNS(namespaceURI) {
2
9
  switch (namespaceURI) {
3
10
  case 'http://www.w3.org/2000/svg': {
@@ -1,2 +1,13 @@
1
1
  import type { ElementSpec } from '../types/index.js';
2
- export declare function getSpecByTagName<K extends keyof ElementSpec = keyof ElementSpec>(specs: readonly Pick<ElementSpec, 'name' | K>[], localName: string, namespace: string | null): Pick<ElementSpec, "name" | K> | null;
2
+ /**
3
+ * Looks up an element specification by its local tag name and namespace. The tag name
4
+ * is resolved to a namespace-qualified form (e.g., `"svg:circle"`) before searching.
5
+ * Results are cached by the namespace-qualified name for subsequent lookups.
6
+ *
7
+ * @template K - The keys of `ElementSpec` to include in the returned spec object (defaults to all keys)
8
+ * @param specs - The array of element specifications to search
9
+ * @param localName - The local tag name of the element
10
+ * @param namespace - The namespace URI string, or null for HTML namespace
11
+ * @returns The matching element specification, or null if not found
12
+ */
13
+ export declare function getSpecByTagName<K extends keyof ElementSpec = keyof ElementSpec>(specs: readonly Pick<ElementSpec, 'name' | K>[], localName: string, namespace: string | null): Pick<ElementSpec, K | "name"> | null;
@@ -1,5 +1,16 @@
1
1
  import { resolveNamespace } from './resolve-namespace.js';
2
2
  const cache = new Map();
3
+ /**
4
+ * Looks up an element specification by its local tag name and namespace. The tag name
5
+ * is resolved to a namespace-qualified form (e.g., `"svg:circle"`) before searching.
6
+ * Results are cached by the namespace-qualified name for subsequent lookups.
7
+ *
8
+ * @template K - The keys of `ElementSpec` to include in the returned spec object (defaults to all keys)
9
+ * @param specs - The array of element specifications to search
10
+ * @param localName - The local tag name of the element
11
+ * @param namespace - The namespace URI string, or null for HTML namespace
12
+ * @returns The matching element specification, or null if not found
13
+ */
3
14
  export function getSpecByTagName(specs, localName, namespace) {
4
15
  const { localNameWithNS } = resolveNamespace(localName, namespace ?? undefined);
5
16
  let spec = cache.get(localNameWithNS);
@@ -1,2 +1,12 @@
1
1
  import type { ElementSpec } from '../types/index.js';
2
- export declare function getSpec<K extends keyof ElementSpec>(el: Element, specs: readonly Pick<ElementSpec, 'name' | K>[]): Pick<ElementSpec, "name" | K> | null;
2
+ /**
3
+ * Retrieves the element specification for a DOM element by looking up its local name
4
+ * and namespace URI in the provided specs array. This is a convenience wrapper around
5
+ * `getSpecByTagName` that accepts a DOM element directly.
6
+ *
7
+ * @template K - The keys of `ElementSpec` to include in the returned spec object
8
+ * @param el - The DOM element to look up
9
+ * @param specs - The array of element specifications to search
10
+ * @returns The matching element specification, or null if not found
11
+ */
12
+ export declare function getSpec<K extends keyof ElementSpec>(el: Element, specs: readonly Pick<ElementSpec, 'name' | K>[]): Pick<ElementSpec, K | "name"> | null;
@@ -1,4 +1,14 @@
1
1
  import { getSpecByTagName } from './get-spec-by-tag-name.js';
2
+ /**
3
+ * Retrieves the element specification for a DOM element by looking up its local name
4
+ * and namespace URI in the provided specs array. This is a convenience wrapper around
5
+ * `getSpecByTagName` that accepts a DOM element directly.
6
+ *
7
+ * @template K - The keys of `ElementSpec` to include in the returned spec object
8
+ * @param el - The DOM element to look up
9
+ * @param specs - The array of element specifications to search
10
+ * @returns The matching element specification, or null if not found
11
+ */
2
12
  export function getSpec(
3
13
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
4
14
  el, specs) {
@@ -1,5 +1,15 @@
1
1
  type NamedDefinition = string | {
2
2
  readonly name: string;
3
3
  };
4
+ /**
5
+ * Merges two arrays of named definitions by name, with items from `b` overriding
6
+ * matching items in `a`. When both items are objects, their properties are merged;
7
+ * when the overriding item is a string, the existing item is kept as-is.
8
+ *
9
+ * @template T - A named definition type (string or object with a `name` property)
10
+ * @param a - The base array of named definitions
11
+ * @param b - The array of named definitions to merge in, or null/undefined to skip
12
+ * @returns A new array with items from `b` merged into `a` by name
13
+ */
4
14
  export declare function mergeArray<T extends NamedDefinition>(a: readonly T[], b: readonly T[] | null | undefined): readonly T[];
5
15
  export {};
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Merges two arrays of named definitions by name, with items from `b` overriding
3
+ * matching items in `a`. When both items are objects, their properties are merged;
4
+ * when the overriding item is a string, the existing item is kept as-is.
5
+ *
6
+ * @template T - A named definition type (string or object with a `name` property)
7
+ * @param a - The base array of named definitions
8
+ * @param b - The array of named definitions to merge in, or null/undefined to skip
9
+ * @returns A new array with items from `b` merged into `a` by name
10
+ */
1
11
  export function mergeArray(a, b) {
2
12
  if (!b) {
3
13
  return a;
@@ -1,9 +1,22 @@
1
1
  import type { NamespaceURI, Namespace } from '@markuplint/ml-ast';
2
+ /**
3
+ * Represents a fully resolved element name with its namespace information.
4
+ */
2
5
  type NamespacedElementName = {
3
6
  localNameWithNS: string;
4
7
  localName: string;
5
8
  namespace: Namespace;
6
9
  namespaceURI: NamespaceURI;
7
10
  };
11
+ /**
12
+ * Resolves an element name and namespace URI into a normalized form containing
13
+ * the namespace-qualified name, bare local name, namespace shorthand, and full
14
+ * namespace URI. Handles explicit namespace prefixes (e.g., `"svg:circle"`) and
15
+ * falls back to HTML namespace when not specified. Results are cached.
16
+ *
17
+ * @param name - The element name, optionally prefixed with a namespace (e.g., `"svg:circle"` or `"div"`)
18
+ * @param namespaceURI - The namespace URI string, or null (defaults to XHTML namespace)
19
+ * @returns The resolved namespace information including qualified name, local name, namespace shorthand, and full URI
20
+ */
8
21
  export declare function resolveNamespace(name: string, namespaceURI?: string | null): NamespacedElementName;
9
22
  export {};
@@ -6,6 +6,16 @@ const namespaceURIMap = {
6
6
  mml: 'http://www.w3.org/1998/Math/MathML',
7
7
  xlink: 'http://www.w3.org/1999/xlink',
8
8
  };
9
+ /**
10
+ * Resolves an element name and namespace URI into a normalized form containing
11
+ * the namespace-qualified name, bare local name, namespace shorthand, and full
12
+ * namespace URI. Handles explicit namespace prefixes (e.g., `"svg:circle"`) and
13
+ * falls back to HTML namespace when not specified. Results are cached.
14
+ *
15
+ * @param name - The element name, optionally prefixed with a namespace (e.g., `"svg:circle"` or `"div"`)
16
+ * @param namespaceURI - The namespace URI string, or null (defaults to XHTML namespace)
17
+ * @returns The resolved namespace information including qualified name, local name, namespace shorthand, and full URI
18
+ */
9
19
  export function resolveNamespace(name, namespaceURI = 'http://www.w3.org/1999/xhtml') {
10
20
  const cached = cache.get(name + namespaceURI);
11
21
  if (cached) {
@@ -1,4 +1,15 @@
1
1
  import type { ARIA } from '../types/aria.js';
2
2
  import type { ARIAVersion } from '../types/index.js';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
+ /**
5
+ * Resolves an element's ARIA specification by merging version-specific overrides
6
+ * on top of the base properties. For each ARIA property (implicitRole, permittedRoles,
7
+ * etc.), the version-specific value takes precedence over the base value.
8
+ * `namingProhibited` is special-cased: ARIA 1.1 always uses the base value since
9
+ * `namingProhibited` was introduced in ARIA 1.2.
10
+ *
11
+ * @param aria - The element's full ARIA specification including version-specific blocks
12
+ * @param version - The ARIA specification version to resolve for
13
+ * @returns The resolved ARIA specification with version-specific overrides applied
14
+ */
4
15
  export declare function resolveVersion(aria: ReadonlyDeep<ARIA>, version: ARIAVersion): Omit<ReadonlyDeep<ARIA>, ARIAVersion>;
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Resolves an element's ARIA specification by merging version-specific overrides
3
+ * on top of the base properties. For each ARIA property (implicitRole, permittedRoles,
4
+ * etc.), the version-specific value takes precedence over the base value.
5
+ * `namingProhibited` is special-cased: ARIA 1.1 always uses the base value since
6
+ * `namingProhibited` was introduced in ARIA 1.2.
7
+ *
8
+ * @param aria - The element's full ARIA specification including version-specific blocks
9
+ * @param version - The ARIA specification version to resolve for
10
+ * @returns The resolved ARIA specification with version-specific overrides applied
11
+ */
1
12
  export function resolveVersion(aria, version) {
2
13
  const implicitRole = aria[version]?.implicitRole ?? aria.implicitRole;
3
14
  const permittedRoles = aria[version]?.permittedRoles ?? aria.permittedRoles;
@@ -1,13 +1,18 @@
1
1
  import type { ElementSpec, ExtendedSpec, MLMLSpec } from '../types/index.js';
2
2
  /**
3
- * Merging HTML-spec schema and extended spec schemas
3
+ * Merges an HTML-spec schema with zero or more extended spec schemas into a single
4
+ * unified specification. Extended specs can add or override global attributes,
5
+ * ARIA definitions, content models, and element specifications.
4
6
  *
5
7
  * Ex: `@markuplint/html-spec` + `{ specs: { "\\.vue$": "@markuplint/vue-spec" } }` in configure files.
6
8
  *
7
- * @param schemas `MLDocument.schemas`
9
+ * @param schemas - A tuple where the first element is the base `MLMLSpec` and subsequent elements are extended specs to merge
10
+ * @returns The merged specification combining the base spec with all extensions
8
11
  */
9
12
  export declare function schemaToSpec(schemas: readonly [MLMLSpec, ...ExtendedSpec[]]): {
10
13
  cites: import("../types/index.js").Cites;
11
14
  def: import("../types/index.js").SpecDefs;
12
15
  specs: readonly ElementSpec[];
16
+ directivePatterns?: readonly import("../types/index.js").DirectivePattern[];
17
+ useIDLAttributeNames?: boolean;
13
18
  };
@@ -1,10 +1,13 @@
1
1
  import { mergeArray } from './merge-array.js';
2
2
  /**
3
- * Merging HTML-spec schema and extended spec schemas
3
+ * Merges an HTML-spec schema with zero or more extended spec schemas into a single
4
+ * unified specification. Extended specs can add or override global attributes,
5
+ * ARIA definitions, content models, and element specifications.
4
6
  *
5
7
  * Ex: `@markuplint/html-spec` + `{ specs: { "\\.vue$": "@markuplint/vue-spec" } }` in configure files.
6
8
  *
7
- * @param schemas `MLDocument.schemas`
9
+ * @param schemas - A tuple where the first element is the base `MLMLSpec` and subsequent elements are extended specs to merge
10
+ * @returns The merged specification combining the base spec with all extensions
8
11
  */
9
12
  export function schemaToSpec(schemas) {
10
13
  const [main, ...extendedSpecs] = schemas;
@@ -16,10 +19,12 @@ export function schemaToSpec(schemas) {
16
19
  if (extendedSpec.def) {
17
20
  const def = { ...result.def };
18
21
  if (extendedSpec.def['#globalAttrs']?.['#extends']) {
19
- const gAttrs = { ...def['#globalAttrs'] };
20
- gAttrs['#HTMLGlobalAttrs'] = {
21
- ...def['#globalAttrs']?.['#HTMLGlobalAttrs'],
22
- ...extendedSpec.def['#globalAttrs']?.['#extends'],
22
+ const gAttrs = {
23
+ ...def['#globalAttrs'],
24
+ '#HTMLGlobalAttrs': {
25
+ ...def['#globalAttrs']?.['#HTMLGlobalAttrs'],
26
+ ...extendedSpec.def['#globalAttrs']?.['#extends'],
27
+ },
23
28
  };
24
29
  def['#globalAttrs'] = gAttrs;
25
30
  }
@@ -29,16 +34,19 @@ export function schemaToSpec(schemas) {
29
34
  roles: mergeArray(def['#aria']['1.1'].roles, extendedSpec.def['#aria']['1.1'].roles),
30
35
  props: mergeArray(def['#aria']['1.1'].props, extendedSpec.def['#aria']['1.1'].props),
31
36
  graphicsRoles: mergeArray(def['#aria']['1.1'].graphicsRoles, extendedSpec.def['#aria']['1.1'].graphicsRoles),
37
+ dpubRoles: mergeArray(def['#aria']['1.1'].dpubRoles, extendedSpec.def['#aria']['1.1'].dpubRoles),
32
38
  },
33
39
  '1.2': {
34
40
  roles: mergeArray(def['#aria']['1.2'].roles, extendedSpec.def['#aria']['1.2'].roles),
35
41
  props: mergeArray(def['#aria']['1.2'].props, extendedSpec.def['#aria']['1.2'].props),
36
42
  graphicsRoles: mergeArray(def['#aria']['1.2'].graphicsRoles, extendedSpec.def['#aria']['1.2'].graphicsRoles),
43
+ dpubRoles: mergeArray(def['#aria']['1.2'].dpubRoles, extendedSpec.def['#aria']['1.2'].dpubRoles),
37
44
  },
38
45
  '1.3': {
39
46
  roles: mergeArray(def['#aria']['1.3'].roles, extendedSpec.def['#aria']['1.3'].roles),
40
47
  props: mergeArray(def['#aria']['1.3'].props, extendedSpec.def['#aria']['1.3'].props),
41
48
  graphicsRoles: mergeArray(def['#aria']['1.3'].graphicsRoles, extendedSpec.def['#aria']['1.3'].graphicsRoles),
49
+ dpubRoles: mergeArray(def['#aria']['1.3'].dpubRoles, extendedSpec.def['#aria']['1.3'].dpubRoles),
42
50
  },
43
51
  };
44
52
  }
@@ -57,6 +65,12 @@ export function schemaToSpec(schemas) {
57
65
  }
58
66
  result.def = def;
59
67
  }
68
+ if (extendedSpec.directivePatterns) {
69
+ result.directivePatterns = [...(result.directivePatterns ?? []), ...extendedSpec.directivePatterns];
70
+ }
71
+ if (extendedSpec.useIDLAttributeNames != null) {
72
+ result.useIDLAttributeNames = extendedSpec.useIDLAttributeNames;
73
+ }
60
74
  if (extendedSpec.specs) {
61
75
  const exSpecs = [...extendedSpec.specs];
62
76
  const specs = [];
@@ -1,2 +1,9 @@
1
1
  import type { ARIAVersion } from '../types/index.js';
2
+ /**
3
+ * Validates whether a string is a supported ARIA specification version.
4
+ * Acts as a type guard, narrowing the input to the `ARIAVersion` type when `true`.
5
+ *
6
+ * @param version - The version string to validate
7
+ * @returns `true` if the version is a supported ARIA version (e.g., '1.1', '1.2', '1.3')
8
+ */
2
9
  export declare function validateAriaVersion(version: string): version is ARIAVersion;
@@ -1,4 +1,11 @@
1
1
  import { ariaVersions } from './aria-version.js';
2
+ /**
3
+ * Validates whether a string is a supported ARIA specification version.
4
+ * Acts as a type guard, narrowing the input to the `ARIAVersion` type when `true`.
5
+ *
6
+ * @param version - The version string to validate
7
+ * @returns `true` if the version is a supported ARIA version (e.g., '1.1', '1.2', '1.3')
8
+ */
2
9
  export function validateAriaVersion(version) {
3
10
  return ariaVersions.includes(version);
4
11
  }
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@markuplint/ml-spec",
3
- "version": "4.10.1",
3
+ "version": "5.0.0-alpha.0",
4
4
  "description": "Types and schema that specs of the Markup languages for markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
7
7
  "license": "MIT",
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
8
11
  "type": "module",
9
12
  "exports": {
10
13
  ".": {
@@ -31,15 +34,14 @@
31
34
  "schema:prettier": "npx prettier --write \"./schemas/*.json\" \"./src/types/*.ts\" --log-level warn"
32
35
  },
33
36
  "dependencies": {
34
- "@markuplint/ml-ast": "4.4.10",
35
- "@markuplint/types": "4.8.1",
36
- "dom-accessibility-api": "0.7.0",
37
+ "@markuplint/ml-ast": "5.0.0-alpha.0",
38
+ "@markuplint/types": "5.0.0-alpha.0",
37
39
  "is-plain-object": "5.0.0",
38
- "type-fest": "4.41.0"
40
+ "type-fest": "5.4.4"
39
41
  },
40
42
  "devDependencies": {
41
- "@markuplint/test-tools": "4.5.22",
43
+ "@markuplint/test-tools": "5.0.0-alpha.0",
42
44
  "json-schema-to-typescript": "15.0.4"
43
45
  },
44
- "gitHead": "6213ea30269ef404f030e67bbcc7fc7443ec1060"
46
+ "gitHead": "13dcfc84ec83d87360c720e253383b60767e1b56"
45
47
  }