@texuli/spec 0.9.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/README.md +33 -11
- package/dist/build.d.ts +5 -0
- package/dist/build.js +1 -0
- package/dist/codegen/kotlin-tokens.d.ts +38 -0
- package/dist/codegen/kotlin-tokens.js +138 -0
- package/dist/codegen/kotlin.d.ts +3 -1
- package/dist/codegen/kotlin.js +5 -2
- package/dist/design-system/index.d.ts +11 -0
- package/dist/design-system/index.js +10 -0
- package/dist/design-system/schema.d.ts +3 -0
- package/dist/design-system/schema.js +164 -0
- package/dist/design-system/validate.d.ts +69 -0
- package/dist/design-system/validate.js +273 -0
- package/dist/design-system/vocabulary.d.ts +70 -0
- package/dist/design-system/vocabulary.js +351 -0
- package/dist/format.js +10 -1
- package/dist/generated/typescript/blueprint.d.ts +67 -11
- package/dist/generated/typescript/blueprint.js +1 -1
- package/dist/generated/typescript/catalog-schema.js +1 -1
- package/dist/generated/typescript/design-system.d.ts +1110 -0
- package/dist/generated/typescript/design-system.js +3 -0
- package/dist/generated/typescript/diagnostics.js +1 -1
- package/dist/generated/typescript/manifest.js +1 -1
- package/dist/generated/typescript/vocabulary.d.ts +3 -1
- package/dist/generated/typescript/vocabulary.js +2 -2
- package/dist/generated/typescript/workflow.js +1 -1
- package/dist/migrations/0.9.0-0.10.0.d.ts +10 -0
- package/dist/migrations/0.9.0-0.10.0.js +13 -0
- package/dist/migrations/index.js +2 -0
- package/dist/validate.js +12 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { isRecord } from "../dialect.js";
|
|
2
|
+
import { DESIGN_SYSTEM_FORMAT_VERSION, DS_DEFS, DS_PATTERNS, DS_RESERVED_KEYS, DS_ROOT, DESIGN_SYSTEM_LIMITS as LIMITS, } from "./vocabulary.js";
|
|
3
|
+
const add = (r, code, path, message, hint) => {
|
|
4
|
+
if (r.e.length < r.max)
|
|
5
|
+
r.e.push(hint ? { code, path, message, hint } : { code, path, message });
|
|
6
|
+
};
|
|
7
|
+
const at = (path, key) => typeof key === 'number'
|
|
8
|
+
? `${path}[${key}]`
|
|
9
|
+
: /^[A-Za-z_$][\w$]*$/.test(key)
|
|
10
|
+
? `${path}.${key}`
|
|
11
|
+
: `${path}[${JSON.stringify(key)}]`;
|
|
12
|
+
/** Code points up to `max`, without spreading a huge string. */
|
|
13
|
+
const fits = (s, max) => s.length <= max || (s.length <= 2 * max && [...s].length <= max);
|
|
14
|
+
/** The code for an `extends` or `ref` value, or `undefined` when it is well formed. */
|
|
15
|
+
function refCode(v) {
|
|
16
|
+
if (DS_PATTERNS.ref.test(v))
|
|
17
|
+
return;
|
|
18
|
+
if (/[/\\]/.test(v) || (!v.startsWith('texuli:') && /^[a-z][a-z0-9+.-]*:/i.test(v)))
|
|
19
|
+
return 'url-refused';
|
|
20
|
+
const [id, range] = v.split('@');
|
|
21
|
+
if (range !== undefined && DS_PATTERNS.id.test(id))
|
|
22
|
+
if (/[\^~*xX<>|]/.test(range) || /^\d+(\.\d+)?$/.test(range))
|
|
23
|
+
return 'extends-range';
|
|
24
|
+
return 'invalid-value';
|
|
25
|
+
}
|
|
26
|
+
function walk(r, node, v, path, depth) {
|
|
27
|
+
if (r.e.length >= r.max)
|
|
28
|
+
return;
|
|
29
|
+
if (++r.seen > LIMITS.values || depth > LIMITS.depth) {
|
|
30
|
+
add(r, 'invalid-value', path, 'The document is too large or too deep.');
|
|
31
|
+
r.max = r.e.length;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const n = typeof node === 'string' ? DS_DEFS[node] : node;
|
|
35
|
+
if (!Array.isArray(n)) {
|
|
36
|
+
const shape = n;
|
|
37
|
+
if (!isRecord(v))
|
|
38
|
+
return add(r, 'invalid-type', path, 'Expected an object.');
|
|
39
|
+
for (const key of Object.keys(shape))
|
|
40
|
+
if (key.endsWith('!') && !r.patch && !Object.hasOwn(v, key.slice(0, -1)))
|
|
41
|
+
add(r, 'required', at(path, key.slice(0, -1)), 'Required.');
|
|
42
|
+
for (const key of Object.keys(v)) {
|
|
43
|
+
const child = Object.hasOwn(shape, key)
|
|
44
|
+
? shape[key]
|
|
45
|
+
: Object.hasOwn(shape, `${key}!`)
|
|
46
|
+
? shape[`${key}!`]
|
|
47
|
+
: undefined;
|
|
48
|
+
if (r.e.length >= r.max)
|
|
49
|
+
return;
|
|
50
|
+
if (child === undefined)
|
|
51
|
+
add(r, 'unknown-key', at(path, key), 'Unknown key.', `Allowed: ${Object.keys(shape)
|
|
52
|
+
.map((k) => k.replace('!', ''))
|
|
53
|
+
.join(', ')}`);
|
|
54
|
+
else if (!(r.patch && v[key] === null))
|
|
55
|
+
walk(r, child, v[key], at(path, key), depth + 1);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const tag = n[0];
|
|
60
|
+
if (tag === 'l' || tag === 'm') {
|
|
61
|
+
const list = tag === 'l';
|
|
62
|
+
if (list ? !Array.isArray(v) : !isRecord(v))
|
|
63
|
+
return add(r, 'invalid-type', path, `Expected ${list ? 'an array' : 'an object'}.`);
|
|
64
|
+
const entries = Object.keys(v);
|
|
65
|
+
const [, item, a, b] = n;
|
|
66
|
+
if (list ? entries.length < a || entries.length > b : entries.length > a)
|
|
67
|
+
return add(r, 'invalid-value', path, `Expected ${list ? `${a} to ${b} items` : `at most ${a} entries`}.`);
|
|
68
|
+
if (list && n[4] && new Set(v).size < entries.length)
|
|
69
|
+
return add(r, 'invalid-value', path, 'Duplicate items.');
|
|
70
|
+
for (const key of entries) {
|
|
71
|
+
const value = v[key];
|
|
72
|
+
const here = list ? at(path, Number(key)) : at(path, key);
|
|
73
|
+
if (!list && (DS_RESERVED_KEYS.has(key) || !b.test(key)))
|
|
74
|
+
add(r, 'invalid-value', here, 'Invalid or reserved key.', `Keys match ${b.source}`);
|
|
75
|
+
else if (!(r.patch && !list && value === null))
|
|
76
|
+
walk(r, item, value, here, depth + 1);
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (tag === 'b') {
|
|
81
|
+
if (typeof v !== 'boolean')
|
|
82
|
+
add(r, 'invalid-type', path, 'Expected a boolean.');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (tag === 'n' || tag === 'i') {
|
|
86
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
87
|
+
return add(r, 'invalid-type', path, 'Expected a number.');
|
|
88
|
+
if ((tag === 'i' && !Number.isInteger(v)) || v < n[1] || v > n[2])
|
|
89
|
+
add(r, 'invalid-value', path, `Expected ${tag === 'i' ? 'an integer' : 'a number'} from ${n[1]} to ${n[2]}.`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (tag === 'k') {
|
|
93
|
+
if (v !== n[1])
|
|
94
|
+
add(r, 'invalid-value', path, `Expected ${JSON.stringify(n[1])}.`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (typeof v !== 'string')
|
|
98
|
+
return add(r, 'invalid-type', path, 'Expected a string.');
|
|
99
|
+
if (tag === 'e') {
|
|
100
|
+
if (!n[1].split(' ').includes(v))
|
|
101
|
+
add(r, 'invalid-value', path, 'Not an allowed value.', `One of: ${n[1].split(' ').join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
else if (tag === 's' || tag === 't') {
|
|
104
|
+
const ok = tag === 's' ? fits(v, n[2]) && n[1].test(v) : fits(v, n[1]) && DS_PATTERNS.text.test(v);
|
|
105
|
+
if (!ok)
|
|
106
|
+
add(r, 'invalid-value', path, tag === 's'
|
|
107
|
+
? `Must match ${n[1].source}.`
|
|
108
|
+
: `At most ${n[1]} characters, no control or bidi characters.`);
|
|
109
|
+
}
|
|
110
|
+
else if (tag === 'x') {
|
|
111
|
+
const code = refCode(v);
|
|
112
|
+
if (code)
|
|
113
|
+
add(r, code, path, 'Expected texuli:<theme> or an exact id@x.y.z.');
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// An image ('i') or font ('f') source: a relative path, or base64 data within caps.
|
|
117
|
+
if (/^data:/i.test(v)) {
|
|
118
|
+
const m = /^data:(image\/(?:png|jpeg|gif|webp|avif)|font\/(?:woff2?|ttf|otf));base64,([A-Za-z0-9+/]+={0,2})$/.exec(v);
|
|
119
|
+
if (!r.trust || !m || m[1]?.[0] !== n[1] || m[2].length % 4)
|
|
120
|
+
return add(r, 'url-refused', path, r.trust ? 'Unsupported data URL.' : 'Data URLs need developer trust.');
|
|
121
|
+
const p = m[2];
|
|
122
|
+
const bytes = (p.length / 4) * 3 - (p.endsWith('==') ? 2 : p.endsWith('=') ? 1 : 0);
|
|
123
|
+
r.bytes += bytes;
|
|
124
|
+
if (bytes > n[2] || r.bytes > LIMITS.inlineTotal)
|
|
125
|
+
add(r, 'inline-bytes', path, `Inline data over ${bytes > n[2] ? n[2] : LIMITS.inlineTotal} bytes.`);
|
|
126
|
+
}
|
|
127
|
+
else if (v.length > 512 || !(n[1] === 'i' ? DS_PATTERNS.image : DS_PATTERNS.font).test(v))
|
|
128
|
+
add(r, 'url-refused', path, 'Expected a same-origin relative path with a file extension.');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const start = (options, patch) => ({
|
|
132
|
+
e: [],
|
|
133
|
+
max: Math.max(1, Math.min(LIMITS.errors, options.maxErrors ?? LIMITS.errors)),
|
|
134
|
+
trust: options.trust === 'developer',
|
|
135
|
+
patch,
|
|
136
|
+
bytes: 0,
|
|
137
|
+
seen: 0,
|
|
138
|
+
});
|
|
139
|
+
const done = (r) => ({ ok: r.e.length === 0, errors: r.e });
|
|
140
|
+
/** The `format-version` issue for a declared `formatVersion`, if any. */
|
|
141
|
+
function versionIssue(doc) {
|
|
142
|
+
const v = doc.formatVersion;
|
|
143
|
+
if (typeof v !== 'number' || !Number.isInteger(v) || v < 1 || v > DESIGN_SYSTEM_FORMAT_VERSION)
|
|
144
|
+
return {
|
|
145
|
+
code: 'format-version',
|
|
146
|
+
path: '$.formatVersion',
|
|
147
|
+
message: `Expected an integer from 1 to ${DESIGN_SYSTEM_FORMAT_VERSION}; migrate older documents.`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check a design-system document against the closed vocabulary. Never
|
|
152
|
+
* throws on a JSON value; returns every issue (up to `maxErrors`) with a
|
|
153
|
+
* stable code and a JSON path. A future `formatVersion` stops at
|
|
154
|
+
* `format-version`.
|
|
155
|
+
*/
|
|
156
|
+
export function validateDesignSystem(doc, options = {}) {
|
|
157
|
+
const r = start(options, false);
|
|
158
|
+
if (!isRecord(doc)) {
|
|
159
|
+
add(r, 'invalid-type', '$', 'Expected an object.');
|
|
160
|
+
return done(r);
|
|
161
|
+
}
|
|
162
|
+
const version = versionIssue(doc);
|
|
163
|
+
if (version)
|
|
164
|
+
return done({ ...r, e: [version] });
|
|
165
|
+
walk(r, DS_ROOT, doc, '$', 0);
|
|
166
|
+
let ref = doc.extends;
|
|
167
|
+
const seen = new Set([`${doc.id}@${doc.version}`]);
|
|
168
|
+
for (let hops = 1; typeof ref === 'string' && !ref.startsWith('texuli:') && DS_PATTERNS.ref.test(ref); hops++) {
|
|
169
|
+
if (seen.has(ref))
|
|
170
|
+
add(r, 'extends-cycle', '$.extends', `The extends chain returns to ${ref}.`);
|
|
171
|
+
else if (hops > LIMITS.extendsDepth)
|
|
172
|
+
add(r, 'extends-depth', '$.extends', `The extends chain is deeper than ${LIMITS.extendsDepth}.`);
|
|
173
|
+
else if (options.resolve) {
|
|
174
|
+
seen.add(ref);
|
|
175
|
+
const next = options.resolve(ref);
|
|
176
|
+
ref = isRecord(next) ? next.extends : undefined;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
return done(r);
|
|
182
|
+
}
|
|
183
|
+
/** Check a patch: the sections only, every field optional, `null` to remove. */
|
|
184
|
+
export function validateDesignSystemPatch(patch, options = {}) {
|
|
185
|
+
const r = start(options, true);
|
|
186
|
+
walk(r, 'variant', patch, '$', 0);
|
|
187
|
+
return done(r);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Merge a patch into a document, purely: objects merge, arrays and scalars
|
|
191
|
+
* replace, `null` removes, and `__proto__`, `constructor` and `prototype`
|
|
192
|
+
* are skipped. Validate the result again.
|
|
193
|
+
*/
|
|
194
|
+
export function applyDesignSystemPatch(base, patch) {
|
|
195
|
+
return merge(base, patch);
|
|
196
|
+
}
|
|
197
|
+
function merge(base, patch) {
|
|
198
|
+
const out = isRecord(base) ? { ...base } : {};
|
|
199
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
200
|
+
if (DS_RESERVED_KEYS.has(key))
|
|
201
|
+
continue;
|
|
202
|
+
if (value === null)
|
|
203
|
+
delete out[key];
|
|
204
|
+
else
|
|
205
|
+
out[key] = isRecord(value) ? merge(out[key], value) : value;
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
/** Every step, in order (none yet: formatVersion 1 is the first). */
|
|
210
|
+
export const DESIGN_SYSTEM_MIGRATIONS = Object.freeze([]);
|
|
211
|
+
/**
|
|
212
|
+
* Bring a document up to the current `formatVersion`. Pure and total: never
|
|
213
|
+
* throws on a JSON value and never mutates it; an unknown or future version
|
|
214
|
+
* is a `format-version` result. Validate the migrated document.
|
|
215
|
+
*/
|
|
216
|
+
export function migrateDesignSystem(doc) {
|
|
217
|
+
if (!isRecord(doc))
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
errors: [{ code: 'invalid-type', path: '$', message: 'Expected an object.' }],
|
|
221
|
+
};
|
|
222
|
+
const issue = versionIssue(doc);
|
|
223
|
+
if (issue)
|
|
224
|
+
return { ok: false, errors: [issue] };
|
|
225
|
+
const from = doc.formatVersion;
|
|
226
|
+
let current = { ...doc };
|
|
227
|
+
const applied = [];
|
|
228
|
+
for (let v = from; v < DESIGN_SYSTEM_FORMAT_VERSION;) {
|
|
229
|
+
const step = DESIGN_SYSTEM_MIGRATIONS.find((m) => m.from === v);
|
|
230
|
+
if (!step)
|
|
231
|
+
return {
|
|
232
|
+
ok: false,
|
|
233
|
+
errors: [
|
|
234
|
+
{ code: 'format-version', path: '$.formatVersion', message: `No migration from ${v}.` },
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
current = step.migrate(current);
|
|
238
|
+
applied.push(`${step.from}->${step.to}`);
|
|
239
|
+
v = step.to;
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
ok: true,
|
|
243
|
+
document: current,
|
|
244
|
+
from,
|
|
245
|
+
to: DESIGN_SYSTEM_FORMAT_VERSION,
|
|
246
|
+
applied,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check a blueprint's design-system reference: exactly one of `ref`
|
|
251
|
+
* (`id@x.y.z` or `texuli:<theme>`) and `inline` (a whole document, checked
|
|
252
|
+
* by {@link validateDesignSystem} at `options.trust`).
|
|
253
|
+
*/
|
|
254
|
+
export function checkDesignSystemReference(value, options = {}) {
|
|
255
|
+
const r = start(options, false);
|
|
256
|
+
if (!isRecord(value)) {
|
|
257
|
+
add(r, 'invalid-type', '$', 'Expected an object.');
|
|
258
|
+
return done(r);
|
|
259
|
+
}
|
|
260
|
+
const keys = Object.keys(value);
|
|
261
|
+
for (const key of keys)
|
|
262
|
+
if (key !== 'ref' && key !== 'inline')
|
|
263
|
+
add(r, 'unknown-key', at('$', key), 'Unknown key.', 'Allowed: ref, inline');
|
|
264
|
+
const ref = Object.hasOwn(value, 'ref');
|
|
265
|
+
if (ref === Object.hasOwn(value, 'inline'))
|
|
266
|
+
add(r, ref ? 'invalid-value' : 'required', '$', 'Set exactly one of ref or inline.');
|
|
267
|
+
else if (ref)
|
|
268
|
+
walk(r, ['x'], value.ref, '$.ref', 1);
|
|
269
|
+
else
|
|
270
|
+
for (const issue of validateDesignSystem(value.inline, options).errors)
|
|
271
|
+
add(r, issue.code, `$.inline${issue.path.slice(1)}`, issue.message, issue.hint);
|
|
272
|
+
return done(r);
|
|
273
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed vocabulary of a design-system document (ADR-021), as a compact
|
|
3
|
+
* table: the validator walks it, and `scripts/design-system-schema.ts`
|
|
4
|
+
* projects it into `schemas/design-system.schema.json` (TypeScript and
|
|
5
|
+
* Kotlin types follow from that schema). Kept as data, not a bundled JSON
|
|
6
|
+
* Schema, so `@texuli/spec/design-system` stays a few KB.
|
|
7
|
+
*
|
|
8
|
+
* A node is a `$defs` name (a string), a closed object (a key ending in `!`
|
|
9
|
+
* is required), or a tagged tuple:
|
|
10
|
+
* `['e', 'a b']` enum · `['n' | 'i', min, max]` number or integer ·
|
|
11
|
+
* `['s', pattern, maxLength]` string · `['t', maxLength]` text without
|
|
12
|
+
* control or bidi characters · `['l', item, min, max, unique?]` list ·
|
|
13
|
+
* `['m', value, maxEntries, keyPattern]` map · `['b']` boolean ·
|
|
14
|
+
* `['k', value]` constant · `['u', 'i' | 'f', capBytes]` an image or font
|
|
15
|
+
* source · `['x']` an `extends` reference.
|
|
16
|
+
*/
|
|
17
|
+
export type DsNode = string | {
|
|
18
|
+
readonly [key: string]: DsNode;
|
|
19
|
+
} | readonly ['e', string] | readonly ['n' | 'i', number, number] | readonly ['s', RegExp, number] | readonly ['t', number] | readonly ['l', DsNode, number, number, 1?] | readonly ['m', DsNode, number, RegExp] | readonly ['b'] | readonly ['k', string | number] | readonly ['u', 'i' | 'f', number] | readonly ['x'];
|
|
20
|
+
export type DsObject = {
|
|
21
|
+
readonly [key: string]: DsNode;
|
|
22
|
+
};
|
|
23
|
+
export declare const DESIGN_SYSTEM_FORMAT = "texuli/design-system";
|
|
24
|
+
export declare const DESIGN_SYSTEM_FORMAT_VERSION = 1;
|
|
25
|
+
/** Stable codes `validate` and `migrate` raise (ADR-021). */
|
|
26
|
+
export declare const DESIGN_SYSTEM_CODES: readonly ["unknown-key", "invalid-type", "invalid-value", "required", "format-version", "extends-range", "extends-cycle", "extends-depth", "url-refused", "inline-bytes"];
|
|
27
|
+
/** Guarantee codes the compiler raises (ADR-022); reserved here, never raised by the spec. */
|
|
28
|
+
export declare const DESIGN_SYSTEM_COMPILER_CODES: readonly ["aa-text", "aa-focus", "target-size"];
|
|
29
|
+
export type DesignSystemCode = (typeof DESIGN_SYSTEM_CODES)[number] | (typeof DESIGN_SYSTEM_COMPILER_CODES)[number];
|
|
30
|
+
/** Caps: visited values, depth, errors, the `extends` chain and inline bytes (decoded). */
|
|
31
|
+
export declare const DESIGN_SYSTEM_LIMITS: Readonly<{
|
|
32
|
+
values: 20000;
|
|
33
|
+
depth: 16;
|
|
34
|
+
errors: 64;
|
|
35
|
+
extendsDepth: 4;
|
|
36
|
+
logo: 32768;
|
|
37
|
+
favicon: 8192;
|
|
38
|
+
font: 131072;
|
|
39
|
+
inlineTotal: 262144;
|
|
40
|
+
}>;
|
|
41
|
+
/** Shared patterns (also written into the schema). */
|
|
42
|
+
export declare const DS_PATTERNS: {
|
|
43
|
+
id: RegExp;
|
|
44
|
+
semver: RegExp;
|
|
45
|
+
ref: RegExp;
|
|
46
|
+
color: RegExp;
|
|
47
|
+
image: RegExp;
|
|
48
|
+
font: RegExp;
|
|
49
|
+
text: RegExp;
|
|
50
|
+
key: RegExp;
|
|
51
|
+
};
|
|
52
|
+
/** Map keys no map may use, whatever its pattern. */
|
|
53
|
+
export declare const DS_RESERVED_KEYS: ReadonlySet<string>;
|
|
54
|
+
/** The semantic roles of `@texuli/tokens` (`SEMANTIC_ROLES`); a test keeps them equal. */
|
|
55
|
+
export declare const DS_ROLES = "background foreground surface surfaceForeground elevated elevatedForeground muted mutedForeground subtle subtleForeground border borderStrong input ring primary primaryForeground primarySoft primarySoftForeground secondary secondaryForeground accent accentForeground destructive destructiveForeground destructiveSoft destructiveSoftForeground success successForeground successSoft successSoftForeground warning warningForeground warningSoft warningSoftForeground info infoForeground infoSoft infoSoftForeground sidebar sidebarForeground sidebarBorder sidebarPrimary overlay scrim shadow link linkVisited selection selectionForeground canvas";
|
|
56
|
+
/** Component token kinds: the letter in {@link DS_COMPONENT_TOKENS} → its value `$defs`. */
|
|
57
|
+
export declare const DS_TOKEN_KINDS: Readonly<Record<string, string>>;
|
|
58
|
+
/**
|
|
59
|
+
* Every component of the token registry (`COMPONENT_TOKEN_FAMILIES` of
|
|
60
|
+
* `@texuli/tokens`, z-index tokens left out) and the defaults vocabulary
|
|
61
|
+
* (`DESIGN_DEFAULTS_VOCABULARY` of `texuli`): `key:kind` pairs. A test
|
|
62
|
+
* keeps it equal to both.
|
|
63
|
+
*/
|
|
64
|
+
export declare const DS_COMPONENT_TOKENS: Readonly<Record<string, string>>;
|
|
65
|
+
/** Component defaults: `[variants, sizes]`, space-separated; a test keeps it equal to `texuli`. */
|
|
66
|
+
export declare const DS_COMPONENT_DEFAULTS: Readonly<Record<string, readonly [string, string]>>;
|
|
67
|
+
/** Every named definition. */
|
|
68
|
+
export declare const DS_DEFS: Readonly<Record<string, DsNode>>;
|
|
69
|
+
/** The document root. */
|
|
70
|
+
export declare const DS_ROOT: DsObject;
|