@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
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Maintenance Guide
|
|
2
|
+
|
|
3
|
+
This is a practical operations and maintenance guide for contributors working on this package.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
| ------------------------------------------------------- | ------------------------------------------------- |
|
|
9
|
+
| `yarn workspace @markuplint/html-spec run gen` | Full generation: build + Prettier formatting |
|
|
10
|
+
| `yarn workspace @markuplint/html-spec run gen:build` | Run `node build.mjs` to generate index.json |
|
|
11
|
+
| `yarn workspace @markuplint/html-spec run gen:prettier` | Format index.json with Prettier |
|
|
12
|
+
| `yarn up:gen` | Regenerate all spec packages from repository root |
|
|
13
|
+
|
|
14
|
+
## Build Pipeline Overview
|
|
15
|
+
|
|
16
|
+
The generation process (`gen`) performs two steps in sequence via `npm-run-all`:
|
|
17
|
+
|
|
18
|
+
1. **`gen:build`** -- Executes `build.mjs`, which calls the `main()` function from
|
|
19
|
+
`@markuplint/spec-generator`. This reads all `src/spec.*.json` files, merges them
|
|
20
|
+
with scraped MDN data and the common attribute/content files, appends obsolete
|
|
21
|
+
element stubs, and writes the consolidated output to `index.json`.
|
|
22
|
+
2. **`gen:prettier`** -- Runs Prettier on `index.json` to ensure consistent formatting
|
|
23
|
+
across regenerations.
|
|
24
|
+
|
|
25
|
+
The build is network-dependent because `@markuplint/spec-generator` fetches live data
|
|
26
|
+
from MDN for each element (descriptions, compatibility flags, attribute metadata).
|
|
27
|
+
Expect the build to take several minutes on a clean run.
|
|
28
|
+
|
|
29
|
+
## Element Name Resolution
|
|
30
|
+
|
|
31
|
+
The build script derives element names from file names using a regex replacement:
|
|
32
|
+
|
|
33
|
+
- `spec.div.json` becomes element name `div`
|
|
34
|
+
- `spec.svg_circle.json` becomes element name `svg_circle`, which is later resolved
|
|
35
|
+
to namespace `svg:circle` by `resolveNamespace()`
|
|
36
|
+
- Heading elements (`h1` through `h6`) are mapped to the MDN URL path `Heading_Elements`
|
|
37
|
+
|
|
38
|
+
This naming convention is critical. Any deviation from the `spec.<name>.json` pattern
|
|
39
|
+
will cause the element to be silently excluded from the build output.
|
|
40
|
+
|
|
41
|
+
## Common Recipes
|
|
42
|
+
|
|
43
|
+
### 1. Adding a New HTML Element
|
|
44
|
+
|
|
45
|
+
1. Create `src/spec.<element>.json` (e.g., `src/spec.dialog.json`)
|
|
46
|
+
2. Define the specification with at minimum:
|
|
47
|
+
- `contentModel` with `contents`
|
|
48
|
+
- `globalAttrs` (typically `#HTMLGlobalAttrs`, `#GlobalEventAttrs`, `#ARIAAttrs` all set to `true`)
|
|
49
|
+
- `attributes` (element-specific attributes, can be empty `{}`)
|
|
50
|
+
- `aria` with `implicitRole` and `permittedRoles`
|
|
51
|
+
3. Add comments at the top referencing the relevant spec URLs:
|
|
52
|
+
```
|
|
53
|
+
// https://html.spec.whatwg.org/multipage/...
|
|
54
|
+
// https://www.w3.org/TR/html-aria/#el-<element>
|
|
55
|
+
// https://w3c.github.io/html-aria/#el-<element>
|
|
56
|
+
```
|
|
57
|
+
4. If the element belongs to any content categories (flow, phrasing, etc.), add it
|
|
58
|
+
to the appropriate categories in `src/spec-common.contents.json` -- otherwise
|
|
59
|
+
`@markuplint/rules`' `permitted-contents` rule will not recognize it as valid
|
|
60
|
+
content in parent elements that allow those categories
|
|
61
|
+
5. Run `yarn workspace @markuplint/html-spec run gen`
|
|
62
|
+
6. Verify the element appears correctly in `index.json`
|
|
63
|
+
|
|
64
|
+
### 2. Modifying an Existing Element's Attributes
|
|
65
|
+
|
|
66
|
+
1. Open the relevant `src/spec.<element>.json`
|
|
67
|
+
2. Add or modify entries in the `attributes` object
|
|
68
|
+
3. For conditional attributes, add a `condition` field with a CSS selector:
|
|
69
|
+
```json
|
|
70
|
+
"accept": {
|
|
71
|
+
"type": { "token": "Accept", "separator": "comma" },
|
|
72
|
+
"condition": "[type='file' i]"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
4. Run `yarn workspace @markuplint/html-spec run gen`
|
|
76
|
+
5. Check `index.json` to confirm the attribute appears with correct metadata
|
|
77
|
+
|
|
78
|
+
### 3. Adding an SVG Element
|
|
79
|
+
|
|
80
|
+
1. Create `src/spec.svg_<localname>.json` (e.g., `src/spec.svg_circle.json`)
|
|
81
|
+
2. The element name will be inferred as `svg:<localname>` (e.g., `svg:circle`)
|
|
82
|
+
3. Use SVG-specific global attribute categories:
|
|
83
|
+
```json
|
|
84
|
+
"globalAttrs": {
|
|
85
|
+
"#HTMLGlobalAttrs": true,
|
|
86
|
+
"#GlobalEventAttrs": true,
|
|
87
|
+
"#ARIAAttrs": true,
|
|
88
|
+
"#SVGCoreAttrs": ["id", "tabindex", "autofocus", "lang", "xml:space", "class", "style"],
|
|
89
|
+
"#SVGPresentationAttrs": [...]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
4. For ARIA, SVG elements typically use AAM references:
|
|
93
|
+
```json
|
|
94
|
+
"aria": {
|
|
95
|
+
"implicitRole": "group",
|
|
96
|
+
"permittedRoles": { "core-aam": true, "graphics-aam": true }
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
5. Run `yarn workspace @markuplint/html-spec run gen`
|
|
100
|
+
|
|
101
|
+
### 4. Updating Global Attribute Categories
|
|
102
|
+
|
|
103
|
+
1. Edit `src/spec-common.attributes.json`
|
|
104
|
+
2. Each top-level key is a category (e.g., `#HTMLGlobalAttrs`)
|
|
105
|
+
3. Add, remove, or modify attribute definitions within the category
|
|
106
|
+
4. Run `yarn workspace @markuplint/html-spec run gen`
|
|
107
|
+
5. All elements referencing that category will pick up the changes
|
|
108
|
+
|
|
109
|
+
### 5. Adding or Updating Content Model Categories
|
|
110
|
+
|
|
111
|
+
1. Edit `src/spec-common.contents.json`
|
|
112
|
+
2. Add a new entry to the `models` object or add elements to existing categories:
|
|
113
|
+
```json
|
|
114
|
+
"#newCategory": ["element1", "element2", "svg|element3"]
|
|
115
|
+
```
|
|
116
|
+
3. Use `svg|<name>` prefix for SVG elements in category lists
|
|
117
|
+
4. Reference the new category in element specs: `":model(newCategory)"`
|
|
118
|
+
5. Run `yarn workspace @markuplint/html-spec run gen`
|
|
119
|
+
|
|
120
|
+
**Important:** Content model categories directly affect downstream behavior:
|
|
121
|
+
|
|
122
|
+
- `@markuplint/ml-spec` resolves category names to element lists at runtime via
|
|
123
|
+
`contentModelCategoryToTagNames()`. A missing element in a category means it
|
|
124
|
+
won't be recognized as valid content where that category is permitted.
|
|
125
|
+
- `@markuplint/rules`' `permitted-contents` rule validates child elements against
|
|
126
|
+
these patterns. If a new element is not added to its categories, it will be
|
|
127
|
+
flagged as an unexpected child.
|
|
128
|
+
- The `#palpable` category is used by the `no-empty-palpable-content` rule.
|
|
129
|
+
- New category names must also conform to the `Category` enum in
|
|
130
|
+
`@markuplint/ml-spec/schemas/content-models.schema.json`.
|
|
131
|
+
|
|
132
|
+
### 6. Updating ARIA Mappings
|
|
133
|
+
|
|
134
|
+
1. Open the relevant `src/spec.<element>.json`
|
|
135
|
+
2. Modify the `aria` object:
|
|
136
|
+
- Change `implicitRole` for the default role
|
|
137
|
+
- Update `permittedRoles` array
|
|
138
|
+
- Add/modify `conditions` for context-dependent ARIA
|
|
139
|
+
- Add version-specific overrides under `"1.1"` or `"1.2"` keys
|
|
140
|
+
3. Reference:
|
|
141
|
+
- HTML-ARIA: https://w3c.github.io/html-aria/
|
|
142
|
+
- WAI-ARIA 1.3: https://w3c.github.io/aria/
|
|
143
|
+
4. Run `yarn workspace @markuplint/html-spec run gen`
|
|
144
|
+
|
|
145
|
+
**Note on ARIA versions:** WAI-ARIA 1.1 and 1.2 are finalized Recommendations --
|
|
146
|
+
their role/property definitions are stable and will not change. Version-specific
|
|
147
|
+
overrides in manual spec files (e.g., `"1.1": { "permittedRoles": [...] }`) exist
|
|
148
|
+
to preserve backward-compatible behavior for these fixed versions. WAI-ARIA 1.3 is
|
|
149
|
+
still a Working Draft and is the primary source of ongoing ARIA changes in
|
|
150
|
+
`yarn up:gen`.
|
|
151
|
+
|
|
152
|
+
### 7. Periodic Specification Update
|
|
153
|
+
|
|
154
|
+
The specification data in this package is kept up-to-date by regenerating `index.json`,
|
|
155
|
+
which fetches the latest data from MDN and W3C. This is the standard workflow for
|
|
156
|
+
incorporating upstream specification changes.
|
|
157
|
+
|
|
158
|
+
**Step 1: Regenerate and review the diff**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
yarn up:gen
|
|
162
|
+
git diff packages/@markuplint/html-spec/index.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`index.json` will reflect the latest MDN-scraped data. Review the diff to identify
|
|
166
|
+
what has changed. Typical changes include:
|
|
167
|
+
|
|
168
|
+
- **Minor description rewording** -- MDN frequently refines element/attribute/role
|
|
169
|
+
descriptions. These are cosmetic and can be committed as-is.
|
|
170
|
+
- **New attributes added** -- MDN may surface newly standardized or experimental
|
|
171
|
+
attributes (e.g., `interestfor`, `switch`). These come from MDN scraping and
|
|
172
|
+
require no manual spec file changes.
|
|
173
|
+
- **Flag changes** -- Attributes may transition between `experimental`, `deprecated`,
|
|
174
|
+
and `nonStandard` status as standards evolve.
|
|
175
|
+
- **Significant specification changes** -- For example, an ARIA property changing
|
|
176
|
+
from `required` to `inherited`, or a content model restructuring.
|
|
177
|
+
- **ARIA changes** -- The ARIA role and property definitions in `index.json` are
|
|
178
|
+
scraped from W3C specifications. WAI-ARIA 1.1 and 1.2 are finalized
|
|
179
|
+
Recommendations and will not change. WAI-ARIA 1.3, however, is still a Working
|
|
180
|
+
Draft, so `yarn up:gen` will regularly pull in new or revised role definitions,
|
|
181
|
+
property requirements, and description updates from the evolving 1.3 spec.
|
|
182
|
+
|
|
183
|
+
**Step 2: Handle minor changes**
|
|
184
|
+
|
|
185
|
+
For description rewording and other cosmetic changes, no action is needed beyond
|
|
186
|
+
committing the updated `index.json`. These changes reflect upstream improvements
|
|
187
|
+
and should be accepted as-is.
|
|
188
|
+
|
|
189
|
+
> **Caution -- ARIA version duplication:** `index.json` contains role definitions for
|
|
190
|
+
> WAI-ARIA 1.1, 1.2, and 1.3, so many strings appear three times. When editing
|
|
191
|
+
> descriptions or properties, **do not use `replace_all`** -- it will modify all three
|
|
192
|
+
> versions simultaneously. Always target the specific version block you intend to change.
|
|
193
|
+
|
|
194
|
+
**Step 3: Handle significant specification changes**
|
|
195
|
+
|
|
196
|
+
If the diff reveals a substantive change to element behavior, ARIA mappings, or
|
|
197
|
+
content models, the manual spec files may need updating:
|
|
198
|
+
|
|
199
|
+
1. Identify which elements are affected
|
|
200
|
+
2. Update the relevant `src/spec.*.json` or `src/spec-common.*.json` files to
|
|
201
|
+
reflect the new specification. In rare cases, `@markuplint/ml-spec` schemas
|
|
202
|
+
or types may also need updating.
|
|
203
|
+
3. Regenerate to incorporate the manual spec changes:
|
|
204
|
+
```bash
|
|
205
|
+
yarn up:gen
|
|
206
|
+
```
|
|
207
|
+
4. **Idempotency verification** -- Confirm your spec file changes produce stable
|
|
208
|
+
output before committing:
|
|
209
|
+
```bash
|
|
210
|
+
# Stage spec files and index.json
|
|
211
|
+
git add packages/@markuplint/html-spec/src/spec.*.json packages/@markuplint/html-spec/index.json
|
|
212
|
+
# Regenerate
|
|
213
|
+
yarn up:gen
|
|
214
|
+
# Check that the attributes you changed are NOT in the diff (= stable output)
|
|
215
|
+
git diff packages/@markuplint/html-spec/index.json | grep '"your-attr"'
|
|
216
|
+
# If stable, discard the regenerated file and use the staged version
|
|
217
|
+
git checkout packages/@markuplint/html-spec/index.json
|
|
218
|
+
```
|
|
219
|
+
If the diff shows unexpected changes for your attribute, it means the spec file
|
|
220
|
+
and the generator produce different values -- investigate before committing.
|
|
221
|
+
|
|
222
|
+
**Step 4: Commit and PR**
|
|
223
|
+
|
|
224
|
+
Stage and commit `index.json` (and any modified `src/` files if applicable).
|
|
225
|
+
|
|
226
|
+
Use conventional commit prefixes based on the nature of the change:
|
|
227
|
+
|
|
228
|
+
| Change type | Prefix | Example |
|
|
229
|
+
| ------------------------ | ------- | ------------------------------------------------- |
|
|
230
|
+
| Description updates only | `chore` | `chore(html-spec): update role descriptions` |
|
|
231
|
+
| Attribute/spec additions | `feat` | `feat(html-spec): add input switch attribute` |
|
|
232
|
+
| Spec data corrections | `fix` | `fix(html-spec): correct ARIA mapping for button` |
|
|
233
|
+
|
|
234
|
+
**PR separation:** Each specification change (new attribute, ARIA mapping fix, etc.)
|
|
235
|
+
should be on its own branch and PR. Description-only updates can be batched into a
|
|
236
|
+
single PR.
|
|
237
|
+
|
|
238
|
+
This process may seem involved, but reviewing the diff is essential for understanding
|
|
239
|
+
what has changed in web standards and ensuring the spec data remains accurate.
|
|
240
|
+
|
|
241
|
+
### 8. Marking an Element as Obsolete
|
|
242
|
+
|
|
243
|
+
Elements can be marked obsolete in two ways:
|
|
244
|
+
|
|
245
|
+
- **Via the hardcoded list**: Add the element name to the `obsoleteList` array in `packages/@markuplint/spec-generator/src/html-elements.ts`
|
|
246
|
+
- **Via manual spec**: Set `"obsolete": true` in the element's spec file
|
|
247
|
+
|
|
248
|
+
Obsolete elements automatically get:
|
|
249
|
+
|
|
250
|
+
- `cite` pointing to the HTML spec obsolete features section
|
|
251
|
+
- `contents: true` (any content allowed)
|
|
252
|
+
- `permittedRoles: true`, `implicitRole: false`
|
|
253
|
+
|
|
254
|
+
## File Classification
|
|
255
|
+
|
|
256
|
+
### Editable Files (modify these)
|
|
257
|
+
|
|
258
|
+
| File | Description |
|
|
259
|
+
| --------------------------------- | -------------------------------------- |
|
|
260
|
+
| `src/spec.*.json` | Per-element specifications (177 files) |
|
|
261
|
+
| `src/spec-common.attributes.json` | Global attribute category definitions |
|
|
262
|
+
| `src/spec-common.contents.json` | Content model category macros |
|
|
263
|
+
| `build.mjs` | Build script configuration |
|
|
264
|
+
|
|
265
|
+
### Generated Files (DO NOT EDIT)
|
|
266
|
+
|
|
267
|
+
| File | Description |
|
|
268
|
+
| ------------ | ---------------------------------------------- |
|
|
269
|
+
| `index.json` | Consolidated specification output (48K+ lines) |
|
|
270
|
+
|
|
271
|
+
### Static Files
|
|
272
|
+
|
|
273
|
+
| File | Description |
|
|
274
|
+
| ------------ | ---------------------------- |
|
|
275
|
+
| `index.js` | CommonJS entry point |
|
|
276
|
+
| `index.d.ts` | TypeScript type declarations |
|
|
277
|
+
|
|
278
|
+
## Testing
|
|
279
|
+
|
|
280
|
+
### Schema Validation Tests
|
|
281
|
+
|
|
282
|
+
The test file `test/structure.spec.mjs` validates:
|
|
283
|
+
|
|
284
|
+
1. **Structure test**: Ensures all elements can be resolved via `resolveNamespace()` and `getAttrSpecsByNames()`
|
|
285
|
+
2. **Schema tests**: Validates source JSON files against JSON schemas from `@markuplint/ml-spec`:
|
|
286
|
+
- `spec.*.json` files against `element.schema.json` (with aria, content-models, global-attributes, attributes, and types schemas)
|
|
287
|
+
- `spec-common.attributes.json` against `global-attributes.schema.json`
|
|
288
|
+
|
|
289
|
+
The schema validation uses `ajv` (Another JSON Schema Validator) with multiple
|
|
290
|
+
interrelated schemas loaded together. The element schema references the aria,
|
|
291
|
+
content-models, global-attributes, attributes, and types schemas, so all must
|
|
292
|
+
be registered in the same `Ajv` instance.
|
|
293
|
+
|
|
294
|
+
Run tests:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
yarn workspace @markuplint/html-spec run test
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Or from the repository root:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
yarn test --scope @markuplint/html-spec
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Manual Verification
|
|
307
|
+
|
|
308
|
+
After regeneration, it is good practice to spot-check `index.json` for the
|
|
309
|
+
elements you changed. Because the file exceeds 48,000 lines, use targeted
|
|
310
|
+
searches rather than manual scrolling:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# Find a specific element's entry
|
|
314
|
+
grep -n '"name": "dialog"' index.json
|
|
315
|
+
|
|
316
|
+
# Check an attribute was added
|
|
317
|
+
grep -A5 '"accept"' index.json
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Dependency Management
|
|
321
|
+
|
|
322
|
+
### Production Dependency
|
|
323
|
+
|
|
324
|
+
- **`@markuplint/ml-spec`**: Provides type definitions (`Cites`, `ElementSpec`, `SpecDefs`) and JSON schemas used for validation. When `ml-spec` types change, element spec files may need updating to match.
|
|
325
|
+
|
|
326
|
+
### Dev Dependencies
|
|
327
|
+
|
|
328
|
+
- **`@markuplint/spec-generator`**: The build tool. Updates may change:
|
|
329
|
+
- How MDN pages are scraped (if MDN layout changes)
|
|
330
|
+
- Which ARIA spec versions are fetched
|
|
331
|
+
- The output format of `index.json`
|
|
332
|
+
- **`@markuplint/test-tools`**: Test utilities. Updates are generally safe.
|
|
333
|
+
|
|
334
|
+
### When Updating Dependencies
|
|
335
|
+
|
|
336
|
+
1. Always regenerate after updating `@markuplint/spec-generator`: `yarn workspace @markuplint/html-spec run gen`
|
|
337
|
+
2. Review `index.json` diff carefully for unexpected changes
|
|
338
|
+
3. Run tests to ensure schema validation passes
|
|
339
|
+
|
|
340
|
+
## Troubleshooting
|
|
341
|
+
|
|
342
|
+
### Build Failure: Network Error During Generation
|
|
343
|
+
|
|
344
|
+
**Symptom**: `gen:build` fails with fetch errors.
|
|
345
|
+
**Cause**: MDN or W3C servers are unreachable or have changed their page structure.
|
|
346
|
+
**Resolution**:
|
|
347
|
+
|
|
348
|
+
- Check network connectivity
|
|
349
|
+
- Failed fetches are cached as empty strings; the build will continue but affected elements will have missing metadata
|
|
350
|
+
- If MDN page structure changed, `@markuplint/spec-generator` scraping selectors may need updating
|
|
351
|
+
|
|
352
|
+
### Schema Validation Error
|
|
353
|
+
|
|
354
|
+
**Symptom**: Tests fail with "X is invalid" errors.
|
|
355
|
+
**Cause**: A spec file doesn't conform to the JSON schema.
|
|
356
|
+
**Resolution**:
|
|
357
|
+
|
|
358
|
+
- Check the reported file against the referenced schema
|
|
359
|
+
- Common issues: missing required fields, wrong type for a field, invalid enum values
|
|
360
|
+
- Schemas are in `packages/@markuplint/ml-spec/schemas/`
|
|
361
|
+
|
|
362
|
+
### Unexpected Changes in index.json
|
|
363
|
+
|
|
364
|
+
**Symptom**: `index.json` diff shows unexpected additions or removals after regeneration.
|
|
365
|
+
**Cause**: External data sources (MDN, W3C) have been updated.
|
|
366
|
+
**Resolution**:
|
|
367
|
+
|
|
368
|
+
- Review changes carefully; MDN updates are generally improvements
|
|
369
|
+
- If a change is incorrect, override it in the manual spec file (manual data takes precedence)
|
|
370
|
+
- Check if MDN page URLs have changed (element pages may have been restructured)
|
|
371
|
+
|
|
372
|
+
### Missing Element After Regeneration
|
|
373
|
+
|
|
374
|
+
**Symptom**: An element disappears from `index.json`.
|
|
375
|
+
**Cause**: The source spec file may have been deleted or renamed incorrectly.
|
|
376
|
+
**Resolution**:
|
|
377
|
+
|
|
378
|
+
- Verify the file exists: `src/spec.<element>.json`
|
|
379
|
+
- Check file naming: must match `spec.*.json` glob pattern
|
|
380
|
+
- For SVG: must be `spec.svg_<name>.json`
|
|
381
|
+
|
|
382
|
+
### JSON Comment Syntax Errors
|
|
383
|
+
|
|
384
|
+
**Symptom**: Build fails with a JSON parse error.
|
|
385
|
+
**Cause**: Spec files support JavaScript-style comments (`//` and `/* */`) via
|
|
386
|
+
`strip-json-comments`, but other non-standard JSON syntax is not supported.
|
|
387
|
+
**Resolution**:
|
|
388
|
+
|
|
389
|
+
- Ensure trailing commas are not present
|
|
390
|
+
- Verify comment syntax uses `//` or `/* */` only
|
|
391
|
+
- Check for unbalanced braces or brackets
|
|
392
|
+
|
|
393
|
+
## Related Documentation
|
|
394
|
+
|
|
395
|
+
- [Element Specification Format](./element-spec-format.md) -- Comprehensive
|
|
396
|
+
reference for the JSON element spec file format, content model patterns,
|
|
397
|
+
attribute definitions, and ARIA integration
|