@markuplint/ml-spec 5.0.0-rc.2 → 5.0.0-rc.5

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 (41) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +0 -8
  3. package/lib/algorithm/aria/accname/aria-steps.d.ts +0 -24
  4. package/lib/algorithm/aria/accname/aria-steps.js +0 -24
  5. package/lib/algorithm/aria/accname/compute.d.ts +0 -10
  6. package/lib/algorithm/aria/accname/compute.js +0 -10
  7. package/lib/algorithm/aria/accname/element-names.d.ts +0 -23
  8. package/lib/algorithm/aria/accname/element-names.js +0 -23
  9. package/lib/algorithm/aria/accname/helpers.d.ts +2 -64
  10. package/lib/algorithm/aria/accname/helpers.js +2 -72
  11. package/lib/algorithm/aria/accname/label-steps.d.ts +2 -18
  12. package/lib/algorithm/aria/accname/label-steps.js +5 -21
  13. package/lib/algorithm/aria/accname/types.d.ts +0 -3
  14. package/lib/algorithm/aria/get-explicit-role.d.ts +1 -8
  15. package/lib/algorithm/aria/get-explicit-role.js +1 -8
  16. package/lib/algorithm/aria/get-non-presentational-ancestor.d.ts +2 -10
  17. package/lib/algorithm/aria/get-non-presentational-ancestor.js +2 -10
  18. package/lib/algorithm/aria/get-permitted-roles-spec.js +1 -0
  19. package/lib/algorithm/aria/matches-context-role.d.ts +3 -10
  20. package/lib/algorithm/aria/matches-context-role.js +3 -10
  21. package/lib/algorithm/html/content-model-category-to-tag-names.d.ts +5 -0
  22. package/lib/algorithm/html/content-model-category-to-tag-names.js +5 -0
  23. package/lib/index.d.ts +28 -0
  24. package/lib/index.js +28 -0
  25. package/lib/types/index.d.ts +35 -4
  26. package/lib/utils/schema-to-spec.d.ts +10 -0
  27. package/lib/utils/schema-to-spec.js +10 -0
  28. package/package.json +7 -7
  29. package/ARCHITECTURE.ja.md +0 -267
  30. package/ARCHITECTURE.md +0 -267
  31. package/SKILL.md +0 -116
  32. package/docs/aria-algorithms.ja.md +0 -802
  33. package/docs/aria-algorithms.md +0 -804
  34. package/docs/html-algorithms.ja.md +0 -469
  35. package/docs/html-algorithms.md +0 -469
  36. package/docs/maintenance.ja.md +0 -359
  37. package/docs/maintenance.md +0 -359
  38. package/docs/spec-resolution.ja.md +0 -575
  39. package/docs/spec-resolution.md +0 -588
  40. package/docs/type-definitions.ja.md +0 -584
  41. package/docs/type-definitions.md +0 -584
