@caelo-cms/shared 0.10.21 → 0.10.23
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/ai-tools.d.ts +291 -231
- package/dist/ai-tools.d.ts.map +1 -1
- package/dist/ai-tools.js +349 -281
- package/dist/ai-tools.js.map +1 -1
- package/dist/auth-forms.d.ts.map +1 -1
- package/dist/auth-forms.js +4 -1
- package/dist/auth-forms.js.map +1 -1
- package/dist/base-css.d.ts +24 -0
- package/dist/base-css.d.ts.map +1 -0
- package/dist/base-css.js +28 -0
- package/dist/base-css.js.map +1 -0
- package/dist/build-page.d.ts +330 -0
- package/dist/build-page.d.ts.map +1 -0
- package/dist/build-page.js +282 -0
- package/dist/build-page.js.map +1 -0
- package/dist/content.d.ts +322 -9
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +354 -11
- package/dist/content.js.map +1 -1
- package/dist/css-gradient-scan.d.ts +14 -0
- package/dist/css-gradient-scan.d.ts.map +1 -0
- package/dist/css-gradient-scan.js +81 -0
- package/dist/css-gradient-scan.js.map +1 -0
- package/dist/css-var-scan.d.ts +56 -0
- package/dist/css-var-scan.d.ts.map +1 -0
- package/dist/css-var-scan.js +97 -0
- package/dist/css-var-scan.js.map +1 -0
- package/dist/design-manifest.d.ts +36 -0
- package/dist/design-manifest.d.ts.map +1 -0
- package/dist/design-manifest.js +90 -0
- package/dist/design-manifest.js.map +1 -0
- package/dist/fonts.d.ts +89 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +241 -0
- package/dist/fonts.js.map +1 -0
- package/dist/genesis-inventory.d.ts +32 -0
- package/dist/genesis-inventory.d.ts.map +1 -0
- package/dist/genesis-inventory.js +186 -0
- package/dist/genesis-inventory.js.map +1 -0
- package/dist/genesis.d.ts +62 -0
- package/dist/genesis.d.ts.map +1 -0
- package/dist/genesis.js +78 -0
- package/dist/genesis.js.map +1 -0
- package/dist/i18n.d.ts +44 -1
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +72 -6
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -1
- package/dist/interactions.d.ts +23 -0
- package/dist/interactions.d.ts.map +1 -0
- package/dist/interactions.js +44 -0
- package/dist/interactions.js.map +1 -0
- package/dist/media.d.ts +101 -16
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +126 -15
- package/dist/media.js.map +1 -1
- package/dist/page-log.d.ts +94 -0
- package/dist/page-log.d.ts.map +1 -0
- package/dist/page-log.js +111 -0
- package/dist/page-log.js.map +1 -0
- package/dist/preview-compose.d.ts +79 -0
- package/dist/preview-compose.d.ts.map +1 -1
- package/dist/preview-compose.js +155 -25
- package/dist/preview-compose.js.map +1 -1
- package/dist/proposal-status.d.ts +40 -0
- package/dist/proposal-status.d.ts.map +1 -0
- package/dist/proposal-status.js +34 -0
- package/dist/proposal-status.js.map +1 -0
- package/dist/responsive-images.d.ts +64 -0
- package/dist/responsive-images.d.ts.map +1 -0
- package/dist/responsive-images.js +98 -0
- package/dist/responsive-images.js.map +1 -0
- package/dist/safe-keys.d.ts +9 -0
- package/dist/safe-keys.d.ts.map +1 -0
- package/dist/safe-keys.js +20 -0
- package/dist/safe-keys.js.map +1 -0
- package/dist/seo.d.ts +8 -0
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +3 -1
- package/dist/seo.js.map +1 -1
- package/dist/skills.d.ts +14 -68
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +19 -113
- package/dist/skills.js.map +1 -1
- package/dist/strip-cdata.d.ts +7 -0
- package/dist/strip-cdata.d.ts.map +1 -0
- package/dist/strip-cdata.js +48 -0
- package/dist/strip-cdata.js.map +1 -0
- package/dist/structured-sets.d.ts +6 -16
- package/dist/structured-sets.d.ts.map +1 -1
- package/dist/structured-sets.js +5 -16
- package/dist/structured-sets.js.map +1 -1
- package/dist/subagents.d.ts +105 -3
- package/dist/subagents.d.ts.map +1 -1
- package/dist/subagents.js +224 -41
- package/dist/subagents.js.map +1 -1
- package/dist/template-engine.d.ts +85 -0
- package/dist/template-engine.d.ts.map +1 -0
- package/dist/template-engine.js +403 -0
- package/dist/template-engine.js.map +1 -0
- package/dist/theme-importers/auto-detect.d.ts +26 -0
- package/dist/theme-importers/auto-detect.d.ts.map +1 -0
- package/dist/theme-importers/auto-detect.js +42 -0
- package/dist/theme-importers/auto-detect.js.map +1 -0
- package/dist/theme-importers/css-comments.d.ts +12 -0
- package/dist/theme-importers/css-comments.d.ts.map +1 -0
- package/dist/theme-importers/css-comments.js +15 -0
- package/dist/theme-importers/css-comments.js.map +1 -0
- package/dist/theme-importers/dtcg.d.ts +46 -0
- package/dist/theme-importers/dtcg.d.ts.map +1 -0
- package/dist/theme-importers/dtcg.js +111 -0
- package/dist/theme-importers/dtcg.js.map +1 -0
- package/dist/theme-importers/loose.d.ts +3 -0
- package/dist/theme-importers/loose.d.ts.map +1 -0
- package/dist/theme-importers/loose.js +76 -0
- package/dist/theme-importers/loose.js.map +1 -0
- package/dist/theme-importers/shadcn.d.ts +24 -0
- package/dist/theme-importers/shadcn.d.ts.map +1 -0
- package/dist/theme-importers/shadcn.js +135 -0
- package/dist/theme-importers/shadcn.js.map +1 -0
- package/dist/theme-importers/style-dictionary.d.ts +17 -0
- package/dist/theme-importers/style-dictionary.d.ts.map +1 -0
- package/dist/theme-importers/style-dictionary.js +125 -0
- package/dist/theme-importers/style-dictionary.js.map +1 -0
- package/dist/theme-importers/tailwind.d.ts +3 -0
- package/dist/theme-importers/tailwind.d.ts.map +1 -0
- package/dist/theme-importers/tailwind.js +218 -0
- package/dist/theme-importers/tailwind.js.map +1 -0
- package/dist/theme-literal-binding.d.ts +37 -0
- package/dist/theme-literal-binding.d.ts.map +1 -0
- package/dist/theme-literal-binding.js +138 -0
- package/dist/theme-literal-binding.js.map +1 -0
- package/dist/theme-normalize.d.ts +31 -0
- package/dist/theme-normalize.d.ts.map +1 -0
- package/dist/theme-normalize.js +587 -0
- package/dist/theme-normalize.js.map +1 -0
- package/dist/theme-ramp.d.ts +55 -0
- package/dist/theme-ramp.d.ts.map +1 -0
- package/dist/theme-ramp.js +149 -0
- package/dist/theme-ramp.js.map +1 -0
- package/dist/theme-render.d.ts +105 -0
- package/dist/theme-render.d.ts.map +1 -0
- package/dist/theme-render.js +441 -0
- package/dist/theme-render.js.map +1 -0
- package/dist/themes-errors.d.ts +109 -0
- package/dist/themes-errors.d.ts.map +1 -0
- package/dist/themes-errors.js +170 -0
- package/dist/themes-errors.js.map +1 -0
- package/dist/themes.d.ts +343 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +697 -0
- package/dist/themes.js.map +1 -0
- package/dist/version.d.ts +7 -4
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +6 -3
- package/dist/version.js.map +1 -1
- package/package.json +10 -2
- package/src/__tests__/redos-hardening.test.ts +160 -0
- package/src/ai-tools-add-module-modes.test.ts +106 -0
- package/src/ai-tools-position.test.ts +134 -0
- package/src/ai-tools.test.ts +81 -0
- package/src/ai-tools.ts +1179 -0
- package/src/auth-forms.ts +36 -0
- package/src/base-css.ts +30 -0
- package/src/build-page.test.ts +228 -0
- package/src/build-page.ts +319 -0
- package/src/cap-failures.ts +67 -0
- package/src/content.test.ts +170 -0
- package/src/content.ts +620 -0
- package/src/context.ts +43 -0
- package/src/css-gradient-scan.ts +88 -0
- package/src/css-var-scan.test.ts +96 -0
- package/src/css-var-scan.ts +144 -0
- package/src/derive-module-type.test.ts +80 -0
- package/src/design-manifest.ts +93 -0
- package/src/fonts.test.ts +157 -0
- package/src/fonts.ts +296 -0
- package/src/genesis-inventory.test.ts +86 -0
- package/src/genesis-inventory.ts +215 -0
- package/src/genesis-sanitize.test.ts +35 -0
- package/src/genesis.ts +87 -0
- package/src/i18n.test.ts +274 -0
- package/src/i18n.ts +269 -0
- package/src/index.test.ts +10 -0
- package/src/index.ts +59 -0
- package/src/interactions.ts +48 -0
- package/src/logger.ts +147 -0
- package/src/media.test.ts +160 -0
- package/src/media.ts +355 -0
- package/src/page-log.test.ts +163 -0
- package/src/page-log.ts +124 -0
- package/src/preview-compose.test.ts +602 -0
- package/src/preview-compose.ts +709 -0
- package/src/preview-scanner.test.ts +96 -0
- package/src/preview-scanner.ts +214 -0
- package/src/proposal-status.test.ts +69 -0
- package/src/proposal-status.ts +40 -0
- package/src/responsive-images.test.ts +104 -0
- package/src/responsive-images.ts +151 -0
- package/src/result.ts +29 -0
- package/src/safe-keys.ts +21 -0
- package/src/seo.test.ts +234 -0
- package/src/seo.ts +261 -0
- package/src/skills.ts +48 -0
- package/src/snapshots.test.ts +80 -0
- package/src/snapshots.ts +81 -0
- package/src/strip-cdata.test.ts +41 -0
- package/src/strip-cdata.ts +50 -0
- package/src/structured-sets.ts +180 -0
- package/src/subagents.test.ts +262 -0
- package/src/subagents.ts +432 -0
- package/src/template-engine.test.ts +379 -0
- package/src/template-engine.ts +520 -0
- package/src/theme-gradient.test.ts +92 -0
- package/src/theme-importers/__tests__/proto-pollution.test.ts +54 -0
- package/src/theme-importers/auto-detect.ts +84 -0
- package/src/theme-importers/css-comments.ts +15 -0
- package/src/theme-importers/dtcg.ts +106 -0
- package/src/theme-importers/loose.ts +76 -0
- package/src/theme-importers/shadcn.ts +133 -0
- package/src/theme-importers/style-dictionary.ts +125 -0
- package/src/theme-importers/tailwind.ts +217 -0
- package/src/theme-literal-binding.test.ts +71 -0
- package/src/theme-literal-binding.ts +159 -0
- package/src/theme-motion.test.ts +115 -0
- package/src/theme-normalize-envelope.test.ts +43 -0
- package/src/theme-normalize-gradient.test.ts +135 -0
- package/src/theme-normalize.ts +661 -0
- package/src/theme-ramp.ts +187 -0
- package/src/theme-render-sanitize.test.ts +45 -0
- package/src/theme-render.test.ts +119 -0
- package/src/theme-render.ts +487 -0
- package/src/theme-shadow.test.ts +56 -0
- package/src/themes-errors.ts +199 -0
- package/src/themes.ts +842 -0
- package/src/translation.test.ts +160 -0
- package/src/translation.ts +295 -0
- package/src/version.ts +66 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* v0.11.1 (issue #76) — Tailwind 4 `@theme { … }` block importer.
|
|
4
|
+
*
|
|
5
|
+
* Tailwind 4 defines theme tokens in a `@theme` (or `@theme inline`) at-rule:
|
|
6
|
+
*
|
|
7
|
+
* @theme {
|
|
8
|
+
* --color-primary: #ff6600;
|
|
9
|
+
* --spacing-md: 1rem;
|
|
10
|
+
* --font-sans: Inter, system-ui;
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* The importer extracts each `--<namespace>-<rest>: <value>;` line from
|
|
14
|
+
* the brace pair and maps it onto a DTCG path via the inverse of
|
|
15
|
+
* `theme-render.ts`'s namespace table (`color.<rest>`, `spacing.<rest>`,
|
|
16
|
+
* etc.). The result is validated by `validateThemeTokens`.
|
|
17
|
+
*
|
|
18
|
+
* Deliberately forgiving — handles `@theme inline`, single-line / block
|
|
19
|
+
* comments, blank lines. Hard-fails (TailwindImportError) on calc() /
|
|
20
|
+
* nested at-rules so the operator gets a concrete fix-it message
|
|
21
|
+
* instead of silently-truncated output.
|
|
22
|
+
*/
|
|
23
|
+
import { isUnsafeKey } from "../safe-keys.js";
|
|
24
|
+
import { validateThemeTokens } from "../themes.js";
|
|
25
|
+
import { NotTailwindShape, TailwindImportError } from "../themes-errors.js";
|
|
26
|
+
import { stripCssComments } from "./css-comments.js";
|
|
27
|
+
export function importTailwind(body) {
|
|
28
|
+
const block = extractAtThemeBlock(body);
|
|
29
|
+
if (block === null) {
|
|
30
|
+
throw new NotTailwindShape();
|
|
31
|
+
}
|
|
32
|
+
const entries = parseCssVarBlock(block);
|
|
33
|
+
if (entries.length === 0) {
|
|
34
|
+
throw new NotTailwindShape("@theme block found but no `--name: value;` pairs inside");
|
|
35
|
+
}
|
|
36
|
+
const doc = mapEntriesToDtcg(entries);
|
|
37
|
+
return validateThemeTokens(doc);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Locate the body of the first `@theme` (or `@theme inline`) at-rule.
|
|
41
|
+
* Returns the contents inside the matching `{ … }` (no braces, no
|
|
42
|
+
* outer whitespace) or null when no block is present.
|
|
43
|
+
*/
|
|
44
|
+
function extractAtThemeBlock(body) {
|
|
45
|
+
const stripped = stripCssComments(body);
|
|
46
|
+
const match = /@theme\s+(?:inline\s+)?\{/i.exec(stripped);
|
|
47
|
+
if (!match)
|
|
48
|
+
return null;
|
|
49
|
+
const start = match.index + match[0].length;
|
|
50
|
+
let depth = 1;
|
|
51
|
+
let i = start;
|
|
52
|
+
while (i < stripped.length && depth > 0) {
|
|
53
|
+
const ch = stripped[i];
|
|
54
|
+
if (ch === "{")
|
|
55
|
+
depth += 1;
|
|
56
|
+
else if (ch === "}")
|
|
57
|
+
depth -= 1;
|
|
58
|
+
if (depth === 0)
|
|
59
|
+
break;
|
|
60
|
+
i += 1;
|
|
61
|
+
}
|
|
62
|
+
if (depth !== 0)
|
|
63
|
+
return null;
|
|
64
|
+
return stripped.slice(start, i);
|
|
65
|
+
}
|
|
66
|
+
function parseCssVarBlock(block) {
|
|
67
|
+
const entries = [];
|
|
68
|
+
// Split on `;` so each entry is one declaration. Skip empty
|
|
69
|
+
// fragments and any line that doesn't start with `--`.
|
|
70
|
+
for (const raw of block.split(";")) {
|
|
71
|
+
const line = raw.trim();
|
|
72
|
+
if (line.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
if (line.startsWith("//"))
|
|
75
|
+
continue;
|
|
76
|
+
if (!line.startsWith("--")) {
|
|
77
|
+
// Catch nested at-rules; the importer doesn't handle them.
|
|
78
|
+
if (line.startsWith("@")) {
|
|
79
|
+
throw new TailwindImportError("nested @-rule", line);
|
|
80
|
+
}
|
|
81
|
+
// Tolerate plain identifiers (`color-scheme: dark` etc.) — skip silently.
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const colonIdx = line.indexOf(":");
|
|
85
|
+
if (colonIdx <= 0)
|
|
86
|
+
continue;
|
|
87
|
+
const name = line.slice(0, colonIdx).trim();
|
|
88
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
89
|
+
if (value.length === 0)
|
|
90
|
+
continue;
|
|
91
|
+
if (/\bcalc\s*\(/i.test(value)) {
|
|
92
|
+
throw new TailwindImportError("calc()", line);
|
|
93
|
+
}
|
|
94
|
+
if (/\bvar\s*\(/i.test(value)) {
|
|
95
|
+
throw new TailwindImportError("var()", line);
|
|
96
|
+
}
|
|
97
|
+
entries.push({ name, value });
|
|
98
|
+
}
|
|
99
|
+
return entries;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Map each `--<namespace>-<rest>` entry to a DTCG group. The namespace
|
|
103
|
+
* table mirrors theme-render.ts's emit table inverted.
|
|
104
|
+
*/
|
|
105
|
+
function mapEntriesToDtcg(entries) {
|
|
106
|
+
const out = {};
|
|
107
|
+
for (const entry of entries) {
|
|
108
|
+
// Strip the leading `--` and split on the first hyphen.
|
|
109
|
+
const stripped = entry.name.slice(2);
|
|
110
|
+
const firstHyphen = stripped.indexOf("-");
|
|
111
|
+
if (firstHyphen <= 0)
|
|
112
|
+
continue; // no category prefix → skip
|
|
113
|
+
const ns = stripped.slice(0, firstHyphen);
|
|
114
|
+
const rest = stripped.slice(firstHyphen + 1);
|
|
115
|
+
let category;
|
|
116
|
+
let leafName;
|
|
117
|
+
let extraSubField = null;
|
|
118
|
+
switch (ns) {
|
|
119
|
+
case "color":
|
|
120
|
+
category = "color";
|
|
121
|
+
leafName = rest;
|
|
122
|
+
break;
|
|
123
|
+
case "spacing":
|
|
124
|
+
category = "spacing";
|
|
125
|
+
leafName = rest;
|
|
126
|
+
break;
|
|
127
|
+
case "radius":
|
|
128
|
+
category = "radius";
|
|
129
|
+
leafName = rest;
|
|
130
|
+
break;
|
|
131
|
+
case "shadow":
|
|
132
|
+
category = "shadow";
|
|
133
|
+
leafName = rest;
|
|
134
|
+
break;
|
|
135
|
+
case "breakpoint":
|
|
136
|
+
category = "breakpoint";
|
|
137
|
+
leafName = rest;
|
|
138
|
+
break;
|
|
139
|
+
case "duration":
|
|
140
|
+
category = "duration";
|
|
141
|
+
leafName = rest;
|
|
142
|
+
break;
|
|
143
|
+
case "ease":
|
|
144
|
+
category = "ease";
|
|
145
|
+
leafName = rest;
|
|
146
|
+
break;
|
|
147
|
+
case "font":
|
|
148
|
+
// --font-sans → typography.sans.fontFamily
|
|
149
|
+
category = "typography";
|
|
150
|
+
leafName = rest;
|
|
151
|
+
extraSubField = "fontFamily";
|
|
152
|
+
break;
|
|
153
|
+
case "text":
|
|
154
|
+
// --text-base → typography.base.fontSize
|
|
155
|
+
category = "typography";
|
|
156
|
+
leafName = rest;
|
|
157
|
+
extraSubField = "fontSize";
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
// Unknown namespace — bucket under its own root so the renderer
|
|
161
|
+
// still emits the var (forward-compat).
|
|
162
|
+
category = ns;
|
|
163
|
+
leafName = rest;
|
|
164
|
+
}
|
|
165
|
+
// `category` and `leafName` are derived from the imported CSS variable
|
|
166
|
+
// name, so a hostile token like `--__proto__-x` could otherwise pollute
|
|
167
|
+
// the prototype chain via `out[category]` / `group[leafName]` (CodeQL
|
|
168
|
+
// js/prototype-polluting-assignment). Skip the entry on any unsafe key.
|
|
169
|
+
if (isUnsafeKey(category) || isUnsafeKey(leafName))
|
|
170
|
+
continue;
|
|
171
|
+
if (!out[category])
|
|
172
|
+
out[category] = {};
|
|
173
|
+
const group = out[category] ?? {};
|
|
174
|
+
if (extraSubField !== null) {
|
|
175
|
+
// Typography composite: merge into the existing leaf's $value.
|
|
176
|
+
const existing = group[leafName];
|
|
177
|
+
const baseObj = existing && typeof existing === "object" && "$value" in existing
|
|
178
|
+
? existing.$value
|
|
179
|
+
: {};
|
|
180
|
+
group[leafName] = {
|
|
181
|
+
$value: { ...baseObj, [extraSubField]: entry.value },
|
|
182
|
+
$type: "typography",
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// v0.11.1 (issue #76 Copilot review #4): if `leafName` looks like
|
|
187
|
+
// a Tailwind ramp suffix (`primary-50` … `primary-900`,
|
|
188
|
+
// `primary-DEFAULT`), nest it as `<group>.<stop>` so the result
|
|
189
|
+
// matches the OKLCh ramp's DTCG group shape. Without this,
|
|
190
|
+
// `--color-primary-50` would land at the flat key `color['primary-50']`
|
|
191
|
+
// and downstream ramp-aware logic (DEFAULT-alias resolver, the
|
|
192
|
+
// ColorEditor's color.primary swatch, the propose-create explicit-
|
|
193
|
+
// stop override path) wouldn't see the stops as a group.
|
|
194
|
+
const rampMatch = /^(.+)-(50|100|200|300|400|500|600|700|800|900|DEFAULT)$/.exec(leafName);
|
|
195
|
+
const tokenLeaf = {
|
|
196
|
+
$value: entry.value,
|
|
197
|
+
$type: category === "color" ? "color" : category === "duration" ? "duration" : "dimension",
|
|
198
|
+
};
|
|
199
|
+
if (rampMatch && category === "color") {
|
|
200
|
+
const [, baseName, stop] = rampMatch;
|
|
201
|
+
// `baseName` is the ramp prefix parsed from the token name; guard it
|
|
202
|
+
// before it becomes a `group[baseName]` assignment target. `stop` is
|
|
203
|
+
// a fixed enum (50…900|DEFAULT), so it needs no guard.
|
|
204
|
+
if (isUnsafeKey(baseName))
|
|
205
|
+
continue;
|
|
206
|
+
if (!group[baseName] || typeof group[baseName] !== "object") {
|
|
207
|
+
group[baseName] = {};
|
|
208
|
+
}
|
|
209
|
+
group[baseName][stop] = tokenLeaf;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
group[leafName] = tokenLeaf;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=tailwind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind.js","sourceRoot":"","sources":["../../src/theme-importers/tailwind.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAsB,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAOrD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,gBAAgB,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,gBAAgB,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,mBAAmB,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,4BAA4B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,GAAG,KAAK,CAAC;IACd,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,IAAI,CAAC,CAAC;aACtB,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,IAAI,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,CAAC;YAAE,MAAM;QACvB,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,4DAA4D;IAC5D,uDAAuD;IACvD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,2DAA2D;YAC3D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,mBAAmB,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC;YACD,0EAA0E;YAC1E,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,IAAI,CAAC;YAAE,SAAS;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAA+B;IACvD,MAAM,GAAG,GAA4C,EAAE,CAAC;IACxD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,wDAAwD;QACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,WAAW,IAAI,CAAC;YAAE,SAAS,CAAC,4BAA4B;QAC5D,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QAE7C,IAAI,QAAgB,CAAC;QACrB,IAAI,QAAgB,CAAC;QACrB,IAAI,aAAa,GAAkB,IAAI,CAAC;QACxC,QAAQ,EAAE,EAAE,CAAC;YACX,KAAK,OAAO;gBACV,QAAQ,GAAG,OAAO,CAAC;gBACnB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,SAAS;gBACZ,QAAQ,GAAG,SAAS,CAAC;gBACrB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,QAAQ;gBACX,QAAQ,GAAG,QAAQ,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,QAAQ;gBACX,QAAQ,GAAG,QAAQ,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,YAAY;gBACf,QAAQ,GAAG,YAAY,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,UAAU;gBACb,QAAQ,GAAG,UAAU,CAAC;gBACtB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,MAAM;gBACT,QAAQ,GAAG,MAAM,CAAC;gBAClB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,MAAM;gBACT,2CAA2C;gBAC3C,QAAQ,GAAG,YAAY,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;gBAChB,aAAa,GAAG,YAAY,CAAC;gBAC7B,MAAM;YACR,KAAK,MAAM;gBACT,yCAAyC;gBACzC,QAAQ,GAAG,YAAY,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;gBAChB,aAAa,GAAG,UAAU,CAAC;gBAC3B,MAAM;YACR;gBACE,gEAAgE;gBAChE,wCAAwC;gBACxC,QAAQ,GAAG,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,uEAAuE;QACvE,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC;YAAE,SAAS;QAE7D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,+DAA+D;YAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;YACjC,MAAM,OAAO,GACX,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,IAAI,QAAQ;gBAC9D,CAAC,CAAG,QAAgC,CAAC,MAAkC;gBACvE,CAAC,CAAC,EAAE,CAAC;YACT,KAAK,CAAC,QAAQ,CAAC,GAAG;gBAChB,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE;gBACpD,KAAK,EAAE,YAAY;aACpB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,kEAAkE;YAClE,wDAAwD;YACxD,gEAAgE;YAChE,2DAA2D;YAC3D,wEAAwE;YACxE,+DAA+D;YAC/D,mEAAmE;YACnE,yDAAyD;YACzD,MAAM,SAAS,GAAG,yDAAyD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC3F,MAAM,SAAS,GAAG;gBAChB,MAAM,EAAE,KAAK,CAAC,KAAK;gBACnB,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW;aAC3F,CAAC;YACF,IAAI,SAAS,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACtC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,SAAgD,CAAC;gBAC5E,qEAAqE;gBACrE,qEAAqE;gBACrE,uDAAuD;gBACvD,IAAI,WAAW,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACpC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;oBAC5D,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBACvB,CAAC;gBACA,KAAK,CAAC,QAAQ,CAA6B,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAoB,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ThemeDocument } from "./themes.js";
|
|
2
|
+
export interface ThemeValueMap {
|
|
3
|
+
/** normalized color value → var name (first-declared wins). */
|
|
4
|
+
readonly colors: ReadonlyMap<string, string>;
|
|
5
|
+
/** exact gradient string (normalized whitespace) → var name. */
|
|
6
|
+
readonly gradients: ReadonlyMap<string, string>;
|
|
7
|
+
/** dimension value → var name (suggestion-only tier). */
|
|
8
|
+
readonly dimensions: ReadonlyMap<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parse the light-branch declarations the renderer emits for this
|
|
12
|
+
* document into value → var-name maps.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildThemeValueMap(tokens: ThemeDocument): ThemeValueMap;
|
|
15
|
+
export interface LiteralBindingResult {
|
|
16
|
+
readonly css: string;
|
|
17
|
+
/** Applied rewrites: literal → var name, with occurrence counts. */
|
|
18
|
+
readonly rewrites: readonly {
|
|
19
|
+
from: string;
|
|
20
|
+
to: string;
|
|
21
|
+
count: number;
|
|
22
|
+
}[];
|
|
23
|
+
/** Dimension matches left in place (too ambiguous to auto-rewrite). */
|
|
24
|
+
readonly suggestions: readonly {
|
|
25
|
+
literal: string;
|
|
26
|
+
varName: string;
|
|
27
|
+
}[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Rewrite color/gradient literals that equal theme token values to
|
|
31
|
+
* `var(--name)`. Longest-first (gradients before their stop colors) so
|
|
32
|
+
* a gradient binds as a whole instead of stop-by-stop.
|
|
33
|
+
*/
|
|
34
|
+
export declare function applyThemeLiteralBinding(css: string, tokens: ThemeDocument): LiteralBindingResult;
|
|
35
|
+
/** Tool-result suffix describing what binding did. Null on no-op. */
|
|
36
|
+
export declare function formatBindingReport(result: LiteralBindingResult): string | null;
|
|
37
|
+
//# sourceMappingURL=theme-literal-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-literal-binding.d.ts","sourceRoot":"","sources":["../src/theme-literal-binding.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AASD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CA8BvE;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1E,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,oBAAoB,CA2CjG;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,CAkB/E"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* issue #164 slice 2 — mechanical token binding ("AI decides, code
|
|
4
|
+
* executes"). During Genesis materialisation the theme is created FROM
|
|
5
|
+
* the draft's palette, so module CSS copied from the draft contains
|
|
6
|
+
* literals that EQUAL theme token values. Hand-translating them to
|
|
7
|
+
* `var(--…)` is transcription work the model can get subtly wrong;
|
|
8
|
+
* this module does it mechanically:
|
|
9
|
+
*
|
|
10
|
+
* - colors + gradients whose literal value equals an emitted token's
|
|
11
|
+
* value are rewritten to `var(--name)` (unambiguous: the value IS
|
|
12
|
+
* the token's value);
|
|
13
|
+
* - dimension-ish matches (a `6rem` that equals `--spacing-2xl`) are
|
|
14
|
+
* reported as SUGGESTIONS only — generic lengths are too ambiguous
|
|
15
|
+
* to rewrite silently.
|
|
16
|
+
*
|
|
17
|
+
* The value map is parsed from `renderThemeCss` output so binding uses
|
|
18
|
+
* exactly what the renderer emits (aliases resolved, ramps included) —
|
|
19
|
+
* no second resolution path to drift.
|
|
20
|
+
*/
|
|
21
|
+
import { replaceCssGradients } from "./css-gradient-scan.js";
|
|
22
|
+
import { renderThemeCss } from "./theme-render.js";
|
|
23
|
+
const COLOR_LITERAL_RE = /#[0-9a-fA-F]{3,8}\b|(?:oklch|rgba?|hsla?|lab|lch|hwb)\([^()]*\)/g;
|
|
24
|
+
const DIMENSION_VALUE_RE = /^-?\d+(\.\d+)?(rem|em|px|%)$/;
|
|
25
|
+
function normalizeColor(v) {
|
|
26
|
+
return v.trim().toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
function normalizeGradient(v) {
|
|
29
|
+
return v.trim().toLowerCase().replace(/\s+/g, " ");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse the light-branch declarations the renderer emits for this
|
|
33
|
+
* document into value → var-name maps.
|
|
34
|
+
*/
|
|
35
|
+
export function buildThemeValueMap(tokens) {
|
|
36
|
+
const css = renderThemeCss(tokens);
|
|
37
|
+
// Only the light branch: `.dark` overrides carry the same names.
|
|
38
|
+
const lightEnd = css.indexOf(".dark{");
|
|
39
|
+
const light = lightEnd === -1 ? css : css.slice(0, lightEnd);
|
|
40
|
+
const colors = new Map();
|
|
41
|
+
const gradients = new Map();
|
|
42
|
+
const dimensions = new Map();
|
|
43
|
+
// Regex-free declaration split (a `(--name):(value);` regex is the
|
|
44
|
+
// #113 polynomial shape on adversarial dash runs). The light block
|
|
45
|
+
// is `:root{--a:v;--b:v;}` — split on `;`, take name:value pairs.
|
|
46
|
+
for (const rawSeg of light.split(";")) {
|
|
47
|
+
const seg = rawSeg.slice(rawSeg.lastIndexOf("{") + 1);
|
|
48
|
+
const colon = seg.indexOf(":");
|
|
49
|
+
if (colon <= 0)
|
|
50
|
+
continue;
|
|
51
|
+
const name = seg.slice(0, colon).trim();
|
|
52
|
+
const value = seg.slice(colon + 1).trim();
|
|
53
|
+
if (!name.startsWith("--") || value.length === 0)
|
|
54
|
+
continue;
|
|
55
|
+
if (name.startsWith("--gradient-")) {
|
|
56
|
+
const key = normalizeGradient(value);
|
|
57
|
+
if (!gradients.has(key))
|
|
58
|
+
gradients.set(key, name);
|
|
59
|
+
}
|
|
60
|
+
else if (name.startsWith("--color-")) {
|
|
61
|
+
const key = normalizeColor(value);
|
|
62
|
+
if (!colors.has(key))
|
|
63
|
+
colors.set(key, name);
|
|
64
|
+
}
|
|
65
|
+
else if (DIMENSION_VALUE_RE.test(value)) {
|
|
66
|
+
if (!dimensions.has(value))
|
|
67
|
+
dimensions.set(value, name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { colors, gradients, dimensions };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rewrite color/gradient literals that equal theme token values to
|
|
74
|
+
* `var(--name)`. Longest-first (gradients before their stop colors) so
|
|
75
|
+
* a gradient binds as a whole instead of stop-by-stop.
|
|
76
|
+
*/
|
|
77
|
+
export function applyThemeLiteralBinding(css, tokens) {
|
|
78
|
+
const map = buildThemeValueMap(tokens);
|
|
79
|
+
const counts = new Map();
|
|
80
|
+
let out = css;
|
|
81
|
+
out = replaceCssGradients(out, (literal) => {
|
|
82
|
+
const varName = map.gradients.get(normalizeGradient(literal));
|
|
83
|
+
if (varName === undefined)
|
|
84
|
+
return literal;
|
|
85
|
+
const entry = counts.get(literal) ?? { to: varName, count: 0 };
|
|
86
|
+
entry.count += 1;
|
|
87
|
+
counts.set(literal, entry);
|
|
88
|
+
return `var(${varName})`;
|
|
89
|
+
});
|
|
90
|
+
out = out.replace(COLOR_LITERAL_RE, (literal, offset) => {
|
|
91
|
+
// Never rewrite inside an already-produced var(...) fallback or a
|
|
92
|
+
// remaining gradient (a gradient that did NOT match stays literal
|
|
93
|
+
// by decision — rebinding its stops would half-tokenise it).
|
|
94
|
+
const before = out.slice(Math.max(0, offset - 64), offset);
|
|
95
|
+
if (/gradient\([^()]*$/i.test(before))
|
|
96
|
+
return literal;
|
|
97
|
+
const varName = map.colors.get(normalizeColor(literal));
|
|
98
|
+
if (varName === undefined)
|
|
99
|
+
return literal;
|
|
100
|
+
const entry = counts.get(literal) ?? { to: varName, count: 0 };
|
|
101
|
+
entry.count += 1;
|
|
102
|
+
counts.set(literal, entry);
|
|
103
|
+
return `var(${varName})`;
|
|
104
|
+
});
|
|
105
|
+
const suggestions = [];
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
for (const m of out.matchAll(/-?\d+(?:\.\d+)?(?:rem|em|px|%)\b/g)) {
|
|
108
|
+
const literal = m[0];
|
|
109
|
+
if (seen.has(literal))
|
|
110
|
+
continue;
|
|
111
|
+
seen.add(literal);
|
|
112
|
+
const varName = map.dimensions.get(literal);
|
|
113
|
+
if (varName !== undefined)
|
|
114
|
+
suggestions.push({ literal, varName });
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
css: out,
|
|
118
|
+
rewrites: [...counts.entries()].map(([from, e]) => ({ from, to: e.to, count: e.count })),
|
|
119
|
+
suggestions,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Tool-result suffix describing what binding did. Null on no-op. */
|
|
123
|
+
export function formatBindingReport(result) {
|
|
124
|
+
const parts = [];
|
|
125
|
+
if (result.rewrites.length > 0) {
|
|
126
|
+
const total = result.rewrites.reduce((n, r) => n + r.count, 0);
|
|
127
|
+
parts.push(`🔗 bound ${total} literal(s) to theme vars: ${result.rewrites
|
|
128
|
+
.map((r) => `${r.from}→var(${r.to})${r.count > 1 ? `×${r.count}` : ""}`)
|
|
129
|
+
.join(", ")}`);
|
|
130
|
+
}
|
|
131
|
+
if (result.suggestions.length > 0) {
|
|
132
|
+
parts.push(`consider tokens for: ${result.suggestions
|
|
133
|
+
.map((s) => `${s.literal}≈var(${s.varName})`)
|
|
134
|
+
.join(", ")} (dimensions are never auto-rewritten)`);
|
|
135
|
+
}
|
|
136
|
+
return parts.length > 0 ? ` ${parts.join(". ")}.` : null;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=theme-literal-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-literal-binding.js","sourceRoot":"","sources":["../src/theme-literal-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type CanonicalPath = string;
|
|
2
|
+
export interface NormalizeResult {
|
|
3
|
+
/**
|
|
4
|
+
* Map from canonical DTCG path (e.g. "color.primary") to the value
|
|
5
|
+
* the caller supplied. The ops layer rebuilds the DTCG leaf
|
|
6
|
+
* (`{$value: <value>, $type: <inferred>}`) from this.
|
|
7
|
+
*/
|
|
8
|
+
readonly set: Record<CanonicalPath, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Inferred `$type` per canonical path. The renderer also knows the
|
|
11
|
+
* category from the path prefix, but the ops layer uses this to set
|
|
12
|
+
* `$type` on the stored token.
|
|
13
|
+
*/
|
|
14
|
+
readonly types: Record<CanonicalPath, "color" | "dimension" | "typography" | "shadow" | "duration" | "cubicBezier" | "gradient">;
|
|
15
|
+
/** Echo-back list for the AI tool's result content. */
|
|
16
|
+
readonly canonicalPaths: readonly CanonicalPath[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Normalize a record of loose-name → value pairs into canonical DTCG
|
|
20
|
+
* paths. Throws `UnknownTokenName` on the first ambiguous entry so the
|
|
21
|
+
* AI gets a single concrete next-step rather than a wall of partial
|
|
22
|
+
* results.
|
|
23
|
+
*/
|
|
24
|
+
export declare function normalizeTokens(input: Record<string, unknown>): NormalizeResult;
|
|
25
|
+
/**
|
|
26
|
+
* Closest-match suggestions for an unknown input. Cheap edit-distance
|
|
27
|
+
* over the canonical-paths set — good enough that the AI gets a useful
|
|
28
|
+
* "did you mean X?" without pulling a fuzzy-search dep.
|
|
29
|
+
*/
|
|
30
|
+
export declare function didYouMean(input: string): readonly string[];
|
|
31
|
+
//# sourceMappingURL=theme-normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-normalize.d.ts","sourceRoot":"","sources":["../src/theme-normalize.ts"],"names":[],"mappings":"AAgCA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CACpB,aAAa,EACb,OAAO,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,UAAU,CAC1F,CAAC;IACF,uDAAuD;IACvD,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;CACnD;AA+JD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CA8D/E;AAoWD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAO3D"}
|