@adobe/design-data-spec 0.8.0 → 0.10.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/components/accordion.json +18 -1
- package/components/action-bar.json +12 -1
- package/components/action-button.json +19 -1
- package/components/action-group.json +12 -1
- package/components/alert-banner.json +11 -1
- package/components/alert-dialog.json +19 -1
- package/components/avatar-group.json +4 -1
- package/components/avatar.json +4 -1
- package/components/badge.json +4 -1
- package/components/body.json +3 -0
- package/components/bottom-navigation-android.json +17 -0
- package/components/breadcrumbs.json +19 -2
- package/components/button-group.json +12 -1
- package/components/button.json +21 -3
- package/components/calendar.json +22 -0
- package/components/cards.json +18 -1
- package/components/checkbox-group.json +17 -1
- package/components/checkbox.json +24 -1
- package/components/close-button.json +19 -1
- package/components/coach-indicator.json +4 -1
- package/components/coach-mark.json +13 -1
- package/components/code.json +3 -0
- package/components/color-area.json +24 -1
- package/components/color-handle.json +13 -1
- package/components/color-loupe.json +4 -1
- package/components/color-slider.json +24 -1
- package/components/color-wheel.json +24 -1
- package/components/combo-box.json +24 -1
- package/components/contextual-help.json +18 -1
- package/components/date-picker.json +23 -1
- package/components/detail.json +3 -0
- package/components/divider.json +4 -1
- package/components/drop-zone.json +18 -1
- package/components/field-label.json +4 -1
- package/components/heading.json +3 -0
- package/components/help-text.json +5 -2
- package/components/illustrated-message.json +4 -1
- package/components/in-field-progress-button.json +18 -0
- package/components/in-field-progress-circle.json +4 -1
- package/components/in-line-alert.json +11 -1
- package/components/link.json +19 -1
- package/components/list-view.json +18 -1
- package/components/menu.json +19 -1
- package/components/meter.json +4 -1
- package/components/number-field.json +24 -1
- package/components/opacity-checkerboard.json +4 -1
- package/components/picker.json +24 -1
- package/components/popover.json +12 -1
- package/components/progress-bar.json +4 -1
- package/components/progress-circle.json +4 -1
- package/components/radio-button.json +24 -1
- package/components/radio-group.json +17 -1
- package/components/rating.json +24 -1
- package/components/scroll-zoom-bar.json +12 -0
- package/components/search-field.json +28 -1
- package/components/segmented-control.json +18 -1
- package/components/select-box.json +18 -1
- package/components/side-navigation.json +18 -1
- package/components/slider.json +24 -1
- package/components/standard-dialog.json +19 -1
- package/components/standard-panel.json +3 -0
- package/components/status-light.json +4 -1
- package/components/steplist.json +18 -1
- package/components/swatch-group.json +12 -1
- package/components/swatch.json +18 -1
- package/components/switch.json +19 -1
- package/components/tab-bar-ios.json +17 -0
- package/components/table.json +23 -1
- package/components/tabs.json +18 -1
- package/components/tag-field.json +18 -1
- package/components/tag-group.json +18 -1
- package/components/tag.json +18 -1
- package/components/takeover-dialog.json +19 -1
- package/components/text-area.json +28 -1
- package/components/text-field.json +28 -1
- package/components/thumbnail.json +4 -1
- package/components/title.json +40 -10
- package/components/toast.json +13 -1
- package/components/tooltip.json +17 -1
- package/components/tray.json +11 -0
- package/components/tree-view.json +19 -1
- package/conformance/README.md +7 -7
- package/conformance/invalid/SPEC-001/dataset.json +10 -0
- package/conformance/invalid/SPEC-001/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-002/dataset.json +16 -0
- package/conformance/invalid/SPEC-002/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-003/dataset.json +15 -0
- package/conformance/invalid/SPEC-003/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-004/dataset.json +15 -0
- package/conformance/invalid/SPEC-004/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-005/dataset.json +11 -0
- package/conformance/invalid/SPEC-005/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-006/dataset.json +15 -0
- package/conformance/invalid/SPEC-006/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-007/dataset.json +9 -0
- package/conformance/invalid/SPEC-007/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-008/dataset.json +25 -0
- package/conformance/invalid/SPEC-008/expected-errors.json +2 -1
- package/conformance/invalid/SPEC-009/dataset.json +12 -0
- package/conformance/invalid/SPEC-009/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-010/dataset.json +12 -0
- package/conformance/invalid/SPEC-011/dataset.json +25 -0
- package/conformance/invalid/SPEC-012/dataset.json +16 -0
- package/conformance/invalid/SPEC-013/dataset.json +11 -0
- package/conformance/invalid/SPEC-014/dataset.json +12 -0
- package/conformance/invalid/SPEC-014/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-015/dataset.json +22 -0
- package/conformance/invalid/SPEC-015/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-015/tokens.tokens.json +19 -0
- package/conformance/invalid/SPEC-016/dataset.json +11 -0
- package/conformance/invalid/SPEC-016/expected-errors.json +2 -2
- package/conformance/invalid/SPEC-017/dataset.json +10 -0
- package/conformance/invalid/SPEC-024/dataset.json +4 -3
- package/conformance/invalid/SPEC-024/expected-errors.json +2 -2
- package/conformance/invalid/SPEC-025/dataset.json +12 -0
- package/conformance/invalid/SPEC-025/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-026/dataset.json +18 -0
- package/conformance/invalid/SPEC-026/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-028/dataset.json +21 -0
- package/conformance/invalid/SPEC-028/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-029/dataset.json +20 -0
- package/conformance/invalid/SPEC-029/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-030/dataset.json +15 -0
- package/conformance/invalid/SPEC-030/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-031/dataset.json +17 -0
- package/conformance/invalid/SPEC-031/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-032/dataset.json +27 -0
- package/conformance/invalid/SPEC-032/expected-errors.json +15 -0
- package/conformance/resolution/base-fallback/expected.json +1 -1
- package/conformance/resolution/product-layer-wins/expected.json +5 -0
- package/conformance/resolution/product-layer-wins/input/tokens.tokens.json +7 -0
- package/conformance/resolution/product-layer-wins/product-context.json +11 -0
- package/conformance/resolution/product-layer-wins/query.json +4 -0
- package/conformance/resolution/specificity-wins/expected.json +1 -1
- package/conformance/valid/SPEC-014/dataset.json +12 -0
- package/conformance/valid/SPEC-016/dataset.json +16 -0
- package/conformance/valid/SPEC-025/dataset.json +24 -0
- package/conformance/valid/SPEC-026/dataset.json +15 -0
- package/conformance/valid/SPEC-028/dataset.json +21 -0
- package/conformance/valid/SPEC-029/dataset.json +24 -0
- package/conformance/valid/SPEC-030/dataset.json +17 -0
- package/conformance/valid/SPEC-031/dataset.json +24 -0
- package/conformance/valid/SPEC-032/dataset.json +16 -0
- package/conformance/valid/component-refs/README.md +5 -0
- package/conformance/valid/component-with-accessibility.json +32 -0
- package/fields/color-scheme.json +2 -2
- package/fields/contrast.json +2 -2
- package/fields/density.json +1 -1
- package/fields/scale.json +2 -2
- package/fields/size.json +1 -1
- package/package.json +4 -13
- package/rules/rules.yaml +40 -4
- package/schemas/accessibility.schema.json +60 -0
- package/schemas/component.schema.json +19 -0
- package/schemas/field.schema.json +2 -2
- package/schemas/manifest.schema.json +1 -1
- package/schemas/{dimension.schema.json → mode-set.schema.json} +3 -3
- package/schemas/token.schema.json +5 -5
- package/schemas/value-types/README.md +20 -0
- package/schemas/value-types/drop-shadow.schema.json +5 -5
- package/schemas/value-types/typography-scale.schema.json +2 -2
- package/schemas/value-types/typography.schema.json +5 -5
- package/spec/accessibility-adapters.md +219 -0
- package/spec/accessibility.md +219 -0
- package/spec/agent-surface.md +4 -4
- package/spec/cascade.md +7 -7
- package/spec/component-format.md +32 -0
- package/spec/document-blocks.md +1 -1
- package/spec/index.md +28 -20
- package/spec/manifest.md +2 -2
- package/spec/mode-sets.md +64 -0
- package/spec/query.md +18 -18
- package/spec/taxonomy.md +5 -5
- package/spec/token-format.md +12 -12
- package/spec/dimensions.md +0 -64
- package/src/canonical.js +0 -61
- package/src/validate.js +0 -190
- /package/conformance/resolution/alias-resolved-after-cascade/{dimensions → mode-sets}/color-scheme.json +0 -0
- /package/conformance/resolution/base-fallback/{dimensions → mode-sets}/color-scheme.json +0 -0
- /package/conformance/resolution/specificity-wins/{dimensions → mode-sets}/color-scheme.json +0 -0
package/spec/index.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Version:** `1.0.0-draft`\
|
|
4
4
|
**Status:** Draft — normative text and schemas may change before `1.0.0`.
|
|
5
5
|
|
|
6
|
-
This document is the top-level overview for the **Design Data Specification**: a machine-readable model for Spectrum design tokens,
|
|
6
|
+
This document is the top-level overview for the **Design Data Specification**: a machine-readable model for Spectrum design tokens, mode sets, platform manifests, and validation.
|
|
7
7
|
|
|
8
8
|
## Scope
|
|
9
9
|
|
|
@@ -12,14 +12,18 @@ The specification defines:
|
|
|
12
12
|
1. **Token format** — structured token identity (`name`), literal `value` or alias `$ref`, and lifecycle metadata ([Token format](token-format.md)).
|
|
13
13
|
2. **Taxonomy** — concept categories, token term vocabulary, formatting style, and the distinction between component anatomy and token objects ([Taxonomy](taxonomy.md)).
|
|
14
14
|
3. **Component format** — component declaration shape: API options, named content slots, anatomy parts, state model, and cross-reference validation rules ([Component format](component-format.md)).
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
* **Anatomy format** — anatomy part declaration shape: field constraints, canonical anatomy vocabulary, and cross-reference rules for token `anatomy` field values ([Anatomy format](anatomy-format.md)).
|
|
16
|
+
* **State model** — state declaration shape: trigger semantics, precedence and resolution algorithm, canonical state vocabulary, and cross-reference rules for token `state` field values ([State model](state-model.md)).
|
|
17
17
|
4. **Cascade and resolution** — layered data (foundation, platform, product), specificity, and how a context picks a winning value ([Cascade](cascade.md)).
|
|
18
|
-
5. **
|
|
18
|
+
5. **Mode Sets** — declared modes, defaults, and coverage expectations ([Mode Sets](mode-sets.md)).
|
|
19
19
|
6. **Platform manifest** — how a platform repo pins foundation data, filters tokens, and applies typed overrides ([Manifest](manifest.md)).
|
|
20
20
|
7. **Semantic diff** — change taxonomy, token identity rules, and property-level change tracking for comparing dataset versions ([Diff](diff.md)).
|
|
21
21
|
8. **Query notation** — filter syntax for selecting tokens by structured fields ([Query](query.md)).
|
|
22
|
-
9. **
|
|
22
|
+
9. **Accessibility** — component accessibility vocabulary: semantic role, interaction and keyboard intents, focus behavior, WCAG criteria, and state-level AT fields ([Accessibility](accessibility.md)).
|
|
23
|
+
* **Accessibility adapters** — informative platform adapter contracts: Web/ARIA, iOS UIAccessibility, Android AccessibilityNodeInfo, and voice/multimodal ([Accessibility adapters](accessibility-adapters.md)).
|
|
24
|
+
10. **Document blocks** — typed prose blocks attachable to tokens, components, and anatomy parts; makes design guidance machine-readable and agent-queryable ([Document blocks](document-blocks.md)).
|
|
25
|
+
11. **Agent-readable surface** — operations and transport contracts (CLI, MCP server, Agent Skill) for AI agents consuming spec-conformant design data; covers session primer, token resolution, validation, query, and component description ([Agent-readable surface](agent-surface.md)).
|
|
26
|
+
12. **Evolution** — deprecation lifecycle, migration windows, change classification, and legacy format contract ([Evolution](evolution.md)).
|
|
23
27
|
|
|
24
28
|
## Conformance
|
|
25
29
|
|
|
@@ -53,27 +57,31 @@ Full governance (compatibility tiers, migration, CLI `--spec-version`) is discus
|
|
|
53
57
|
|
|
54
58
|
## Normative references (sibling documents)
|
|
55
59
|
|
|
56
|
-
| Document
|
|
57
|
-
|
|
|
58
|
-
| [Token format](token-format.md)
|
|
59
|
-
| [Taxonomy](taxonomy.md)
|
|
60
|
-
| [Component format](component-format.md)
|
|
61
|
-
| [Anatomy format](anatomy-format.md)
|
|
62
|
-
| [State model](state-model.md)
|
|
63
|
-
| [Cascade](cascade.md)
|
|
64
|
-
| [
|
|
65
|
-
| [Manifest](manifest.md)
|
|
66
|
-
| [Product context](product-context.md)
|
|
67
|
-
| [Diff](diff.md)
|
|
68
|
-
| [Query](query.md)
|
|
69
|
-
| [
|
|
60
|
+
| Document | Role |
|
|
61
|
+
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| [Token format](token-format.md) | Token `name`, `value` / `$ref`, value types, lifecycle metadata. |
|
|
63
|
+
| [Taxonomy](taxonomy.md) | Concept categories, vocabulary, formatting, anatomy vs objects. |
|
|
64
|
+
| [Component format](component-format.md) | Component declaration: options, slots, anatomy (→ anatomy-format.md), states (→ state-model.md), lifecycle. |
|
|
65
|
+
| [Anatomy format](anatomy-format.md) | Anatomy part declarations: field constraints, canonical vocabulary, SPEC-020/SPEC-023/SPEC-024/SPEC-025. |
|
|
66
|
+
| [State model](state-model.md) | State declarations: trigger semantics, precedence algorithm, canonical vocabulary, SPEC-022/SPEC-026. |
|
|
67
|
+
| [Cascade](cascade.md) | Layers, specificity, resolution algorithm. |
|
|
68
|
+
| [Mode Sets](mode-sets.md) | Mode set declarations, built-in mode sets, coverage. |
|
|
69
|
+
| [Manifest](manifest.md) | Platform manifest fields and validation expectations. |
|
|
70
|
+
| [Product context](product-context.md) | Product-layer context document: rationale, overrides, and extensions. |
|
|
71
|
+
| [Diff](diff.md) | Semantic diff change taxonomy, token identity, property changes. |
|
|
72
|
+
| [Query](query.md) | Filter notation for selecting tokens by structured fields. |
|
|
73
|
+
| [Accessibility](accessibility.md) | Component accessibility vocabulary: role, intents, focusable, keyboardIntents, wcag, and state-level AT fields (SPEC-030/031). |
|
|
74
|
+
| [Accessibility adapters](accessibility-adapters.md) | Informative platform adapter contracts mapping foundation accessibility vocabulary to Web/ARIA, iOS, Android, and voice surfaces. |
|
|
75
|
+
| [Document blocks](document-blocks.md) | Typed prose blocks (purpose, guideline, accessibility, do-dont, examples) attachable to any entity. |
|
|
76
|
+
| [Agent-readable surface](agent-surface.md) | Transport contracts (CLI, MCP, Agent Skill) and operation catalog for AI agents consuming spec-conformant design data. |
|
|
77
|
+
| [Evolution](evolution.md) | Deprecation lifecycle, migration windows, change classification. |
|
|
70
78
|
|
|
71
79
|
## JSON Schema `$id` and versioning
|
|
72
80
|
|
|
73
81
|
**NORMATIVE:** Canonical schema documents use **versioned path** `$id` URIs so major revisions can coexist on the documentation host:
|
|
74
82
|
|
|
75
83
|
* Base: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/`
|
|
76
|
-
* Examples: `.../v0/token.schema.json`, `.../v0/
|
|
84
|
+
* Examples: `.../v0/token.schema.json`, `.../v0/mode-set.schema.json`, `.../v0/manifest.schema.json`
|
|
77
85
|
|
|
78
86
|
The **`v0`** segment denotes the **draft / pre-1.0** schema family aligned with spec version `1.0.0-draft`. A future **1.0.0** stable release MAY introduce `v1` paths without reusing `v0` URLs for incompatible shapes.
|
|
79
87
|
|
package/spec/manifest.md
CHANGED
|
@@ -22,7 +22,7 @@ A manifest **MUST** conform to [`manifest.schema.json`](../schemas/manifest.sche
|
|
|
22
22
|
| `include` | array of string | Semantic **queries** selecting subsets of foundation tokens to materialize. |
|
|
23
23
|
| `exclude` | array of string | Queries removing tokens from the included set. |
|
|
24
24
|
| `overrides` | array of object | Typed overrides; each entry **MUST** preserve the target token’s **value type**. |
|
|
25
|
-
| `extensions` | object | New tokens or
|
|
25
|
+
| `extensions` | object | New tokens or mode sets introduced at the platform layer. |
|
|
26
26
|
|
|
27
27
|
### `include` / `exclude`
|
|
28
28
|
|
|
@@ -38,7 +38,7 @@ Each override object **MUST** include enough information to identify a target to
|
|
|
38
38
|
|
|
39
39
|
### `extensions`
|
|
40
40
|
|
|
41
|
-
**RECOMMENDED:** `extensions` follows the same structural conventions as foundation token files (tokens,
|
|
41
|
+
**RECOMMENDED:** `extensions` follows the same structural conventions as foundation token files (tokens, mode sets) and **SHOULD** be validated with the same Layer 1 and Layer 2 rules.
|
|
42
42
|
|
|
43
43
|
#### `extensions.formatting`
|
|
44
44
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Mode Sets
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines how **mode sets** (axes such as color scheme, scale, contrast) are **declared**, assigned **defaults**, and validated for **coverage**.
|
|
6
|
+
|
|
7
|
+
## Mode Set declaration
|
|
8
|
+
|
|
9
|
+
A **mode set declaration** is a JSON object describing one axis of variation. It **MUST** conform to [`mode-set.schema.json`](../schemas/mode-set.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/mode-set.schema.json`).
|
|
10
|
+
|
|
11
|
+
### Required fields
|
|
12
|
+
|
|
13
|
+
| Field | Description |
|
|
14
|
+
| --------- | -------------------------------------------------------- |
|
|
15
|
+
| `name` | Stable identifier for the mode set (e.g. `colorScheme`). |
|
|
16
|
+
| `modes` | Array of allowed mode values (strings). |
|
|
17
|
+
| `default` | Default mode; **MUST** be a member of `modes`. |
|
|
18
|
+
|
|
19
|
+
### Optional fields
|
|
20
|
+
|
|
21
|
+
| Field | Description |
|
|
22
|
+
| ------------- | ------------------------------------ |
|
|
23
|
+
| `description` | Human-readable documentation. |
|
|
24
|
+
| `coverage` | Rules for mode coverage (see below). |
|
|
25
|
+
|
|
26
|
+
## Built-in mode sets
|
|
27
|
+
|
|
28
|
+
These mode sets are declared in the `mode-sets/` catalog (see [Mode Set catalog](#mode-set-catalog)) and **SHOULD** be used consistently across Spectrum-compatible datasets:
|
|
29
|
+
|
|
30
|
+
| `name` | `modes` | `default` | Notes |
|
|
31
|
+
| ------------- | ---------------------------- | --------- | --------------------------------------------------------------------------------- |
|
|
32
|
+
| `colorScheme` | `light`, `dark`, `wireframe` | `light` | Theme / appearance. |
|
|
33
|
+
| `scale` | `desktop`, `mobile` | `desktop` | Density scale. Legacy names; desktop = medium, mobile = large in W3C terminology. |
|
|
34
|
+
| `contrast` | `regular`, `high` | `regular` | Accessibility contrast level. |
|
|
35
|
+
|
|
36
|
+
## Mode Set catalog
|
|
37
|
+
|
|
38
|
+
The Spectrum foundation publishes mode set declarations as JSON files under `packages/design-data-spec/mode-sets/`. Each file conforms to [`mode-set.schema.json`](../schemas/mode-set.schema.json).
|
|
39
|
+
|
|
40
|
+
**NORMATIVE:** Tooling (validators, resolution engine) **MUST** load mode set declarations from the dataset's mode set catalog before performing specificity calculations or coverage validation.
|
|
41
|
+
|
|
42
|
+
**RECOMMENDED:** The catalog directory is named `mode-sets/` and is co-located with the dataset's spec package or manifest.
|
|
43
|
+
|
|
44
|
+
## Optional mode sets
|
|
45
|
+
|
|
46
|
+
Additional mode sets (e.g. `language`, `motion`) **MAY** be declared in a dataset's mode set catalog. Token name objects **MAY** include keys matching declared mode set names.
|
|
47
|
+
|
|
48
|
+
## Defaults and specificity
|
|
49
|
+
|
|
50
|
+
**NORMATIVE:** A token name object **omitting** a mode set field implies the token applies under the mode set's **`default`** mode for specificity and matching purposes unless the spec for that mode set states otherwise.
|
|
51
|
+
|
|
52
|
+
**NORMATIVE:** Only **non-default** mode set fields on the name object increase **semantic specificity** (see [Cascade](cascade.md)).
|
|
53
|
+
|
|
54
|
+
## Coverage validation
|
|
55
|
+
|
|
56
|
+
**RECOMMENDED:** If a mode set's `coverage` requires **peer modes** (e.g. defining `dark` requires `light`), validators implement rule **`SPEC-005`** (see `rules/rules.yaml`).
|
|
57
|
+
|
|
58
|
+
**RECOMMENDED:** Explicit **combination** tokens are used for rare cross-mode-set cases instead of inferring Cartesian products.
|
|
59
|
+
|
|
60
|
+
## References
|
|
61
|
+
|
|
62
|
+
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
|
63
|
+
* [#714 — Design Data Specification](https://github.com/adobe/spectrum-design-data/discussions/714)
|
|
64
|
+
* [#746 — Phase 2: Mode Set declarations (machine-readable)](https://github.com/adobe/spectrum-design-data/issues/746)
|
package/spec/query.md
CHANGED
|
@@ -8,29 +8,29 @@ This document defines the **query filter notation**: a concise syntax for select
|
|
|
8
8
|
|
|
9
9
|
A **filter expression** is a string that describes a set of conditions a token must satisfy to be included in the result. The notation uses `key=value` pairs combined with logical operators.
|
|
10
10
|
|
|
11
|
-
| Operator | Syntax
|
|
12
|
-
| -------- |
|
|
13
|
-
| `=` | `key=value`
|
|
14
|
-
| `!=` | `key!=value`
|
|
15
|
-
| `,` | `a=x,b=y`
|
|
16
|
-
| `\|` | `a=x\|b=y`
|
|
17
|
-
| `*` | `key=patt*ern`
|
|
11
|
+
| Operator | Syntax | Meaning |
|
|
12
|
+
| -------- | -------------- | ---------------------------------------------------- |
|
|
13
|
+
| `=` | `key=value` | Field `key` equals `value`. |
|
|
14
|
+
| `!=` | `key!=value` | Field `key` does not equal `value`. |
|
|
15
|
+
| `,` | `a=x,b=y` | Logical AND — both conditions must match. |
|
|
16
|
+
| `\|` | `a=x\|b=y` | Logical OR — at least one condition must match. |
|
|
17
|
+
| `*` | `key=patt*ern` | Glob wildcard — `*` matches zero or more characters. |
|
|
18
18
|
|
|
19
19
|
## Supported keys
|
|
20
20
|
|
|
21
21
|
**NORMATIVE:** Implementations **MUST** support the following keys:
|
|
22
22
|
|
|
23
|
-
| Key
|
|
24
|
-
|
|
|
25
|
-
| `property`
|
|
26
|
-
| `component`
|
|
27
|
-
| `variant`
|
|
28
|
-
| `state`
|
|
29
|
-
| `colorScheme`
|
|
30
|
-
| `scale`
|
|
31
|
-
| `contrast`
|
|
32
|
-
| `uuid`
|
|
33
|
-
| `$schema`
|
|
23
|
+
| Key | Source | Description |
|
|
24
|
+
| ------------- | ------------------ | ----------------------------------- |
|
|
25
|
+
| `property` | `name.property` | Token property identifier. |
|
|
26
|
+
| `component` | `name.component` | Associated component name. |
|
|
27
|
+
| `variant` | `name.variant` | Component variant. |
|
|
28
|
+
| `state` | `name.state` | Component or interaction state. |
|
|
29
|
+
| `colorScheme` | `name.colorScheme` | Color scheme mode set value. |
|
|
30
|
+
| `scale` | `name.scale` | Scale mode set value. |
|
|
31
|
+
| `contrast` | `name.contrast` | Contrast mode set value. |
|
|
32
|
+
| `uuid` | `uuid` | Token UUID (top-level field). |
|
|
33
|
+
| `$schema` | `$schema` | Token schema URL (top-level field). |
|
|
34
34
|
|
|
35
35
|
**NORMATIVE:** Implementations **MUST** reject filter expressions containing keys not listed above with a parse error. Future spec versions MAY add keys.
|
|
36
36
|
|
package/spec/taxonomy.md
CHANGED
|
@@ -139,15 +139,15 @@ Semantic fields describe identity, structure, and intent. They are used for quer
|
|
|
139
139
|
|
|
140
140
|
Semantic fields are those declared with `kind: "semantic"` in the field catalog. In Spectrum's foundation catalog, these are: `structure`, `substructure`, `component`, `anatomy`, `object`, `property`, `variant`, `state`, `orientation`, `position`, `size`, `density`, `shape`.
|
|
141
141
|
|
|
142
|
-
###
|
|
142
|
+
### Mode-set fields
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
Mode-set fields represent axes of variation that drive the [cascade](cascade.md) resolution algorithm and [specificity](cascade.md#semantic-specificity) calculation.
|
|
145
145
|
|
|
146
|
-
**NORMATIVE:**
|
|
146
|
+
**NORMATIVE:** Mode-set field values are validated against declared [mode set](mode-sets.md) modes with **strict** severity (error). An invalid mode value would silently fail to match any context during cascade resolution.
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
Mode-set fields are those declared with `kind: "mode-set"` in the field catalog, plus any additional mode set keys from the dataset's [mode set declarations](mode-sets.md). In Spectrum's foundation catalog, the standard mode-set fields are: `colorScheme`, `scale`, `contrast`.
|
|
149
149
|
|
|
150
|
-
See [
|
|
150
|
+
See [Mode Sets](mode-sets.md) for mode set declarations, modes, and defaults.
|
|
151
151
|
|
|
152
152
|
## Default serialization (legacy format)
|
|
153
153
|
|
package/spec/token-format.md
CHANGED
|
@@ -35,7 +35,7 @@ A token's `name` field **MAY** be a non-empty plain string instead of a name obj
|
|
|
35
35
|
|
|
36
36
|
**NORMATIVE:** String-named tokens **MUST** trigger rule SPEC-017 (severity: `warning`, category: `tech-debt`). The warning surfaces the token as tracked debt requiring future remediation.
|
|
37
37
|
|
|
38
|
-
**NORMATIVE:** String-named tokens **MUST NOT** participate in name-object cascade
|
|
38
|
+
**NORMATIVE:** String-named tokens **MUST NOT** participate in name-object cascade mode-set matching, specificity calculation, or registry vocabulary checks (SPEC-009 does not apply).
|
|
39
39
|
|
|
40
40
|
**RECOMMENDED:** Authors **SHOULD** treat string names as a temporary escape hatch and track a remediation plan. Each string-named token **SHOULD** eventually be given a structured name object, at which point SPEC-017 no longer fires.
|
|
41
41
|
|
|
@@ -45,9 +45,9 @@ The **name object** identifies the token in a structured way. Implementations us
|
|
|
45
45
|
|
|
46
46
|
**NORMATIVE fields** (all string unless noted):
|
|
47
47
|
|
|
48
|
-
The set of available name-object fields is declared in the design system's **field catalog** (`fields/` directory). Each field declaration conforms to [`field.schema.json`](../schemas/field.schema.json) and specifies its kind (`semantic` or `
|
|
48
|
+
The set of available name-object fields is declared in the design system's **field catalog** (`fields/` directory). Each field declaration conforms to [`field.schema.json`](../schemas/field.schema.json) and specifies its kind (`semantic` or `mode-set`), vocabulary registry, validation severity, and default serialization position. See [Taxonomy](taxonomy.md) for the full concept category hierarchy, component anatomy vs. token objects, and serialization rules.
|
|
49
49
|
|
|
50
|
-
Fields are divided into **semantic fields** (identity, structure, intent) and **
|
|
50
|
+
Fields are divided into **semantic fields** (identity, structure, intent) and **mode-set fields** (axes of variation for cascade resolution). The tables below list Spectrum's foundation-standard fields as declared in the catalog.
|
|
51
51
|
|
|
52
52
|
#### Semantic fields
|
|
53
53
|
|
|
@@ -67,16 +67,16 @@ Fields are divided into **semantic fields** (identity, structure, intent) and **
|
|
|
67
67
|
| `density` | OPTIONAL | Density | Space within or around component parts (e.g. `spacious`, `compact`). |
|
|
68
68
|
| `shape` | OPTIONAL | Shape | Relative to overall component shape (e.g. `uniform`). |
|
|
69
69
|
|
|
70
|
-
####
|
|
70
|
+
#### Mode-set fields
|
|
71
71
|
|
|
72
|
-
| Field | Status | Description
|
|
73
|
-
| --------------- | -------- |
|
|
74
|
-
| `colorScheme` | OPTIONAL |
|
|
75
|
-
| `scale` | OPTIONAL |
|
|
76
|
-
| `contrast` | OPTIONAL |
|
|
77
|
-
| Additional keys | OPTIONAL | Other
|
|
72
|
+
| Field | Status | Description |
|
|
73
|
+
| --------------- | -------- | ------------------------------------------------------------------------------------------- |
|
|
74
|
+
| `colorScheme` | OPTIONAL | Mode set: light / dark / wireframe / etc. |
|
|
75
|
+
| `scale` | OPTIONAL | Mode set: platform density scale (e.g. `desktop`, `mobile`). Distinct from semantic `size`. |
|
|
76
|
+
| `contrast` | OPTIONAL | Mode set: contrast level (e.g. `regular`, `high`). |
|
|
77
|
+
| Additional keys | OPTIONAL | Other mode sets declared in the dataset’s mode set catalog (see [Mode Sets](mode-sets.md)). |
|
|
78
78
|
|
|
79
|
-
**NORMATIVE:** Each field is validated according to the `validation` severity declared in its field declaration. Semantic fields typically use **advisory** severity (warning);
|
|
79
|
+
**NORMATIVE:** Each field is validated according to the `validation` severity declared in its field declaration. Semantic fields typically use **advisory** severity (warning); mode-set fields use **strict** severity (error). See [Taxonomy — Name object field categories](taxonomy.md#name-object-field-categories).
|
|
80
80
|
|
|
81
81
|
**RECOMMENDED:** Name objects use a consistent key ordering in authored files for diffs; this is not a conformance requirement. Concept ordering for serialized names is defined in [Taxonomy — Default serialization](taxonomy.md#default-serialization-legacy-format).
|
|
82
82
|
|
|
@@ -249,7 +249,7 @@ The current `@adobe/spectrum-tokens` JSON uses **sets** (`color-set`, `scale-set
|
|
|
249
249
|
| ------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
250
250
|
| Identity field | `id` | `uuid` |
|
|
251
251
|
| Name model | `name.original` (string) + `name.structure` (nested object) | Flat fields directly on `name` (`property`, `component`, `colorScheme`, …) |
|
|
252
|
-
| Complexity tracking | `name.semanticComplexity` (stored on token) | Computed at validation time from
|
|
252
|
+
| Complexity tracking | `name.semanticComplexity` (stored on token) | Computed at validation time from mode set declarations |
|
|
253
253
|
|
|
254
254
|
**NORMATIVE:** The flat `name` object defined in this spec is the authoritative serialization format. RFC [#646](https://github.com/adobe/spectrum-design-data/issues/646)'s `name.structure` / `name.original` shape is not a conformance target; it remains a useful reference for the analytical model that informed this design.
|
|
255
255
|
|
package/spec/dimensions.md
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Dimensions
|
|
2
|
-
|
|
3
|
-
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
-
|
|
5
|
-
This document defines how **dimensions** (modes such as color scheme, scale, contrast) are **declared**, assigned **defaults**, and validated for **coverage**.
|
|
6
|
-
|
|
7
|
-
## Dimension declaration
|
|
8
|
-
|
|
9
|
-
A **dimension declaration** is a JSON object describing one axis of variation. It **MUST** conform to [`dimension.schema.json`](../schemas/dimension.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/dimension.schema.json`).
|
|
10
|
-
|
|
11
|
-
### Required fields
|
|
12
|
-
|
|
13
|
-
| Field | Description |
|
|
14
|
-
| --------- | --------------------------------------------------------- |
|
|
15
|
-
| `name` | Stable identifier for the dimension (e.g. `colorScheme`). |
|
|
16
|
-
| `modes` | Array of allowed mode values (strings). |
|
|
17
|
-
| `default` | Default mode; **MUST** be a member of `modes`. |
|
|
18
|
-
|
|
19
|
-
### Optional fields
|
|
20
|
-
|
|
21
|
-
| Field | Description |
|
|
22
|
-
| ------------- | ------------------------------------ |
|
|
23
|
-
| `description` | Human-readable documentation. |
|
|
24
|
-
| `coverage` | Rules for mode coverage (see below). |
|
|
25
|
-
|
|
26
|
-
## Built-in dimensions
|
|
27
|
-
|
|
28
|
-
These dimensions are declared in the `dimensions/` catalog (see [Dimension catalog](#dimension-catalog)) and **SHOULD** be used consistently across Spectrum-compatible datasets:
|
|
29
|
-
|
|
30
|
-
| `name` | `modes` | `default` | Notes |
|
|
31
|
-
| ------------- | ---------------------------- | --------- | --------------------------------------------------------------------------------- |
|
|
32
|
-
| `colorScheme` | `light`, `dark`, `wireframe` | `light` | Theme / appearance. |
|
|
33
|
-
| `scale` | `desktop`, `mobile` | `desktop` | Density scale. Legacy names; desktop = medium, mobile = large in W3C terminology. |
|
|
34
|
-
| `contrast` | `regular`, `high` | `regular` | Accessibility contrast level. |
|
|
35
|
-
|
|
36
|
-
## Dimension catalog
|
|
37
|
-
|
|
38
|
-
The Spectrum foundation publishes dimension declarations as JSON files under `packages/design-data-spec/dimensions/`. Each file conforms to [`dimension.schema.json`](../schemas/dimension.schema.json).
|
|
39
|
-
|
|
40
|
-
**NORMATIVE:** Tooling (validators, resolution engine) **MUST** load dimension declarations from the dataset’s dimension catalog before performing specificity calculations or coverage validation.
|
|
41
|
-
|
|
42
|
-
**RECOMMENDED:** The catalog directory is named `dimensions/` and is co-located with the dataset’s spec package or manifest.
|
|
43
|
-
|
|
44
|
-
## Optional dimensions
|
|
45
|
-
|
|
46
|
-
Additional dimensions (e.g. `language`, `motion`) **MAY** be declared in a dataset’s dimension catalog. Token name objects **MAY** include keys matching declared dimension names.
|
|
47
|
-
|
|
48
|
-
## Defaults and specificity
|
|
49
|
-
|
|
50
|
-
**NORMATIVE:** A token name object **omitting** a dimension field implies the token applies under the dimension’s **`default`** mode for specificity and matching purposes unless the spec for that dimension states otherwise.
|
|
51
|
-
|
|
52
|
-
**NORMATIVE:** Only **non-default** dimension fields on the name object increase **semantic specificity** (see [Cascade](cascade.md)).
|
|
53
|
-
|
|
54
|
-
## Coverage validation
|
|
55
|
-
|
|
56
|
-
**RECOMMENDED:** If a dimension’s `coverage` requires **peer modes** (e.g. defining `dark` requires `light`), validators implement rule **`SPEC-005`** (see `rules/rules.yaml`).
|
|
57
|
-
|
|
58
|
-
**RECOMMENDED:** Explicit **combination** tokens are used for rare cross-dimensional cases instead of inferring Cartesian products.
|
|
59
|
-
|
|
60
|
-
## References
|
|
61
|
-
|
|
62
|
-
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
|
63
|
-
* [#714 — Design Data Specification](https://github.com/adobe/spectrum-design-data/discussions/714)
|
|
64
|
-
* [#746 — Phase 2: Dimension declarations (machine-readable)](https://github.com/adobe/spectrum-design-data/issues/746)
|
package/src/canonical.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 Adobe. All rights reserved.
|
|
3
|
-
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
|
|
7
|
-
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// Canonical vocabulary sets derived from spec chapters.
|
|
14
|
-
// Sources: spec/component-format.md, spec/anatomy-format.md, spec/state-model.md
|
|
15
|
-
|
|
16
|
-
export const CANONICAL_SLOTS = new Set([
|
|
17
|
-
"default",
|
|
18
|
-
"icon",
|
|
19
|
-
"label",
|
|
20
|
-
"help-text",
|
|
21
|
-
"negative-help-text",
|
|
22
|
-
"action",
|
|
23
|
-
"heading",
|
|
24
|
-
"description",
|
|
25
|
-
"hero",
|
|
26
|
-
"footer",
|
|
27
|
-
"tooltip",
|
|
28
|
-
]);
|
|
29
|
-
|
|
30
|
-
export const CANONICAL_ANATOMY_PARTS = new Set([
|
|
31
|
-
"body",
|
|
32
|
-
"checkmark",
|
|
33
|
-
"disclosure-triangle",
|
|
34
|
-
"field",
|
|
35
|
-
"handle",
|
|
36
|
-
"header",
|
|
37
|
-
"icon",
|
|
38
|
-
"label",
|
|
39
|
-
"picker",
|
|
40
|
-
"progress-bar",
|
|
41
|
-
"swatch",
|
|
42
|
-
"thumbnail",
|
|
43
|
-
"track",
|
|
44
|
-
"value",
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
|
-
export const CANONICAL_STATES = new Set([
|
|
48
|
-
"default",
|
|
49
|
-
"hover",
|
|
50
|
-
"focus",
|
|
51
|
-
"focus-visible",
|
|
52
|
-
"active",
|
|
53
|
-
"pressed",
|
|
54
|
-
"selected",
|
|
55
|
-
"indeterminate",
|
|
56
|
-
"disabled",
|
|
57
|
-
"read-only",
|
|
58
|
-
"invalid",
|
|
59
|
-
"valid",
|
|
60
|
-
"dragging",
|
|
61
|
-
]);
|
package/src/validate.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 Adobe. All rights reserved.
|
|
3
|
-
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
|
|
7
|
-
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Layer 2 cross-reference validator for design-data-spec.
|
|
15
|
-
*
|
|
16
|
-
* Implements SPEC-018 through SPEC-027: semantic rules that validate token
|
|
17
|
-
* name-object fields against component declarations, validate component
|
|
18
|
-
* declarations internally, and validate tokenBindings references.
|
|
19
|
-
*
|
|
20
|
-
* @see spec/component-format.md#spec-rules
|
|
21
|
-
* @see spec/anatomy-format.md#spec-rules
|
|
22
|
-
* @see spec/state-model.md#spec-rules
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
CANONICAL_SLOTS,
|
|
27
|
-
CANONICAL_ANATOMY_PARTS,
|
|
28
|
-
CANONICAL_STATES,
|
|
29
|
-
} from "./canonical.js";
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @typedef {{ ruleId: string, severity: 'error'|'warning', message: string, tokenName?: string, componentName?: string }} Diagnostic
|
|
33
|
-
* @typedef {{ name: string|object, [key: string]: unknown }} Token
|
|
34
|
-
* @typedef {{ name: string, options?: object, anatomy?: Array<{name:string,description?:string}>, slots?: Array<{name:string,description?:string}>, states?: Array<{name:string,trigger?:string,precedence?:number,layered?:boolean,description?:string}> }} ComponentDeclaration
|
|
35
|
-
* @typedef {{ tokens?: Token[], components?: ComponentDeclaration[] }} Dataset
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Validate a dataset for SPEC-018 through SPEC-024 compliance.
|
|
40
|
-
*
|
|
41
|
-
* @param {Dataset} dataset
|
|
42
|
-
* @returns {Diagnostic[]}
|
|
43
|
-
*/
|
|
44
|
-
export function validateDataset(dataset) {
|
|
45
|
-
const tokens = dataset.tokens ?? [];
|
|
46
|
-
const components = dataset.components ?? [];
|
|
47
|
-
|
|
48
|
-
// Build component lookup map keyed by name.
|
|
49
|
-
const componentMap = new Map(components.map((c) => [c.name, c]));
|
|
50
|
-
|
|
51
|
-
const diagnostics = [];
|
|
52
|
-
|
|
53
|
-
// --- Token cross-reference rules ---
|
|
54
|
-
for (const token of tokens) {
|
|
55
|
-
const name = token.name;
|
|
56
|
-
// String names (SPEC-017 escape hatch) skip cross-reference checks.
|
|
57
|
-
if (typeof name !== "object" || name === null) continue;
|
|
58
|
-
|
|
59
|
-
const tokenLabel = JSON.stringify(name);
|
|
60
|
-
|
|
61
|
-
if (name.component != null) {
|
|
62
|
-
// SPEC-018: component name must be declared
|
|
63
|
-
if (!componentMap.has(name.component)) {
|
|
64
|
-
diagnostics.push({
|
|
65
|
-
ruleId: "SPEC-018",
|
|
66
|
-
severity: "error",
|
|
67
|
-
message: `Token '${tokenLabel}' references undeclared component '${name.component}'`,
|
|
68
|
-
tokenName: tokenLabel,
|
|
69
|
-
});
|
|
70
|
-
// Can't validate further fields without a component declaration.
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const component = componentMap.get(name.component);
|
|
75
|
-
|
|
76
|
-
// SPEC-019: variant must be in component's variant option enum
|
|
77
|
-
if (name.variant != null) {
|
|
78
|
-
const variantEnum = component.options?.variant?.enum;
|
|
79
|
-
if (Array.isArray(variantEnum) && !variantEnum.includes(name.variant)) {
|
|
80
|
-
diagnostics.push({
|
|
81
|
-
ruleId: "SPEC-019",
|
|
82
|
-
severity: "error",
|
|
83
|
-
message: `Token '${tokenLabel}' has variant '${name.variant}' which is not declared on component '${name.component}'`,
|
|
84
|
-
tokenName: tokenLabel,
|
|
85
|
-
componentName: name.component,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// SPEC-020: anatomy must match a declared anatomy part name
|
|
91
|
-
if (name.anatomy != null) {
|
|
92
|
-
const declaredParts = new Set(
|
|
93
|
-
(component.anatomy ?? []).map((p) => p.name),
|
|
94
|
-
);
|
|
95
|
-
if (declaredParts.size > 0 && !declaredParts.has(name.anatomy)) {
|
|
96
|
-
diagnostics.push({
|
|
97
|
-
ruleId: "SPEC-020",
|
|
98
|
-
severity: "error",
|
|
99
|
-
message: `Token '${tokenLabel}' references undeclared anatomy part '${name.anatomy}' on component '${name.component}'`,
|
|
100
|
-
tokenName: tokenLabel,
|
|
101
|
-
componentName: name.component,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// SPEC-022: state must match a declared state name (only when states are declared)
|
|
107
|
-
if (name.state != null) {
|
|
108
|
-
const declaredStates = new Set(
|
|
109
|
-
(component.states ?? []).map((s) => s.name),
|
|
110
|
-
);
|
|
111
|
-
if (declaredStates.size > 0 && !declaredStates.has(name.state)) {
|
|
112
|
-
diagnostics.push({
|
|
113
|
-
ruleId: "SPEC-022",
|
|
114
|
-
severity: "error",
|
|
115
|
-
message: `Token '${tokenLabel}' references undeclared state '${name.state}' on component '${name.component}'`,
|
|
116
|
-
tokenName: tokenLabel,
|
|
117
|
-
componentName: name.component,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// --- Component declaration internal rules ---
|
|
125
|
-
for (const component of components) {
|
|
126
|
-
const cName = component.name;
|
|
127
|
-
|
|
128
|
-
// SPEC-021: custom slot names should have descriptions
|
|
129
|
-
for (const slot of component.slots ?? []) {
|
|
130
|
-
if (!CANONICAL_SLOTS.has(slot.name) && !slot.description) {
|
|
131
|
-
diagnostics.push({
|
|
132
|
-
ruleId: "SPEC-021",
|
|
133
|
-
severity: "warning",
|
|
134
|
-
message: `Component '${cName}' has custom slot '${slot.name}' with no description — add a description or use a canonical slot name`,
|
|
135
|
-
componentName: cName,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// SPEC-023: custom anatomy part names should have descriptions
|
|
141
|
-
for (const part of component.anatomy ?? []) {
|
|
142
|
-
if (!CANONICAL_ANATOMY_PARTS.has(part.name) && !part.description) {
|
|
143
|
-
diagnostics.push({
|
|
144
|
-
ruleId: "SPEC-023",
|
|
145
|
-
severity: "warning",
|
|
146
|
-
message: `Component '${cName}' has custom anatomy part '${part.name}' with no description`,
|
|
147
|
-
componentName: cName,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// SPEC-024: custom state names should have descriptions
|
|
153
|
-
for (const state of component.states ?? []) {
|
|
154
|
-
if (!CANONICAL_STATES.has(state.name) && !state.description) {
|
|
155
|
-
diagnostics.push({
|
|
156
|
-
ruleId: "SPEC-024",
|
|
157
|
-
severity: "warning",
|
|
158
|
-
message: `Component '${cName}' has custom state '${state.name}' with no description`,
|
|
159
|
-
componentName: cName,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// --- Token binding rules ---
|
|
166
|
-
|
|
167
|
-
// SPEC-027: each tokenBindings[].token must resolve to a known token name.
|
|
168
|
-
// String-named tokens are matched directly. Name-object tokens are skipped
|
|
169
|
-
// here because tokenBindings always reference tokens by their string name.
|
|
170
|
-
const tokenNameSet = new Set(
|
|
171
|
-
tokens
|
|
172
|
-
.map((t) => (typeof t.name === "string" ? t.name : null))
|
|
173
|
-
.filter(Boolean),
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
for (const component of components) {
|
|
177
|
-
for (const binding of component.tokenBindings ?? []) {
|
|
178
|
-
if (!tokenNameSet.has(binding.token)) {
|
|
179
|
-
diagnostics.push({
|
|
180
|
-
ruleId: "SPEC-027",
|
|
181
|
-
severity: "error",
|
|
182
|
-
message: `Component '${component.name}' tokenBindings references unknown token '${binding.token}'`,
|
|
183
|
-
componentName: component.name,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return diagnostics;
|
|
190
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|