@@ -1,584 +0,0 @@
1
- # Type Definitions Reference
2
-
3
- This document describes the type definitions and JSON schemas used by `@markuplint/ml-spec`.
4
-
5
- ## Overview
6
-
7
- `@markuplint/ml-spec` employs a two-layer type system:
8
-
9
- 1. **Hand-written types** in `src/types/index.ts` -- define the runtime interfaces used throughout markuplint for element specs, ARIA roles, attributes, and role computation results.
10
- 2. **Generated types** from JSON schemas -- define schema-validated structures that are auto-generated from `.schema.json` files using `json-schema-to-typescript`. These files carry "DO NOT MODIFY" headers.
11
-
12
- Hand-written types import and extend generated types where needed (for example, `Attribute` extends `AttributeJSON`), creating a clean separation between the schema-validated data layer and the runtime API layer.
13
-
14
- ## Core Specification Types
15
-
16
- These types are defined in `src/types/index.ts` and form the backbone of markuplint's spec system.
17
-
18
- ### `MLMLSpec`
19
-
20
- The root specification type representing a complete markup language spec.
21
-
22
- ```ts
23
- interface MLMLSpec {
24
- readonly cites: Cites; // Reference URLs (readonly string[])
25
- readonly def: SpecDefs; // Internal definitions (global attrs, ARIA, content models)
26
- readonly specs: readonly ElementSpec[]; // Element specifications array
27
- }
28
- ```
29
-
30
- ### `ExtendedSpec`
31
-
32
- A partial specification used by framework-specific packages to extend or customize the base spec. Used by `@markuplint/vue-spec`, `@markuplint/react-spec`, and similar packages.
33
-
34
- ```ts
35
- type ExtendedSpec = {
36
- readonly cites?: Cites;
37
- readonly def?: Partial<SpecDefs>;
38
- readonly specs?: readonly ExtendedElementSpec[];
39
- };
40
- ```
41
-
42
- `ExtendedElementSpec` is a partial version of `ElementSpec` where only `name` is required. All other properties are optional overrides. Attributes use `Partial<Attribute>` to allow specifying only changed fields:
43
-
44
- ```ts
45
- type ExtendedElementSpec = Partial<Omit<ElementSpec, 'name' | 'attributes'>> & {
46
- readonly name: ElementSpec['name'];
47
- readonly attributes?: Readonly<Record<string, Partial<Attribute>>>;
48
- };
49
- ```
50
-
51
- ### `SpecDefs`
52
-
53
- Internal definition data within a markup language spec, containing global attributes, ARIA role/property definitions, and content model category mappings.
54
-
55
- ```ts
56
- type SpecDefs = {
57
- readonly '#globalAttrs': {
58
- readonly [category: string]: Readonly<Record<string, Partial<Attribute>>>;
59
- };
60
- readonly '#aria': {
61
- readonly '1.3': ARIASpec;
62
- readonly '1.2': ARIASpec;
63
- readonly '1.1': ARIASpec;
64
- };
65
- readonly '#contentModels': {
66
- readonly [model in Category]?: readonly string[];
67
- };
68
- };
69
- ```
70
-
71
- - **`#globalAttrs`** -- Category-keyed attribute definitions. Each category (e.g., `#HTMLGlobalAttrs`, `#ARIAAttrs`) maps to a record of partial attribute definitions.
72
- - **`#aria`** -- ARIA role/property definitions for each specification version (1.1, 1.2, 1.3). Each version contains `roles`, `graphicsRoles`, `dpubRoles`, and `props` arrays.
73
- - **`#contentModels`** -- Content model category to selector array mappings. Maps `Category` values (like `#flow`, `#phrasing`) to arrays of CSS selectors that match elements belonging to that category.
74
-
75
- ### `ElementSpec`
76
-
77
- A complete element specification describing all aspects of a single HTML or SVG element.
78
-
79
- ```ts
80
- type ElementSpec = {
81
- readonly name: string; // Tag name
82
- readonly namespace?: NamespaceURI; // XML namespace URI
83
- readonly cite: string; // Reference URL
84
- readonly description?: string; // Human-readable description
85
-
86
- // Status flags
87
- readonly experimental?: true; // Experimental technology
88
- readonly obsolete?: true | { readonly alt: string }; // Obsolete (optionally with alternative)
89
- readonly deprecated?: true; // Deprecated
90
- readonly nonStandard?: true; // Non-standard
91
-
92
- // Structural properties
93
- readonly categories: readonly Category[]; // Element categories
94
- readonly contentModel: ReadonlyDeep<ContentModel>; // Permitted content patterns
95
- readonly omission: ElementSpecOmission; // Tag omission rules
96
-
97
- // Attributes and ARIA
98
- readonly globalAttrs: ReadonlyDeep<GlobalAttributes>; // Global attribute selection
99
- readonly attributes: Readonly<Record<string, Attribute>>; // Element-specific attributes
100
- readonly aria: ReadonlyDeep<ARIA>; // WAI-ARIA role and property mappings
101
-
102
- // Template engine support
103
- readonly possibleToAddProperties?: true; // Allow arbitrary properties (for template engines)
104
- };
105
- ```
106
-
107
- `ElementSpecOmission` is either `false` (no omission allowed) or an object with `startTag` and `endTag` fields indicating whether tag omission is permitted.
108
-
109
- ### `Attribute`
110
-
111
- Describes a single HTML/SVG attribute with its type, description, and status flags.
112
-
113
- ```ts
114
- type Attribute = {
115
- readonly name: string;
116
- readonly type:
117
- | ReadonlyDeep<AttributeType>
118
- | readonly ReadonlyDeep<AttributeType>[]
119
- | readonly ReadonlyDeep<ConditionalAttributeType>[];
120
- readonly description?: string;
121
- readonly caseSensitive?: true;
122
- readonly experimental?: boolean;
123
- readonly obsolete?: true;
124
- readonly deprecated?: boolean;
125
- readonly nonStandard?: true;
126
- } & ExtendableAttributeSpec;
127
- ```
128
-
129
- The `& ExtendableAttributeSpec` intersection adds fields from the generated `AttributeJSON` type (excluding `type`, which is overridden with the `ReadonlyDeep` wrapper): `defaultValue`, `required`, `requiredEither`, `noUse`, `condition`, `ineffective`, `animatable`.
130
-
131
- The `type` union includes `readonly ReadonlyDeep<ConditionalAttributeType>[]` for attributes whose value type depends on another attribute's value (see [`ConditionalAttributeType`](#from-attributesschemajson----srctypesattributests) below). This variant is shipped type-only in v5.0 (#3685); follow-ups #3598 and #3189 implement the runtime resolution.
132
-
133
- ## ARIA Types
134
-
135
- ### `ARIARole`
136
-
137
- A fully resolved ARIA role with all its properties, requirements, and naming constraints.
138
-
139
- ```ts
140
- type ARIARole = {
141
- readonly name: string; // Role name (e.g., 'button', 'navigation')
142
- readonly isAbstract: boolean; // Whether this is an abstract role
143
- readonly deprecated: boolean; // Whether this role is deprecated
144
-
145
- // Context requirements (ARIA 1.3 names)
146
- readonly requiredAccessibilityParentRole: readonly string[];
147
- readonly allowedAccessibilityChildRoles: readonly string[];
148
-
149
- // Backward compatibility (ARIA 1.2 names, deprecated)
150
- readonly requiredContextRole: readonly string[]; // @deprecated
151
- readonly requiredOwnedElements: readonly string[]; // @deprecated
152
-
153
- // Accessible name constraints
154
- readonly accessibleNameRequired: boolean; // Must have an accessible name
155
- readonly accessibleNameFromAuthor: boolean; // Name can come from author (aria-label, etc.)
156
- readonly accessibleNameFromContent: boolean; // Name can come from element content
157
- readonly accessibleNameProhibited: boolean; // Name is prohibited
158
-
159
- // Properties
160
- readonly childrenPresentational: boolean; // Children are presentational
161
- readonly ownedProperties: readonly ARIARoleOwnedProperties[];
162
- readonly prohibitedProperties: readonly string[];
163
- };
164
- ```
165
-
166
- ### `ARIARoleInSchema`
167
-
168
- An ARIA role as defined in the raw schema data. All properties are optional except `name`, since the schema may provide only partial role information. Also includes optional `description` and `generalization` (super-class roles) fields.
169
-
170
- ```ts
171
- type ARIARoleInSchema = Partial<
172
- ARIARole & {
173
- readonly description: string;
174
- readonly generalization: readonly string[];
175
- }
176
- > & {
177
- readonly name: string;
178
- };
179
- ```
180
-
181
- ### `ARIARoleOwnedProperties`
182
-
183
- Describes a property owned by an ARIA role, including whether it is inherited, required, or deprecated.
184
-
185
- ```ts
186
- type ARIARoleOwnedProperties = {
187
- readonly name: string; // Property name (e.g., 'aria-expanded')
188
- readonly inherited?: true; // Inherited from a superclass role
189
- readonly required?: true; // Required for this role
190
- readonly deprecated?: true; // Deprecated for this role
191
- };
192
- ```
193
-
194
- ### `ARIAProperty`
195
-
196
- Describes an ARIA property or state, including its value type, enumeration values, and equivalent HTML attributes.
197
-
198
- ```ts
199
- type ARIAProperty = {
200
- readonly name: string; // Property name (e.g., 'aria-hidden')
201
- readonly type: 'property' | 'state'; // Whether this is a property or state
202
- readonly deprecated?: true;
203
- readonly isGlobal?: true; // Whether this is a global ARIA attribute
204
- readonly value: ARIAAttributeValue; // Value type
205
- readonly conditionalValue?: readonly {
206
- // Role-specific value overrides
207
- readonly role: readonly string[];
208
- readonly value: ARIAAttributeValue;
209
- }[];
210
- readonly enum: readonly string[]; // Allowed token values
211
- readonly defaultValue?: string;
212
- readonly equivalentHtmlAttrs?: readonly EquivalentHtmlAttr[];
213
- readonly valueDescriptions?: Readonly<Record<string, string>>;
214
- };
215
- ```
216
-
217
- ### `ARIAAttributeValue`
218
-
219
- The possible value types for ARIA attributes, as defined by the WAI-ARIA specification.
220
-
221
- ```ts
222
- type ARIAAttributeValue =
223
- | 'true/false'
224
- | 'tristate'
225
- | 'true/false/undefined'
226
- | 'ID reference'
227
- | 'ID reference list'
228
- | 'integer'
229
- | 'number'
230
- | 'string'
231
- | 'token'
232
- | 'token list'
233
- | 'URI';
234
- ```
235
-
236
- ### `ARIAVersion`
237
-
238
- A union type of supported ARIA specification version strings, derived from the `ariaVersions` tuple (`['1.1', '1.2', '1.3'] as const`).
239
-
240
- ```ts
241
- type ARIAVersion = '1.1' | '1.2' | '1.3';
242
- ```
243
-
244
- The recommended default version is `'1.3'` (defined as `ARIA_RECOMMENDED_VERSION` in `src/utils/aria-version.ts`).
245
-
246
- ### `ComputedRole`
247
-
248
- The result of computing an element's ARIA role.
249
-
250
- ```ts
251
- type ComputedRole = {
252
- readonly el: Element;
253
- readonly role:
254
- | (ARIARole & {
255
- readonly superClassRoles: readonly ARIARoleInSchema[];
256
- readonly isImplicit?: boolean;
257
- })
258
- | null;
259
- readonly errorType?: RoleComputationError;
260
- };
261
- ```
262
-
263
- - **`el`** -- The DOM element reference.
264
- - **`role`** -- The resolved role (with super-class chain and implicit flag), or `null` if no role applies.
265
- - **`errorType`** -- Optional error code indicating issues during role computation.
266
-
267
- ### `RoleComputationError`
268
-
269
- Error codes that may arise during ARIA role computation, indicating specific issues such as abstract roles, invalid context, or presentational conflicts.
270
-
271
- | Error Code | Description |
272
- | --------------------------------------------------- | ------------------------------------------------------------------------ |
273
- | `ABSTRACT` | An abstract role was assigned (abstract roles must not be used directly) |
274
- | `GLOBAL_PROP_MUST_NOT_BE_PRESENTATIONAL` | Element with global ARIA properties must not be presentational |
275
- | `IMPLICIT_ROLE_NAMESPACE_ERROR` | Implicit role does not match the element's namespace |
276
- | `INTERACTIVE_ELEMENT_MUST_NOT_BE_PRESENTATIONAL` | Interactive element must not be presentational |
277
- | `INVALID_LANDMARK` | Invalid landmark role usage |
278
- | `INVALID_REQUIRED_CONTEXT_ROLE` | Required context role is not satisfied |
279
- | `NO_EXPLICIT` | No explicit role was assigned |
280
- | `NO_OWNER` | No owning element found for required context |
281
- | `NO_PERMITTED` | The role is not permitted on this element |
282
- | `REQUIRED_OWNED_ELEMENT_MUST_NOT_BE_PRESENTATIONAL` | Required owned element must not be presentational |
283
- | `ROLE_NO_EXISTS` | The specified role does not exist |
284
-
285
- ## Utility Types
286
-
287
- ### `Matches`
288
-
289
- A function type that tests whether an element matches a given CSS selector string. Typically bound to `Element.prototype.matches`.
290
-
291
- ```ts
292
- type Matches = (selector: string) => boolean;
293
- ```
294
-
295
- ### `Cites`
296
-
297
- Reference URL array type used throughout the spec.
298
-
299
- ```ts
300
- type Cites = readonly string[];
301
- ```
302
-
303
- ### `EquivalentHtmlAttr`
304
-
305
- Describes an HTML attribute that is semantically equivalent to an ARIA property, enabling automatic mapping from HTML attributes to ARIA states/properties.
306
-
307
- ```ts
308
- type EquivalentHtmlAttr = {
309
- readonly htmlAttrName: string;
310
- readonly isNotStrictEquivalent?: true;
311
- readonly value: string | null;
312
- };
313
- ```
314
-
315
- ## Generated Types
316
-
317
- These types are automatically generated from JSON schema files by `json-schema-to-typescript`. They carry "DO NOT MODIFY" headers and should not be edited directly.
318
-
319
- ### From `aria.schema.json` -- `src/types/aria.ts`
320
-
321
- **`ARIA`** -- Element-level ARIA specification with conditions and version overrides.
322
-
323
- ```ts
324
- interface ARIA {
325
- implicitRole: ImplicitRole;
326
- permittedRoles: PermittedRoles;
327
- namingProhibited?: true;
328
- implicitProperties?: ImplicitProperties;
329
- properties?: PermittedARIAProperties;
330
- conditions?: {
331
- [selector: string]: {
332
- /* per-condition overrides */
333
- };
334
- };
335
- '1.3'?: {
336
- /* version-specific overrides */
337
- };
338
- '1.2'?: {
339
- /* version-specific overrides */
340
- };
341
- '1.1'?: {
342
- /* version-specific overrides */
343
- };
344
- }
345
- ```
346
-
347
- **`ImplicitRole`** -- The element's implicit (default) role.
348
-
349
- ```ts
350
- type ImplicitRole = false | string; // false means "No corresponding role"
351
- ```
352
-
353
- **`PermittedRoles`** -- Which roles are permitted on the element.
354
-
355
- ```ts
356
- type PermittedRoles =
357
- | boolean // true = "Any role", false = "No role"
358
- | (string | { name: string; deprecated?: true })[] // Specific role list
359
- | PermittedARIAAAMInfo; // AAM-delegated (core-aam or graphics-aam)
360
- ```
361
-
362
- **`PermittedARIAProperties`** -- ARIA property constraints for an element.
363
-
364
- ```ts
365
- type PermittedARIAProperties =
366
- | false // "No role or aria-* attributes"
367
- | {
368
- global?: true; // Allow global ARIA properties
369
- role?: true | string | [string, ...string[]]; // Properties applicable to allowed roles
370
- only?: [
371
- /* specific properties */
372
- ]; // Whitelist of allowed properties
373
- without?: [
374
- /* prohibited properties with severity */
375
- ]; // Blacklist with severity levels
376
- };
377
- ```
378
-
379
- **`ImplicitProperties`** -- Default ARIA property values (keys matching `^aria-.+`).
380
-
381
- ```ts
382
- interface ImplicitProperties {
383
- [ariaProperty: string]: string; // e.g., { 'aria-checked': 'false' }
384
- }
385
- ```
386
-
387
- ### From `attributes.schema.json` -- `src/types/attributes.ts`
388
-
389
- **`AttributeType`** -- A large union type covering all recognized attribute value types. Includes:
390
-
391
- - **CSS property names**: `<'color'>`, `<'display'>`, `<'font-size'>`, etc. (hundreds of standard, vendor-prefixed, and deprecated CSS properties)
392
- - **CSS value types**: `<color>`, `<length>`, `<number>`, `<url>`, `<integer>`, etc.
393
- - **SVG-specific types**: `<svg-path>`, `<view-box>`, `<preserve-aspect-ratio>`, etc.
394
- - **markuplint custom types**: `DOMID`, `URL`, `BCP47`, `MIMEType`, `DateTime`, `AutoComplete`, `Int`, `Uint`, `Number`, `Boolean`, `Any`, `JSON`, `FunctionBody`, etc.
395
- - **Structured type variants**: `List`, `Enum`, `Number`, `Directive`
396
-
397
- **`GlobalAttributes`** -- Attribute category selection specifying which global attribute categories apply to an element.
398
-
399
- ```ts
400
- interface GlobalAttributes {
401
- '#HTMLGlobalAttrs'?: boolean;
402
- '#GlobalEventAttrs'?: boolean | string[];
403
- '#HTMLLinkAndFetchingAttrs'?: string[];
404
- '#HTMLEmbededAndMediaContentAttrs'?: string[];
405
- '#HTMLFormControlElementAttrs'?: string[];
406
- '#HTMLTableCellElementAttrs'?: string[];
407
- '#ARIAAttrs'?: boolean;
408
- '#SVGAnimationAdditionAttrs'?: string[];
409
- '#SVGAnimationAttributeTargetAttrs'?: string[];
410
- '#SVGAnimationEventAttrs'?: string[];
411
- '#SVGAnimationTargetElementAttrs'?: string[];
412
- '#SVGAnimationTimingAttrs'?: string[];
413
- '#SVGAnimationValueAttrs'?: string[];
414
- '#SVGConditionalProcessingAttrs'?: string[];
415
- '#SVGCoreAttrs'?: string[];
416
- '#SVGFilterPrimitiveAttrs'?: string[];
417
- '#SVGPresentationAttrs'?: string[];
418
- '#SVGTransferFunctionAttrs'?: string[];
419
- '#XLinkAttrs'?: string[];
420
- }
421
- ```
422
-
423
- **`AttributeJSON`** -- Raw attribute definition with type, conditions, and flags.
424
-
425
- ```ts
426
- interface AttributeJSON {
427
- type?:
428
- | AttributeType
429
- | [AttributeType, ...AttributeType[]]
430
- | [ConditionalAttributeType, ...ConditionalAttributeType[]];
431
- defaultValue?: string;
432
- deprecated?: boolean;
433
- required?: boolean | AttributeCondition;
434
- requiredEither?: string[];
435
- noUse?: boolean;
436
- condition?: AttributeCondition;
437
- ineffective?: AttributeCondition;
438
- animatable?: boolean;
439
- experimental?: boolean;
440
- }
441
- ```
442
-
443
- **`ConditionalAttributeType`** -- Conditional type switching: declares that an attribute's expected value type depends on the value of _another_ attribute on the same element. Used when the spec states, for example, that `<input value>` must be a valid simple color when `type=color` but a valid URL when `type=url`, or that `<link as>` accepts different destination keywords depending on whether `rel` is `preload` or `modulepreload`.
444
-
445
- ```ts
446
- interface ConditionalAttributeType {
447
- condition: AttributeCondition; // CSS selector against the owning element
448
- type: AttributeType | [AttributeType, ...AttributeType[]];
449
- }
450
- ```
451
-
452
- > **Status:** The type definition shipped in v5.0 (#3685). Conditional resolution is fully implemented: `input[value]` by `type` in [#3598](https://github.com/markuplint/markuplint/issues/3598), `link[as]` by `rel` in [#3189](https://github.com/markuplint/markuplint/issues/3189). `isValidAttr()` in `helpers.ts` matches the element against each condition and validates against the resolved type; unmatched conditions fall back to `Any`. A safety-net guard in `attrCheck()` treats any remaining unresolved `ConditionalAttributeType[]` as valid for direct callers.
453
-
454
- **`List`** -- Structured type for space-separated or comma-separated token lists.
455
-
456
- ```ts
457
- interface List {
458
- token: string | Enum; // Token type or enum definition
459
- separator: 'space' | 'comma'; // Separator type
460
- disallowToSurroundBySpaces?: boolean;
461
- allowEmpty?: boolean;
462
- ordered?: boolean;
463
- unique?: boolean;
464
- caseInsensitive?: boolean;
465
- number?: ('zeroOrMore' | 'oneOrMore') | { min: number; max: number };
466
- }
467
- ```
468
-
469
- **`Enum`** -- Enumerated attribute values.
470
-
471
- ```ts
472
- interface Enum {
473
- enum: [string, ...string[]]; // At least one value required
474
- disallowToSurroundBySpaces?: boolean;
475
- caseInsensitive?: boolean;
476
- invalidValueDefault?: string; // Default when value is invalid
477
- missingValueDefault?: string; // Default when attribute is missing
478
- sameStates?: { [k: string]: unknown };
479
- }
480
- ```
481
-
482
- **`Number`** -- Numeric attribute constraints.
483
-
484
- ```ts
485
- interface Number {
486
- type: 'float' | 'integer';
487
- gt?: number; // Greater than
488
- gte?: number; // Greater than or equal
489
- lt?: number; // Less than
490
- lte?: number; // Less than or equal
491
- clampable?: boolean;
492
- }
493
- ```
494
-
495
- **`Directive`** -- Directive-based attribute validation for complex attributes containing both directives and tokens.
496
-
497
- ```ts
498
- interface Directive {
499
- directive: [string, ...string[]]; // At least one directive
500
- token: AttributeType; // Token type to validate
501
- ref?: string; // Reference URL
502
- }
503
- ```
504
-
505
- ### From `content-models.schema.json` -- `src/types/permitted-structures.ts`
506
-
507
- **`PermittedContentPattern`** -- A union of all content model pattern types.
508
-
509
- ```ts
510
- type PermittedContentPattern =
511
- | PermittedContentRequire // Required content
512
- | PermittedContentOptional // Optional content
513
- | PermittedContentOneOrMore // One or more occurrences
514
- | PermittedContentZeroOrMore // Zero or more occurrences
515
- | PermittedContentChoice // Choice between content alternatives
516
- | PermittedContentTransparent; // Transparent content model
517
- ```
518
-
519
- Each pattern variant (except `PermittedContentTransparent`) accepts either a `Model` or a nested `PermittedContentPattern[]` and supports an optional `max` count.
520
-
521
- **`ContentModel`** -- Complete content model for an element.
522
-
523
- ```ts
524
- interface ContentModel {
525
- contents: PermittedContentPattern[] | boolean; // Content patterns or boolean
526
- descendantOf?: string; // Context restriction
527
- conditional?: {
528
- // Condition-dependent content
529
- condition: string;
530
- contents: PermittedContentPattern[] | boolean;
531
- }[];
532
- }
533
- ```
534
-
535
- **`Category`** -- Content model category. Includes 13 HTML categories and 19 SVG categories.
536
-
537
- HTML categories:
538
-
539
- - `#text`, `#phrasing`, `#flow`, `#interactive`, `#heading`
540
- - `#sectioning`, `#metadata`, `#embedded`, `#palpable`, `#script-supporting`
541
-
542
- SVG categories:
543
-
544
- - `#SVGAnimation`, `#SVGBasicShapes`, `#SVGContainer`, `#SVGDescriptive`
545
- - `#SVGFilterPrimitive`, `#SVGFont`, `#SVGGradient`, `#SVGGraphics`
546
- - `#SVGGraphicsReferencing`, `#SVGLightSource`, `#SVGNeverRendered`
547
- - `#SVGNone`, `#SVGPaintServer`, `#SVGRenderable`, `#SVGShape`
548
- - `#SVGStructural`, `#SVGStructurallyExternal`, `#SVGTextContent`, `#SVGTextContentChild`
549
-
550
- **`Model`** and **`ContentType`**:
551
-
552
- ```ts
553
- type Model = ContentType | ContentType[];
554
- type ContentType = string | Category;
555
- ```
556
-
557
- ## JSON Schema Files
558
-
559
- The following JSON schema files are located in the `schemas/` directory.
560
-
561
- | Schema File | Lines | Description |
562
- | ------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------- |
563
- | `element.schema.json` | 11 | Top-level element schema combining `$ref` pointers to content models, attributes, global attributes, and ARIA |
564
- | `aria.schema.json` | 291 | ARIA role/property definitions including implicit roles, permitted roles, properties, and version overrides |
565
- | `attributes.schema.json` | 190 | Attribute type unions, attribute JSON definitions, global attribute category selection, and attribute name patterns |
566
- | `content-models.schema.json` | 215 | Content model patterns (require, optional, oneOrMore, zeroOrMore, choice, transparent) and category definitions |
567
- | `global-attributes.schema.json` | 787 | Global attribute categories for HTML and SVG (auto-generated from `gen/global-attribute.data.ts`) |
568
-
569
- ## Schema Generation Workflow
570
-
571
- The schema generation pipeline works as follows:
572
-
573
- 1. **`gen/global-attribute.data.ts`** defines the source-of-truth data for global attribute categories, listing all attribute names per category.
574
-
575
- 2. **`gen/gen.ts`** reads the global attribute data and generates two schema files:
576
- - `schemas/global-attributes.schema.json` -- The full global attributes schema with category definitions and per-category enums.
577
- - `schemas/attributes.schema.json` -- The attributes schema including `GlobalAttributes` type with category-specific property selectors.
578
-
579
- 3. **`json-schema-to-typescript`** converts each `.schema.json` file into corresponding TypeScript files:
580
- - `schemas/aria.schema.json` --> `src/types/aria.ts`
581
- - `schemas/attributes.schema.json` --> `src/types/attributes.ts`
582
- - `schemas/content-models.schema.json` --> `src/types/permitted-structures.ts`
583
-
584
- 4. Generated TypeScript files include "DO NOT MODIFY" headers. To update generated types, modify the source JSON schema (or the generation script for auto-generated schemas), then re-run the generation pipeline.