@pantoken/utils 1.1.0 → 1.2.1
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/dist/index.d.mts +2 -1
- package/dist/index.mjs +37 -10
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -78,7 +78,8 @@ interface ResolveOptions {
|
|
|
78
78
|
/**
|
|
79
79
|
* Build a resolver that expands `var(--x)` references to concrete leaf values against `base` (plus
|
|
80
80
|
* any `overrides`). With `mode` it collapses `light-dark()` to that branch; without, it leaves
|
|
81
|
-
* `light-dark()` in place.
|
|
81
|
+
* `light-dark()` in place. A token carrying a {@link Token.flatValue} resolves through that rather
|
|
82
|
+
* than its CSS-expression `value`, so callers always land on a real colour.
|
|
82
83
|
*
|
|
83
84
|
* @param base - The token set to resolve references against.
|
|
84
85
|
* @param options - {@link ResolveOptions}.
|
package/dist/index.mjs
CHANGED
|
@@ -132,10 +132,33 @@ const VAR_RE = regex(VAR_SOURCE, "g");
|
|
|
132
132
|
/** A `light-dark(<light>, <dark>)` value; capture groups 1 and 2 are the two branches. */
|
|
133
133
|
const LIGHT_DARK_RE = regex(LIGHT_DARK_SOURCE);
|
|
134
134
|
const MAX_DEPTH = 12;
|
|
135
|
+
function lightDarkBranches(value) {
|
|
136
|
+
const trimmed = value.trim();
|
|
137
|
+
if (!trimmed.startsWith("light-dark(") || !trimmed.endsWith(")")) return void 0;
|
|
138
|
+
const content = trimmed.slice(11, -1);
|
|
139
|
+
let depth = 0;
|
|
140
|
+
let separator = -1;
|
|
141
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
142
|
+
const char = content[index];
|
|
143
|
+
if (char === "(") depth += 1;
|
|
144
|
+
else if (char === ")") {
|
|
145
|
+
depth -= 1;
|
|
146
|
+
if (depth < 0) return void 0;
|
|
147
|
+
} else if (char === "," && depth === 0) {
|
|
148
|
+
if (separator !== -1) return void 0;
|
|
149
|
+
separator = index;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (depth !== 0 || separator === -1) return void 0;
|
|
153
|
+
const light = content.slice(0, separator).trim();
|
|
154
|
+
const dark = content.slice(separator + 1).trim();
|
|
155
|
+
return light && dark ? [light, dark] : void 0;
|
|
156
|
+
}
|
|
135
157
|
/**
|
|
136
158
|
* Build a resolver that expands `var(--x)` references to concrete leaf values against `base` (plus
|
|
137
159
|
* any `overrides`). With `mode` it collapses `light-dark()` to that branch; without, it leaves
|
|
138
|
-
* `light-dark()` in place.
|
|
160
|
+
* `light-dark()` in place. A token carrying a {@link Token.flatValue} resolves through that rather
|
|
161
|
+
* than its CSS-expression `value`, so callers always land on a real colour.
|
|
139
162
|
*
|
|
140
163
|
* @param base - The token set to resolve references against.
|
|
141
164
|
* @param options - {@link ResolveOptions}.
|
|
@@ -186,12 +209,12 @@ const MAX_DEPTH = 12;
|
|
|
186
209
|
* ```
|
|
187
210
|
*/
|
|
188
211
|
function makeResolver(base, options = {}) {
|
|
189
|
-
const map = new Map(base.map((t) => [t.name, t.value]));
|
|
190
|
-
for (const t of options.overrides ?? []) map.set(t.name, t.value);
|
|
212
|
+
const map = new Map(base.map((t) => [t.name, t.flatValue ?? t.value]));
|
|
213
|
+
for (const t of options.overrides ?? []) map.set(t.name, t.flatValue ?? t.value);
|
|
191
214
|
const pickMode = (value) => {
|
|
192
215
|
if (!options.mode) return value;
|
|
193
|
-
const
|
|
194
|
-
return
|
|
216
|
+
const branches = lightDarkBranches(value);
|
|
217
|
+
return branches ? branches[options.mode === "light" ? 0 : 1] : value;
|
|
195
218
|
};
|
|
196
219
|
const expand = (value, depth) => {
|
|
197
220
|
const picked = pickMode(value);
|
|
@@ -224,7 +247,7 @@ function makeResolver(base, options = {}) {
|
|
|
224
247
|
*/
|
|
225
248
|
function resolveTokens(base, options = {}) {
|
|
226
249
|
const resolve = makeResolver(base, options);
|
|
227
|
-
return new Map(base.map((t) => [t.name, resolve(t.value)]));
|
|
250
|
+
return new Map(base.map((t) => [t.name, resolve(t.flatValue ?? t.value)]));
|
|
228
251
|
}
|
|
229
252
|
//#endregion
|
|
230
253
|
//#region src/drift.ts
|
|
@@ -259,6 +282,11 @@ function extractInstuiRefs(text) {
|
|
|
259
282
|
function tokenNames(ir) {
|
|
260
283
|
return new Set(ir.map((t) => t.name));
|
|
261
284
|
}
|
|
285
|
+
function declaredInstuiProperties(text) {
|
|
286
|
+
const declared = new Set([...text.matchAll(/@property\s+(--instui-[\w-]+)/g)].map((m) => m[1]));
|
|
287
|
+
for (const match of text.matchAll(/(--instui-[\w]+(?:-[\w]+)*)\s*:/g)) declared.add(match[1]);
|
|
288
|
+
return declared;
|
|
289
|
+
}
|
|
262
290
|
/**
|
|
263
291
|
* Drift check: `--instui-*` names in `text` that the IR doesn't define (sorted; empty means no
|
|
264
292
|
* drift). Use for outputs that *reference* tokens defined elsewhere — e.g. the docusaurus/vitepress
|
|
@@ -284,7 +312,8 @@ function tokenNames(ir) {
|
|
|
284
312
|
*/
|
|
285
313
|
function unknownReferences(text, ir) {
|
|
286
314
|
const names = tokenNames(ir);
|
|
287
|
-
|
|
315
|
+
const declared = declaredInstuiProperties(text);
|
|
316
|
+
return [...extractInstuiRefs(text)].filter((name) => !names.has(name) && !declared.has(name)).sort();
|
|
288
317
|
}
|
|
289
318
|
/**
|
|
290
319
|
* Self-containment check: `--instui-*` names referenced via `var()` in a stylesheet that it never
|
|
@@ -309,9 +338,7 @@ function unknownReferences(text, ir) {
|
|
|
309
338
|
*/
|
|
310
339
|
function danglingReferences(css) {
|
|
311
340
|
const referenced = new Set([...css.matchAll(/var\(\s*?(--instui-[\w-]+)/g)].map((m) => m[1]));
|
|
312
|
-
const defined =
|
|
313
|
-
for (const m of css.matchAll(/@property\s+(--instui-[\w-]+)/g)) defined.add(m[1]);
|
|
314
|
-
for (const m of css.matchAll(/(--instui-[\w]+(?:-[\w]+)*)\s*:/g)) defined.add(m[1]);
|
|
341
|
+
const defined = declaredInstuiProperties(css);
|
|
315
342
|
return [...referenced].filter((name) => !defined.has(name)).sort();
|
|
316
343
|
}
|
|
317
344
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pantoken/utils",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Shared pantoken helpers: token reference resolver, typed regexes (arkregex), name-case, and hex-colour parsing.",
|
|
5
5
|
"homepage": "https://pantoken.app",
|
|
6
6
|
"bugs": "https://github.com/thedannywahl/pantoken/issues",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"provenance": true
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@pantoken/model": "0.
|
|
29
|
+
"@pantoken/model": "0.5.0",
|
|
30
30
|
"arkregex": "^0.0.8",
|
|
31
31
|
"css-tree": "^3.2.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/css-tree": "^3.2.0",
|
|
35
|
-
"@types/node": "^26.6.
|
|
35
|
+
"@types/node": "^26.6.3",
|
|
36
36
|
"typescript": "^7.0.2",
|
|
37
37
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.0.0-rc.0",
|
|
38
38
|
"vite-plus": "1.0.0-rc.0"
|