stera-ui 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-JUBSRCDJ.js → add-WUTTJN25.js} +24 -113
- package/dist/chunk-5NLD52O5.js +376 -0
- package/dist/{chunk-SIXUH4HI.js → chunk-V4TMOT6I.js} +158 -94
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -3
- package/dist/{init-E7O5WAUI.js → init-QYYCGWYV.js} +54 -87
- package/dist/schema/index.d.ts +20 -20
- package/dist/utils/index.d.ts +54 -30
- package/dist/utils/index.js +9 -3
- package/package.json +1 -1
- package/dist/chunk-2Y64FOD3.js +0 -161
|
@@ -255,43 +255,15 @@ function detectAliasPrefix(cwd) {
|
|
|
255
255
|
return first ? first.replace(/\/\*$/, "") : null;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
// src/utils/write-
|
|
259
|
-
import
|
|
260
|
-
import
|
|
261
|
-
|
|
262
|
-
const lines = content.split("\n");
|
|
263
|
-
const imports = [];
|
|
264
|
-
const kept = [];
|
|
265
|
-
for (const line of lines) {
|
|
266
|
-
if (line.trim().match(/^@import\s+["'].+["']/)) {
|
|
267
|
-
if (!line.trim().match(/^@import\s+["']tailwindcss["']/)) {
|
|
268
|
-
imports.push(line.trim());
|
|
269
|
-
}
|
|
270
|
-
} else {
|
|
271
|
-
kept.push(line);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return { content: kept.join("\n"), imports };
|
|
275
|
-
}
|
|
276
|
-
async function writeSteraUiCss(config, cwd) {
|
|
277
|
-
const item = await fetchRegistryItem("globals");
|
|
278
|
-
const rawContent = item.files?.[0]?.content ?? "";
|
|
279
|
-
const { content, imports } = stripImportLines(rawContent);
|
|
280
|
-
const cssDir = path4.dirname(path4.resolve(cwd, config.css));
|
|
281
|
-
const steraUiPath = path4.join(cssDir, "stera-ui.css");
|
|
282
|
-
await fs3.mkdir(cssDir, { recursive: true });
|
|
283
|
-
await fs3.writeFile(steraUiPath, content, "utf-8");
|
|
284
|
-
return {
|
|
285
|
-
steraUiPath,
|
|
286
|
-
extraImports: imports,
|
|
287
|
-
dependencies: item.dependencies ?? []
|
|
288
|
-
};
|
|
289
|
-
}
|
|
258
|
+
// src/utils/write-styles.ts
|
|
259
|
+
import fs6 from "fs/promises";
|
|
260
|
+
import { existsSync } from "fs";
|
|
261
|
+
import path5 from "path";
|
|
290
262
|
|
|
291
263
|
// src/utils/css-imports.ts
|
|
292
|
-
import
|
|
264
|
+
import fs3 from "fs/promises";
|
|
293
265
|
async function insertImportLine(filePath, importStatement) {
|
|
294
|
-
const content = await
|
|
266
|
+
const content = await fs3.readFile(filePath, "utf-8");
|
|
295
267
|
const importPath = importStatement.match(/["']([^"']+)["']/)?.[1];
|
|
296
268
|
if (importPath) {
|
|
297
269
|
const escaped = importPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -309,12 +281,147 @@ async function insertImportLine(filePath, importStatement) {
|
|
|
309
281
|
} else {
|
|
310
282
|
lines.unshift(importStatement);
|
|
311
283
|
}
|
|
312
|
-
await
|
|
284
|
+
await fs3.writeFile(filePath, lines.join("\n"), "utf-8");
|
|
313
285
|
}
|
|
314
286
|
|
|
315
|
-
// src/utils/
|
|
287
|
+
// src/utils/patch-css-vars.ts
|
|
288
|
+
import fs4 from "fs";
|
|
289
|
+
function removeCssImport(filePath, importPath) {
|
|
290
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
291
|
+
const pattern = new RegExp(
|
|
292
|
+
`@import\\s+['"]${escapeRegex(importPath)}['"]\\s*;?\\n?`
|
|
293
|
+
);
|
|
294
|
+
if (!pattern.test(content)) return false;
|
|
295
|
+
fs4.writeFileSync(filePath, content.replace(pattern, ""), "utf-8");
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
function escapeRegex(str) {
|
|
299
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/utils/write-files.ts
|
|
316
303
|
import fs5 from "fs";
|
|
317
|
-
import
|
|
304
|
+
import path4 from "path";
|
|
305
|
+
import { confirm } from "@inquirer/prompts";
|
|
306
|
+
async function confirmOverwrite(relativePath) {
|
|
307
|
+
if (!process.stdin.isTTY) {
|
|
308
|
+
console.log(
|
|
309
|
+
` Skipping ${relativePath} (already exists, use --overwrite to replace)`
|
|
310
|
+
);
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
return confirm({
|
|
314
|
+
message: `${relativePath} already exists. Overwrite?`,
|
|
315
|
+
default: false
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
async function writeComponentFiles(items, config, projectRoot, options = {}) {
|
|
319
|
+
const written = [];
|
|
320
|
+
const skipped = [];
|
|
321
|
+
for (const item of items) {
|
|
322
|
+
for (const file of item.files ?? []) {
|
|
323
|
+
const outputPath = resolveOutputPath(config, projectRoot, file);
|
|
324
|
+
const relativePath = path4.relative(projectRoot, outputPath);
|
|
325
|
+
if (fs5.existsSync(outputPath)) {
|
|
326
|
+
const existing = fs5.readFileSync(outputPath, "utf-8");
|
|
327
|
+
if (existing === file.content) {
|
|
328
|
+
skipped.push({ path: relativePath, reason: "unchanged" });
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (!options.overwrite) {
|
|
332
|
+
const confirmed = await confirmOverwrite(relativePath);
|
|
333
|
+
if (!confirmed) {
|
|
334
|
+
skipped.push({ path: relativePath, reason: "declined" });
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const dir = path4.dirname(outputPath);
|
|
340
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
341
|
+
fs5.writeFileSync(outputPath, file.content ?? "", "utf-8");
|
|
342
|
+
written.push(relativePath);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return { written, skipped };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/utils/write-styles.ts
|
|
349
|
+
var INDEX_TARGET = "ui/index.css";
|
|
350
|
+
var TYPOGRAPHY_TARGET = "ui/typography.css";
|
|
351
|
+
var PROTECTED_TARGETS = /* @__PURE__ */ new Set([TYPOGRAPHY_TARGET, "ui/colors.css"]);
|
|
352
|
+
var LEGACY_FILENAME = "stera-ui.css";
|
|
353
|
+
var LEGACY_IMPORT = "./stera-ui.css";
|
|
354
|
+
function partitionImports(content) {
|
|
355
|
+
const lines = content.split("\n");
|
|
356
|
+
const hoisted = [];
|
|
357
|
+
const kept = [];
|
|
358
|
+
for (const line of lines) {
|
|
359
|
+
const specifier = line.trim().match(/^@import\s+["'](.+?)["']/)?.[1];
|
|
360
|
+
if (specifier === void 0) {
|
|
361
|
+
kept.push(line);
|
|
362
|
+
} else if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
363
|
+
kept.push(line);
|
|
364
|
+
} else if (specifier !== "tailwindcss") {
|
|
365
|
+
hoisted.push(line.trim());
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
369
|
+
return { content: cleaned, hoisted };
|
|
370
|
+
}
|
|
371
|
+
async function migrateLegacyStyles(config, cwd) {
|
|
372
|
+
const globalsPath = path5.resolve(cwd, config.css);
|
|
373
|
+
const legacyPath = path5.join(path5.dirname(globalsPath), LEGACY_FILENAME);
|
|
374
|
+
if (!existsSync(legacyPath)) return null;
|
|
375
|
+
await fs6.rm(legacyPath);
|
|
376
|
+
if (existsSync(globalsPath)) {
|
|
377
|
+
removeCssImport(globalsPath, LEGACY_IMPORT);
|
|
378
|
+
await insertImportLine(globalsPath, `@import "./${INDEX_TARGET}";`);
|
|
379
|
+
}
|
|
380
|
+
return legacyPath;
|
|
381
|
+
}
|
|
382
|
+
async function writeStyles(config, cwd, options = {}) {
|
|
383
|
+
const item = await fetchRegistryItem("globals");
|
|
384
|
+
const cssDir = path5.dirname(path5.resolve(cwd, config.css));
|
|
385
|
+
const written = [];
|
|
386
|
+
const skipped = [];
|
|
387
|
+
let extraImports = [];
|
|
388
|
+
for (const file of item.files ?? []) {
|
|
389
|
+
const target = file.target ?? path5.basename(file.path);
|
|
390
|
+
const outputPath = path5.join(cssDir, target);
|
|
391
|
+
let content = file.content ?? "";
|
|
392
|
+
if (target === INDEX_TARGET) {
|
|
393
|
+
const partitioned = partitionImports(content);
|
|
394
|
+
content = partitioned.content;
|
|
395
|
+
extraImports = partitioned.hoisted;
|
|
396
|
+
}
|
|
397
|
+
if (PROTECTED_TARGETS.has(target) && existsSync(outputPath)) {
|
|
398
|
+
const existing = await fs6.readFile(outputPath, "utf-8");
|
|
399
|
+
if (existing === content) {
|
|
400
|
+
skipped.push({ path: target, reason: "unchanged" });
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (!options.overwrite && !await confirmOverwrite(target)) {
|
|
404
|
+
skipped.push({ path: target, reason: "declined" });
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
await fs6.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
409
|
+
await fs6.writeFile(outputPath, content, "utf-8");
|
|
410
|
+
written.push(target);
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
indexPath: path5.join(cssDir, INDEX_TARGET),
|
|
414
|
+
typographyPath: path5.join(cssDir, TYPOGRAPHY_TARGET),
|
|
415
|
+
extraImports,
|
|
416
|
+
dependencies: item.dependencies ?? [],
|
|
417
|
+
written,
|
|
418
|
+
skipped
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/utils/install-deps.ts
|
|
423
|
+
import fs7 from "fs";
|
|
424
|
+
import path6 from "path";
|
|
318
425
|
import { detect } from "@antfu/ni";
|
|
319
426
|
import { execa } from "execa";
|
|
320
427
|
|
|
@@ -400,11 +507,11 @@ function getInstallArgs(pm, deps) {
|
|
|
400
507
|
}
|
|
401
508
|
async function installDependencies(deps, cwd) {
|
|
402
509
|
if (deps.length === 0) return;
|
|
403
|
-
const pkgPath =
|
|
510
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
404
511
|
let existing = /* @__PURE__ */ new Set();
|
|
405
|
-
if (
|
|
512
|
+
if (fs7.existsSync(pkgPath)) {
|
|
406
513
|
try {
|
|
407
|
-
const pkg = JSON.parse(
|
|
514
|
+
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
408
515
|
existing = new Set(
|
|
409
516
|
Object.keys({ ...pkg.dependencies, ...pkg.devDependencies })
|
|
410
517
|
);
|
|
@@ -432,54 +539,8 @@ or use "pnpm add -w <package>" manually to install at the root.`
|
|
|
432
539
|
}
|
|
433
540
|
}
|
|
434
541
|
|
|
435
|
-
// src/utils/write-files.ts
|
|
436
|
-
import fs6 from "fs";
|
|
437
|
-
import path6 from "path";
|
|
438
|
-
import { confirm } from "@inquirer/prompts";
|
|
439
|
-
async function confirmOverwrite(relativePath) {
|
|
440
|
-
if (!process.stdin.isTTY) {
|
|
441
|
-
console.log(
|
|
442
|
-
` Skipping ${relativePath} (already exists, use --overwrite to replace)`
|
|
443
|
-
);
|
|
444
|
-
return false;
|
|
445
|
-
}
|
|
446
|
-
return confirm({
|
|
447
|
-
message: `${relativePath} already exists. Overwrite?`,
|
|
448
|
-
default: false
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
async function writeComponentFiles(items, config, projectRoot, options = {}) {
|
|
452
|
-
const written = [];
|
|
453
|
-
const skipped = [];
|
|
454
|
-
for (const item of items) {
|
|
455
|
-
for (const file of item.files ?? []) {
|
|
456
|
-
const outputPath = resolveOutputPath(config, projectRoot, file);
|
|
457
|
-
const relativePath = path6.relative(projectRoot, outputPath);
|
|
458
|
-
if (fs6.existsSync(outputPath)) {
|
|
459
|
-
const existing = fs6.readFileSync(outputPath, "utf-8");
|
|
460
|
-
if (existing === file.content) {
|
|
461
|
-
skipped.push({ path: relativePath, reason: "unchanged" });
|
|
462
|
-
continue;
|
|
463
|
-
}
|
|
464
|
-
if (!options.overwrite) {
|
|
465
|
-
const confirmed = await confirmOverwrite(relativePath);
|
|
466
|
-
if (!confirmed) {
|
|
467
|
-
skipped.push({ path: relativePath, reason: "declined" });
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
const dir = path6.dirname(outputPath);
|
|
473
|
-
fs6.mkdirSync(dir, { recursive: true });
|
|
474
|
-
fs6.writeFileSync(outputPath, file.content ?? "", "utf-8");
|
|
475
|
-
written.push(relativePath);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
return { written, skipped };
|
|
479
|
-
}
|
|
480
|
-
|
|
481
542
|
// src/utils/update-fonts.ts
|
|
482
|
-
import { existsSync, promises as
|
|
543
|
+
import { existsSync as existsSync2, promises as fs8 } from "fs";
|
|
483
544
|
import path7 from "path";
|
|
484
545
|
import {
|
|
485
546
|
Project,
|
|
@@ -520,10 +581,10 @@ async function updateFonts(fonts, project, cwd, options = {}) {
|
|
|
520
581
|
if (!layoutPath) return;
|
|
521
582
|
if (options.silent) {
|
|
522
583
|
try {
|
|
523
|
-
const layoutContent = await
|
|
584
|
+
const layoutContent = await fs8.readFile(layoutPath, "utf-8");
|
|
524
585
|
const updatedContent = transformLayoutFonts(layoutContent, fonts);
|
|
525
586
|
if (updatedContent !== layoutContent) {
|
|
526
|
-
await
|
|
587
|
+
await fs8.writeFile(layoutPath, updatedContent, "utf-8");
|
|
527
588
|
}
|
|
528
589
|
} catch {
|
|
529
590
|
}
|
|
@@ -531,10 +592,10 @@ async function updateFonts(fonts, project, cwd, options = {}) {
|
|
|
531
592
|
}
|
|
532
593
|
const spinner = createSpinner("Updating fonts");
|
|
533
594
|
try {
|
|
534
|
-
const layoutContent = await
|
|
595
|
+
const layoutContent = await fs8.readFile(layoutPath, "utf-8");
|
|
535
596
|
const updatedContent = transformLayoutFonts(layoutContent, fonts);
|
|
536
597
|
if (updatedContent !== layoutContent) {
|
|
537
|
-
await
|
|
598
|
+
await fs8.writeFile(layoutPath, updatedContent, "utf-8");
|
|
538
599
|
}
|
|
539
600
|
spinner.succeed("Updated layout with font imports");
|
|
540
601
|
} catch {
|
|
@@ -544,7 +605,7 @@ async function updateFonts(fonts, project, cwd, options = {}) {
|
|
|
544
605
|
function findLayoutFile(project, cwd) {
|
|
545
606
|
if (!project.layoutFile) return null;
|
|
546
607
|
const fullPath = path7.join(cwd, project.layoutFile);
|
|
547
|
-
return
|
|
608
|
+
return existsSync2(fullPath) ? fullPath : null;
|
|
548
609
|
}
|
|
549
610
|
function transformLayoutFonts(input, fonts) {
|
|
550
611
|
const project = new Project({ compilerOptions: {} });
|
|
@@ -799,8 +860,12 @@ export {
|
|
|
799
860
|
loadConfig2 as loadConfig,
|
|
800
861
|
detectProject,
|
|
801
862
|
detectAliasPrefix,
|
|
802
|
-
writeSteraUiCss,
|
|
803
863
|
insertImportLine,
|
|
864
|
+
writeComponentFiles,
|
|
865
|
+
INDEX_TARGET,
|
|
866
|
+
TYPOGRAPHY_TARGET,
|
|
867
|
+
migrateLegacyStyles,
|
|
868
|
+
writeStyles,
|
|
804
869
|
brand,
|
|
805
870
|
dim,
|
|
806
871
|
LOGO,
|
|
@@ -810,7 +875,6 @@ export {
|
|
|
810
875
|
createSpinner,
|
|
811
876
|
detectPackageManager,
|
|
812
877
|
installDependencies,
|
|
813
|
-
writeComponentFiles,
|
|
814
878
|
massageTreeForFonts,
|
|
815
879
|
updateFonts
|
|
816
880
|
};
|
package/dist/cli.js
CHANGED
|
@@ -10,11 +10,11 @@ var pkg = createRequire(import.meta.url)("../package.json");
|
|
|
10
10
|
var program = new Command();
|
|
11
11
|
program.name("stera-ui").description("Add Stera UI components to your project.").version(pkg.version);
|
|
12
12
|
program.command("init").description("Initialize Stera UI in your project.").option("-c, --cwd <path>", "Working directory", process.cwd()).option("-y, --yes", "Skip confirmation prompts").action(async (options) => {
|
|
13
|
-
const { init } = await import("./init-
|
|
13
|
+
const { init } = await import("./init-QYYCGWYV.js");
|
|
14
14
|
await init(options);
|
|
15
15
|
});
|
|
16
16
|
program.command("add").description("Add components to your project.").argument("<components...>", "Components to add").option("-c, --cwd <path>", "Working directory", process.cwd()).option("-y, --yes", "Skip confirmation prompts").option("-o, --overwrite", "Overwrite existing files without prompting").action(async (components, options) => {
|
|
17
|
-
const { add } = await import("./add-
|
|
17
|
+
const { add } = await import("./add-WUTTJN25.js");
|
|
18
18
|
await add(components, options);
|
|
19
19
|
});
|
|
20
20
|
program.command("list").description("List all available components.").action(async () => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { ComponentNotFoundError, fetchRegistryIndex, fetchRegistryItem, getAllComponents, getComponent, resolveDependencies } from './registry/index.js';
|
|
2
2
|
export { RegistryFontItem, RegistryIndex, RegistryIndexEntry, RegistryItem, RegistryItemFile, RegistryItemFont, RegistryItemType, SteraConfig, configSchema, registryIndexEntrySchema, registryIndexSchema, registryItemFileSchema, registryItemFontSchema, registryItemSchema, registryItemTypeSchema } from './schema/index.js';
|
|
3
|
-
export { CHECK, CONFIG_FILE, CROSS, LEGACY_CONFIG_FILE, LOGO, ProjectInfo, SkippedFile, TransformContext, TransformFn, WARN, WriteOptions, WriteResult,
|
|
3
|
+
export { CHECK, CONFIG_FILE, CROSS, INDEX_TARGET, LEGACY_CONFIG_FILE, LOGO, ProjectInfo, SkippedFile, TYPOGRAPHY_TARGET, TransformContext, TransformFn, WARN, WriteOptions, WriteResult, WriteStylesResult, applyTransforms, brand, createSpinner, detectAliasPrefix, detectPackageManager, detectProject, dim, findConfigPath, insertImportLine, installDependencies, loadConfig, massageTreeForFonts, migrateLegacyStyles, resolveOutputPath, transformImports, updateFonts, writeComponentFiles, writeStyles } from './utils/index.js';
|
|
4
4
|
import 'zod';
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
CHECK,
|
|
3
3
|
CONFIG_FILE,
|
|
4
4
|
CROSS,
|
|
5
|
+
INDEX_TARGET,
|
|
5
6
|
LEGACY_CONFIG_FILE,
|
|
6
7
|
LOGO,
|
|
8
|
+
TYPOGRAPHY_TARGET,
|
|
7
9
|
WARN,
|
|
8
10
|
applyTransforms,
|
|
9
11
|
brand,
|
|
@@ -17,12 +19,13 @@ import {
|
|
|
17
19
|
installDependencies,
|
|
18
20
|
loadConfig,
|
|
19
21
|
massageTreeForFonts,
|
|
22
|
+
migrateLegacyStyles,
|
|
20
23
|
resolveOutputPath,
|
|
21
24
|
transformImports,
|
|
22
25
|
updateFonts,
|
|
23
26
|
writeComponentFiles,
|
|
24
|
-
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
writeStyles
|
|
28
|
+
} from "./chunk-V4TMOT6I.js";
|
|
26
29
|
import {
|
|
27
30
|
ComponentNotFoundError,
|
|
28
31
|
fetchRegistryIndex,
|
|
@@ -45,8 +48,10 @@ export {
|
|
|
45
48
|
CONFIG_FILE,
|
|
46
49
|
CROSS,
|
|
47
50
|
ComponentNotFoundError,
|
|
51
|
+
INDEX_TARGET,
|
|
48
52
|
LEGACY_CONFIG_FILE,
|
|
49
53
|
LOGO,
|
|
54
|
+
TYPOGRAPHY_TARGET,
|
|
50
55
|
WARN,
|
|
51
56
|
applyTransforms,
|
|
52
57
|
brand,
|
|
@@ -65,6 +70,7 @@ export {
|
|
|
65
70
|
installDependencies,
|
|
66
71
|
loadConfig,
|
|
67
72
|
massageTreeForFonts,
|
|
73
|
+
migrateLegacyStyles,
|
|
68
74
|
registryIndexEntrySchema,
|
|
69
75
|
registryIndexSchema,
|
|
70
76
|
registryItemFileSchema,
|
|
@@ -76,5 +82,5 @@ export {
|
|
|
76
82
|
transformImports,
|
|
77
83
|
updateFonts,
|
|
78
84
|
writeComponentFiles,
|
|
79
|
-
|
|
85
|
+
writeStyles
|
|
80
86
|
};
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CONFIG_FILE,
|
|
4
4
|
LEGACY_CONFIG_FILE,
|
|
5
|
+
TYPOGRAPHY_TARGET,
|
|
5
6
|
findConfigPath,
|
|
7
|
+
insertImportLine,
|
|
6
8
|
installDependencies,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
migrateLegacyStyles,
|
|
10
|
+
patchCssVariables,
|
|
11
|
+
writeStyles
|
|
12
|
+
} from "./chunk-5NLD52O5.js";
|
|
9
13
|
import {
|
|
10
14
|
createSpinner,
|
|
11
15
|
fetchRegistryItem
|
|
@@ -17,7 +21,7 @@ import {
|
|
|
17
21
|
} from "./chunk-KGMF6UW4.js";
|
|
18
22
|
|
|
19
23
|
// src/commands/init.ts
|
|
20
|
-
import
|
|
24
|
+
import fs4 from "fs";
|
|
21
25
|
import fsp from "fs/promises";
|
|
22
26
|
import path4 from "path";
|
|
23
27
|
import { confirm, select } from "@inquirer/prompts";
|
|
@@ -192,36 +196,8 @@ function detectFonts(cwd, project) {
|
|
|
192
196
|
return result;
|
|
193
197
|
}
|
|
194
198
|
|
|
195
|
-
// src/utils/patch-css-vars.ts
|
|
196
|
-
import fs3 from "fs";
|
|
197
|
-
function patchCssVariables(filePath, patches) {
|
|
198
|
-
const content = fs3.readFileSync(filePath, "utf-8");
|
|
199
|
-
const lines = content.split("\n");
|
|
200
|
-
const patched = [];
|
|
201
|
-
const compiled = Object.entries(patches).map(([prop, newValue]) => ({
|
|
202
|
-
prop,
|
|
203
|
-
newValue,
|
|
204
|
-
regex: new RegExp(`(\\s*${escapeRegex(prop)}:\\s*).+?(;)`)
|
|
205
|
-
}));
|
|
206
|
-
for (let i = 0; i < lines.length; i++) {
|
|
207
|
-
for (const { prop, newValue, regex } of compiled) {
|
|
208
|
-
if (regex.test(lines[i])) {
|
|
209
|
-
lines[i] = lines[i].replace(regex, `$1${newValue}$2`);
|
|
210
|
-
if (!patched.includes(prop)) patched.push(prop);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (patched.length > 0) {
|
|
215
|
-
fs3.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
216
|
-
}
|
|
217
|
-
return patched;
|
|
218
|
-
}
|
|
219
|
-
function escapeRegex(str) {
|
|
220
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
221
|
-
}
|
|
222
|
-
|
|
223
199
|
// src/utils/update-fonts.ts
|
|
224
|
-
import { existsSync, promises as
|
|
200
|
+
import { existsSync, promises as fs3 } from "fs";
|
|
225
201
|
import path3 from "path";
|
|
226
202
|
import {
|
|
227
203
|
Project,
|
|
@@ -262,10 +238,10 @@ async function updateFonts(fonts, project, cwd, options = {}) {
|
|
|
262
238
|
if (!layoutPath) return;
|
|
263
239
|
if (options.silent) {
|
|
264
240
|
try {
|
|
265
|
-
const layoutContent = await
|
|
241
|
+
const layoutContent = await fs3.readFile(layoutPath, "utf-8");
|
|
266
242
|
const updatedContent = transformLayoutFonts(layoutContent, fonts);
|
|
267
243
|
if (updatedContent !== layoutContent) {
|
|
268
|
-
await
|
|
244
|
+
await fs3.writeFile(layoutPath, updatedContent, "utf-8");
|
|
269
245
|
}
|
|
270
246
|
} catch {
|
|
271
247
|
}
|
|
@@ -273,10 +249,10 @@ async function updateFonts(fonts, project, cwd, options = {}) {
|
|
|
273
249
|
}
|
|
274
250
|
const spinner = createSpinner("Updating fonts");
|
|
275
251
|
try {
|
|
276
|
-
const layoutContent = await
|
|
252
|
+
const layoutContent = await fs3.readFile(layoutPath, "utf-8");
|
|
277
253
|
const updatedContent = transformLayoutFonts(layoutContent, fonts);
|
|
278
254
|
if (updatedContent !== layoutContent) {
|
|
279
|
-
await
|
|
255
|
+
await fs3.writeFile(layoutPath, updatedContent, "utf-8");
|
|
280
256
|
}
|
|
281
257
|
spinner.succeed("Updated layout with font imports");
|
|
282
258
|
} catch {
|
|
@@ -531,41 +507,14 @@ function parseTemplateLiteralToCnArgs(templateLiteral) {
|
|
|
531
507
|
return [...staticArgs, ...variableArgs];
|
|
532
508
|
}
|
|
533
509
|
|
|
534
|
-
// src/utils/css-imports.ts
|
|
535
|
-
import fs5 from "fs/promises";
|
|
536
|
-
async function insertImportLine(filePath, importStatement) {
|
|
537
|
-
const content = await fs5.readFile(filePath, "utf-8");
|
|
538
|
-
const importPath = importStatement.match(/["']([^"']+)["']/)?.[1];
|
|
539
|
-
if (importPath) {
|
|
540
|
-
const escaped = importPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
541
|
-
if (new RegExp(`@import\\s+["']${escaped}["']`).test(content)) return;
|
|
542
|
-
}
|
|
543
|
-
const lines = content.split("\n");
|
|
544
|
-
let lastImportIndex = -1;
|
|
545
|
-
for (let i = 0; i < lines.length; i++) {
|
|
546
|
-
if (lines[i].trim().startsWith("@import")) {
|
|
547
|
-
lastImportIndex = i;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (lastImportIndex >= 0) {
|
|
551
|
-
lines.splice(lastImportIndex + 1, 0, importStatement);
|
|
552
|
-
} else {
|
|
553
|
-
lines.unshift(importStatement);
|
|
554
|
-
}
|
|
555
|
-
await fs5.writeFile(filePath, lines.join("\n"), "utf-8");
|
|
556
|
-
}
|
|
557
|
-
|
|
558
510
|
// src/commands/init.ts
|
|
559
511
|
var DEFAULT_FONT_NAMES = ["font-geist", "font-geist-mono"];
|
|
512
|
+
function resolveCssPath(project) {
|
|
513
|
+
if (project.existingCssFile) return project.existingCssFile;
|
|
514
|
+
return project.hasSrc ? "src/styles/globals.css" : "styles/globals.css";
|
|
515
|
+
}
|
|
560
516
|
function buildConfig(project, strategy, aliasPrefix) {
|
|
561
|
-
|
|
562
|
-
if (project.existingCssFile) {
|
|
563
|
-
cssPath = project.existingCssFile;
|
|
564
|
-
} else if (project.hasSrc) {
|
|
565
|
-
cssPath = "src/styles/globals.css";
|
|
566
|
-
} else {
|
|
567
|
-
cssPath = "styles/globals.css";
|
|
568
|
-
}
|
|
517
|
+
const cssPath = resolveCssPath(project);
|
|
569
518
|
return {
|
|
570
519
|
$schema: "https://ui.stera.sh/schema.json",
|
|
571
520
|
version: 1,
|
|
@@ -640,11 +589,11 @@ async function fetchDefaultFonts() {
|
|
|
640
589
|
async function executeFontStrategy(strategy, project, detected, config, cwd) {
|
|
641
590
|
if (strategy === "skip") return;
|
|
642
591
|
const cssDir = path4.dirname(path4.resolve(cwd, config.css));
|
|
643
|
-
const
|
|
592
|
+
const typographyPath = path4.join(cssDir, TYPOGRAPHY_TARGET);
|
|
644
593
|
if (strategy === "keep-existing") {
|
|
645
594
|
const fontFamily = detected.fontFamilies.length > 0 ? detected.fontFamilies[0] : null;
|
|
646
595
|
const fontValue = detected.nextFontVariable ? `var(${detected.nextFontVariable})` : fontFamily ?? "Geist";
|
|
647
|
-
const patched = patchCssVariables(
|
|
596
|
+
const patched = patchCssVariables(typographyPath, {
|
|
648
597
|
"--font-heading": fontValue,
|
|
649
598
|
"--font-sans": fontValue
|
|
650
599
|
});
|
|
@@ -661,17 +610,17 @@ async function executeFontStrategy(strategy, project, detected, config, cwd) {
|
|
|
661
610
|
}
|
|
662
611
|
if (fontTree.cssImports.length > 0) {
|
|
663
612
|
for (const importLine of fontTree.cssImports) {
|
|
664
|
-
await insertImportLine(
|
|
613
|
+
await insertImportLine(typographyPath, importLine);
|
|
665
614
|
}
|
|
666
615
|
console.log(
|
|
667
|
-
` ${CHECK} Added font imports to ${path4.relative(cwd,
|
|
616
|
+
` ${CHECK} Added font imports to ${path4.relative(cwd, typographyPath)}`
|
|
668
617
|
);
|
|
669
618
|
}
|
|
670
619
|
if (Object.keys(fontTree.cssVars).length > 0) {
|
|
671
|
-
const patched = patchCssVariables(
|
|
620
|
+
const patched = patchCssVariables(typographyPath, fontTree.cssVars);
|
|
672
621
|
if (patched.length > 0) {
|
|
673
622
|
console.log(
|
|
674
|
-
` ${CHECK} Updated font variables in ${path4.relative(cwd,
|
|
623
|
+
` ${CHECK} Updated font variables in ${path4.relative(cwd, typographyPath)}`
|
|
675
624
|
);
|
|
676
625
|
}
|
|
677
626
|
}
|
|
@@ -693,7 +642,7 @@ async function init(options) {
|
|
|
693
642
|
});
|
|
694
643
|
if (shouldRename) {
|
|
695
644
|
const renamed = path4.join(path4.dirname(existing), CONFIG_FILE);
|
|
696
|
-
|
|
645
|
+
fs4.renameSync(existing, renamed);
|
|
697
646
|
console.log(` ${CHECK} Renamed to ${CONFIG_FILE}`);
|
|
698
647
|
console.log(' Run "stera-ui add <component>" to add components.\n');
|
|
699
648
|
} else {
|
|
@@ -709,7 +658,7 @@ async function init(options) {
|
|
|
709
658
|
return;
|
|
710
659
|
}
|
|
711
660
|
const pkgPath = path4.join(cwd, "package.json");
|
|
712
|
-
if (!
|
|
661
|
+
if (!fs4.existsSync(pkgPath)) {
|
|
713
662
|
console.error(
|
|
714
663
|
" Error: No package.json found. Please run this in a project directory."
|
|
715
664
|
);
|
|
@@ -738,29 +687,47 @@ async function init(options) {
|
|
|
738
687
|
`);
|
|
739
688
|
}
|
|
740
689
|
const detectedFonts = detectFonts(cwd, project);
|
|
690
|
+
const uiDir = path4.join(path4.dirname(path4.resolve(cwd, resolveCssPath(project))), "ui");
|
|
691
|
+
if (fs4.existsSync(uiDir) && fs4.readdirSync(uiDir).length > 0) {
|
|
692
|
+
const relativeUiDir = path4.relative(cwd, uiDir);
|
|
693
|
+
console.log("");
|
|
694
|
+
console.log(` ${relativeUiDir} already exists and is not empty.`);
|
|
695
|
+
const proceed = options.yes || process.stdin.isTTY && await confirm({
|
|
696
|
+
message: `Write the style partials into ${relativeUiDir}?`,
|
|
697
|
+
default: false
|
|
698
|
+
});
|
|
699
|
+
if (!proceed) {
|
|
700
|
+
console.log("");
|
|
701
|
+
console.log(
|
|
702
|
+
` Aborted. Move ${relativeUiDir} aside, or point "css" in ${CONFIG_FILE} at a different stylesheet, then run init again.`
|
|
703
|
+
);
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
741
707
|
const strategy = await promptFontStrategy(detectedFonts, options.yes ?? false);
|
|
742
708
|
const config = buildConfig(project, strategy, aliasPrefix);
|
|
743
709
|
const configPath = path4.join(cwd, CONFIG_FILE);
|
|
744
|
-
|
|
710
|
+
fs4.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
745
711
|
console.log(` ${CHECK} Created ${CONFIG_FILE}`);
|
|
746
712
|
const fetchSpinner = createSpinner("Fetching base styles");
|
|
747
|
-
let
|
|
713
|
+
let stylesResult;
|
|
748
714
|
try {
|
|
749
|
-
|
|
715
|
+
await migrateLegacyStyles(config, cwd);
|
|
716
|
+
stylesResult = await writeStyles(config, cwd);
|
|
750
717
|
} catch (err) {
|
|
751
718
|
fetchSpinner.fail("Failed to fetch base styles");
|
|
752
719
|
throw err;
|
|
753
720
|
}
|
|
754
721
|
fetchSpinner.succeed("Base styles resolved");
|
|
755
722
|
console.log(
|
|
756
|
-
` ${CHECK} Created ${path4.relative(cwd,
|
|
723
|
+
` ${CHECK} Created ${path4.relative(cwd, stylesResult.indexPath)}`
|
|
757
724
|
);
|
|
758
725
|
const globalsPath = project.existingCssFile ? path4.resolve(cwd, project.existingCssFile) : path4.resolve(cwd, config.css);
|
|
759
|
-
if (
|
|
760
|
-
for (const imp of
|
|
726
|
+
if (fs4.existsSync(globalsPath)) {
|
|
727
|
+
for (const imp of stylesResult.extraImports) {
|
|
761
728
|
await insertImportLine(globalsPath, imp);
|
|
762
729
|
}
|
|
763
|
-
await insertImportLine(globalsPath, '@import "./
|
|
730
|
+
await insertImportLine(globalsPath, '@import "./ui/index.css";');
|
|
764
731
|
console.log(
|
|
765
732
|
` ${CHECK} Added @import to ${path4.relative(cwd, globalsPath)}`
|
|
766
733
|
);
|
|
@@ -768,15 +735,15 @@ async function init(options) {
|
|
|
768
735
|
await fsp.mkdir(path4.dirname(globalsPath), { recursive: true });
|
|
769
736
|
const scaffold = [
|
|
770
737
|
'@import "tailwindcss";',
|
|
771
|
-
...
|
|
772
|
-
'@import "./
|
|
738
|
+
...stylesResult.extraImports,
|
|
739
|
+
'@import "./ui/index.css";'
|
|
773
740
|
].join("\n") + "\n";
|
|
774
741
|
await fsp.writeFile(globalsPath, scaffold, "utf-8");
|
|
775
742
|
console.log(` ${CHECK} Created ${path4.relative(cwd, globalsPath)}`);
|
|
776
743
|
}
|
|
777
744
|
await executeFontStrategy(strategy, project, detectedFonts, config, cwd);
|
|
778
|
-
if (
|
|
779
|
-
const deps = [...new Set(
|
|
745
|
+
if (stylesResult.dependencies.length > 0) {
|
|
746
|
+
const deps = [...new Set(stylesResult.dependencies)].sort();
|
|
780
747
|
console.log("");
|
|
781
748
|
await installDependencies(deps, cwd);
|
|
782
749
|
}
|