@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 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 m = LIGHT_DARK_RE.exec(value.trim());
194
- return m ? options.mode === "light" ? m[1] : m[2] : value;
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
- return [...extractInstuiRefs(text)].filter((name) => !names.has(name)).sort();
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 = /* @__PURE__ */ new Set();
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.0",
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.4.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.2",
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"