@markuplint/html-spec 4.16.1 → 4.17.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 +285 -0
- package/ARCHITECTURE.md +196 -0
- package/CHANGELOG.md +22 -2
- package/README.md +11 -259
- package/SKILL.md +358 -0
- package/docs/build-pipeline.ja.md +170 -0
- package/docs/build-pipeline.md +171 -0
- package/docs/element-spec-format.ja.md +952 -0
- package/docs/element-spec-format.md +521 -0
- package/docs/maintenance.ja.md +359 -0
- package/docs/maintenance.md +397 -0
- package/index.json +370 -42
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -16,8 +16,6 @@ This package serves as the data layer in markuplint's specification system, depe
|
|
|
16
16
|
|
|
17
17
|
## Package Architecture
|
|
18
18
|
|
|
19
|
-
This package serves as the data layer in markuplint's specification system:
|
|
20
|
-
|
|
21
19
|
```
|
|
22
20
|
@markuplint/ml-spec (Foundation Layer)
|
|
23
21
|
↓ provides types, algorithms, schemas
|
|
@@ -34,69 +32,17 @@ Core packages (Application Layer)
|
|
|
34
32
|
### Generated Output (DO NOT EDIT)
|
|
35
33
|
|
|
36
34
|
- **`index.json`** - Consolidated specification data (48K+ lines)
|
|
37
|
-
- All HTML elements with complete specifications
|
|
38
|
-
- Global attribute definitions (`#HTMLGlobalAttrs`, `#ARIAAttrs`)
|
|
39
|
-
- ARIA role and property definitions (`#aria`)
|
|
40
|
-
- Content model macros (`#contentModels`)
|
|
41
|
-
- Citation references to authoritative sources
|
|
42
35
|
|
|
43
36
|
### Source Files (EDIT THESE)
|
|
44
37
|
|
|
45
|
-
- **`src/spec
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- `src/spec.svg_text.json` → `<svg:text>` element specification
|
|
49
|
-
- **`src/spec-common.attributes.json`** - Shared attribute definitions
|
|
50
|
-
- **`src/spec-common.contents.json`** - Reusable content model macros
|
|
38
|
+
- **`src/spec.*.json`** - Individual element specifications (177 files)
|
|
39
|
+
- **`src/spec-common.attributes.json`** - Global attribute category definitions (19 categories)
|
|
40
|
+
- **`src/spec-common.contents.json`** - Content model category macros (HTML 10 + SVG 19 categories)
|
|
51
41
|
|
|
52
|
-
### Build
|
|
42
|
+
### Build System
|
|
53
43
|
|
|
54
44
|
- **`build.mjs`** - Generation script that invokes `@markuplint/spec-generator`
|
|
55
|
-
-
|
|
56
|
-
- **MDN Web Docs** - Element descriptions, compatibility data, attribute metadata
|
|
57
|
-
- **W3C ARIA specifications** - Role definitions, property mappings (1.1/1.2/1.3)
|
|
58
|
-
- **HTML Living Standard** - Obsolete element definitions
|
|
59
|
-
- **SVG specifications** - SVG element definitions and categories
|
|
60
|
-
|
|
61
|
-
## Data Structure
|
|
62
|
-
|
|
63
|
-
The generated `index.json` follows this structure:
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
{
|
|
67
|
-
cites: Cites; // Reference citations to external specs
|
|
68
|
-
def: { // Global definitions
|
|
69
|
-
"#HTMLGlobalAttrs": GlobalAttributes;
|
|
70
|
-
"#ARIAAttrs": ARIAAttributes;
|
|
71
|
-
"#aria": ARIASpecification;
|
|
72
|
-
"#contentModels": ContentModelMacros;
|
|
73
|
-
};
|
|
74
|
-
specs: ElementSpec[]; // Individual element specifications
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Element Specification Format
|
|
79
|
-
|
|
80
|
-
Each element specification includes:
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
{
|
|
84
|
-
name: string; // Element name (e.g., "table", "tr")
|
|
85
|
-
cite: string; // MDN reference URL
|
|
86
|
-
description: string; // Human-readable description
|
|
87
|
-
categories: string[]; // Content categories (flow, phrasing, etc.)
|
|
88
|
-
contentModel: ContentModel; // Permitted child elements
|
|
89
|
-
globalAttrs: GlobalAttrSets; // Applicable global attributes
|
|
90
|
-
attributes: AttributeSpecs; // Element-specific attributes
|
|
91
|
-
aria: { // ARIA integration
|
|
92
|
-
implicitRole: string | null; // Default ARIA role
|
|
93
|
-
permittedRoles: string[] | boolean; // Allowed ARIA roles
|
|
94
|
-
namingProhibited?: boolean; // Accessible name constraints
|
|
95
|
-
conditions?: ConditionalARIA; // Context-specific ARIA rules
|
|
96
|
-
};
|
|
97
|
-
omission?: TagOmissionRules; // Start/end tag omission rules
|
|
98
|
-
}
|
|
99
|
-
```
|
|
45
|
+
- Fetches live data from MDN, W3C ARIA specs, and HTML Living Standard
|
|
100
46
|
|
|
101
47
|
## Relationship to @markuplint/ml-spec
|
|
102
48
|
|
|
@@ -105,190 +51,12 @@ Each element specification includes:
|
|
|
105
51
|
- **Type definitions** (`ElementSpec`, `ExtendedSpec`, `MLMLSpec`) that structure this data
|
|
106
52
|
- **JSON schemas** that validate the specification format
|
|
107
53
|
- **Algorithms** that process and compute values from this specification data
|
|
108
|
-
- **Runtime utilities** that consume this consolidated specification data
|
|
109
54
|
|
|
110
55
|
**@markuplint/html-spec** (this package) provides:
|
|
111
56
|
|
|
112
57
|
- **Canonical HTML data** following the type definitions from `@markuplint/ml-spec`
|
|
113
58
|
- **External data enrichment** from MDN and W3C specifications
|
|
114
59
|
- **Build automation** that keeps data synchronized with external sources
|
|
115
|
-
- **Single consolidated dataset** optimized for runtime consumption
|
|
116
|
-
|
|
117
|
-
This separation enables:
|
|
118
|
-
|
|
119
|
-
- **Independent data updates** without affecting type definitions or algorithms
|
|
120
|
-
- **Algorithm improvements** without requiring data regeneration
|
|
121
|
-
- **Framework extensions** that can augment this base HTML data
|
|
122
|
-
|
|
123
|
-
## Development Workflow
|
|
124
|
-
|
|
125
|
-
### Adding or Editing HTML Elements
|
|
126
|
-
|
|
127
|
-
1. **Edit source specifications**
|
|
128
|
-
- Add new file: `src/spec.<element>.json` (e.g., `src/spec.dialog.json`)
|
|
129
|
-
- Edit existing: Update relevant `src/spec-*.json` file
|
|
130
|
-
- For SVG elements: Use pattern `src/spec.svg_<local>.json`
|
|
131
|
-
|
|
132
|
-
2. **Regenerate the dataset**
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
# From repository root (recommended)
|
|
136
|
-
yarn up:gen
|
|
137
|
-
|
|
138
|
-
# Or for this package only
|
|
139
|
-
yarn workspace @markuplint/html-spec run gen
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
3. **Verify output**
|
|
143
|
-
- Check `index.json` for expected changes
|
|
144
|
-
- Ensure no unintended modifications to other elements
|
|
145
|
-
|
|
146
|
-
### Element Specification Guide
|
|
147
|
-
|
|
148
|
-
**Minimal element specification**:
|
|
149
|
-
|
|
150
|
-
```json
|
|
151
|
-
{
|
|
152
|
-
"contentModel": {
|
|
153
|
-
"contents": [{ "require": "#phrasing" }]
|
|
154
|
-
},
|
|
155
|
-
"globalAttrs": {
|
|
156
|
-
"#HTMLGlobalAttrs": true,
|
|
157
|
-
"#ARIAAttrs": true
|
|
158
|
-
},
|
|
159
|
-
"attributes": {
|
|
160
|
-
"custom-attr": { "type": "String" }
|
|
161
|
-
},
|
|
162
|
-
"aria": {
|
|
163
|
-
"implicitRole": "button",
|
|
164
|
-
"permittedRoles": ["link", "tab"]
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
**Key principles**:
|
|
170
|
-
|
|
171
|
-
- Only specify what differs from defaults or overrides MDN data
|
|
172
|
-
- Use references to global attribute sets when possible
|
|
173
|
-
- Define content models using semantic categories (`#flow`, `#phrasing`)
|
|
174
|
-
- Include ARIA specifications following HTML-ARIA mapping guidelines
|
|
175
|
-
|
|
176
|
-
### Common Editing Patterns
|
|
177
|
-
|
|
178
|
-
**Adding element-specific attributes**:
|
|
179
|
-
|
|
180
|
-
```json
|
|
181
|
-
{
|
|
182
|
-
"attributes": {
|
|
183
|
-
"href": {
|
|
184
|
-
"type": "URL",
|
|
185
|
-
"required": false,
|
|
186
|
-
"description": "Target URL for navigation"
|
|
187
|
-
},
|
|
188
|
-
"download": {
|
|
189
|
-
"type": "String",
|
|
190
|
-
"experimental": true
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
**Conditional ARIA rules**:
|
|
197
|
-
|
|
198
|
-
```json
|
|
199
|
-
{
|
|
200
|
-
"aria": {
|
|
201
|
-
"implicitRole": "link",
|
|
202
|
-
"permittedRoles": ["button", "menuitem"],
|
|
203
|
-
"conditions": {
|
|
204
|
-
":not([href])": {
|
|
205
|
-
"implicitRole": "generic",
|
|
206
|
-
"namingProhibited": true
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Complex content models**:
|
|
214
|
-
|
|
215
|
-
```json
|
|
216
|
-
{
|
|
217
|
-
"contentModel": {
|
|
218
|
-
"contents": [{ "transparent": ":not(:model(interactive), a, [tabindex])" }]
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
## Build Process Details
|
|
224
|
-
|
|
225
|
-
### What `yarn up:gen` does
|
|
226
|
-
|
|
227
|
-
1. **Invokes spec-generator** with inputs:
|
|
228
|
-
- HTML spec sources: `src/spec-*.json`
|
|
229
|
-
- Common attributes: `src/spec-common.attributes.json`
|
|
230
|
-
- Common content models: `src/spec-common.contents.json`
|
|
231
|
-
|
|
232
|
-
2. **External data enrichment**:
|
|
233
|
-
- **MDN scraping**: Fetches descriptions, categories, attribute metadata
|
|
234
|
-
- **ARIA integration**: Downloads W3C ARIA specifications (1.1/1.2/1.3)
|
|
235
|
-
- **Obsolete elements**: Adds deprecated elements from HTML Living Standard
|
|
236
|
-
- **SVG specifications**: Includes SVG element definitions and categories
|
|
237
|
-
|
|
238
|
-
3. **Data consolidation**:
|
|
239
|
-
- Merges manual specifications with fetched data
|
|
240
|
-
- Resolves conflicts (manual data takes precedence)
|
|
241
|
-
- Validates against JSON schemas from `@markuplint/ml-spec`
|
|
242
|
-
- Generates citations and references
|
|
243
|
-
|
|
244
|
-
4. **Output generation**:
|
|
245
|
-
- Writes consolidated `index.json`
|
|
246
|
-
- Formats with Prettier
|
|
247
|
-
- Validates structural integrity
|
|
248
|
-
|
|
249
|
-
### External Data Sources
|
|
250
|
-
|
|
251
|
-
**MDN Web Docs** (`developer.mozilla.org`):
|
|
252
|
-
|
|
253
|
-
- Element descriptions and usage guidance
|
|
254
|
-
- Compatibility tables and browser support
|
|
255
|
-
- Attribute metadata (deprecated, experimental, obsolete)
|
|
256
|
-
- Tag omission rules and semantic information
|
|
257
|
-
|
|
258
|
-
**W3C ARIA Specifications**:
|
|
259
|
-
|
|
260
|
-
- **ARIA 1.1**: `https://www.w3.org/TR/wai-aria-1.1/`
|
|
261
|
-
- **ARIA 1.2**: `https://www.w3.org/TR/wai-aria-1.2/`
|
|
262
|
-
- **ARIA 1.3**: `https://w3c.github.io/aria/`
|
|
263
|
-
- **HTML-ARIA**: `https://www.w3.org/TR/html-aria/`
|
|
264
|
-
|
|
265
|
-
**HTML Living Standard** (`https://html.spec.whatwg.org/`):
|
|
266
|
-
|
|
267
|
-
- Obsolete element definitions
|
|
268
|
-
- Semantic category classifications
|
|
269
|
-
- Content model specifications
|
|
270
|
-
|
|
271
|
-
### Caching and Performance
|
|
272
|
-
|
|
273
|
-
- **External fetches are cached** to prevent unnecessary network requests during development
|
|
274
|
-
- **CI/CD builds** refresh external data to stay current with specification changes
|
|
275
|
-
- **Generated output is optimized** for runtime consumption (single file, pre-resolved references)
|
|
276
|
-
|
|
277
|
-
## File Naming Conventions
|
|
278
|
-
|
|
279
|
-
**HTML elements**: `src/spec.<tag>.json`
|
|
280
|
-
|
|
281
|
-
- Examples: `spec.div.json`, `spec.table.json`, `spec.input.json`
|
|
282
|
-
|
|
283
|
-
**SVG elements**: `src/spec.svg_<local>.json`
|
|
284
|
-
|
|
285
|
-
- Examples: `spec.svg_text.json`, `spec.svg_circle.json`
|
|
286
|
-
- Element name inferred as `svg:<local>` (e.g., `svg:text`)
|
|
287
|
-
|
|
288
|
-
**Special files**:
|
|
289
|
-
|
|
290
|
-
- `spec-common.attributes.json` - Global attribute category definitions
|
|
291
|
-
- `spec-common.contents.json` - Reusable content model macros
|
|
292
60
|
|
|
293
61
|
## Install
|
|
294
62
|
|
|
@@ -305,30 +73,14 @@ $ yarn add @markuplint/html-spec
|
|
|
305
73
|
|
|
306
74
|
</details>
|
|
307
75
|
|
|
308
|
-
##
|
|
309
|
-
|
|
310
|
-
### Do Not Edit Generated Files
|
|
311
|
-
|
|
312
|
-
- **Never modify `index.json` directly** - it will be overwritten
|
|
313
|
-
- Always update source files in `src/` and regenerate
|
|
314
|
-
|
|
315
|
-
### Manual Data Takes Precedence
|
|
316
|
-
|
|
317
|
-
- Your specifications in `src/spec-*.json` override scraped MDN data
|
|
318
|
-
- Use this to correct inaccuracies or add missing information
|
|
319
|
-
- External data fills gaps but doesn't override manual specifications
|
|
320
|
-
|
|
321
|
-
### Specification Compliance
|
|
322
|
-
|
|
323
|
-
- ARIA mappings should follow W3C HTML-ARIA mapping guidelines
|
|
324
|
-
- Content models should align with HTML Living Standard definitions
|
|
325
|
-
- Attribute types should reference `@markuplint/types` definitions
|
|
76
|
+
## Contributing
|
|
326
77
|
|
|
327
|
-
|
|
78
|
+
For detailed documentation, see:
|
|
328
79
|
|
|
329
|
-
-
|
|
330
|
-
-
|
|
331
|
-
-
|
|
80
|
+
- [Architecture](ARCHITECTURE.md) -- Package structure, data flow, and integration points
|
|
81
|
+
- [Element Specification Format](docs/element-spec-format.md) -- JSON spec file reference, content models, ARIA integration
|
|
82
|
+
- [Build Pipeline](docs/build-pipeline.md) -- Build process, external data sources, spec-generator modules
|
|
83
|
+
- [Maintenance Guide](docs/maintenance.md) -- Common recipes, testing, troubleshooting
|
|
332
84
|
|
|
333
85
|
## License
|
|
334
86
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Perform maintenance tasks for @markuplint/html-spec
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# html-spec-maintenance
|
|
6
|
+
|
|
7
|
+
Perform maintenance tasks for `@markuplint/html-spec`: regenerate specification data,
|
|
8
|
+
review upstream changes, update manual spec files, and ensure cross-package consistency.
|
|
9
|
+
|
|
10
|
+
## Input
|
|
11
|
+
|
|
12
|
+
`$ARGUMENTS` specifies the task. Supported tasks:
|
|
13
|
+
|
|
14
|
+
| Task | Description |
|
|
15
|
+
| ------------------------------------- | ------------------------------------------------------ |
|
|
16
|
+
| `update` | Regenerate `index.json` and review upstream changes |
|
|
17
|
+
| `add-element <name>` | Add a new HTML element specification |
|
|
18
|
+
| `add-svg-element <name>` | Add a new SVG element specification |
|
|
19
|
+
| `add-attribute <element> <attr>` | Add an attribute to an element |
|
|
20
|
+
| `remove-attribute <element> <attr>` | Remove an attribute from an element |
|
|
21
|
+
| `obsolete-element <name>` | Mark an element as obsolete |
|
|
22
|
+
| `obsolete-attribute <element> <attr>` | Mark an attribute as deprecated |
|
|
23
|
+
| `change-flag <element> <attr> <flag>` | Change `experimental`/`deprecated`/`nonStandard` flags |
|
|
24
|
+
| `check` | Verify cross-package consistency |
|
|
25
|
+
|
|
26
|
+
If omitted, defaults to `update`.
|
|
27
|
+
|
|
28
|
+
## Reference
|
|
29
|
+
|
|
30
|
+
Before executing any task, read `docs/maintenance.md` (or `docs/maintenance.ja.md`)
|
|
31
|
+
for the full guide. The recipes there are the source of truth for procedures.
|
|
32
|
+
|
|
33
|
+
Also read:
|
|
34
|
+
|
|
35
|
+
- `docs/element-spec-format.md` -- JSON spec file format reference
|
|
36
|
+
- `docs/build-pipeline.md` -- Build pipeline and data precedence rules
|
|
37
|
+
|
|
38
|
+
## Task: update
|
|
39
|
+
|
|
40
|
+
The primary maintenance workflow. Regenerate `index.json` with the latest MDN/W3C data
|
|
41
|
+
and review what has changed.
|
|
42
|
+
|
|
43
|
+
### Step 1: Regenerate
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
yarn up:gen
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This runs `@markuplint/spec-generator`, which scrapes live MDN data and merges it with
|
|
50
|
+
the manual spec files in `src/`. The result is written to `index.json`.
|
|
51
|
+
|
|
52
|
+
### Step 2: Review the diff
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git diff packages/@markuplint/html-spec/index.json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Categorize each change:
|
|
59
|
+
|
|
60
|
+
| Category | Examples | Action |
|
|
61
|
+
| ------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| **Minor description rewording** | MDN refines role/element/attribute descriptions | Commit as-is |
|
|
63
|
+
| **New attributes** | `interestfor`, `switch` added by MDN | Commit as-is (MDN-sourced, no manual spec change needed) |
|
|
64
|
+
| **Flag transitions** | `experimental` → `deprecated`, `nonStandard` added/removed | Commit as-is |
|
|
65
|
+
| **Significant spec changes** | ARIA property `required` → `inherited`, content model restructured | Requires manual spec update (go to Step 3) |
|
|
66
|
+
| **ARIA 1.3 updates** | New/revised role definitions, property requirement changes | WAI-ARIA 1.3 is a Working Draft -- expect ongoing changes. 1.1 and 1.2 are finalized Recommendations and will not change. |
|
|
67
|
+
|
|
68
|
+
> **Caution -- ARIA version duplication:** `index.json` contains role definitions for
|
|
69
|
+
> WAI-ARIA 1.1, 1.2, and 1.3, so many strings appear three times. When editing
|
|
70
|
+
> descriptions or properties, **do not use `replace_all`** -- it will modify all three
|
|
71
|
+
> versions simultaneously. Always target the specific version block you intend to change.
|
|
72
|
+
|
|
73
|
+
### Step 3: Handle significant changes (if any)
|
|
74
|
+
|
|
75
|
+
If the diff contains substantive changes to element behavior, ARIA mappings, or
|
|
76
|
+
content models:
|
|
77
|
+
|
|
78
|
+
1. Identify the affected elements
|
|
79
|
+
2. Determine which source files need updating:
|
|
80
|
+
- `src/spec.<element>.json` for element-specific changes
|
|
81
|
+
- `src/spec-common.contents.json` for content model category changes
|
|
82
|
+
- `src/spec-common.attributes.json` for global attribute changes
|
|
83
|
+
- In rare cases, `@markuplint/ml-spec` schemas or types may need updating
|
|
84
|
+
3. Make the changes, referencing the authoritative specification:
|
|
85
|
+
- HTML Living Standard: https://html.spec.whatwg.org/multipage/
|
|
86
|
+
- HTML-ARIA: https://w3c.github.io/html-aria/
|
|
87
|
+
- WAI-ARIA: https://w3c.github.io/aria/
|
|
88
|
+
4. Regenerate to incorporate manual spec changes:
|
|
89
|
+
```bash
|
|
90
|
+
yarn up:gen
|
|
91
|
+
```
|
|
92
|
+
5. Verify the final diff is correct
|
|
93
|
+
|
|
94
|
+
### Step 3b: Idempotency verification (when spec files are modified)
|
|
95
|
+
|
|
96
|
+
When you modify `src/spec.*.json` files, verify that your changes produce stable output
|
|
97
|
+
before committing. This ensures the generated `index.json` does not contain unintended
|
|
98
|
+
drift:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# 1. Stage spec files and index.json
|
|
102
|
+
git add packages/@markuplint/html-spec/src/spec.*.json packages/@markuplint/html-spec/index.json
|
|
103
|
+
|
|
104
|
+
# 2. Regenerate
|
|
105
|
+
yarn up:gen
|
|
106
|
+
|
|
107
|
+
# 3. Check that the attributes you changed are NOT in the diff (= stable output)
|
|
108
|
+
git diff packages/@markuplint/html-spec/index.json | grep '"your-attr"'
|
|
109
|
+
|
|
110
|
+
# 4. If stable, discard the regenerated file and use the staged version
|
|
111
|
+
git checkout packages/@markuplint/html-spec/index.json
|
|
112
|
+
|
|
113
|
+
# 5. Proceed to commit
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If the diff shows unexpected changes for your attribute, it means the spec file and
|
|
117
|
+
the generator produce different values -- investigate before committing.
|
|
118
|
+
|
|
119
|
+
### Step 4: Test and commit
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
yarn workspace @markuplint/html-spec run test
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Stage and commit `index.json` and any modified `src/` files.
|
|
126
|
+
|
|
127
|
+
## Task: add-element
|
|
128
|
+
|
|
129
|
+
Add a new HTML element specification. Follow recipe #1 in `docs/maintenance.md`.
|
|
130
|
+
|
|
131
|
+
1. Read `src/spec.a.json` as a reference for a typical element
|
|
132
|
+
2. Create `src/spec.<name>.json` with required fields:
|
|
133
|
+
- `contentModel` with `contents`
|
|
134
|
+
- `globalAttrs` (`#HTMLGlobalAttrs`, `#GlobalEventAttrs`, `#ARIAAttrs` set to `true`)
|
|
135
|
+
- `attributes` (element-specific, can be `{}`)
|
|
136
|
+
- `aria` with `implicitRole` and `permittedRoles`
|
|
137
|
+
3. Add spec URL comments at the top (`//` format)
|
|
138
|
+
4. **Cross-package step**: If the element belongs to content categories (flow, phrasing, etc.),
|
|
139
|
+
add it to the appropriate categories in `src/spec-common.contents.json`.
|
|
140
|
+
Without this, `@markuplint/rules`' `permitted-contents` rule will flag the element
|
|
141
|
+
as invalid content in parent elements that allow those categories.
|
|
142
|
+
5. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
143
|
+
6. Verify the element appears in `index.json`
|
|
144
|
+
7. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
145
|
+
|
|
146
|
+
## Task: add-svg-element
|
|
147
|
+
|
|
148
|
+
Add a new SVG element specification. Follow recipe #3 in `docs/maintenance.md`.
|
|
149
|
+
|
|
150
|
+
1. Read `src/spec.svg_circle.json` as a reference for a typical SVG element
|
|
151
|
+
2. Create `src/spec.svg_<name>.json` (the `svg_` prefix maps to namespace `svg:<name>`)
|
|
152
|
+
3. Use SVG-specific global attribute categories (`#SVGCoreAttrs`, `#SVGPresentationAttrs`)
|
|
153
|
+
4. For ARIA, use AAM references: `{ "core-aam": true, "graphics-aam": true }`
|
|
154
|
+
5. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
155
|
+
6. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
156
|
+
|
|
157
|
+
## Task: add-attribute
|
|
158
|
+
|
|
159
|
+
Add an attribute to an element. Follow recipe #2 in `docs/maintenance.md`.
|
|
160
|
+
|
|
161
|
+
1. Open `src/spec.<element>.json`
|
|
162
|
+
2. Add the attribute entry to the `attributes` object. See `docs/element-spec-format.md`
|
|
163
|
+
for the full attribute definition format. Common patterns:
|
|
164
|
+
- Simple typed attribute: `"href": { "type": "URL" }`
|
|
165
|
+
- Conditional attribute: `"accept": { "type": ..., "condition": "[type='file' i]" }`
|
|
166
|
+
- Boolean attribute: `"disabled": { "type": "Boolean" }`
|
|
167
|
+
3. For a **global** attribute (applies to all elements), edit
|
|
168
|
+
`src/spec-common.attributes.json` instead, adding the attribute to the
|
|
169
|
+
appropriate category (e.g., `#HTMLGlobalAttrs`)
|
|
170
|
+
4. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
171
|
+
5. Verify the attribute appears in `index.json` with correct metadata
|
|
172
|
+
6. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
173
|
+
|
|
174
|
+
## Task: remove-attribute
|
|
175
|
+
|
|
176
|
+
Remove an attribute from an element's manual specification.
|
|
177
|
+
|
|
178
|
+
1. Open `src/spec.<element>.json`
|
|
179
|
+
2. Remove the attribute entry from the `attributes` object
|
|
180
|
+
3. For a **global** attribute, edit `src/spec-common.attributes.json` instead
|
|
181
|
+
4. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
182
|
+
5. Verify the attribute no longer appears in `index.json` for the element.
|
|
183
|
+
**Note**: If the attribute also exists in MDN data, it will still appear in
|
|
184
|
+
`index.json` from the MDN source. To fully suppress an MDN-sourced attribute,
|
|
185
|
+
you may need to override it in the manual spec rather than simply removing it.
|
|
186
|
+
6. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
187
|
+
|
|
188
|
+
## Task: obsolete-element
|
|
189
|
+
|
|
190
|
+
Mark an element as obsolete. Follow recipe #8 in `docs/maintenance.md`.
|
|
191
|
+
|
|
192
|
+
There are two approaches:
|
|
193
|
+
|
|
194
|
+
- **Via spec-generator's hardcoded list** (preferred for standard obsolete elements):
|
|
195
|
+
Add the element name to the `obsoleteList` array in
|
|
196
|
+
`packages/@markuplint/spec-generator/src/html-elements.ts`
|
|
197
|
+
- **Via manual spec file**: Set `"obsolete": true` in the element's
|
|
198
|
+
`src/spec.<element>.json`
|
|
199
|
+
|
|
200
|
+
Obsolete elements automatically get:
|
|
201
|
+
|
|
202
|
+
- `cite` pointing to the HTML spec obsolete features section
|
|
203
|
+
- `contents: true` (any content allowed)
|
|
204
|
+
- `permittedRoles: true`, `implicitRole: false`
|
|
205
|
+
|
|
206
|
+
After making the change:
|
|
207
|
+
|
|
208
|
+
1. Regenerate: `yarn up:gen`
|
|
209
|
+
2. Verify the element appears in `index.json` with `"obsolete": true`
|
|
210
|
+
3. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
211
|
+
|
|
212
|
+
## Task: obsolete-attribute
|
|
213
|
+
|
|
214
|
+
Mark an attribute as deprecated in an element's specification.
|
|
215
|
+
|
|
216
|
+
1. Open `src/spec.<element>.json`
|
|
217
|
+
2. Add `"deprecated": true` to the attribute definition:
|
|
218
|
+
```json
|
|
219
|
+
"align": {
|
|
220
|
+
"deprecated": true
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
If the attribute already has other fields (`type`, `condition`, etc.),
|
|
224
|
+
simply add `"deprecated": true` alongside them.
|
|
225
|
+
3. For a **global** attribute, edit `src/spec-common.attributes.json` instead
|
|
226
|
+
4. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
227
|
+
5. Verify the attribute shows `"deprecated": true` in `index.json`
|
|
228
|
+
6. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
229
|
+
|
|
230
|
+
## Task: change-flag
|
|
231
|
+
|
|
232
|
+
Change the `experimental`, `deprecated`, or `nonStandard` flag on an attribute.
|
|
233
|
+
|
|
234
|
+
These boolean flags indicate the standardization status of an attribute:
|
|
235
|
+
|
|
236
|
+
| Flag | Meaning |
|
|
237
|
+
| -------------- | ----------------------------------------------------------------- |
|
|
238
|
+
| `experimental` | The attribute is part of an emerging specification not yet stable |
|
|
239
|
+
| `deprecated` | The attribute is obsolete and should not be used |
|
|
240
|
+
| `nonStandard` | The attribute is not part of any standard |
|
|
241
|
+
|
|
242
|
+
1. Open `src/spec.<element>.json` (or `src/spec-common.attributes.json` for globals)
|
|
243
|
+
2. Add, change, or remove the flag on the target attribute:
|
|
244
|
+
```json
|
|
245
|
+
"attributionsrc": {
|
|
246
|
+
"deprecated": true
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
To remove a flag, delete the property entirely.
|
|
250
|
+
3. **Note**: Flags from MDN scraping also appear in `index.json`. Manual spec flags
|
|
251
|
+
take precedence, so setting a flag in the manual spec will override the MDN value.
|
|
252
|
+
However, MDN-only attributes (not defined in manual specs) can only be overridden
|
|
253
|
+
by adding an entry for that attribute in the manual spec.
|
|
254
|
+
4. Regenerate: `yarn workspace @markuplint/html-spec run gen`
|
|
255
|
+
5. Verify the flag change in `index.json`
|
|
256
|
+
6. Run tests: `yarn workspace @markuplint/html-spec run test`
|
|
257
|
+
|
|
258
|
+
## ARIA Version System
|
|
259
|
+
|
|
260
|
+
### Resolution Logic
|
|
261
|
+
|
|
262
|
+
`resolveVersion()` (`@markuplint/ml-spec/src/utils/resolve-version.ts`) checks
|
|
263
|
+
`aria[version]` first, falls back to top-level `aria`. The runtime default is
|
|
264
|
+
`ARIA_RECOMMENDED_VERSION = '1.2'` (`@markuplint/ml-spec/src/utils/aria-version.ts`).
|
|
265
|
+
|
|
266
|
+
### Key Placement Rules
|
|
267
|
+
|
|
268
|
+
| Key | Meaning | Mutability |
|
|
269
|
+
| ---------------- | --------------------------------------------------------- | -------------------------------------------- |
|
|
270
|
+
| Top-level `aria` | Default / latest. Fallback for versions without overrides | Mutable — update to match current W3C Rec |
|
|
271
|
+
| `"1.1"` | ARIA 1.1 snapshot | **Frozen** — never add new roles |
|
|
272
|
+
| `"1.2"` | ARIA 1.2 snapshot (rarely needed) | Only create when top-level diverges from 1.2 |
|
|
273
|
+
|
|
274
|
+
### Decision: Where to add new permittedRoles
|
|
275
|
+
|
|
276
|
+
1. Is the role in the W3C Recommendation "ARIA in HTML" (ARIA 1.2 based, Aug 2025)?
|
|
277
|
+
→ Add to **top-level only**
|
|
278
|
+
2. Is the role ARIA 1.3 draft-only (not in W3C Rec)?
|
|
279
|
+
→ Add to **top-level**, AND create `"1.2"` key with the current 1.2 list to freeze it
|
|
280
|
+
3. Was the role in the original ARIA 1.1 spec for this element?
|
|
281
|
+
→ It should already be in `"1.1"`. **Never add new roles to `"1.1"`**.
|
|
282
|
+
|
|
283
|
+
### permittedRoles Quick Reference
|
|
284
|
+
|
|
285
|
+
| Pattern | Meaning |
|
|
286
|
+
| ---------------------------------------- | ----------------------------------- |
|
|
287
|
+
| `true` | Any role allowed |
|
|
288
|
+
| `false` | No roles allowed |
|
|
289
|
+
| `["role1", "role2"]` | Specific roles (alphabetical order) |
|
|
290
|
+
| `[{"name": "role", "deprecated": true}]` | Deprecated role |
|
|
291
|
+
|
|
292
|
+
## Task: check
|
|
293
|
+
|
|
294
|
+
Verify cross-package consistency between `@markuplint/html-spec` and related packages.
|
|
295
|
+
|
|
296
|
+
1. **Content model categories**: Verify that category names in `src/spec-common.contents.json`
|
|
297
|
+
match the `Category` enum in `@markuplint/ml-spec/schemas/content-models.schema.json`
|
|
298
|
+
2. **Element membership**: Verify that elements listed in content categories have
|
|
299
|
+
corresponding `src/spec.<element>.json` files and consistent `contentModel` definitions
|
|
300
|
+
3. **Attribute types**: Check that attribute type references (e.g., `"URL"`, `"<color>"`)
|
|
301
|
+
exist in `@markuplint/types`' definitions registry
|
|
302
|
+
4. **Schema validation**: Run `yarn workspace @markuplint/html-spec run test` to validate
|
|
303
|
+
all source JSON files against `@markuplint/ml-spec` schemas
|
|
304
|
+
|
|
305
|
+
Report results as:
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
| # | Check | Status | Notes |
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Testing Requirements for Spec Changes
|
|
312
|
+
|
|
313
|
+
Spec data changes propagate to multiple test suites. Always run `yarn test`
|
|
314
|
+
(full suite) before committing.
|
|
315
|
+
|
|
316
|
+
### Test Matrix
|
|
317
|
+
|
|
318
|
+
| Change type | Primary test file | Also check |
|
|
319
|
+
| ----------------------------------- | -------------------------------------------- | ------------------------------------------------------------- |
|
|
320
|
+
| ARIA (implicitRole, permittedRoles) | `rules/src/wai-aria/index.spec.ts` | `ml-spec/src/algorithm/aria/get-permitted-roles-spec.spec.ts` |
|
|
321
|
+
| Attributes (new/changed) | `rules/src/invalid-attr/index.spec.ts` | Existing tests with changed enum error messages |
|
|
322
|
+
| Content model | `rules/src/permitted-contents/index.spec.ts` | — |
|
|
323
|
+
|
|
324
|
+
### Cross-Package Impact
|
|
325
|
+
|
|
326
|
+
- **Hardcoded role arrays**: `ml-spec/.../get-permitted-roles-spec.spec.ts` has
|
|
327
|
+
hardcoded `permittedRoles` for img, button, input, form, etc. Update these
|
|
328
|
+
when changing `permittedRoles` in html-spec.
|
|
329
|
+
- **Enum error messages**: Adding a value to an enum (e.g., button `command`)
|
|
330
|
+
changes the error message string in existing `invalid-attr` tests.
|
|
331
|
+
|
|
332
|
+
### Test Conventions
|
|
333
|
+
|
|
334
|
+
- `toStrictEqual` with exact `{ severity, line, col, message, raw }` — never `toBeGreaterThan(0)`
|
|
335
|
+
- Always include both valid (empty violations) and invalid (exact violation) cases
|
|
336
|
+
- ARIA version in tests: `{ rule: { options: { version: '1.1' } } }`
|
|
337
|
+
- Some roles require ARIA attributes: focusable `separator` → `aria-valuenow`,
|
|
338
|
+
`meter` → `aria-valuenow`
|
|
339
|
+
|
|
340
|
+
## Rules
|
|
341
|
+
|
|
342
|
+
1. **`index.json` is generated -- never edit it directly.** Always modify `src/` files and regenerate.
|
|
343
|
+
2. **Manual spec data takes precedence over MDN data.** Attributes defined in `src/spec.*.json` override same-named MDN-sourced attributes. Use this to correct inaccurate MDN data.
|
|
344
|
+
3. **Minor MDN description changes should be committed as-is.** Do not attempt to override cosmetic upstream improvements.
|
|
345
|
+
4. **Content model category membership is critical.** A missing element in a category causes `permitted-contents` rule false positives in downstream linting.
|
|
346
|
+
5. **Always run tests after changes.** Schema validation catches structural errors before they propagate to downstream packages.
|
|
347
|
+
6. **Reference authoritative specs for significant changes.** Use WebSearch to verify against HTML Living Standard, WAI-ARIA, and HTML-ARIA before modifying manual spec files.
|
|
348
|
+
7. **Use conventional commit prefixes based on the nature of the change:**
|
|
349
|
+
|
|
350
|
+
| Change type | Prefix | Example |
|
|
351
|
+
| ------------------------ | ------- | ------------------------------------------------- |
|
|
352
|
+
| Description updates only | `chore` | `chore(html-spec): update role descriptions` |
|
|
353
|
+
| Attribute/spec additions | `feat` | `feat(html-spec): add input switch attribute` |
|
|
354
|
+
| Spec data corrections | `fix` | `fix(html-spec): correct ARIA mapping for button` |
|
|
355
|
+
|
|
356
|
+
8. **Separate spec changes into individual PRs.** Each specification change (new attribute, ARIA mapping fix, etc.) should be on its own branch and PR. Description-only updates can be batched into a single PR.
|
|
357
|
+
9. **Run `yarn test` (full suite) before committing.** Spec changes affect `@markuplint/rules` and `@markuplint/ml-spec` tests.
|
|
358
|
+
10. **Keep `permittedRoles` arrays in alphabetical order.**
|