@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,359 +0,0 @@
1
- # Maintenance Guide
2
-
3
- ## Overview
4
-
5
- This guide covers the day-to-day operational and maintenance tasks for `@markuplint/ml-spec`. It focuses on schema generation, dependency management, testing, common recipes, and troubleshooting.
6
-
7
- ## Build and Development Commands
8
-
9
- | Command | Scope | Description |
10
- | ----------------------------------------------- | -------- | ---------------------------------------------------- |
11
- | `yarn build --scope @markuplint/ml-spec` | Package | Compile TypeScript to `lib/` |
12
- | `yarn workspace @markuplint/ml-spec run dev` | Package | Watch mode compilation |
13
- | `yarn workspace @markuplint/ml-spec run clean` | Package | Remove `lib/` output |
14
- | `yarn workspace @markuplint/ml-spec run schema` | Package | Regenerate schemas and types |
15
- | `yarn up:schema` | Monorepo | Regenerate schemas across all packages (recommended) |
16
- | `yarn test` | Monorepo | Run all tests via vitest |
17
-
18
- ## Schema Generation Pipeline
19
-
20
- ### Why schema generation exists
21
-
22
- The package uses JSON Schema files as a single source of truth for complex type structures (ARIA definitions, attribute types, content models, global attributes). TypeScript types are auto-generated from these schemas via `json-schema-to-typescript` (`json2ts`). This ensures that:
23
-
24
- - JSON data files consumed at runtime are validated against the same structure as TypeScript types.
25
- - Schema changes automatically propagate to type definitions.
26
- - The `@markuplint/html-spec` JSON data stays consistent with the type system.
27
-
28
- ### Generation flow
29
-
30
- ```
31
- gen/global-attribute.data.ts schemas/aria.schema.json
32
- │ schemas/content-models.schema.json
33
- ▼ │
34
- gen/gen.ts │
35
- │ │
36
- ▼ ▼
37
- schemas/global-attributes.schema.json │
38
- schemas/attributes.schema.json │
39
- │ │
40
- └──────────┬───────────────────┘
41
- ▼
42
- json-schema-to-typescript
43
- │
44
- ┌──────────┼──────────────┐
45
- ▼ ▼ ▼
46
- types/aria.ts types/ types/permitted-
47
- attributes.ts structures.ts
48
- │
49
- ▼
50
- prettier + eslint
51
- ```
52
-
53
- ### Script breakdown (`yarn workspace @markuplint/ml-spec run schema`)
54
-
55
- The `schema` script is a sequential pipeline using `run-s`:
56
-
57
- ```
58
- schema:json → schema:content-models → schema:attributes → schema:aria → schema:prettier → schema:eslint → schema:prettier
59
- ```
60
-
61
- | Step | Command | Input | Output |
62
- | ----------------------- | ---------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------- |
63
- | `schema:json` | `tsx ./gen/gen.ts` | `gen/global-attribute.data.ts` | `schemas/global-attributes.schema.json`, `schemas/attributes.schema.json` |
64
- | `schema:content-models` | `json2ts ./schemas/content-models.schema.json` | `schemas/content-models.schema.json` | `src/types/permitted-structures.ts` |
65
- | `schema:attributes` | `json2ts ./schemas/attributes.schema.json --cwd ./schemas` | `schemas/attributes.schema.json` | `src/types/attributes.ts` |
66
- | `schema:aria` | `json2ts ./schemas/aria.schema.json --cwd ./schemas` | `schemas/aria.schema.json` | `src/types/aria.ts` |
67
- | `schema:prettier` | `prettier --write` | `schemas/*.json`, `src/types/*.ts` | Formatted files |
68
- | `schema:eslint` | `eslint --fix` | `src/types/*.ts` | Lint-fixed files |
69
-
70
- Note: `schema:prettier` runs **twice** -- once after `schema:aria` to format generated files, then again after `schema:eslint` to clean up any eslint auto-fix formatting changes.
71
-
72
- ### Cross-package dependency: `@markuplint/types`
73
-
74
- `schemas/attributes.schema.json` contains a `$ref` to `@markuplint/types`:
75
-
76
- ```json
77
- {
78
- "AttributeType": {
79
- "$ref": "../../types/types.schema.json#/definitions/type"
80
- }
81
- }
82
- ```
83
-
84
- This means `@markuplint/types` must regenerate its schema **before** `@markuplint/ml-spec`. The monorepo-level `yarn up:schema` handles this order automatically:
85
-
86
- 1. `@markuplint/types` -- generates `types.schema.json`, builds the package
87
- 2. `@markuplint/ml-spec` -- generates schemas referencing `types.schema.json`
88
- 3. Other packages with `schema` scripts
89
-
90
- **Always prefer `yarn up:schema` from the repository root** when updating schemas that may involve cross-package references.
91
-
92
- ## File Classification: Editable vs Generated
93
-
94
- ### Files you MUST NOT edit directly
95
-
96
- These files carry "DO NOT MODIFY" headers and are overwritten by the generation pipeline:
97
-
98
- | File | Generated from |
99
- | --------------------------------------- | --------------------------------------------- |
100
- | `src/types/aria.ts` | `schemas/aria.schema.json` |
101
- | `src/types/attributes.ts` | `schemas/attributes.schema.json` |
102
- | `src/types/permitted-structures.ts` | `schemas/content-models.schema.json` |
103
- | `schemas/global-attributes.schema.json` | `gen/gen.ts` + `gen/global-attribute.data.ts` |
104
- | `schemas/attributes.schema.json` | `gen/gen.ts` + `gen/global-attribute.data.ts` |
105
-
106
- ### Files you edit to change generated output
107
-
108
- | To change... | Edit this file | Then run |
109
- | ------------------------------------------ | --------------------------------------------- | ----------------------------------------------- |
110
- | Global attribute categories/items | `gen/global-attribute.data.ts` | `yarn workspace @markuplint/ml-spec run schema` |
111
- | `AttributeJSON` shape (add field) | `gen/gen.ts` (the `AttributeJSON` definition) | `yarn workspace @markuplint/ml-spec run schema` |
112
- | ARIA role/property structure | `schemas/aria.schema.json` | `yarn workspace @markuplint/ml-spec run schema` |
113
- | Content model patterns | `schemas/content-models.schema.json` | `yarn workspace @markuplint/ml-spec run schema` |
114
- | Attribute value types (CSS keywords, etc.) | `@markuplint/types` package | `yarn up:schema` (from root) |
115
-
116
- ### Files you edit directly (hand-written)
117
-
118
- | File | Purpose |
119
- | ----------------------------- | --------------------------------------------------------------------- |
120
- | `src/types/index.ts` | Core hand-written types (`MLMLSpec`, `ElementSpec`, `ARIARole`, etc.) |
121
- | `src/algorithm/aria/*.ts` | ARIA algorithm implementations |
122
- | `src/algorithm/html/*.ts` | HTML algorithm implementations |
123
- | `src/utils/*.ts` | Utility functions |
124
- | `src/index.ts` | Public API exports |
125
- | `schemas/element.schema.json` | Top-level element schema (manual, 11 lines) |
126
-
127
- ## Testing
128
-
129
- ### Test files
130
-
131
- The package has 18 test files using vitest:
132
-
133
- | Directory | Test files | Coverage |
134
- | ----------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
135
- | `src/algorithm/aria/` | 11 | `accname-computation`, `get-computed-aria-props`, `get-computed-role`, `get-implicit-role-spec`, `get-implicit-role`, `get-permitted-roles-spec`, `get-role-spec`, `has-required-owned-elements`, `is-exposed`, `matches-context-role` |
136
- | `src/algorithm/aria/accname/` | 3 | `aria-steps`, `compute`, `element-names`, `label-steps` |
137
- | `src/utils/` | 4 | `get-attr-specs-spec`, `get-spec-by-tag-name`, `resolve-namespace`, `resolve-version`, `schema-to-spec` |
138
-
139
- ### Running tests
140
-
141
- ```bash
142
- # All tests in the monorepo
143
- yarn test
144
-
145
- # Only ml-spec tests
146
- yarn test packages/@markuplint/ml-spec
147
-
148
- # Specific test file
149
- yarn test packages/@markuplint/ml-spec/src/algorithm/aria/get-computed-role.spec.ts
150
- ```
151
-
152
- Tests depend on `@markuplint/test-tools` (devDependency) which provides HTML parsing utilities for creating DOM elements in test environments.
153
-
154
- ## Dependency Management
155
-
156
- ### Runtime dependencies
157
-
158
- | Package | Version | Purpose | Update risk |
159
- | -------------------- | ------- | -------------------------------------- | ------------------------- |
160
- | `@markuplint/ml-ast` | 4.4.10 | `NamespaceURI` type | Low (internal) |
161
- | `@markuplint/types` | 4.8.1 | `Type` union for attribute value types | Medium (schema reference) |
162
- | `is-plain-object` | 5.0.0 | Plain object detection for AAM info | Low (stable API) |
163
- | `type-fest` | 4.41.0 | `ReadonlyDeep` utility type | Low (types only) |
164
-
165
- ### Dev dependencies
166
-
167
- | Package | Version | Purpose |
168
- | --------------------------- | ------- | --------------------------------------- |
169
- | `@markuplint/test-tools` | 4.5.22 | Test utilities for DOM element creation |
170
- | `json-schema-to-typescript` | 15.0.4 | Schema → TypeScript type generation |
171
-
172
- ### Updating dependencies
173
-
174
- - **`json-schema-to-typescript`**: Major version updates may change generated type output (formatting, optional handling). After updating, run `yarn workspace @markuplint/ml-spec run schema` and review diffs in `src/types/*.ts`.
175
- - **`@markuplint/types`**: Always run `yarn up:schema` after updating to ensure schema references stay consistent.
176
- - **`type-fest`**: Type-only dependency. Update freely, but verify the build succeeds (`yarn build --scope @markuplint/ml-spec`).
177
-
178
- ## Common Maintenance Recipes
179
-
180
- ### 1. Add a new global attribute
181
-
182
- Edit `gen/global-attribute.data.ts`, add the attribute name to the appropriate category array:
183
-
184
- ```ts
185
- '#HTMLGlobalAttrs': {
186
- attrs: [
187
- // ...existing attributes...
188
- 'newattribute', // ← add here
189
- ],
190
- },
191
- ```
192
-
193
- Then regenerate:
194
-
195
- ```bash
196
- yarn workspace @markuplint/ml-spec run schema
197
- ```
198
-
199
- ### 2. Add a new global attribute category
200
-
201
- Edit `gen/global-attribute.data.ts`, add a new entry:
202
-
203
- ```ts
204
- '#NewCategoryAttrs': {
205
- description: 'Description with spec link',
206
- attrs: ['attr1', 'attr2'],
207
- },
208
- ```
209
-
210
- The key must match the pattern `#${string}Attrs`. The generator (`gen/gen.ts`) automatically handles the new category in both `global-attributes.schema.json` and `attributes.schema.json`.
211
-
212
- Then regenerate:
213
-
214
- ```bash
215
- yarn workspace @markuplint/ml-spec run schema
216
- ```
217
-
218
- ### 3. Add a new field to `AttributeJSON`
219
-
220
- Edit `gen/gen.ts`, add the property inside the `AttributeJSON` definition object:
221
-
222
- ```ts
223
- AttributeJSON: {
224
- properties: {
225
- // ...existing properties...
226
- newField: { type: 'boolean' }, // ← add here
227
- },
228
- },
229
- ```
230
-
231
- Then regenerate. The new field will appear in `src/types/attributes.ts` as an optional property.
232
-
233
- > **Warning:** `schemas/attributes.schema.json` and `schemas/global-attributes.schema.json` are both _overwritten_ by `gen/gen.ts`. **Never hand-edit those files** — your changes will be blown away the next time `schema:json` (or `yarn up:schema`) runs. All edits must live in `gen/gen.ts`.
234
-
235
- ### 3b. Add a new definition to `attributes.schema.json` (new schema type)
236
-
237
- When you need to add a brand-new definition (not just a field on `AttributeJSON`) — for example, adding a new structured type variant like `ConditionalAttributeType` (#3685) — edit `gen/gen.ts` and place the new definition alongside `AttributeJSON` inside the `definitions` object of the second `fs.writeFileSync` call.
238
-
239
- ```ts
240
- fs.writeFileSync(
241
- path.resolve(import.meta.dirname, '..', 'schemas', 'attributes.schema.json'),
242
- JSON.stringify({
243
- definitions: {
244
- // ...existing definitions...
245
- NewType: {
246
- type: 'object',
247
- additionalProperties: false,
248
- required: ['foo'],
249
- properties: { foo: { type: 'string' } },
250
- },
251
- AttributeJSON: {
252
- /* ... */
253
- },
254
- },
255
- }),
256
- );
257
- ```
258
-
259
- After regeneration, the new definition is exported from `src/types/attributes.ts` as a TypeScript `interface`. If downstream packages (e.g. `@markuplint/rules`) need to narrow against it, add a type guard in `src/utils/` and re-export from `src/index.ts` — see `is-conditional-attribute-type.ts` for the pattern established by #3685.
260
-
261
- ### 4. Modify ARIA role/property schema
262
-
263
- Edit `schemas/aria.schema.json` directly. For example, to add a new field to the role definition:
264
-
265
- ```json
266
- {
267
- "definitions": {
268
- "role": {
269
- "properties": {
270
- "newField": { "type": "boolean" }
271
- }
272
- }
273
- }
274
- }
275
- ```
276
-
277
- Then regenerate. The new field will appear in `src/types/aria.ts`.
278
-
279
- ### 5. Add a new content model category
280
-
281
- Edit `schemas/content-models.schema.json`, add the category to the `Category` enum and define its pattern.
282
-
283
- ### 6. Add a new ARIA algorithm function
284
-
285
- 1. Create the implementation file in `src/algorithm/aria/`.
286
- 2. Create a corresponding `.spec.ts` test file.
287
- 3. Export the function from `src/index.ts`.
288
- 4. Update `docs/aria-algorithms.md` and `docs/aria-algorithms.ja.md`.
289
-
290
- ### 7. Update W3C specification compliance
291
-
292
- When a W3C specification updates (e.g., WAI-ARIA 1.3 becomes a Recommendation):
293
-
294
- 1. Update `@markuplint/html-spec` data if element-level ARIA mappings changed.
295
- 2. Update algorithm implementations in `src/algorithm/aria/*.ts` if algorithm behavior changed.
296
- 3. Update `src/utils/aria-version.ts` if a new ARIA version is added.
297
- 4. Run `yarn up:schema` to regenerate types.
298
- 5. Run tests to verify compliance.
299
-
300
- ## Caching Considerations
301
-
302
- The package uses several runtime caches that are **never invalidated during a process lifetime**. This is safe for markuplint's single-run lint model, but be aware of it when:
303
-
304
- | Cache location | Scope | Notes |
305
- | ---------------------------------------- | ------------------------------------------------ | ------------------------------- |
306
- | `getARIA()` internal cache | `Map` keyed by `localName + namespace + version` | Cleared only on process restart |
307
- | `getSpecByTagName()` cache | `Map` keyed by `namespace:localName` | Per-specs instance |
308
- | `getContentModel()` cache | `WeakMap<Element, ...>` | Per-element, GC-safe |
309
- | `contentModelCategoryToTagNames()` cache | Module-level `Map<Category, string[]>` | Global, never invalidated |
310
- | `getAttrSpecs()` cache | `WeakSet` + `Map` per schema | New schema resets cache |
311
- | `resolveNamespace()` cache | Module-level `Map` | Global, never invalidated |
312
-
313
- If you add a new algorithm function that computes expensive results, consider adding a similar caching strategy keyed by element + specs + version.
314
-
315
- ## Versioning Policy
316
-
317
- - HTML Schema/Specs are **not** part of the public API surface of markuplint.
318
- - Changes to schemas, generated types, or algorithm behavior are treated as a **minor release**.
319
- - Publishing is handled by Lerna during the normal release process.
320
- - The `version` field in `package.json` is managed by Lerna -- do not manually update it.
321
-
322
- ## Troubleshooting
323
-
324
- ### Schema generation fails with `$ref` error
325
-
326
- **Symptom:** `json2ts` reports an unresolved `$ref` during `schema:attributes`.
327
-
328
- **Cause:** The `$ref` to `../../types/types.schema.json` requires `@markuplint/types` to have generated its schema first.
329
-
330
- **Fix:** Run `yarn up:schema` from the repository root instead of the package-level `schema` script.
331
-
332
- ### Generated types differ after `json-schema-to-typescript` update
333
-
334
- **Symptom:** After updating `json-schema-to-typescript`, `src/types/*.ts` has unexpected changes.
335
-
336
- **Cause:** New versions may change formatting, optional handling, or type generation strategy.
337
-
338
- **Fix:** Review the diff carefully. If the types are semantically equivalent, commit the changes. If behavior changed (e.g., previously optional fields became required), investigate the `json-schema-to-typescript` changelog.
339
-
340
- ### Build error: generated type mismatch
341
-
342
- **Symptom:** TypeScript build errors referencing types in `src/types/aria.ts`, `attributes.ts`, or `permitted-structures.ts`.
343
-
344
- **Cause:** The JSON schema was edited but types were not regenerated, or a cross-package schema reference is stale.
345
-
346
- **Fix:**
347
-
348
- ```bash
349
- yarn up:schema
350
- yarn build --scope @markuplint/ml-spec
351
- ```
352
-
353
- ### Cache-related issues in long-running processes
354
-
355
- **Symptom:** Stale data when reusing the same Node.js process across multiple lint runs with different configurations.
356
-
357
- **Cause:** Module-level caches (`contentModelCategoryToTagNames`, `resolveNamespace`) are never invalidated.
358
-
359
- **Fix:** This is by design for markuplint's single-run model. If you embed markuplint in a long-running process (e.g., a language server), be aware that spec data is cached at first access. Restarting the process clears all caches.