wensity 0.1.6 → 0.1.7
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.js +1186 -265
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,10 +4,160 @@
|
|
|
4
4
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
5
5
|
import { dirname as dirname6, join as join6 } from "path";
|
|
6
6
|
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var CLI_NAME = "wensity";
|
|
9
|
+
var CLI_VERSION = "0.1.7";
|
|
10
|
+
var CONFIG_FILE_NAME = "wensity.json";
|
|
11
|
+
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
12
|
+
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
13
|
+
var DEFAULT_COMPONENTS_DIR = "src/components/wensity";
|
|
14
|
+
var DEFAULT_UTILS_PATH = "src/lib/utils";
|
|
15
|
+
var DEFAULT_COMPONENTS_ALIAS = "@/components/wensity";
|
|
16
|
+
var DEFAULT_UTILS_ALIAS = "@/lib/utils";
|
|
17
|
+
var INIT_PRIMITIVE_CSS_SLUG = "button";
|
|
18
|
+
var HELP_TEXT = `Wensity CLI ${CLI_VERSION}
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
wensity init [--preset <code>] [--preset-file <path>] [options]
|
|
22
|
+
wensity login [options]
|
|
23
|
+
wensity logout
|
|
24
|
+
wensity whoami [--json]
|
|
25
|
+
wensity list [--type component|block] [options]
|
|
26
|
+
wensity add <slug> [--type component|block] [options]
|
|
27
|
+
wensity update <slug> [--type component|block] [options]
|
|
28
|
+
wensity version
|
|
29
|
+
|
|
30
|
+
Commands:
|
|
31
|
+
init Create wensity.json and local helper files (optional --preset applies style + CSS)
|
|
32
|
+
login Save a Wensity API token for premium component access
|
|
33
|
+
logout Remove saved CLI credentials
|
|
34
|
+
whoami Verify the saved token and print the authenticated account
|
|
35
|
+
list List registry components or blocks
|
|
36
|
+
add Download a component or block source file into this project
|
|
37
|
+
update Re-download a component or block and overwrite the local copy
|
|
38
|
+
version Print the CLI version
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
--api-url <url> Override the Wensity app origin, defaults to ${DEFAULT_API_ORIGIN}
|
|
42
|
+
--registry <url> Override the registry endpoint
|
|
43
|
+
--type <type> Select component or block, defaults to component
|
|
44
|
+
--token <token> Provide a token non-interactively for login
|
|
45
|
+
--preset <code> Apply a shareable Wensity style preset (wsty1.\u2026); merges style when config exists
|
|
46
|
+
--preset-file <path> Read a preset code or JSON payload from a file
|
|
47
|
+
--force Overwrite generated files when adding or initializing
|
|
48
|
+
--no-install Write files without running the package manager
|
|
49
|
+
--dry-run Print planned writes and installs without changing files
|
|
50
|
+
--json Print machine-readable output where supported
|
|
51
|
+
--help Show help
|
|
52
|
+
--version Print the CLI version
|
|
53
|
+
|
|
54
|
+
Preset notes:
|
|
55
|
+
Generate codes at ${DEFAULT_API_ORIGIN}/docs/primitives/setup
|
|
56
|
+
Plain init refuses an existing wensity.json unless --force
|
|
57
|
+
init --preset merges style + primitive CSS; does not rewrite installed source
|
|
58
|
+
add/update read style.iconLibrary for UI primitives only (Tabler|Lucide)
|
|
59
|
+
Invalid/expired/unsupported codes exit non-zero with an actionable message
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
// src/errors.ts
|
|
63
|
+
var CliError = class extends Error {
|
|
64
|
+
exitCode;
|
|
65
|
+
constructor(message, exitCode = 1) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "CliError";
|
|
68
|
+
this.exitCode = exitCode;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function isNodeError(error) {
|
|
72
|
+
return error instanceof Error && "code" in error;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/args.ts
|
|
76
|
+
function parseArgs(argv) {
|
|
77
|
+
const positionals = [];
|
|
78
|
+
const options = /* @__PURE__ */ new Map();
|
|
79
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
80
|
+
const token = argv[index];
|
|
81
|
+
if (!token.startsWith("--")) {
|
|
82
|
+
positionals.push(token);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (token === "--") {
|
|
86
|
+
positionals.push(...argv.slice(index + 1));
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const inlineValueIndex = token.indexOf("=");
|
|
90
|
+
const rawName = inlineValueIndex > -1 ? token.slice(2, inlineValueIndex) : token.slice(2);
|
|
91
|
+
const name = normalizeOptionName(rawName);
|
|
92
|
+
if (!name) {
|
|
93
|
+
throw new CliError(`Invalid option: ${token}`);
|
|
94
|
+
}
|
|
95
|
+
if (inlineValueIndex > -1) {
|
|
96
|
+
options.set(name, token.slice(inlineValueIndex + 1));
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const nextToken = argv[index + 1];
|
|
100
|
+
if (nextToken && !nextToken.startsWith("--") && expectsValue(name)) {
|
|
101
|
+
options.set(name, nextToken);
|
|
102
|
+
index += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
options.set(name, true);
|
|
106
|
+
}
|
|
107
|
+
return { positionals, options };
|
|
108
|
+
}
|
|
109
|
+
function getStringOption(args, name) {
|
|
110
|
+
const value = args.options.get(name);
|
|
111
|
+
if (value === void 0) return void 0;
|
|
112
|
+
if (typeof value === "boolean") {
|
|
113
|
+
throw new CliError(`--${name} expects a value.`);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function hasFlag(args, name) {
|
|
118
|
+
return args.options.get(name) === true;
|
|
119
|
+
}
|
|
120
|
+
function expectsValue(name) {
|
|
121
|
+
return ["api-url", "registry", "token", "type", "preset", "preset-file"].includes(name);
|
|
122
|
+
}
|
|
123
|
+
function normalizeOptionName(name) {
|
|
124
|
+
if (name === "dry") return "dry-run";
|
|
125
|
+
return name;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/config.ts
|
|
129
|
+
import { existsSync } from "fs";
|
|
130
|
+
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
131
|
+
import { dirname as dirname2, join as join2, relative as relative2 } from "path";
|
|
132
|
+
|
|
7
133
|
// ../wensity-preset/src/constants.ts
|
|
8
134
|
var ICON_LIBRARIES = ["tabler", "lucide"];
|
|
9
135
|
var RADIUS_PRESETS = ["none", "small", "medium", "large"];
|
|
10
136
|
var BUILTIN_FONT_IDS = ["site", "system-sans", "system-mono"];
|
|
137
|
+
var BASE_COLOR_IDS = [
|
|
138
|
+
"inherit",
|
|
139
|
+
"neutral",
|
|
140
|
+
"zinc",
|
|
141
|
+
"slate",
|
|
142
|
+
"stone",
|
|
143
|
+
"taupe"
|
|
144
|
+
];
|
|
145
|
+
var THEME_COLOR_IDS = [
|
|
146
|
+
"ink",
|
|
147
|
+
"red",
|
|
148
|
+
"blue",
|
|
149
|
+
"violet",
|
|
150
|
+
"green",
|
|
151
|
+
"orange"
|
|
152
|
+
];
|
|
153
|
+
var CHART_PALETTE_IDS = [
|
|
154
|
+
"theme",
|
|
155
|
+
"warm",
|
|
156
|
+
"cool",
|
|
157
|
+
"mixed"
|
|
158
|
+
];
|
|
159
|
+
var HEADING_FONT_IDS = ["system", "playfair"];
|
|
160
|
+
var BODY_FONT_IDS = ["system", "inter"];
|
|
11
161
|
var RADIUS_PRESET_CSS = {
|
|
12
162
|
none: "0px",
|
|
13
163
|
small: "0.5rem",
|
|
@@ -27,12 +177,6 @@ var CONTROL_SOLID_COLOR_KEYS = [
|
|
|
27
177
|
"controlSolidActive",
|
|
28
178
|
"controlSolidForeground"
|
|
29
179
|
];
|
|
30
|
-
var CONTROL_SOLID_CSS_VARS = {
|
|
31
|
-
controlSolid: "--primitive-control-solid",
|
|
32
|
-
controlSolidHover: "--primitive-control-solid-hover",
|
|
33
|
-
controlSolidActive: "--primitive-control-solid-active",
|
|
34
|
-
controlSolidForeground: "--primitive-control-solid-foreground"
|
|
35
|
-
};
|
|
36
180
|
var STYLE_OBJECT_KEYS = [
|
|
37
181
|
"iconLibrary",
|
|
38
182
|
"radius",
|
|
@@ -40,6 +184,16 @@ var STYLE_OBJECT_KEYS = [
|
|
|
40
184
|
"colors",
|
|
41
185
|
"presetCode"
|
|
42
186
|
];
|
|
187
|
+
var STYLE_OBJECT_KEYS_CANONICAL = [
|
|
188
|
+
"baseColor",
|
|
189
|
+
"themeColor",
|
|
190
|
+
"chartPalette",
|
|
191
|
+
"headingFont",
|
|
192
|
+
"bodyFont",
|
|
193
|
+
"iconLibrary",
|
|
194
|
+
"radius",
|
|
195
|
+
"presetCode"
|
|
196
|
+
];
|
|
43
197
|
var FONT_ROLE_KEYS = ["sans", "display", "mono"];
|
|
44
198
|
var COLOR_MODE_KEYS = ["light", "dark"];
|
|
45
199
|
var HEX_COLOR_PATTERN = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
@@ -62,6 +216,21 @@ function isFontRoleValue(value) {
|
|
|
62
216
|
if (isBuiltinFontId(value)) return true;
|
|
63
217
|
return value.startsWith(CUSTOM_FONT_PREFIX) && value.length > CUSTOM_FONT_PREFIX.length;
|
|
64
218
|
}
|
|
219
|
+
function isBaseColorId(value) {
|
|
220
|
+
return BASE_COLOR_IDS.includes(value);
|
|
221
|
+
}
|
|
222
|
+
function isThemeColorId(value) {
|
|
223
|
+
return THEME_COLOR_IDS.includes(value);
|
|
224
|
+
}
|
|
225
|
+
function isChartPaletteId(value) {
|
|
226
|
+
return CHART_PALETTE_IDS.includes(value);
|
|
227
|
+
}
|
|
228
|
+
function isHeadingFontId(value) {
|
|
229
|
+
return HEADING_FONT_IDS.includes(value);
|
|
230
|
+
}
|
|
231
|
+
function isBodyFontId(value) {
|
|
232
|
+
return BODY_FONT_IDS.includes(value);
|
|
233
|
+
}
|
|
65
234
|
|
|
66
235
|
// ../wensity-preset/src/defaults.ts
|
|
67
236
|
var DEFAULT_STYLE_FONTS = {
|
|
@@ -101,6 +270,26 @@ function createDefaultStyleConfig() {
|
|
|
101
270
|
}
|
|
102
271
|
};
|
|
103
272
|
}
|
|
273
|
+
var DEFAULT_STYLE_CONFIG_CANONICAL = {
|
|
274
|
+
baseColor: "inherit",
|
|
275
|
+
themeColor: "ink",
|
|
276
|
+
chartPalette: "theme",
|
|
277
|
+
headingFont: "system",
|
|
278
|
+
bodyFont: "system",
|
|
279
|
+
iconLibrary: "tabler",
|
|
280
|
+
radius: "medium"
|
|
281
|
+
};
|
|
282
|
+
function createDefaultStyleConfigCanonical() {
|
|
283
|
+
return {
|
|
284
|
+
baseColor: DEFAULT_STYLE_CONFIG_CANONICAL.baseColor,
|
|
285
|
+
themeColor: DEFAULT_STYLE_CONFIG_CANONICAL.themeColor,
|
|
286
|
+
chartPalette: DEFAULT_STYLE_CONFIG_CANONICAL.chartPalette,
|
|
287
|
+
headingFont: DEFAULT_STYLE_CONFIG_CANONICAL.headingFont,
|
|
288
|
+
bodyFont: DEFAULT_STYLE_CONFIG_CANONICAL.bodyFont,
|
|
289
|
+
iconLibrary: DEFAULT_STYLE_CONFIG_CANONICAL.iconLibrary,
|
|
290
|
+
radius: DEFAULT_STYLE_CONFIG_CANONICAL.radius
|
|
291
|
+
};
|
|
292
|
+
}
|
|
104
293
|
|
|
105
294
|
// ../wensity-preset/src/schema.ts
|
|
106
295
|
var fontRoleSchema = {
|
|
@@ -123,66 +312,53 @@ var controlSolidColorsSchema = {
|
|
|
123
312
|
])
|
|
124
313
|
)
|
|
125
314
|
};
|
|
126
|
-
var
|
|
127
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
128
|
-
$id: "https://ui.wensity.com/schema/wensity.json",
|
|
129
|
-
title: "Wensity CLI configuration",
|
|
315
|
+
var legacyStyleSchema = {
|
|
130
316
|
type: "object",
|
|
131
317
|
additionalProperties: false,
|
|
132
318
|
properties: {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
components: { type: "string", minLength: 1 },
|
|
137
|
-
utils: { type: "string", minLength: 1 },
|
|
138
|
-
tailwind: {
|
|
319
|
+
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
320
|
+
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
321
|
+
fonts: {
|
|
139
322
|
type: "object",
|
|
140
323
|
additionalProperties: false,
|
|
141
324
|
properties: {
|
|
142
|
-
|
|
143
|
-
|
|
325
|
+
sans: fontRoleSchema,
|
|
326
|
+
display: fontRoleSchema,
|
|
327
|
+
mono: fontRoleSchema
|
|
144
328
|
}
|
|
145
329
|
},
|
|
146
|
-
|
|
330
|
+
colors: {
|
|
147
331
|
type: "object",
|
|
148
332
|
additionalProperties: false,
|
|
149
333
|
properties: {
|
|
150
|
-
|
|
151
|
-
|
|
334
|
+
light: controlSolidColorsSchema,
|
|
335
|
+
dark: controlSolidColorsSchema
|
|
152
336
|
}
|
|
153
337
|
},
|
|
154
|
-
|
|
155
|
-
type: "
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
159
|
-
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
160
|
-
fonts: {
|
|
161
|
-
type: "object",
|
|
162
|
-
additionalProperties: false,
|
|
163
|
-
properties: {
|
|
164
|
-
sans: fontRoleSchema,
|
|
165
|
-
display: fontRoleSchema,
|
|
166
|
-
mono: fontRoleSchema
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
colors: {
|
|
170
|
-
type: "object",
|
|
171
|
-
additionalProperties: false,
|
|
172
|
-
properties: {
|
|
173
|
-
light: controlSolidColorsSchema,
|
|
174
|
-
dark: controlSolidColorsSchema
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
presetCode: {
|
|
178
|
-
type: "string",
|
|
179
|
-
minLength: 1,
|
|
180
|
-
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
181
|
-
}
|
|
182
|
-
}
|
|
338
|
+
presetCode: {
|
|
339
|
+
type: "string",
|
|
340
|
+
minLength: 1,
|
|
341
|
+
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
183
342
|
}
|
|
184
|
-
}
|
|
185
|
-
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var canonicalStyleSchema = {
|
|
346
|
+
type: "object",
|
|
347
|
+
additionalProperties: false,
|
|
348
|
+
properties: {
|
|
349
|
+
baseColor: { type: "string", enum: [...BASE_COLOR_IDS] },
|
|
350
|
+
themeColor: { type: "string", enum: [...THEME_COLOR_IDS] },
|
|
351
|
+
chartPalette: { type: "string", enum: [...CHART_PALETTE_IDS] },
|
|
352
|
+
headingFont: { type: "string", enum: [...HEADING_FONT_IDS] },
|
|
353
|
+
bodyFont: { type: "string", enum: [...BODY_FONT_IDS] },
|
|
354
|
+
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
355
|
+
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
356
|
+
presetCode: {
|
|
357
|
+
type: "string",
|
|
358
|
+
minLength: 1,
|
|
359
|
+
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
360
|
+
}
|
|
361
|
+
}
|
|
186
362
|
};
|
|
187
363
|
|
|
188
364
|
// ../wensity-preset/src/fonts.ts
|
|
@@ -420,6 +596,91 @@ function validateStyleConfigPartial(value) {
|
|
|
420
596
|
}
|
|
421
597
|
return result;
|
|
422
598
|
}
|
|
599
|
+
function validateStyleConfigCanonicalPartial(value) {
|
|
600
|
+
if (value === void 0 || value === null) return {};
|
|
601
|
+
assertPlainObject(value, "style");
|
|
602
|
+
assertAllowedKeys(value, STYLE_OBJECT_KEYS_CANONICAL, "style");
|
|
603
|
+
const result = {};
|
|
604
|
+
if ("baseColor" in value) {
|
|
605
|
+
if (typeof value.baseColor !== "string" || !isBaseColorId(value.baseColor)) {
|
|
606
|
+
throw new PresetValidationError(
|
|
607
|
+
"Invalid style.baseColor. Expected inherit | neutral | zinc | slate | stone | taupe.",
|
|
608
|
+
"style.baseColor"
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
result.baseColor = value.baseColor;
|
|
612
|
+
}
|
|
613
|
+
if ("themeColor" in value) {
|
|
614
|
+
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
615
|
+
throw new PresetValidationError(
|
|
616
|
+
"Invalid style.themeColor. Expected ink | red | blue | violet | green | orange.",
|
|
617
|
+
"style.themeColor"
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
result.themeColor = value.themeColor;
|
|
621
|
+
}
|
|
622
|
+
if ("chartPalette" in value) {
|
|
623
|
+
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
624
|
+
throw new PresetValidationError(
|
|
625
|
+
"Invalid style.chartPalette. Expected theme | warm | cool | mixed.",
|
|
626
|
+
"style.chartPalette"
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
result.chartPalette = value.chartPalette;
|
|
630
|
+
}
|
|
631
|
+
if ("headingFont" in value) {
|
|
632
|
+
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
633
|
+
throw new PresetValidationError(
|
|
634
|
+
"Invalid style.headingFont. Expected system | playfair.",
|
|
635
|
+
"style.headingFont"
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
result.headingFont = value.headingFont;
|
|
639
|
+
}
|
|
640
|
+
if ("bodyFont" in value) {
|
|
641
|
+
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
642
|
+
throw new PresetValidationError(
|
|
643
|
+
"Invalid style.bodyFont. Expected system | inter.",
|
|
644
|
+
"style.bodyFont"
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
result.bodyFont = value.bodyFont;
|
|
648
|
+
}
|
|
649
|
+
if ("iconLibrary" in value) {
|
|
650
|
+
if (typeof value.iconLibrary !== "string" || !isIconLibrary(value.iconLibrary)) {
|
|
651
|
+
throw new PresetValidationError(
|
|
652
|
+
"Invalid style.iconLibrary. Expected tabler | lucide.",
|
|
653
|
+
"style.iconLibrary"
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
result.iconLibrary = value.iconLibrary;
|
|
657
|
+
}
|
|
658
|
+
if ("radius" in value) {
|
|
659
|
+
if (typeof value.radius !== "string" || !isRadiusPreset(value.radius)) {
|
|
660
|
+
throw new PresetValidationError(
|
|
661
|
+
"Invalid style.radius. Expected none | small | medium | large.",
|
|
662
|
+
"style.radius"
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
result.radius = value.radius;
|
|
666
|
+
}
|
|
667
|
+
if ("presetCode" in value) {
|
|
668
|
+
if (typeof value.presetCode !== "string" || value.presetCode.length === 0) {
|
|
669
|
+
throw new PresetValidationError(
|
|
670
|
+
"Invalid style.presetCode. Expected a non-empty string.",
|
|
671
|
+
"style.presetCode"
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
if (value.presetCode.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
675
|
+
throw new PresetValidationError(
|
|
676
|
+
`Invalid style.presetCode. Exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
677
|
+
"style.presetCode"
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
result.presetCode = value.presetCode;
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
423
684
|
|
|
424
685
|
// ../wensity-preset/src/normalize.ts
|
|
425
686
|
function mergeControlSolid(base, partial) {
|
|
@@ -460,9 +721,36 @@ function normalizeStyleConfig(partial) {
|
|
|
460
721
|
}
|
|
461
722
|
return normalized;
|
|
462
723
|
}
|
|
724
|
+
function normalizeStyleConfigCanonical(partial) {
|
|
725
|
+
const validated = validateStyleConfigCanonicalPartial(partial ?? void 0);
|
|
726
|
+
const defaults = createDefaultStyleConfigCanonical();
|
|
727
|
+
const normalized = {
|
|
728
|
+
baseColor: validated.baseColor ?? defaults.baseColor,
|
|
729
|
+
themeColor: validated.themeColor ?? defaults.themeColor,
|
|
730
|
+
chartPalette: validated.chartPalette ?? defaults.chartPalette,
|
|
731
|
+
headingFont: validated.headingFont ?? defaults.headingFont,
|
|
732
|
+
bodyFont: validated.bodyFont ?? defaults.bodyFont,
|
|
733
|
+
iconLibrary: validated.iconLibrary ?? defaults.iconLibrary,
|
|
734
|
+
radius: validated.radius ?? defaults.radius
|
|
735
|
+
};
|
|
736
|
+
if (validated.presetCode !== void 0) {
|
|
737
|
+
normalized.presetCode = validated.presetCode;
|
|
738
|
+
}
|
|
739
|
+
return normalized;
|
|
740
|
+
}
|
|
463
741
|
|
|
464
742
|
// ../wensity-preset/src/codec.ts
|
|
465
743
|
var CODEC_PAYLOAD_KEYS = ["v", "iconLibrary", "radius", "fonts", "colors"];
|
|
744
|
+
var CODEC_PAYLOAD_KEYS_CANONICAL = [
|
|
745
|
+
"v",
|
|
746
|
+
"baseColor",
|
|
747
|
+
"themeColor",
|
|
748
|
+
"chartPalette",
|
|
749
|
+
"headingFont",
|
|
750
|
+
"bodyFont",
|
|
751
|
+
"iconLibrary",
|
|
752
|
+
"radius"
|
|
753
|
+
];
|
|
466
754
|
function assertPlainObject2(value, path) {
|
|
467
755
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
468
756
|
throw new PresetValidationError(`Expected an object at ${path}.`, path);
|
|
@@ -675,7 +963,124 @@ function pickDefinedColors(partial) {
|
|
|
675
963
|
}
|
|
676
964
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
677
965
|
}
|
|
678
|
-
|
|
966
|
+
var CODEC_CANONICAL_REQUIRED_FIELDS = [
|
|
967
|
+
"baseColor",
|
|
968
|
+
"themeColor",
|
|
969
|
+
"chartPalette",
|
|
970
|
+
"headingFont",
|
|
971
|
+
"bodyFont",
|
|
972
|
+
"iconLibrary",
|
|
973
|
+
"radius"
|
|
974
|
+
];
|
|
975
|
+
function validateCodecPayloadCanonical(value) {
|
|
976
|
+
assertPlainObject2(value, "preset");
|
|
977
|
+
assertAllowedKeys2(value, CODEC_PAYLOAD_KEYS_CANONICAL, "preset");
|
|
978
|
+
if (value.v !== 2) {
|
|
979
|
+
throw new PresetValidationError(
|
|
980
|
+
typeof value.v === "number" ? `Unsupported preset codec version ${value.v}. Expected v: 2.` : "Preset payload missing v: 2.",
|
|
981
|
+
"preset.v"
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
for (const key of CODEC_CANONICAL_REQUIRED_FIELDS) {
|
|
985
|
+
if (!(key in value)) {
|
|
986
|
+
throw new PresetValidationError(`Preset payload missing ${key}.`, `preset.${key}`);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (typeof value.baseColor !== "string" || !isBaseColorId(value.baseColor)) {
|
|
990
|
+
throw new PresetValidationError(
|
|
991
|
+
"Invalid preset.baseColor. Expected inherit | neutral | zinc | slate | stone | taupe.",
|
|
992
|
+
"preset.baseColor"
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
996
|
+
throw new PresetValidationError(
|
|
997
|
+
"Invalid preset.themeColor. Expected ink | red | blue | violet | green | orange.",
|
|
998
|
+
"preset.themeColor"
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
1002
|
+
throw new PresetValidationError(
|
|
1003
|
+
"Invalid preset.chartPalette. Expected theme | warm | cool | mixed.",
|
|
1004
|
+
"preset.chartPalette"
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
1008
|
+
throw new PresetValidationError(
|
|
1009
|
+
"Invalid preset.headingFont. Expected system | playfair.",
|
|
1010
|
+
"preset.headingFont"
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
1014
|
+
throw new PresetValidationError(
|
|
1015
|
+
"Invalid preset.bodyFont. Expected system | inter.",
|
|
1016
|
+
"preset.bodyFont"
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
if (typeof value.iconLibrary !== "string" || !isIconLibrary(value.iconLibrary)) {
|
|
1020
|
+
throw new PresetValidationError(
|
|
1021
|
+
"Invalid preset.iconLibrary. Expected tabler | lucide.",
|
|
1022
|
+
"preset.iconLibrary"
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
if (typeof value.radius !== "string" || !isRadiusPreset(value.radius)) {
|
|
1026
|
+
throw new PresetValidationError(
|
|
1027
|
+
"Invalid preset.radius. Expected none | small | medium | large.",
|
|
1028
|
+
"preset.radius"
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
return {
|
|
1032
|
+
v: 2,
|
|
1033
|
+
baseColor: value.baseColor,
|
|
1034
|
+
themeColor: value.themeColor,
|
|
1035
|
+
chartPalette: value.chartPalette,
|
|
1036
|
+
headingFont: value.headingFont,
|
|
1037
|
+
bodyFont: value.bodyFont,
|
|
1038
|
+
iconLibrary: value.iconLibrary,
|
|
1039
|
+
radius: value.radius
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
function stableStringifyCodecPayloadCanonical(payload) {
|
|
1043
|
+
return `{${[
|
|
1044
|
+
`"v":${payload.v}`,
|
|
1045
|
+
`"baseColor":${JSON.stringify(payload.baseColor)}`,
|
|
1046
|
+
`"themeColor":${JSON.stringify(payload.themeColor)}`,
|
|
1047
|
+
`"chartPalette":${JSON.stringify(payload.chartPalette)}`,
|
|
1048
|
+
`"headingFont":${JSON.stringify(payload.headingFont)}`,
|
|
1049
|
+
`"bodyFont":${JSON.stringify(payload.bodyFont)}`,
|
|
1050
|
+
`"iconLibrary":${JSON.stringify(payload.iconLibrary)}`,
|
|
1051
|
+
`"radius":${JSON.stringify(payload.radius)}`
|
|
1052
|
+
].join(",")}}`;
|
|
1053
|
+
}
|
|
1054
|
+
function encodePresetCanonical(style) {
|
|
1055
|
+
const normalized = normalizeStyleConfigCanonical(style);
|
|
1056
|
+
const payload = {
|
|
1057
|
+
v: 2,
|
|
1058
|
+
baseColor: normalized.baseColor,
|
|
1059
|
+
themeColor: normalized.themeColor,
|
|
1060
|
+
chartPalette: normalized.chartPalette,
|
|
1061
|
+
headingFont: normalized.headingFont,
|
|
1062
|
+
bodyFont: normalized.bodyFont,
|
|
1063
|
+
iconLibrary: normalized.iconLibrary,
|
|
1064
|
+
radius: normalized.radius
|
|
1065
|
+
};
|
|
1066
|
+
const json = stableStringifyCodecPayloadCanonical(payload);
|
|
1067
|
+
const bytes = new TextEncoder().encode(json);
|
|
1068
|
+
if (bytes.byteLength > PRESET_CODEC_MAX_DECODED_JSON_BYTES) {
|
|
1069
|
+
throw new PresetValidationError(
|
|
1070
|
+
`Preset JSON exceeds ${PRESET_CODEC_MAX_DECODED_JSON_BYTES} bytes.`,
|
|
1071
|
+
"preset"
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
const code = `${PRESET_CODEC_PREFIX}.${toBase64Url(bytes)}`;
|
|
1075
|
+
if (code.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
1076
|
+
throw new PresetValidationError(
|
|
1077
|
+
`Preset code exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
1078
|
+
"preset"
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
return code;
|
|
1082
|
+
}
|
|
1083
|
+
function decodePresetEnvelope(code) {
|
|
679
1084
|
if (typeof code !== "string" || code.length === 0) {
|
|
680
1085
|
throw new PresetValidationError("Preset code is required.", "preset");
|
|
681
1086
|
}
|
|
@@ -727,7 +1132,26 @@ function decodePreset(code) {
|
|
|
727
1132
|
} catch {
|
|
728
1133
|
throw new PresetValidationError("Preset payload is not valid JSON.", "preset");
|
|
729
1134
|
}
|
|
730
|
-
return
|
|
1135
|
+
return parsed;
|
|
1136
|
+
}
|
|
1137
|
+
function formatUnsupportedPayloadVersion(v) {
|
|
1138
|
+
const label = v === void 0 ? "undefined" : String(v);
|
|
1139
|
+
return `Unsupported preset payload version ${label}. This preset may require a newer version of the Wensity CLI.`;
|
|
1140
|
+
}
|
|
1141
|
+
function decodeAnyPreset(code) {
|
|
1142
|
+
const parsed = decodePresetEnvelope(code);
|
|
1143
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1144
|
+
throw new PresetValidationError("Expected an object at preset.", "preset");
|
|
1145
|
+
}
|
|
1146
|
+
assertNoForbiddenObjectKeys(parsed, "preset");
|
|
1147
|
+
const v = parsed.v;
|
|
1148
|
+
if (v === 1) {
|
|
1149
|
+
return validateCodecPayload(parsed);
|
|
1150
|
+
}
|
|
1151
|
+
if (v === 2) {
|
|
1152
|
+
return validateCodecPayloadCanonical(parsed);
|
|
1153
|
+
}
|
|
1154
|
+
throw new PresetValidationError(formatUnsupportedPayloadVersion(v), "preset.v");
|
|
731
1155
|
}
|
|
732
1156
|
|
|
733
1157
|
// ../wensity-preset/src/icon-map.ts
|
|
@@ -747,185 +1171,473 @@ var TABLER_TO_LUCIDE = {
|
|
|
747
1171
|
IconArrowUpRight: "ArrowUpRight",
|
|
748
1172
|
IconCalendar: "Calendar",
|
|
749
1173
|
IconCamera: "Camera",
|
|
750
|
-
IconCheck: "Check",
|
|
751
|
-
IconChevronDown: "ChevronDown",
|
|
752
|
-
IconChevronLeft: "ChevronLeft",
|
|
753
|
-
IconChevronRight: "ChevronRight",
|
|
754
|
-
IconChevronUp: "ChevronUp",
|
|
755
|
-
IconChevronsLeft: "ChevronsLeft",
|
|
756
|
-
IconChevronsRight: "ChevronsRight",
|
|
757
|
-
IconCircleX: "CircleX",
|
|
758
|
-
IconClock: "Clock",
|
|
759
|
-
IconCornerDownLeft: "CornerDownLeft",
|
|
760
|
-
IconDots: "Ellipsis",
|
|
761
|
-
IconDownload: "Download",
|
|
762
|
-
IconFile: "File",
|
|
763
|
-
IconFileMusic: "FileAudio",
|
|
764
|
-
IconFileText: "FileText",
|
|
765
|
-
IconFileZip: "FileArchive",
|
|
766
|
-
IconInfoCircle: "Info",
|
|
767
|
-
IconLayoutSidebarLeftCollapse: "PanelLeftClose",
|
|
768
|
-
IconLayoutSidebarLeftExpand: "PanelLeftOpen",
|
|
769
|
-
IconMinus: "Minus",
|
|
770
|
-
IconPhoto: "Image",
|
|
771
|
-
IconPlus: "Plus",
|
|
772
|
-
IconRefresh: "RefreshCw",
|
|
773
|
-
IconSearch: "Search",
|
|
774
|
-
IconSelector: "ChevronsUpDown",
|
|
775
|
-
IconSlash: "Slash",
|
|
776
|
-
IconUser: "User",
|
|
777
|
-
IconVideo: "Video",
|
|
778
|
-
IconX: "X"
|
|
779
|
-
};
|
|
780
|
-
var EXCLUSION_SET = new Set(ICON_TRANSFORM_EXCLUSIONS);
|
|
781
|
-
function isIconTransformExclusion(name) {
|
|
782
|
-
return EXCLUSION_SET.has(name);
|
|
783
|
-
}
|
|
784
|
-
function isMappedTablerIcon(name) {
|
|
785
|
-
return Object.prototype.hasOwnProperty.call(TABLER_TO_LUCIDE, name);
|
|
786
|
-
}
|
|
787
|
-
function resolveLucideExport(tablerName) {
|
|
788
|
-
if (isIconTransformExclusion(tablerName)) {
|
|
789
|
-
throw new Error(
|
|
790
|
-
`Icon "${tablerName}" is a Phase 0 exclusion and must not be transformed. Use internal SVG/CSS geometry instead.`
|
|
791
|
-
);
|
|
792
|
-
}
|
|
793
|
-
if (!isMappedTablerIcon(tablerName)) {
|
|
794
|
-
throw new Error(
|
|
795
|
-
`No approved Lucide mapping for Tabler icon "${tablerName}". Add an audited map entry or convert it to internal geometry.`
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
return TABLER_TO_LUCIDE[tablerName];
|
|
799
|
-
}
|
|
800
|
-
var LUCIDE_TO_TABLER = Object.fromEntries(
|
|
801
|
-
Object.entries(TABLER_TO_LUCIDE).map(([tabler, lucide]) => [lucide, tabler])
|
|
802
|
-
);
|
|
803
|
-
|
|
804
|
-
// src/constants.ts
|
|
805
|
-
var CLI_NAME = "wensity";
|
|
806
|
-
var CLI_VERSION = "0.1.6";
|
|
807
|
-
var CONFIG_FILE_NAME = "wensity.json";
|
|
808
|
-
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
809
|
-
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
810
|
-
var DEFAULT_COMPONENTS_DIR = "src/components/wensity";
|
|
811
|
-
var DEFAULT_UTILS_PATH = "src/lib/utils";
|
|
812
|
-
var DEFAULT_COMPONENTS_ALIAS = "@/components/wensity";
|
|
813
|
-
var DEFAULT_UTILS_ALIAS = "@/lib/utils";
|
|
814
|
-
var INIT_PRIMITIVE_CSS_SLUG = "button";
|
|
815
|
-
var HELP_TEXT = `Wensity CLI ${CLI_VERSION}
|
|
816
|
-
|
|
817
|
-
Usage:
|
|
818
|
-
wensity init [--preset <code>] [--preset-file <path>] [options]
|
|
819
|
-
wensity login [options]
|
|
820
|
-
wensity logout
|
|
821
|
-
wensity whoami [--json]
|
|
822
|
-
wensity list [--type component|block] [options]
|
|
823
|
-
wensity add <slug> [--type component|block] [options]
|
|
824
|
-
wensity update <slug> [--type component|block] [options]
|
|
825
|
-
wensity version
|
|
826
|
-
|
|
827
|
-
Commands:
|
|
828
|
-
init Create wensity.json and local helper files (optional --preset applies style + CSS)
|
|
829
|
-
login Save a Wensity API token for premium component access
|
|
830
|
-
logout Remove saved CLI credentials
|
|
831
|
-
whoami Verify the saved token and print the authenticated account
|
|
832
|
-
list List registry components or blocks
|
|
833
|
-
add Download a component or block source file into this project
|
|
834
|
-
update Re-download a component or block and overwrite the local copy
|
|
835
|
-
version Print the CLI version
|
|
836
|
-
|
|
837
|
-
Options:
|
|
838
|
-
--api-url <url> Override the Wensity app origin, defaults to ${DEFAULT_API_ORIGIN}
|
|
839
|
-
--registry <url> Override the registry endpoint
|
|
840
|
-
--type <type> Select component or block, defaults to component
|
|
841
|
-
--token <token> Provide a token non-interactively for login
|
|
842
|
-
--preset <code> Apply a shareable Wensity style preset (wsty1.\u2026); merges style when config exists
|
|
843
|
-
--preset-file <path> Read a preset code or JSON payload from a file
|
|
844
|
-
--force Overwrite generated files when adding or initializing
|
|
845
|
-
--no-install Write files without running the package manager
|
|
846
|
-
--dry-run Print planned writes and installs without changing files
|
|
847
|
-
--json Print machine-readable output where supported
|
|
848
|
-
--help Show help
|
|
849
|
-
--version Print the CLI version
|
|
850
|
-
|
|
851
|
-
Preset notes:
|
|
852
|
-
Generate codes at ${DEFAULT_API_ORIGIN}/docs/primitives/setup
|
|
853
|
-
Plain init refuses an existing wensity.json unless --force
|
|
854
|
-
init --preset merges style + primitive CSS; does not rewrite installed source
|
|
855
|
-
add/update read style.iconLibrary for UI primitives only (Tabler|Lucide)
|
|
856
|
-
Invalid/expired/unsupported codes exit non-zero with an actionable message
|
|
857
|
-
`;
|
|
858
|
-
|
|
859
|
-
// src/errors.ts
|
|
860
|
-
var CliError = class extends Error {
|
|
861
|
-
exitCode;
|
|
862
|
-
constructor(message, exitCode = 1) {
|
|
863
|
-
super(message);
|
|
864
|
-
this.name = "CliError";
|
|
865
|
-
this.exitCode = exitCode;
|
|
866
|
-
}
|
|
1174
|
+
IconCheck: "Check",
|
|
1175
|
+
IconChevronDown: "ChevronDown",
|
|
1176
|
+
IconChevronLeft: "ChevronLeft",
|
|
1177
|
+
IconChevronRight: "ChevronRight",
|
|
1178
|
+
IconChevronUp: "ChevronUp",
|
|
1179
|
+
IconChevronsLeft: "ChevronsLeft",
|
|
1180
|
+
IconChevronsRight: "ChevronsRight",
|
|
1181
|
+
IconCircleX: "CircleX",
|
|
1182
|
+
IconClock: "Clock",
|
|
1183
|
+
IconCornerDownLeft: "CornerDownLeft",
|
|
1184
|
+
IconDots: "Ellipsis",
|
|
1185
|
+
IconDownload: "Download",
|
|
1186
|
+
IconFile: "File",
|
|
1187
|
+
IconFileMusic: "FileAudio",
|
|
1188
|
+
IconFileText: "FileText",
|
|
1189
|
+
IconFileZip: "FileArchive",
|
|
1190
|
+
IconInfoCircle: "Info",
|
|
1191
|
+
IconLayoutSidebarLeftCollapse: "PanelLeftClose",
|
|
1192
|
+
IconLayoutSidebarLeftExpand: "PanelLeftOpen",
|
|
1193
|
+
IconMinus: "Minus",
|
|
1194
|
+
IconPhoto: "Image",
|
|
1195
|
+
IconPlus: "Plus",
|
|
1196
|
+
IconRefresh: "RefreshCw",
|
|
1197
|
+
IconSearch: "Search",
|
|
1198
|
+
IconSelector: "ChevronsUpDown",
|
|
1199
|
+
IconSlash: "Slash",
|
|
1200
|
+
IconUser: "User",
|
|
1201
|
+
IconVideo: "Video",
|
|
1202
|
+
IconX: "X"
|
|
867
1203
|
};
|
|
868
|
-
|
|
869
|
-
|
|
1204
|
+
var EXCLUSION_SET = new Set(ICON_TRANSFORM_EXCLUSIONS);
|
|
1205
|
+
function isIconTransformExclusion(name) {
|
|
1206
|
+
return EXCLUSION_SET.has(name);
|
|
1207
|
+
}
|
|
1208
|
+
function isMappedTablerIcon(name) {
|
|
1209
|
+
return Object.prototype.hasOwnProperty.call(TABLER_TO_LUCIDE, name);
|
|
1210
|
+
}
|
|
1211
|
+
function resolveLucideExport(tablerName) {
|
|
1212
|
+
if (isIconTransformExclusion(tablerName)) {
|
|
1213
|
+
throw new Error(
|
|
1214
|
+
`Icon "${tablerName}" is a Phase 0 exclusion and must not be transformed. Use internal SVG/CSS geometry instead.`
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
if (!isMappedTablerIcon(tablerName)) {
|
|
1218
|
+
throw new Error(
|
|
1219
|
+
`No approved Lucide mapping for Tabler icon "${tablerName}". Add an audited map entry or convert it to internal geometry.`
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
return TABLER_TO_LUCIDE[tablerName];
|
|
870
1223
|
}
|
|
1224
|
+
var LUCIDE_TO_TABLER = Object.fromEntries(
|
|
1225
|
+
Object.entries(TABLER_TO_LUCIDE).map(([tabler, lucide]) => [lucide, tabler])
|
|
1226
|
+
);
|
|
871
1227
|
|
|
872
|
-
// src/
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
1228
|
+
// ../wensity-preset/src/palettes.ts
|
|
1229
|
+
var BASE_COLOR_PALETTE = {
|
|
1230
|
+
zinc: {
|
|
1231
|
+
light: {
|
|
1232
|
+
surfaceElevated: "#ffffff",
|
|
1233
|
+
surfaceOverlay: "#ffffff",
|
|
1234
|
+
foreground: "#09090b",
|
|
1235
|
+
border: "rgba(9, 9, 11, 0.08)",
|
|
1236
|
+
mutedForeground: "#71717a"
|
|
1237
|
+
},
|
|
1238
|
+
dark: {
|
|
1239
|
+
surfaceElevated: "#18181b",
|
|
1240
|
+
surfaceOverlay: "#27272a",
|
|
1241
|
+
foreground: "#fafafa",
|
|
1242
|
+
border: "rgba(250, 250, 250, 0.10)",
|
|
1243
|
+
mutedForeground: "#a1a1aa"
|
|
881
1244
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1245
|
+
},
|
|
1246
|
+
neutral: {
|
|
1247
|
+
light: {
|
|
1248
|
+
surfaceElevated: "#ffffff",
|
|
1249
|
+
surfaceOverlay: "#ffffff",
|
|
1250
|
+
foreground: "#171717",
|
|
1251
|
+
border: "rgba(23, 23, 23, 0.08)",
|
|
1252
|
+
mutedForeground: "#737373"
|
|
1253
|
+
},
|
|
1254
|
+
dark: {
|
|
1255
|
+
surfaceElevated: "#171717",
|
|
1256
|
+
surfaceOverlay: "#262626",
|
|
1257
|
+
foreground: "#fafafa",
|
|
1258
|
+
border: "rgba(250, 250, 250, 0.10)",
|
|
1259
|
+
mutedForeground: "#a3a3a3"
|
|
885
1260
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1261
|
+
},
|
|
1262
|
+
slate: {
|
|
1263
|
+
light: {
|
|
1264
|
+
surfaceElevated: "#ffffff",
|
|
1265
|
+
surfaceOverlay: "#ffffff",
|
|
1266
|
+
foreground: "#0f172a",
|
|
1267
|
+
border: "rgba(15, 23, 42, 0.08)",
|
|
1268
|
+
mutedForeground: "#64748b"
|
|
1269
|
+
},
|
|
1270
|
+
dark: {
|
|
1271
|
+
surfaceElevated: "#0f172a",
|
|
1272
|
+
surfaceOverlay: "#1e293b",
|
|
1273
|
+
foreground: "#f8fafc",
|
|
1274
|
+
border: "rgba(248, 250, 252, 0.10)",
|
|
1275
|
+
mutedForeground: "#94a3b8"
|
|
891
1276
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1277
|
+
},
|
|
1278
|
+
stone: {
|
|
1279
|
+
light: {
|
|
1280
|
+
surfaceElevated: "#ffffff",
|
|
1281
|
+
surfaceOverlay: "#ffffff",
|
|
1282
|
+
foreground: "#1c1917",
|
|
1283
|
+
border: "rgba(28, 25, 23, 0.08)",
|
|
1284
|
+
mutedForeground: "#78716c"
|
|
1285
|
+
},
|
|
1286
|
+
dark: {
|
|
1287
|
+
surfaceElevated: "#1c1917",
|
|
1288
|
+
surfaceOverlay: "#292524",
|
|
1289
|
+
foreground: "#fafaf9",
|
|
1290
|
+
border: "rgba(250, 250, 249, 0.10)",
|
|
1291
|
+
mutedForeground: "#a8a29e"
|
|
895
1292
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1293
|
+
},
|
|
1294
|
+
taupe: {
|
|
1295
|
+
light: {
|
|
1296
|
+
surfaceElevated: "#faf8f5",
|
|
1297
|
+
surfaceOverlay: "#ffffff",
|
|
1298
|
+
foreground: "#3b342e",
|
|
1299
|
+
border: "rgba(59, 52, 46, 0.10)",
|
|
1300
|
+
mutedForeground: "#8a7f74"
|
|
1301
|
+
},
|
|
1302
|
+
dark: {
|
|
1303
|
+
surfaceElevated: "#1c1916",
|
|
1304
|
+
surfaceOverlay: "#2a2521",
|
|
1305
|
+
foreground: "#f5f0ea",
|
|
1306
|
+
border: "rgba(245, 240, 234, 0.10)",
|
|
1307
|
+
mutedForeground: "#a89f94"
|
|
901
1308
|
}
|
|
902
|
-
options.set(name, true);
|
|
903
1309
|
}
|
|
904
|
-
|
|
1310
|
+
};
|
|
1311
|
+
var THEME_COLOR_PALETTE = {
|
|
1312
|
+
ink: {
|
|
1313
|
+
light: { ...DEFAULT_CONTROL_SOLID_LIGHT },
|
|
1314
|
+
dark: { ...DEFAULT_CONTROL_SOLID_DARK }
|
|
1315
|
+
},
|
|
1316
|
+
red: {
|
|
1317
|
+
light: {
|
|
1318
|
+
controlSolid: "#b91c1c",
|
|
1319
|
+
controlSolidHover: "#dc2626",
|
|
1320
|
+
controlSolidActive: "#991b1b",
|
|
1321
|
+
controlSolidForeground: "#ffffff"
|
|
1322
|
+
},
|
|
1323
|
+
dark: {
|
|
1324
|
+
controlSolid: "#f87171",
|
|
1325
|
+
controlSolidHover: "#fca5a5",
|
|
1326
|
+
controlSolidActive: "#ef4444",
|
|
1327
|
+
controlSolidForeground: "#450a0a"
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1330
|
+
blue: {
|
|
1331
|
+
light: {
|
|
1332
|
+
controlSolid: "#1d4ed8",
|
|
1333
|
+
controlSolidHover: "#2563eb",
|
|
1334
|
+
controlSolidActive: "#1e40af",
|
|
1335
|
+
controlSolidForeground: "#ffffff"
|
|
1336
|
+
},
|
|
1337
|
+
dark: {
|
|
1338
|
+
controlSolid: "#60a5fa",
|
|
1339
|
+
controlSolidHover: "#93c5fd",
|
|
1340
|
+
controlSolidActive: "#3b82f6",
|
|
1341
|
+
controlSolidForeground: "#172554"
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
violet: {
|
|
1345
|
+
light: {
|
|
1346
|
+
controlSolid: "#6d28d9",
|
|
1347
|
+
controlSolidHover: "#7c3aed",
|
|
1348
|
+
controlSolidActive: "#5b21b6",
|
|
1349
|
+
controlSolidForeground: "#ffffff"
|
|
1350
|
+
},
|
|
1351
|
+
dark: {
|
|
1352
|
+
controlSolid: "#a78bfa",
|
|
1353
|
+
controlSolidHover: "#c4b5fd",
|
|
1354
|
+
controlSolidActive: "#8b5cf6",
|
|
1355
|
+
controlSolidForeground: "#2e1065"
|
|
1356
|
+
}
|
|
1357
|
+
},
|
|
1358
|
+
green: {
|
|
1359
|
+
light: {
|
|
1360
|
+
controlSolid: "#047857",
|
|
1361
|
+
controlSolidHover: "#059669",
|
|
1362
|
+
controlSolidActive: "#065f46",
|
|
1363
|
+
controlSolidForeground: "#ffffff"
|
|
1364
|
+
},
|
|
1365
|
+
dark: {
|
|
1366
|
+
controlSolid: "#34d399",
|
|
1367
|
+
controlSolidHover: "#6ee7b7",
|
|
1368
|
+
controlSolidActive: "#10b981",
|
|
1369
|
+
controlSolidForeground: "#022c22"
|
|
1370
|
+
}
|
|
1371
|
+
},
|
|
1372
|
+
orange: {
|
|
1373
|
+
light: {
|
|
1374
|
+
controlSolid: "#c2410c",
|
|
1375
|
+
controlSolidHover: "#ea580c",
|
|
1376
|
+
controlSolidActive: "#9a3412",
|
|
1377
|
+
controlSolidForeground: "#ffffff"
|
|
1378
|
+
},
|
|
1379
|
+
dark: {
|
|
1380
|
+
controlSolid: "#fb923c",
|
|
1381
|
+
controlSolidHover: "#fdba74",
|
|
1382
|
+
controlSolidActive: "#f97316",
|
|
1383
|
+
controlSolidForeground: "#431407"
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
var DEFAULT_CHART_STOPS = {
|
|
1388
|
+
light: [
|
|
1389
|
+
"#2a78d6",
|
|
1390
|
+
"#1baf7a",
|
|
1391
|
+
"#eda100",
|
|
1392
|
+
"#008300",
|
|
1393
|
+
"#4a3aa7",
|
|
1394
|
+
"#e34948"
|
|
1395
|
+
],
|
|
1396
|
+
dark: [
|
|
1397
|
+
"#3987e5",
|
|
1398
|
+
"#199e70",
|
|
1399
|
+
"#c98500",
|
|
1400
|
+
"#008300",
|
|
1401
|
+
"#9085e9",
|
|
1402
|
+
"#e66767"
|
|
1403
|
+
]
|
|
1404
|
+
};
|
|
1405
|
+
var CHART_PALETTES = {
|
|
1406
|
+
theme: {
|
|
1407
|
+
ink: DEFAULT_CHART_STOPS,
|
|
1408
|
+
red: {
|
|
1409
|
+
light: ["#e34948", "#f97316", "#eda100", "#db2777", "#b91c1c", "#9f1239"],
|
|
1410
|
+
dark: ["#e66767", "#fb923c", "#c98500", "#f472b6", "#f87171", "#fb7185"]
|
|
1411
|
+
},
|
|
1412
|
+
blue: {
|
|
1413
|
+
light: ["#2a78d6", "#0284c7", "#4a3aa7", "#0e7490", "#1d4ed8", "#0369a1"],
|
|
1414
|
+
dark: ["#3987e5", "#38bdf8", "#9085e9", "#22d3ee", "#60a5fa", "#7dd3fc"]
|
|
1415
|
+
},
|
|
1416
|
+
violet: {
|
|
1417
|
+
light: ["#4a3aa7", "#7c3aed", "#2a78d6", "#a21caf", "#6d28d9", "#db2777"],
|
|
1418
|
+
dark: ["#9085e9", "#a78bfa", "#3987e5", "#e879f9", "#c4b5fd", "#f472b6"]
|
|
1419
|
+
},
|
|
1420
|
+
green: {
|
|
1421
|
+
light: ["#1baf7a", "#008300", "#0d9488", "#2a78d6", "#047857", "#65a30d"],
|
|
1422
|
+
dark: ["#199e70", "#34d399", "#2dd4bf", "#3987e5", "#4ade80", "#a3e635"]
|
|
1423
|
+
},
|
|
1424
|
+
orange: {
|
|
1425
|
+
light: ["#eda100", "#f97316", "#e34948", "#ca8a04", "#c2410c", "#db2777"],
|
|
1426
|
+
dark: ["#c98500", "#fb923c", "#e66767", "#facc15", "#fdba74", "#f472b6"]
|
|
1427
|
+
}
|
|
1428
|
+
},
|
|
1429
|
+
warm: {
|
|
1430
|
+
light: ["#ea580c", "#d97706", "#e34948", "#db2777", "#ca8a04", "#c2410c"],
|
|
1431
|
+
dark: ["#fb923c", "#fbbf24", "#e66767", "#f472b6", "#facc15", "#fdba74"]
|
|
1432
|
+
},
|
|
1433
|
+
cool: {
|
|
1434
|
+
light: ["#2a78d6", "#0e7490", "#4a3aa7", "#0284c7", "#1d4ed8", "#0f766e"],
|
|
1435
|
+
dark: ["#3987e5", "#22d3ee", "#9085e9", "#38bdf8", "#60a5fa", "#2dd4bf"]
|
|
1436
|
+
},
|
|
1437
|
+
mixed: {
|
|
1438
|
+
light: ["#2a78d6", "#e34948", "#1baf7a", "#eda100", "#4a3aa7", "#db2777"],
|
|
1439
|
+
dark: ["#3987e5", "#e66767", "#199e70", "#c98500", "#9085e9", "#f472b6"]
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
|
|
1443
|
+
// ../wensity-preset/src/curated-fonts.ts
|
|
1444
|
+
var HEADING_FONT_PACKAGES = {
|
|
1445
|
+
playfair: {
|
|
1446
|
+
packageName: "@fontsource/playfair-display",
|
|
1447
|
+
importSpecifier: "@fontsource/playfair-display",
|
|
1448
|
+
familyName: "Playfair Display"
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1451
|
+
var BODY_FONT_PACKAGES = {
|
|
1452
|
+
inter: {
|
|
1453
|
+
packageName: "@fontsource/inter",
|
|
1454
|
+
importSpecifier: "@fontsource/inter",
|
|
1455
|
+
familyName: "Inter"
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
var HEADING_FONT_CSS = {
|
|
1459
|
+
system: "var(--font-display)",
|
|
1460
|
+
playfair: "'Playfair Display', Georgia, 'Times New Roman', serif"
|
|
1461
|
+
};
|
|
1462
|
+
var BODY_FONT_CSS = {
|
|
1463
|
+
system: "var(--font-sans)",
|
|
1464
|
+
inter: "'Inter', ui-sans-serif, system-ui, sans-serif"
|
|
1465
|
+
};
|
|
1466
|
+
|
|
1467
|
+
// ../wensity-preset/src/resolve.ts
|
|
1468
|
+
var RESOLVED_TOKEN_CSS_VARS = {
|
|
1469
|
+
surfaceElevated: "--primitive-surface-elevated",
|
|
1470
|
+
surfaceOverlay: "--primitive-surface-overlay",
|
|
1471
|
+
surfaceHover: "--primitive-surface-hover",
|
|
1472
|
+
surfaceActive: "--primitive-surface-active",
|
|
1473
|
+
surfaceSelected: "--primitive-surface-selected",
|
|
1474
|
+
borderSubtle: "--primitive-border-subtle",
|
|
1475
|
+
ring: "--primitive-ring",
|
|
1476
|
+
textSecondary: "--primitive-text-secondary",
|
|
1477
|
+
textPlaceholder: "--primitive-text-placeholder",
|
|
1478
|
+
controlSolid: "--primitive-control-solid",
|
|
1479
|
+
controlSolidHover: "--primitive-control-solid-hover",
|
|
1480
|
+
controlSolidActive: "--primitive-control-solid-active",
|
|
1481
|
+
controlSolidForeground: "--primitive-control-solid-foreground",
|
|
1482
|
+
chart1: "--primitive-chart-1",
|
|
1483
|
+
chart2: "--primitive-chart-2",
|
|
1484
|
+
chart3: "--primitive-chart-3",
|
|
1485
|
+
chart4: "--primitive-chart-4",
|
|
1486
|
+
chart5: "--primitive-chart-5",
|
|
1487
|
+
chart6: "--primitive-chart-6",
|
|
1488
|
+
radius: "--primitive-radius",
|
|
1489
|
+
fontSans: "--primitive-font-sans",
|
|
1490
|
+
fontDisplay: "--primitive-font-display",
|
|
1491
|
+
fontMono: "--primitive-font-mono"
|
|
1492
|
+
};
|
|
1493
|
+
var INHERIT_BASE_EXPRESSIONS = {
|
|
1494
|
+
light: {
|
|
1495
|
+
surfaceElevated: "#ffffff",
|
|
1496
|
+
surfaceOverlay: "#ffffff",
|
|
1497
|
+
surfaceHover: "color-mix(in srgb, var(--foreground) 4%, transparent)",
|
|
1498
|
+
surfaceActive: "color-mix(in srgb, var(--foreground) 7%, transparent)",
|
|
1499
|
+
borderSubtle: "color-mix(in srgb, var(--border) 60%, transparent)",
|
|
1500
|
+
textSecondary: "color-mix(in srgb, var(--foreground) 72%, transparent)",
|
|
1501
|
+
textPlaceholder: "color-mix(in srgb, var(--muted-foreground) 85%, transparent)"
|
|
1502
|
+
},
|
|
1503
|
+
dark: {
|
|
1504
|
+
surfaceElevated: "#0f0f10",
|
|
1505
|
+
surfaceOverlay: "#141415",
|
|
1506
|
+
surfaceHover: "color-mix(in srgb, var(--foreground) 5%, transparent)",
|
|
1507
|
+
surfaceActive: "color-mix(in srgb, var(--foreground) 10%, transparent)",
|
|
1508
|
+
borderSubtle: "color-mix(in srgb, var(--border) 60%, transparent)",
|
|
1509
|
+
textSecondary: "color-mix(in srgb, var(--foreground) 72%, transparent)",
|
|
1510
|
+
textPlaceholder: "color-mix(in srgb, var(--muted-foreground) 85%, transparent)"
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
var FIXED_RING = "color-mix(in srgb, var(--foreground) 45%, transparent)";
|
|
1514
|
+
var FIXED_SURFACE_SELECTED = {
|
|
1515
|
+
light: "color-mix(in srgb, var(--foreground) 6%, transparent)",
|
|
1516
|
+
dark: "color-mix(in srgb, var(--foreground) 8%, transparent)"
|
|
1517
|
+
};
|
|
1518
|
+
var COLORED_THEME_IDS = /* @__PURE__ */ new Set([
|
|
1519
|
+
"red",
|
|
1520
|
+
"blue",
|
|
1521
|
+
"violet",
|
|
1522
|
+
"green",
|
|
1523
|
+
"orange"
|
|
1524
|
+
]);
|
|
1525
|
+
function colorMix(source, percent) {
|
|
1526
|
+
return `color-mix(in srgb, ${source} ${percent}%, transparent)`;
|
|
905
1527
|
}
|
|
906
|
-
function
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1528
|
+
function resolveControlSolid(partial, fallback) {
|
|
1529
|
+
const out = { ...fallback };
|
|
1530
|
+
for (const key of CONTROL_SOLID_COLOR_KEYS) {
|
|
1531
|
+
const value = partial?.[key];
|
|
1532
|
+
if (value !== void 0) out[key] = value;
|
|
911
1533
|
}
|
|
912
|
-
return
|
|
1534
|
+
return out;
|
|
913
1535
|
}
|
|
914
|
-
function
|
|
915
|
-
return
|
|
1536
|
+
function chartStopsToModeTokens(stops) {
|
|
1537
|
+
return {
|
|
1538
|
+
chart1: stops[0],
|
|
1539
|
+
chart2: stops[1],
|
|
1540
|
+
chart3: stops[2],
|
|
1541
|
+
chart4: stops[3],
|
|
1542
|
+
chart5: stops[4],
|
|
1543
|
+
chart6: stops[5]
|
|
1544
|
+
};
|
|
916
1545
|
}
|
|
917
|
-
function
|
|
918
|
-
return [
|
|
1546
|
+
function baseFromInherit(mode) {
|
|
1547
|
+
return { ...INHERIT_BASE_EXPRESSIONS[mode] };
|
|
919
1548
|
}
|
|
920
|
-
function
|
|
921
|
-
|
|
922
|
-
|
|
1549
|
+
function baseFromSeeds(seeds, mode) {
|
|
1550
|
+
const hoverPercent = mode === "light" ? 4 : 5;
|
|
1551
|
+
const activePercent = mode === "light" ? 7 : 10;
|
|
1552
|
+
return {
|
|
1553
|
+
surfaceElevated: seeds.surfaceElevated,
|
|
1554
|
+
surfaceOverlay: seeds.surfaceOverlay,
|
|
1555
|
+
surfaceHover: colorMix(seeds.foreground, hoverPercent),
|
|
1556
|
+
surfaceActive: colorMix(seeds.foreground, activePercent),
|
|
1557
|
+
borderSubtle: colorMix(seeds.border, 60),
|
|
1558
|
+
textSecondary: colorMix(seeds.foreground, 72),
|
|
1559
|
+
textPlaceholder: colorMix(seeds.mutedForeground, 85)
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
function ringAndSelectedForInk(mode) {
|
|
1563
|
+
return {
|
|
1564
|
+
ring: FIXED_RING,
|
|
1565
|
+
surfaceSelected: FIXED_SURFACE_SELECTED[mode]
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
function ringAndSelectedFromAccent(accent, mode) {
|
|
1569
|
+
return {
|
|
1570
|
+
ring: colorMix(accent, 45),
|
|
1571
|
+
surfaceSelected: colorMix(accent, mode === "light" ? 6 : 8)
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
function buildModeTokens(args) {
|
|
1575
|
+
return {
|
|
1576
|
+
...args.base,
|
|
1577
|
+
...args.ringSelected,
|
|
1578
|
+
controlSolid: args.control.controlSolid,
|
|
1579
|
+
controlSolidHover: args.control.controlSolidHover,
|
|
1580
|
+
controlSolidActive: args.control.controlSolidActive,
|
|
1581
|
+
controlSolidForeground: args.control.controlSolidForeground,
|
|
1582
|
+
...chartStopsToModeTokens(args.charts)
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
function resolveStyleConfig(style) {
|
|
1586
|
+
const lightControl = resolveControlSolid(
|
|
1587
|
+
style.colors?.light,
|
|
1588
|
+
DEFAULT_CONTROL_SOLID_LIGHT
|
|
1589
|
+
);
|
|
1590
|
+
const darkControl = resolveControlSolid(
|
|
1591
|
+
style.colors?.dark,
|
|
1592
|
+
DEFAULT_CONTROL_SOLID_DARK
|
|
1593
|
+
);
|
|
1594
|
+
return {
|
|
1595
|
+
iconLibrary: style.iconLibrary,
|
|
1596
|
+
radius: RADIUS_PRESET_CSS[style.radius],
|
|
1597
|
+
fontSans: expandFontRole(style.fonts.sans, "sans"),
|
|
1598
|
+
fontDisplay: expandFontRole(style.fonts.display, "display"),
|
|
1599
|
+
fontMono: expandFontRole(style.fonts.mono, "mono"),
|
|
1600
|
+
light: buildModeTokens({
|
|
1601
|
+
base: baseFromInherit("light"),
|
|
1602
|
+
control: lightControl,
|
|
1603
|
+
ringSelected: ringAndSelectedForInk("light"),
|
|
1604
|
+
charts: DEFAULT_CHART_STOPS.light
|
|
1605
|
+
}),
|
|
1606
|
+
dark: buildModeTokens({
|
|
1607
|
+
base: baseFromInherit("dark"),
|
|
1608
|
+
control: darkControl,
|
|
1609
|
+
ringSelected: ringAndSelectedForInk("dark"),
|
|
1610
|
+
charts: DEFAULT_CHART_STOPS.dark
|
|
1611
|
+
})
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
function resolveChartStops(chartPalette, themeColor, mode) {
|
|
1615
|
+
if (chartPalette === "theme") {
|
|
1616
|
+
return CHART_PALETTES.theme[themeColor][mode];
|
|
1617
|
+
}
|
|
1618
|
+
return CHART_PALETTES[chartPalette][mode];
|
|
1619
|
+
}
|
|
1620
|
+
function resolveStyleConfigCanonical(style) {
|
|
1621
|
+
const theme = THEME_COLOR_PALETTE[style.themeColor];
|
|
1622
|
+
const useAccentRing = COLORED_THEME_IDS.has(style.themeColor);
|
|
1623
|
+
const resolveMode = (mode) => {
|
|
1624
|
+
const base = style.baseColor === "inherit" ? baseFromInherit(mode) : baseFromSeeds(BASE_COLOR_PALETTE[style.baseColor][mode], mode);
|
|
1625
|
+
const control = theme[mode];
|
|
1626
|
+
const ringSelected = useAccentRing ? ringAndSelectedFromAccent(control.controlSolid, mode) : ringAndSelectedForInk(mode);
|
|
1627
|
+
const charts = resolveChartStops(style.chartPalette, style.themeColor, mode);
|
|
1628
|
+
return buildModeTokens({ base, control, ringSelected, charts });
|
|
1629
|
+
};
|
|
1630
|
+
return {
|
|
1631
|
+
iconLibrary: style.iconLibrary,
|
|
1632
|
+
radius: RADIUS_PRESET_CSS[style.radius],
|
|
1633
|
+
fontSans: BODY_FONT_CSS[style.bodyFont],
|
|
1634
|
+
fontDisplay: HEADING_FONT_CSS[style.headingFont],
|
|
1635
|
+
// Canonical model has no mono field — lock to today's system-mono expansion.
|
|
1636
|
+
fontMono: FONT_ID_EXPANSIONS["system-mono"],
|
|
1637
|
+
light: resolveMode("light"),
|
|
1638
|
+
dark: resolveMode("dark")
|
|
1639
|
+
};
|
|
923
1640
|
}
|
|
924
|
-
|
|
925
|
-
// src/config.ts
|
|
926
|
-
import { existsSync } from "fs";
|
|
927
|
-
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
928
|
-
import { dirname as dirname2, join as join2, relative as relative2 } from "path";
|
|
929
1641
|
|
|
930
1642
|
// src/paths.ts
|
|
931
1643
|
import { dirname, isAbsolute, relative, resolve, sep } from "path";
|
|
@@ -995,6 +1707,35 @@ function extensionlessPath(path) {
|
|
|
995
1707
|
return path.replace(/\.(tsx|ts|jsx|js)$/, "");
|
|
996
1708
|
}
|
|
997
1709
|
|
|
1710
|
+
// src/style-shape.ts
|
|
1711
|
+
function isCanonicalStyleShape(value) {
|
|
1712
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1713
|
+
const record = value;
|
|
1714
|
+
return "baseColor" in record || "themeColor" in record || "chartPalette" in record || "headingFont" in record || "bodyFont" in record;
|
|
1715
|
+
}
|
|
1716
|
+
function normalizeProjectStyle(style) {
|
|
1717
|
+
if (isCanonicalStyleShape(style)) {
|
|
1718
|
+
return normalizeStyleConfigCanonical(style);
|
|
1719
|
+
}
|
|
1720
|
+
return normalizeStyleConfig(style);
|
|
1721
|
+
}
|
|
1722
|
+
function resolveTokensForStyle(style) {
|
|
1723
|
+
if (isCanonicalStyleShape(style)) {
|
|
1724
|
+
return resolveStyleConfigCanonical(normalizeStyleConfigCanonical(style));
|
|
1725
|
+
}
|
|
1726
|
+
return resolveStyleConfig(normalizeStyleConfig(style));
|
|
1727
|
+
}
|
|
1728
|
+
function curatedFontsFromStyle(style) {
|
|
1729
|
+
if (isCanonicalStyleShape(style)) {
|
|
1730
|
+
const normalized = normalizeStyleConfigCanonical(style);
|
|
1731
|
+
return {
|
|
1732
|
+
headingFont: normalized.headingFont,
|
|
1733
|
+
bodyFont: normalized.bodyFont
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
return { headingFont: "system", bodyFont: "system" };
|
|
1737
|
+
}
|
|
1738
|
+
|
|
998
1739
|
// src/config.ts
|
|
999
1740
|
async function loadConfig(cwd, overrides = {}) {
|
|
1000
1741
|
const foundPath = await findUp(cwd, CONFIG_FILE_NAME);
|
|
@@ -1128,7 +1869,8 @@ function normalizeConfig(config, overrides) {
|
|
|
1128
1869
|
utils: config.aliases?.utils || DEFAULT_UTILS_ALIAS
|
|
1129
1870
|
},
|
|
1130
1871
|
// In-memory only: missing style fields resolve to defaults without rewriting disk.
|
|
1131
|
-
style
|
|
1872
|
+
// Accepts either legacy or canonical style shapes.
|
|
1873
|
+
style: normalizeProjectStyle(config.style)
|
|
1132
1874
|
};
|
|
1133
1875
|
} catch (error) {
|
|
1134
1876
|
if (error instanceof PresetValidationError) {
|
|
@@ -1257,6 +1999,122 @@ function requiredHome(env) {
|
|
|
1257
1999
|
throw new CliError("HOME is not set, so the CLI cannot locate ~/.config/wensity.");
|
|
1258
2000
|
}
|
|
1259
2001
|
|
|
2002
|
+
// src/font-install.ts
|
|
2003
|
+
var FONT_CSS_START_MARKER = "/* \u2500\u2500 Wensity Fonts";
|
|
2004
|
+
var FONT_CSS_END_MARKER = "/* \u2500\u2500 End Wensity Fonts \u2500\u2500 */";
|
|
2005
|
+
function planFontInstall(headingFont, bodyFont) {
|
|
2006
|
+
const packages = [];
|
|
2007
|
+
const importLines = [];
|
|
2008
|
+
const seenPackages = /* @__PURE__ */ new Set();
|
|
2009
|
+
const seenImports = /* @__PURE__ */ new Set();
|
|
2010
|
+
const pushFont = (meta) => {
|
|
2011
|
+
if (!meta) return;
|
|
2012
|
+
if (!seenPackages.has(meta.packageName)) {
|
|
2013
|
+
seenPackages.add(meta.packageName);
|
|
2014
|
+
packages.push(meta.packageName);
|
|
2015
|
+
}
|
|
2016
|
+
const line = `@import "${meta.importSpecifier}";`;
|
|
2017
|
+
if (!seenImports.has(line)) {
|
|
2018
|
+
seenImports.add(line);
|
|
2019
|
+
importLines.push(line);
|
|
2020
|
+
}
|
|
2021
|
+
};
|
|
2022
|
+
if (headingFont !== "system") {
|
|
2023
|
+
pushFont(HEADING_FONT_PACKAGES[headingFont]);
|
|
2024
|
+
}
|
|
2025
|
+
if (bodyFont !== "system") {
|
|
2026
|
+
pushFont(BODY_FONT_PACKAGES[bodyFont]);
|
|
2027
|
+
}
|
|
2028
|
+
packages.sort();
|
|
2029
|
+
if (importLines.length === 0) {
|
|
2030
|
+
return { packages: [], importLines: [], block: null };
|
|
2031
|
+
}
|
|
2032
|
+
const block = [
|
|
2033
|
+
`${FONT_CSS_START_MARKER} \u2500\u2500 */`,
|
|
2034
|
+
...importLines,
|
|
2035
|
+
FONT_CSS_END_MARKER
|
|
2036
|
+
].join("\n");
|
|
2037
|
+
return { packages, importLines, block };
|
|
2038
|
+
}
|
|
2039
|
+
function upsertFontImportBlock(existingCss, block) {
|
|
2040
|
+
const start = existingCss.indexOf(FONT_CSS_START_MARKER);
|
|
2041
|
+
const end = existingCss.indexOf(FONT_CSS_END_MARKER);
|
|
2042
|
+
if (start !== -1 || end !== -1) {
|
|
2043
|
+
if (start === -1 || end === -1 || end <= start) {
|
|
2044
|
+
throw new CliError(
|
|
2045
|
+
"Configured Tailwind CSS has a partial Wensity Fonts block. Remove the broken markers and re-run install."
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
const before2 = existingCss.slice(0, start).replace(/\s*$/, "");
|
|
2049
|
+
const after2 = existingCss.slice(end + FONT_CSS_END_MARKER.length).replace(/^\s*/, "");
|
|
2050
|
+
if (!block) {
|
|
2051
|
+
const joined = [before2, after2].filter((part) => part.length > 0).join("\n\n");
|
|
2052
|
+
return joined ? `${joined.replace(/\n{3,}/g, "\n\n")}
|
|
2053
|
+
` : "";
|
|
2054
|
+
}
|
|
2055
|
+
const normalizedBlock2 = block.trim();
|
|
2056
|
+
const prefix2 = before2 ? `${before2}
|
|
2057
|
+
|
|
2058
|
+
` : "";
|
|
2059
|
+
const suffix2 = after2 ? `
|
|
2060
|
+
|
|
2061
|
+
${after2}` : "\n";
|
|
2062
|
+
return `${prefix2}${normalizedBlock2}${suffix2}`.replace(/\n{3,}/g, "\n\n");
|
|
2063
|
+
}
|
|
2064
|
+
if (!block) return existingCss;
|
|
2065
|
+
const normalizedBlock = block.trim();
|
|
2066
|
+
const insertAt = findFontBlockInsertIndex(existingCss);
|
|
2067
|
+
const before = existingCss.slice(0, insertAt).replace(/\s*$/, "");
|
|
2068
|
+
const after = existingCss.slice(insertAt).replace(/^\s*/, "");
|
|
2069
|
+
const prefix = before ? `${before}
|
|
2070
|
+
|
|
2071
|
+
` : "";
|
|
2072
|
+
const suffix = after ? `
|
|
2073
|
+
|
|
2074
|
+
${after}` : "\n";
|
|
2075
|
+
return `${prefix}${normalizedBlock}${suffix}`.replace(/\n{3,}/g, "\n\n");
|
|
2076
|
+
}
|
|
2077
|
+
function warnUnusedFontPackageMessage(headingFont, bodyFont, installedPackages) {
|
|
2078
|
+
const needed = new Set(planFontInstall(headingFont, bodyFont).packages);
|
|
2079
|
+
const curated = [
|
|
2080
|
+
...Object.values(HEADING_FONT_PACKAGES).map((entry) => entry.packageName),
|
|
2081
|
+
...Object.values(BODY_FONT_PACKAGES).map((entry) => entry.packageName)
|
|
2082
|
+
];
|
|
2083
|
+
const leftover = curated.filter(
|
|
2084
|
+
(pkg) => installedPackages.has(pkg) && !needed.has(pkg)
|
|
2085
|
+
);
|
|
2086
|
+
if (leftover.length === 0) return void 0;
|
|
2087
|
+
return `Project package.json still lists ${leftover.join(", ")} while curated fonts are set to heading="${headingFont}" body="${bodyFont}". Wensity removed the @import for unused fonts but will not uninstall ${leftover.join(", ")} (it may be used outside Wensity).`;
|
|
2088
|
+
}
|
|
2089
|
+
function findFontBlockInsertIndex(css) {
|
|
2090
|
+
let index = 0;
|
|
2091
|
+
const length = css.length;
|
|
2092
|
+
while (index < length) {
|
|
2093
|
+
while (index < length && /\s/.test(css[index])) index += 1;
|
|
2094
|
+
if (index >= length) break;
|
|
2095
|
+
if (css.startsWith("/*", index)) {
|
|
2096
|
+
const end = css.indexOf("*/", index + 2);
|
|
2097
|
+
if (end === -1) break;
|
|
2098
|
+
index = end + 2;
|
|
2099
|
+
continue;
|
|
2100
|
+
}
|
|
2101
|
+
if (css.startsWith("//", index)) {
|
|
2102
|
+
const end = css.indexOf("\n", index);
|
|
2103
|
+
if (end === -1) return length;
|
|
2104
|
+
index = end + 1;
|
|
2105
|
+
continue;
|
|
2106
|
+
}
|
|
2107
|
+
if (css.startsWith("@charset", index) || css.startsWith("@import", index)) {
|
|
2108
|
+
const end = css.indexOf(";", index);
|
|
2109
|
+
if (end === -1) break;
|
|
2110
|
+
index = end + 1;
|
|
2111
|
+
continue;
|
|
2112
|
+
}
|
|
2113
|
+
break;
|
|
2114
|
+
}
|
|
2115
|
+
return index;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
1260
2118
|
// src/output.ts
|
|
1261
2119
|
import boxen from "boxen";
|
|
1262
2120
|
import Table from "cli-table3";
|
|
@@ -1807,19 +2665,13 @@ async function resolvePresetStyle(input) {
|
|
|
1807
2665
|
const trimmed = raw.trim();
|
|
1808
2666
|
if (trimmed.startsWith("{")) {
|
|
1809
2667
|
const parsed = JSON.parse(trimmed);
|
|
1810
|
-
|
|
1811
|
-
const payload = validateCodecPayload(parsed);
|
|
1812
|
-
const json = stableStringifyCodecPayload(payload);
|
|
1813
|
-
code = `${PRESET_CODEC_PREFIX}.${Buffer.from(json, "utf8").toString("base64url")}`;
|
|
1814
|
-
} else {
|
|
1815
|
-
code = encodePreset(parsed);
|
|
1816
|
-
}
|
|
2668
|
+
code = encodePresetFileJson(parsed);
|
|
1817
2669
|
} else {
|
|
1818
2670
|
code = trimmed;
|
|
1819
2671
|
}
|
|
1820
2672
|
} catch (error) {
|
|
1821
2673
|
if (error instanceof PresetValidationError) {
|
|
1822
|
-
throw
|
|
2674
|
+
throw toCliPresetError(error);
|
|
1823
2675
|
}
|
|
1824
2676
|
if (error instanceof SyntaxError) {
|
|
1825
2677
|
throw new CliError(`Preset file contains invalid JSON: ${error.message}`);
|
|
@@ -1834,19 +2686,69 @@ async function resolvePresetStyle(input) {
|
|
|
1834
2686
|
}
|
|
1835
2687
|
try {
|
|
1836
2688
|
const trimmed = code.trim();
|
|
1837
|
-
const payload =
|
|
1838
|
-
const style =
|
|
1839
|
-
...codecPayloadToStyleInput(payload),
|
|
1840
|
-
presetCode: trimmed
|
|
1841
|
-
});
|
|
2689
|
+
const payload = decodeAnyPreset(trimmed);
|
|
2690
|
+
const style = styleFromDecodedPayload(payload, trimmed);
|
|
1842
2691
|
return { style, presetCode: trimmed };
|
|
1843
2692
|
} catch (error) {
|
|
1844
2693
|
if (error instanceof PresetValidationError) {
|
|
1845
|
-
throw
|
|
2694
|
+
throw toCliPresetError(error);
|
|
1846
2695
|
}
|
|
1847
2696
|
throw error;
|
|
1848
2697
|
}
|
|
1849
2698
|
}
|
|
2699
|
+
function encodePresetFileJson(parsed) {
|
|
2700
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2701
|
+
throw new PresetValidationError("Expected an object at preset.", "preset");
|
|
2702
|
+
}
|
|
2703
|
+
if ("v" in parsed) {
|
|
2704
|
+
const v = parsed.v;
|
|
2705
|
+
if (v === 1) {
|
|
2706
|
+
const payload = validateCodecPayload(parsed);
|
|
2707
|
+
const json = stableStringifyCodecPayload(payload);
|
|
2708
|
+
return `${PRESET_CODEC_PREFIX}.${Buffer.from(json, "utf8").toString("base64url")}`;
|
|
2709
|
+
}
|
|
2710
|
+
if (v === 2) {
|
|
2711
|
+
const payload = validateCodecPayloadCanonical(parsed);
|
|
2712
|
+
const json = stableStringifyCodecPayloadCanonical(payload);
|
|
2713
|
+
return `${PRESET_CODEC_PREFIX}.${Buffer.from(json, "utf8").toString("base64url")}`;
|
|
2714
|
+
}
|
|
2715
|
+
throw new PresetValidationError(
|
|
2716
|
+
`Unsupported preset payload version ${String(v)}. This preset may require a newer version of the Wensity CLI.`,
|
|
2717
|
+
"preset.v"
|
|
2718
|
+
);
|
|
2719
|
+
}
|
|
2720
|
+
if ("baseColor" in parsed || "themeColor" in parsed || "chartPalette" in parsed || "headingFont" in parsed || "bodyFont" in parsed) {
|
|
2721
|
+
return encodePresetCanonical(parsed);
|
|
2722
|
+
}
|
|
2723
|
+
return encodePreset(parsed);
|
|
2724
|
+
}
|
|
2725
|
+
function styleFromDecodedPayload(payload, presetCode) {
|
|
2726
|
+
if (payload.v === 1) {
|
|
2727
|
+
return normalizeStyleConfig({
|
|
2728
|
+
...codecPayloadToStyleInput(payload),
|
|
2729
|
+
presetCode
|
|
2730
|
+
});
|
|
2731
|
+
}
|
|
2732
|
+
return normalizeStyleConfigCanonical({
|
|
2733
|
+
baseColor: payload.baseColor,
|
|
2734
|
+
themeColor: payload.themeColor,
|
|
2735
|
+
chartPalette: payload.chartPalette,
|
|
2736
|
+
headingFont: payload.headingFont,
|
|
2737
|
+
bodyFont: payload.bodyFont,
|
|
2738
|
+
iconLibrary: payload.iconLibrary,
|
|
2739
|
+
radius: payload.radius,
|
|
2740
|
+
presetCode
|
|
2741
|
+
});
|
|
2742
|
+
}
|
|
2743
|
+
function toCliPresetError(error) {
|
|
2744
|
+
const message = error.message;
|
|
2745
|
+
if (/Unsupported preset payload version/i.test(message)) {
|
|
2746
|
+
return new CliError(
|
|
2747
|
+
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@0.1.7 or newer) and try again.`
|
|
2748
|
+
);
|
|
2749
|
+
}
|
|
2750
|
+
return new CliError(`Invalid preset: ${message}`);
|
|
2751
|
+
}
|
|
1850
2752
|
|
|
1851
2753
|
// src/preset-init-writes.ts
|
|
1852
2754
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
@@ -1878,34 +2780,29 @@ async function commitPresetInitWrites(input) {
|
|
|
1878
2780
|
// src/style-css.ts
|
|
1879
2781
|
var ROOT_SELECTOR = ":root";
|
|
1880
2782
|
var DARK_SELECTOR = ".dark";
|
|
1881
|
-
|
|
1882
|
-
|
|
2783
|
+
var SHARED_TOKEN_KEYS = ["radius", "fontSans", "fontDisplay", "fontMono"];
|
|
2784
|
+
var MODE_TOKEN_KEYS = Object.keys(RESOLVED_TOKEN_CSS_VARS).filter(
|
|
2785
|
+
(key) => !SHARED_TOKEN_KEYS.includes(key)
|
|
2786
|
+
);
|
|
2787
|
+
function applyResolvedTokensToPrimitiveCss(block, tokens) {
|
|
1883
2788
|
let next = block;
|
|
1884
|
-
const
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
const cssValue = expandFontRole(style.fonts[role], role);
|
|
1890
|
-
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, cssValue);
|
|
1891
|
-
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, cssValue);
|
|
1892
|
-
}
|
|
1893
|
-
if (style.colors?.light) {
|
|
1894
|
-
for (const key of CONTROL_SOLID_COLOR_KEYS) {
|
|
1895
|
-
const value = style.colors.light[key];
|
|
1896
|
-
if (value === void 0) continue;
|
|
1897
|
-
next = replaceDeclInSelector(next, ROOT_SELECTOR, CONTROL_SOLID_CSS_VARS[key], value);
|
|
1898
|
-
}
|
|
2789
|
+
for (const key of SHARED_TOKEN_KEYS) {
|
|
2790
|
+
const cssVar = RESOLVED_TOKEN_CSS_VARS[key];
|
|
2791
|
+
const value = tokens[key];
|
|
2792
|
+
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, value);
|
|
2793
|
+
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, value);
|
|
1899
2794
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
next = replaceDeclInSelector(next, DARK_SELECTOR, CONTROL_SOLID_CSS_VARS[key], value);
|
|
1905
|
-
}
|
|
2795
|
+
for (const key of MODE_TOKEN_KEYS) {
|
|
2796
|
+
const cssVar = RESOLVED_TOKEN_CSS_VARS[key];
|
|
2797
|
+
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, tokens.light[key]);
|
|
2798
|
+
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, tokens.dark[key]);
|
|
1906
2799
|
}
|
|
1907
2800
|
return next;
|
|
1908
2801
|
}
|
|
2802
|
+
function applyStyleToPrimitiveCss(block, styleInput) {
|
|
2803
|
+
const style = normalizeProjectStyle(styleInput);
|
|
2804
|
+
return applyResolvedTokensToPrimitiveCss(block, resolveTokensForStyle(style));
|
|
2805
|
+
}
|
|
1909
2806
|
function replaceDeclInSelector(css, selector, property, value) {
|
|
1910
2807
|
const block = findTopLevelRule(css, selector);
|
|
1911
2808
|
if (!block) return css;
|
|
@@ -2131,7 +3028,7 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2131
3028
|
const files = [];
|
|
2132
3029
|
const componentContents = [];
|
|
2133
3030
|
const iconSwaps = [];
|
|
2134
|
-
const style =
|
|
3031
|
+
const style = normalizeProjectStyle(config.style);
|
|
2135
3032
|
const isPrimitiveCategory = isPrimitivePayloadCategory(payload.category);
|
|
2136
3033
|
const payloadHelperNeeds = normalizePayloadHelperNeeds(
|
|
2137
3034
|
"helperNeeds" in payload ? payload.helperNeeds : void 0
|
|
@@ -2188,8 +3085,10 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2188
3085
|
}
|
|
2189
3086
|
const iconDependencySwap = aggregateIconDependencySwaps(iconSwaps);
|
|
2190
3087
|
const declaredAfterSwap = applyIconDependencySwap(payload.dependencies ?? [], iconDependencySwap);
|
|
3088
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3089
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
2191
3090
|
const dependencies = collectDependencies({
|
|
2192
|
-
declared: declaredAfterSwap,
|
|
3091
|
+
declared: [...declaredAfterSwap, ...fontPlan.packages],
|
|
2193
3092
|
source: componentContents.join("\n"),
|
|
2194
3093
|
needsUtility: helperNeeds.utils
|
|
2195
3094
|
});
|
|
@@ -2198,7 +3097,8 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2198
3097
|
files,
|
|
2199
3098
|
dependencies,
|
|
2200
3099
|
...cssFile ? { cssFile } : {},
|
|
2201
|
-
...isPrimitiveCategory ? { iconDependencySwap } : {}
|
|
3100
|
+
...isPrimitiveCategory ? { iconDependencySwap } : {},
|
|
3101
|
+
...fontPlan.packages.length > 0 ? { fontPackages: fontPlan.packages } : {}
|
|
2202
3102
|
};
|
|
2203
3103
|
}
|
|
2204
3104
|
async function planPrimitiveCssFile(projectRoot, config, payload) {
|
|
@@ -2207,13 +3107,16 @@ async function planPrimitiveCssFile(projectRoot, config, payload) {
|
|
|
2207
3107
|
}
|
|
2208
3108
|
let primitiveCss = payload.primitiveCss.trim();
|
|
2209
3109
|
if (!primitiveCss) return void 0;
|
|
2210
|
-
const style =
|
|
3110
|
+
const style = normalizeProjectStyle(config.style);
|
|
2211
3111
|
primitiveCss = applyStyleToPrimitiveCss(primitiveCss, style).trim();
|
|
2212
3112
|
const cssRelative = config.tailwind?.css;
|
|
2213
3113
|
if (!cssRelative) return void 0;
|
|
2214
3114
|
const absolutePath = resolveInside(projectRoot, cssRelative);
|
|
2215
3115
|
const existing = await fileExists(absolutePath) ? await readFile4(absolutePath, "utf8") : "";
|
|
2216
|
-
const
|
|
3116
|
+
const withTokens = upsertPrimitiveCssBlock(existing, primitiveCss);
|
|
3117
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3118
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
3119
|
+
const next = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
2217
3120
|
if (next === existing) return void 0;
|
|
2218
3121
|
return {
|
|
2219
3122
|
absolutePath,
|
|
@@ -2489,6 +3392,9 @@ async function initWithPreset(context, options) {
|
|
|
2489
3392
|
presetCode: options.presetCode,
|
|
2490
3393
|
presetFile: options.presetFile
|
|
2491
3394
|
});
|
|
3395
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3396
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
3397
|
+
const installDependencies = [...options.dependencies, ...fontPlan.packages];
|
|
2492
3398
|
const configPath = join6(context.cwd, CONFIG_FILE_NAME);
|
|
2493
3399
|
const configExists = await fileExists(configPath);
|
|
2494
3400
|
let config;
|
|
@@ -2531,8 +3437,11 @@ async function initWithPreset(context, options) {
|
|
|
2531
3437
|
}
|
|
2532
3438
|
const cssAbsolute = resolveInside(context.cwd, cssRelative);
|
|
2533
3439
|
const existingCss = await fileExists(cssAbsolute) ? await readFile5(cssAbsolute, "utf8") : "";
|
|
2534
|
-
const
|
|
3440
|
+
const withTokens = upsertPrimitiveCssBlock(existingCss, primitiveCss);
|
|
3441
|
+
const nextCss = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
2535
3442
|
const cssChanged = nextCss !== existingCss;
|
|
3443
|
+
const installedPackages = readInstalledPackageNames(context.cwd);
|
|
3444
|
+
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
2536
3445
|
if (options.dryRun) {
|
|
2537
3446
|
printTitle("Project initialization preview (preset)");
|
|
2538
3447
|
print(action("Would write:"));
|
|
@@ -2541,7 +3450,11 @@ async function initWithPreset(context, options) {
|
|
|
2541
3450
|
print(formatList(planned));
|
|
2542
3451
|
print(action(`Preset: ${presetCode.slice(0, 24)}\u2026`));
|
|
2543
3452
|
print(action(`Style: icon=${style.iconLibrary} radius=${style.radius}`));
|
|
2544
|
-
if (
|
|
3453
|
+
if (fontPlan.packages.length > 0) {
|
|
3454
|
+
print(action(`Fonts: ${fontPlan.packages.join(" ")}`));
|
|
3455
|
+
}
|
|
3456
|
+
if (options.install) print(action(`Would install: ${installDependencies.join(" ")}`));
|
|
3457
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2545
3458
|
return;
|
|
2546
3459
|
}
|
|
2547
3460
|
const shouldWriteUtility = options.force || !await fileExists(utilityPath);
|
|
@@ -2562,7 +3475,7 @@ async function initWithPreset(context, options) {
|
|
|
2562
3475
|
}
|
|
2563
3476
|
});
|
|
2564
3477
|
if (options.install) {
|
|
2565
|
-
runInstall(context.cwd, missingDependencies(context.cwd,
|
|
3478
|
+
runInstall(context.cwd, missingDependencies(context.cwd, installDependencies));
|
|
2566
3479
|
}
|
|
2567
3480
|
printTitle("Project initialized");
|
|
2568
3481
|
const created = [
|
|
@@ -2576,7 +3489,11 @@ async function initWithPreset(context, options) {
|
|
|
2576
3489
|
} else {
|
|
2577
3490
|
created.push(action(`CSS tokens unchanged: ${toPosixPath(cssRelative)}`));
|
|
2578
3491
|
}
|
|
3492
|
+
if (fontPlan.packages.length > 0) {
|
|
3493
|
+
created.push(success(`fonts: ${fontPlan.packages.join(", ")}`));
|
|
3494
|
+
}
|
|
2579
3495
|
print(panel("Created", created));
|
|
3496
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2580
3497
|
print(nextSteps([
|
|
2581
3498
|
"Browse available components: npx wensity list",
|
|
2582
3499
|
"Install a primitive: npx wensity add button"
|
|
@@ -2721,9 +3638,11 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2721
3638
|
await assertNoConflicts(plannedInstallFiles, force || dryRun);
|
|
2722
3639
|
const plannedFiles = summarizeFiles(loaded.projectRoot, plannedInstallFiles);
|
|
2723
3640
|
const missing = missingDependencies(loaded.projectRoot, prepared.dependencies);
|
|
2724
|
-
const style =
|
|
3641
|
+
const style = normalizeProjectStyle(loaded.config.style);
|
|
3642
|
+
const fonts = curatedFontsFromStyle(style);
|
|
2725
3643
|
const installedPackages = readInstalledPackageNames(loaded.projectRoot);
|
|
2726
3644
|
const oppositeIconWarning = installedPackages && prepared.iconDependencySwap ? warnOppositeIconPackageMessage(style.iconLibrary, installedPackages) : void 0;
|
|
3645
|
+
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
2727
3646
|
if (dryRun) {
|
|
2728
3647
|
printTitle(updateMode ? "Update preview" : "Install preview");
|
|
2729
3648
|
print(action("Would write:"));
|
|
@@ -2733,6 +3652,7 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2733
3652
|
}
|
|
2734
3653
|
if (install && missing.length > 0) print(action(`Would install: ${missing.join(" ")}`));
|
|
2735
3654
|
if (oppositeIconWarning) warn(oppositeIconWarning);
|
|
3655
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2736
3656
|
return;
|
|
2737
3657
|
}
|
|
2738
3658
|
await writePlannedFiles(plannedInstallFiles);
|
|
@@ -2745,6 +3665,7 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2745
3665
|
...plannedFiles.map((file) => success(file))
|
|
2746
3666
|
]));
|
|
2747
3667
|
if (oppositeIconWarning) warn(oppositeIconWarning);
|
|
3668
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2748
3669
|
if (!install && missing.length > 0) {
|
|
2749
3670
|
warn(`Dependencies were not installed: ${missing.join(" ")}`);
|
|
2750
3671
|
print(nextSteps([
|