rizzo-css 0.0.27 → 0.0.28

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.
Files changed (33) hide show
  1. package/README.md +7 -2
  2. package/bin/rizzo-css.js +192 -36
  3. package/package.json +1 -1
  4. package/scaffold/astro-minimal/gitignore +24 -0
  5. package/scaffold/svelte-minimal/gitignore +10 -0
  6. package/scaffold/vanilla/README-RIZZO.md +1 -1
  7. package/scaffold/vanilla/components/accordion.html +4 -0
  8. package/scaffold/vanilla/components/alert.html +4 -0
  9. package/scaffold/vanilla/components/avatar.html +4 -0
  10. package/scaffold/vanilla/components/badge.html +4 -0
  11. package/scaffold/vanilla/components/breadcrumb.html +4 -0
  12. package/scaffold/vanilla/components/button.html +4 -0
  13. package/scaffold/vanilla/components/cards.html +4 -0
  14. package/scaffold/vanilla/components/copy-to-clipboard.html +4 -0
  15. package/scaffold/vanilla/components/divider.html +4 -0
  16. package/scaffold/vanilla/components/dropdown.html +4 -0
  17. package/scaffold/vanilla/components/forms.html +4 -0
  18. package/scaffold/vanilla/components/icons.html +4 -0
  19. package/scaffold/vanilla/components/index.html +4 -0
  20. package/scaffold/vanilla/components/modal.html +4 -0
  21. package/scaffold/vanilla/components/navbar.html +4 -0
  22. package/scaffold/vanilla/components/pagination.html +4 -0
  23. package/scaffold/vanilla/components/progress-bar.html +4 -0
  24. package/scaffold/vanilla/components/search.html +4 -0
  25. package/scaffold/vanilla/components/settings.html +4 -0
  26. package/scaffold/vanilla/components/spinner.html +4 -0
  27. package/scaffold/vanilla/components/table.html +4 -0
  28. package/scaffold/vanilla/components/tabs.html +4 -0
  29. package/scaffold/vanilla/components/theme-switcher.html +4 -0
  30. package/scaffold/vanilla/components/toast.html +4 -0
  31. package/scaffold/vanilla/components/tooltip.html +4 -0
  32. package/scaffold/vanilla/gitignore +27 -0
  33. package/scaffold/vanilla/index.html +4 -0
package/README.md CHANGED
@@ -19,7 +19,12 @@ npm create svelte@latest my-app && cd my-app && npx rizzo-css add
19
19
  npm create astro@latest my-app && cd my-app && npx rizzo-css add
20
20
  ```
21
21
 
22
- `add` auto-detects Svelte/Astro and copies CSS to the right place (`static/css` or `public/css`). `npx rizzo-css theme` lists themes.
22
+ `add` writes **RIZZO-SNIPPET.txt** (link + theme) by default; use `--no-snippet` to skip. `npx rizzo-css doctor` checks config and CSS path. `npx rizzo-css theme` lists themes.
23
+
24
+ | | **Create new** (`init` → new) | **Add to existing** (`add` or `init` → existing) |
25
+ |---|------------------------------|--------------------------------------------------|
26
+ | Writes | Scaffold, CSS, config, LICENSE-RIZZO, README-RIZZO, .gitignore | CSS, components, config, optional RIZZO-SNIPPET.txt |
27
+ | Link | Already in scaffold | You add it (CLI prints the tag) |
23
28
 
24
29
  ## One package, any framework
25
30
 
@@ -56,7 +61,7 @@ import 'rizzo-css';
56
61
  **Without a bundler (plain HTML):** Use a CDN. Both unpkg and jsDelivr resolve the package root to the built CSS (via the `unpkg` / `jsdelivr` fields in this package). For reliability or to pin a version, use the explicit path:
57
62
 
58
63
  ```html
59
- <!-- unpkg (pin version: replace @latest with @0.0.27 or any version) -->
64
+ <!-- unpkg (pin version: replace @latest with @0.0.28 or any version) -->
60
65
  <link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css" />
61
66
 
62
67
  <!-- or jsDelivr -->
package/bin/rizzo-css.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { copyFileSync, mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, statSync } = require('fs');
3
+ const { copyFileSync, mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, statSync, unlinkSync } = require('fs');
4
4
  const { join, dirname } = require('path');
5
5
  const { spawnSync } = require('child_process');
6
6
  const readline = require('readline');
@@ -10,8 +10,10 @@ const RIZZO_CONFIG_FILE = 'rizzo-css.json';
10
10
  const SCAFFOLD_README_FILENAME = 'README-RIZZO.md';
11
11
  /** Scaffold license filename; avoids overwriting an existing project LICENSE. */
12
12
  const SCAFFOLD_LICENSE_FILENAME = 'LICENSE-RIZZO';
13
+ /** Snippet file written by add command for copy-paste of link and theme. */
14
+ const RIZZO_SNIPPET_FILE = 'RIZZO-SNIPPET.txt';
13
15
 
14
- const COMMANDS = ['init', 'add', 'theme', 'help'];
16
+ const COMMANDS = ['init', 'add', 'theme', 'doctor', 'help'];
15
17
  const FRAMEWORKS = ['vanilla', 'astro', 'svelte'];
16
18
  /** Supported package managers: detection, install/add commands, and --package-manager override. */
17
19
  const VALID_PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun'];
@@ -112,6 +114,9 @@ const RECOMMENDED_COMPONENTS = [
112
114
  'Button', 'Badge', 'Card', 'Modal', 'Tabs', 'ThemeSwitcher', 'FormGroup', 'Alert', 'Toast', 'Dropdown',
113
115
  ];
114
116
 
117
+ // Vanilla components that need js/main.js for interactivity (modal, dropdown, tabs, toast, theme switcher).
118
+ const VANILLA_JS_COMPONENTS = ['Modal', 'Dropdown', 'Tabs', 'Toast', 'ThemeSwitcher'];
119
+
115
120
  // Component dependencies per framework: when user selects a component, these are copied automatically so it works.
116
121
  // Manual users can run: npx rizzo-css help components
117
122
  const COMPONENT_DEPS = {
@@ -271,31 +276,38 @@ function copyPackageLicense(projectDir) {
271
276
  }
272
277
  }
273
278
 
274
- /** Copy scaffold vanilla .gitignore into project so new vanilla projects have sensible defaults. */
279
+ /** Name of the scaffold gitignore file (no leading dot so npm pack includes it). Copied to project as .gitignore. */
280
+ const SCAFFOLD_GITIGNORE_FILE = 'gitignore';
281
+
282
+ /** Copy scaffold vanilla gitignore into project as .gitignore so new vanilla projects have sensible defaults. */
275
283
  function copyVanillaGitignore(projectDir) {
276
- const gitignorePath = join(getPackageRoot(), 'scaffold', 'vanilla', '.gitignore');
284
+ const gitignorePath = join(getPackageRoot(), 'scaffold', 'vanilla', SCAFFOLD_GITIGNORE_FILE);
277
285
  if (existsSync(gitignorePath)) {
278
286
  copyFileSync(gitignorePath, join(projectDir, '.gitignore'));
279
287
  }
280
288
  }
281
289
 
282
- /** Copy Astro minimal scaffold .gitignore into project (full and minimal templates). */
290
+ /** Copy Astro minimal scaffold gitignore into project as .gitignore (full and minimal templates). */
283
291
  function copyAstroGitignore(projectDir) {
284
- const gitignorePath = join(getScaffoldAstroMinimalDir(), '.gitignore');
292
+ const gitignorePath = join(getScaffoldAstroMinimalDir(), SCAFFOLD_GITIGNORE_FILE);
285
293
  if (existsSync(gitignorePath)) {
286
294
  copyFileSync(gitignorePath, join(projectDir, '.gitignore'));
295
+ const copiedAsFile = join(projectDir, SCAFFOLD_GITIGNORE_FILE);
296
+ if (existsSync(copiedAsFile)) unlinkSync(copiedAsFile);
287
297
  }
288
298
  }
289
299
 
290
- /** Copy Svelte minimal scaffold .gitignore into project (full and minimal templates). */
300
+ /** Copy Svelte minimal scaffold gitignore into project as .gitignore (full and minimal templates). */
291
301
  function copySvelteGitignore(projectDir) {
292
- const gitignorePath = join(getScaffoldSvelteMinimalDir(), '.gitignore');
302
+ const gitignorePath = join(getScaffoldSvelteMinimalDir(), SCAFFOLD_GITIGNORE_FILE);
293
303
  if (existsSync(gitignorePath)) {
294
304
  copyFileSync(gitignorePath, join(projectDir, '.gitignore'));
305
+ const copiedAsFile = join(projectDir, SCAFFOLD_GITIGNORE_FILE);
306
+ if (existsSync(copiedAsFile)) unlinkSync(copiedAsFile);
295
307
  }
296
308
  }
297
309
 
298
- /** Read rizzo-css.json from cwd. Returns { targetDir?, framework?, packageManager? } or null. */
310
+ /** Read rizzo-css.json from cwd. Returns { targetDir?, framework?, packageManager?, theme? } or null. Preserves unknown keys. */
299
311
  function readRizzoConfig(cwd) {
300
312
  if (!cwd || !existsSync(cwd)) return null;
301
313
  const configPath = join(cwd, RIZZO_CONFIG_FILE);
@@ -306,6 +318,7 @@ function readRizzoConfig(cwd) {
306
318
  if (typeof raw.targetDir === 'string') out.targetDir = raw.targetDir;
307
319
  if (typeof raw.framework === 'string' && FRAMEWORKS.includes(raw.framework)) out.framework = raw.framework;
308
320
  if (typeof raw.packageManager === 'string' && ['npm', 'pnpm', 'yarn', 'bun'].includes(raw.packageManager)) out.packageManager = raw.packageManager;
321
+ if (typeof raw.theme === 'string') out.theme = raw.theme;
309
322
  return Object.keys(out).length ? out : null;
310
323
  } catch (_) { return null; }
311
324
  }
@@ -324,6 +337,7 @@ function writeRizzoConfig(cwd, config) {
324
337
  if (config.targetDir != null) obj.targetDir = config.targetDir;
325
338
  if (config.framework != null) obj.framework = config.framework;
326
339
  if (config.packageManager != null) obj.packageManager = config.packageManager;
340
+ if (config.theme != null) obj.theme = config.theme;
327
341
  writeFileSync(configPath, JSON.stringify(obj, null, 2) + '\n', 'utf8');
328
342
  }
329
343
 
@@ -449,6 +463,24 @@ async function confirmRunInstall(pm) {
449
463
  return answer === '' || /^y(es)?$/i.test(answer);
450
464
  }
451
465
 
466
+ /** Ask user to copy js/main.js for vanilla interactive components. */
467
+ async function confirmCopyVanillaJs() {
468
+ const answer = await question('\nCopy js/main.js for modal, dropdown, tabs, toast, theme switcher? (Y/n) ');
469
+ return answer === '' || /^y(es)?$/i.test(answer);
470
+ }
471
+
472
+ /** True if directory looks like an existing project (has package.json, src/, or index.html). */
473
+ function isDirNonEmpty(dir) {
474
+ if (!dir || !existsSync(dir)) return false;
475
+ return existsSync(join(dir, 'package.json')) || existsSync(join(dir, 'src')) || existsSync(join(dir, 'index.html'));
476
+ }
477
+
478
+ /** Ask user to confirm creating in a non-empty directory. */
479
+ async function confirmNonEmptyDir(projectDir) {
480
+ const answer = await question('\nCurrent directory is not empty. Continue? (y/N) ');
481
+ return /^y(es)?$/i.test(answer);
482
+ }
483
+
452
484
  /** Format label with optional ANSI color (item.color). */
453
485
  function formatLabel(item) {
454
486
  const text = item.label || item.value;
@@ -740,12 +772,13 @@ function printHelp() {
740
772
  console.log(`
741
773
  rizzo-css CLI — Add Rizzo CSS to your project (Vanilla, Astro, Svelte)
742
774
 
743
- Available commands: init, add, theme, help
775
+ Available commands: init, add, theme, doctor, help
744
776
 
745
777
  Flags summary:
746
778
  init --yes --framework <fw> --template <t> --package-manager <pm> --install --no-install
747
- add --path <dir> --framework <fw> --package-manager <pm> --install-package --no-install
779
+ add --path <dir> --framework <fw> ... --no-snippet --readme --force --vanilla-js
748
780
  theme (no flags)
781
+ doctor Check config, CSS file, and optional layout link
749
782
  help (no flags)
750
783
 
751
784
  Usage (use your package manager):
@@ -775,6 +808,10 @@ Options (add):
775
808
  --package-manager <pm> npm | pnpm | yarn | bun (override detection for install/print commands)
776
809
  --install-package After copying CSS, run package manager add rizzo-css
777
810
  --no-install Do not run install or add (overrides --install-package)
811
+ --no-snippet Do not write RIZZO-SNIPPET.txt (link + theme copy-paste)
812
+ --readme Write README-RIZZO.md into the project
813
+ --force Overwrite existing rizzo.min.css without prompting
814
+ --vanilla-js (Vanilla) Copy js/main.js for interactive components (modal, dropdown, tabs, toast, theme switcher)
778
815
 
779
816
  Package managers:
780
817
  Supported: npm, pnpm, yarn, bun. Detection: lockfiles (pnpm-lock.yaml, yarn.lock, bun.lockb, package-lock.json) or package.json "packageManager"/"devEngines.packageManager". Use --package-manager to override.
@@ -841,6 +878,11 @@ Dependencies (when you pick the component on the left, the right is added automa
841
878
  ThemeSwitcher and ThemeIcon: when selected, themes.ts (and Svelte theme.ts) is copied so they work.
842
879
  Icons: copied whenever you add any component.
843
880
 
881
+ Where components are copied:
882
+ Astro → src/components/rizzo/ (import from there)
883
+ Svelte → src/lib/rizzo/ (import from '$lib/rizzo')
884
+ Vanilla → components/ (HTML) (for interactivity add js/main.js; use --vanilla-js on add)
885
+
844
886
  Full = all components above; dependencies are included so everything works.
845
887
  Minimal = recommended set; any component in that set that requires others gets them.
846
888
  Manual = you pick; the picker shows e.g. "Settings (adds ThemeSwitcher)". Required deps are added when you confirm.
@@ -857,6 +899,45 @@ function cmdTheme() {
857
899
  process.stdout.write('\nExample: <html lang="en" data-theme="github-dark-classic">\n\n');
858
900
  }
859
901
 
902
+ /** Check project for Rizzo CSS: config, CSS file, optional link in layout. */
903
+ function cmdDoctor() {
904
+ const cwd = process.cwd();
905
+ const config = readRizzoConfig(cwd);
906
+ console.log('\nRizzo CSS doctor\n');
907
+ let ok = true;
908
+ if (!config) {
909
+ console.log(' ✗ No ' + RIZZO_CONFIG_FILE + '. Run: npx rizzo-css add or init');
910
+ ok = false;
911
+ } else {
912
+ console.log(' ✓ ' + RIZZO_CONFIG_FILE + ' (framework: ' + (config.framework || '?') + ')');
913
+ const fw = config.framework || 'vanilla';
914
+ const paths = getFrameworkCssPaths(fw);
915
+ const targetDir = (config.targetDir || paths.targetDir);
916
+ const cssPath = fw === 'astro' ? join(cwd, 'public', 'css', 'rizzo.min.css') : fw === 'svelte' ? join(cwd, 'static', 'css', 'rizzo.min.css') : join(cwd, targetDir, 'rizzo.min.css');
917
+ if (!existsSync(cssPath)) {
918
+ console.log(' ✗ CSS not found at ' + cssPath);
919
+ ok = false;
920
+ } else {
921
+ console.log(' ✓ CSS at ' + cssPath);
922
+ }
923
+ const layoutPaths = fw === 'svelte' ? ['src/app.html'] : fw === 'astro' ? ['src/layouts/Layout.astro', 'src/layouts/BaseLayout.astro'] : [];
924
+ for (const lp of layoutPaths) {
925
+ const full = join(cwd, lp);
926
+ if (existsSync(full)) {
927
+ const content = readFileSync(full, 'utf8');
928
+ if (!content.includes('rizzo') && !content.includes('rizzo.min.css')) {
929
+ console.log(' ? Layout ' + lp + ' may not include the stylesheet — add <link rel="stylesheet" href="' + (fw === 'svelte' ? '/css/rizzo.min.css' : '/css/rizzo.min.css') + '" />');
930
+ } else {
931
+ console.log(' ✓ Layout ' + lp + ' includes Rizzo link');
932
+ }
933
+ break;
934
+ }
935
+ }
936
+ }
937
+ if (config && config.theme) console.log(' Theme (from config): ' + config.theme);
938
+ console.log(ok ? '\nAll checks passed.\n' : '\nFix the items above, then run your dev server.\n');
939
+ }
940
+
860
941
  /** Prompt for default dark theme, default light theme, and initial theme. Returns { theme, defaultDark, defaultLight }. */
861
942
  async function promptThemes() {
862
943
  const defaultDark = await selectMenu(
@@ -974,6 +1055,10 @@ async function cmdAdd(argv) {
974
1055
  const explicitFramework = explicitFrameworkRaw && FRAMEWORKS.includes(explicitFrameworkRaw.toLowerCase()) ? explicitFrameworkRaw.toLowerCase() : null;
975
1056
  const installPackage = hasFlag(argv, '--install-package');
976
1057
  const noInstall = hasFlag(argv, '--no-install');
1058
+ const writeSnippet = !hasFlag(argv, '--no-snippet');
1059
+ const writeReadme = hasFlag(argv, '--readme');
1060
+ const force = hasFlag(argv, '--force');
1061
+ const copyVanillaJs = hasFlag(argv, '--vanilla-js');
977
1062
  const positionals = getPositionalArgs(argv);
978
1063
 
979
1064
  const cwd = process.cwd();
@@ -984,6 +1069,10 @@ async function cmdAdd(argv) {
984
1069
  targetDir: customPath || (config && config.targetDir) || undefined,
985
1070
  packageManager: pmOverride || undefined,
986
1071
  preselectedComponents: positionals.length > 0 ? positionals : undefined,
1072
+ writeSnippet,
1073
+ writeReadme,
1074
+ force,
1075
+ copyVanillaJs,
987
1076
  };
988
1077
  await runAddToExisting(explicitFramework, options);
989
1078
  if (installPackage && !noInstall) {
@@ -1320,17 +1409,37 @@ async function runAddToExisting(frameworkOverride, options) {
1320
1409
  const targetDirRaw = (options && options.targetDir) || (config && config.targetDir) || paths.targetDir;
1321
1410
  let cssTarget;
1322
1411
  if (framework === 'astro') {
1323
- copyRizzoCssAndFontsForAstro(cwd, cssSource);
1324
1412
  cssTarget = join(cwd, 'public', 'css', 'rizzo.min.css');
1325
1413
  } else if (framework === 'svelte') {
1326
- copyRizzoCssAndFontsForSvelte(cwd, cssSource);
1327
1414
  cssTarget = join(cwd, 'static', 'css', 'rizzo.min.css');
1328
1415
  } else {
1329
1416
  const targetDir = join(cwd, targetDirRaw);
1330
1417
  cssTarget = join(targetDir, 'rizzo.min.css');
1331
- mkdirSync(targetDir, { recursive: true });
1332
- copyFileSync(cssSource, cssTarget);
1333
- copyRizzoFonts(targetDir);
1418
+ }
1419
+ const cssExists = existsSync(cssTarget);
1420
+ if (cssExists && !options.force) {
1421
+ const answer = await question('\nCSS already exists at ' + cssTarget + '. Overwrite? (y/N) ');
1422
+ if (answer !== '' && !/^y(es)?$/i.test(answer)) {
1423
+ console.log('Skipping CSS copy. Updating config and components only.');
1424
+ } else {
1425
+ options._overwriteCss = true;
1426
+ }
1427
+ } else if (cssExists && options.force) {
1428
+ options._overwriteCss = true;
1429
+ } else {
1430
+ options._overwriteCss = true;
1431
+ }
1432
+ if (options._overwriteCss) {
1433
+ if (framework === 'astro') {
1434
+ copyRizzoCssAndFontsForAstro(cwd, cssSource);
1435
+ } else if (framework === 'svelte') {
1436
+ copyRizzoCssAndFontsForSvelte(cwd, cssSource);
1437
+ } else {
1438
+ const targetDir = join(cwd, targetDirRaw);
1439
+ mkdirSync(targetDir, { recursive: true });
1440
+ copyFileSync(cssSource, cssTarget);
1441
+ copyRizzoFonts(dirname(cssTarget));
1442
+ }
1334
1443
  }
1335
1444
 
1336
1445
  copyRizzoIcons(cwd, framework);
@@ -1346,6 +1455,20 @@ async function runAddToExisting(frameworkOverride, options) {
1346
1455
  const linkHrefForVanilla = (options && options.targetDir) ? getLinkHrefForTargetDir(framework, options.targetDir) : paths.linkHref;
1347
1456
  const vanillaRepl = { '{{LINK_HREF}}': linkHrefForVanilla, '{{DATA_THEME}}': theme };
1348
1457
  copyVanillaComponents(cwd, selectedComponents, vanillaRepl);
1458
+ const needsJs = selectedComponents.some((c) => VANILLA_JS_COMPONENTS.includes(c));
1459
+ const vanillaJsPath = join(cwd, 'js', 'main.js');
1460
+ if (needsJs && !existsSync(vanillaJsPath) && (options.copyVanillaJs || (!preselected && (await confirmCopyVanillaJs())))) {
1461
+ const vanillaJsSrc = join(getPackageRoot(), 'scaffold', 'vanilla', 'js', 'main.js');
1462
+ if (existsSync(vanillaJsSrc)) {
1463
+ mkdirSync(join(cwd, 'js'), { recursive: true });
1464
+ let mainJs = readFileSync(vanillaJsSrc, 'utf8');
1465
+ mainJs = mainJs.replace(/\{\{DEFAULT_DARK\}\}/g, defaultDark).replace(/\{\{DEFAULT_LIGHT\}\}/g, defaultLight);
1466
+ writeFileSync(vanillaJsPath, mainJs, 'utf8');
1467
+ console.log(' - Wrote js/main.js (for modal, dropdown, tabs, toast, theme switcher)');
1468
+ }
1469
+ } else if (needsJs && !existsSync(vanillaJsPath)) {
1470
+ options._vanillaJsHint = true;
1471
+ }
1349
1472
  }
1350
1473
 
1351
1474
  const linkHref = (framework === 'astro' || framework === 'svelte') ? paths.linkHref : ((options && options.targetDir) ? getLinkHrefForTargetDir(framework, options.targetDir) : paths.linkHref);
@@ -1357,38 +1480,56 @@ async function runAddToExisting(frameworkOverride, options) {
1357
1480
  : resolvePackageManager(cwd);
1358
1481
  const cliExample = pm.dlx('rizzo-css theme');
1359
1482
  const configTargetDir = framework === 'astro' ? 'public/css' : framework === 'svelte' ? 'static/css' : targetDirRaw;
1360
- writeRizzoConfig(cwd, { targetDir: configTargetDir, framework, packageManager: pm.agent });
1483
+ writeRizzoConfig(cwd, { targetDir: configTargetDir, framework, packageManager: pm.agent, theme });
1484
+ const writeSnippet = options.writeSnippet !== false;
1485
+ if (writeSnippet) {
1486
+ const where = framework === 'svelte' ? 'Root layout (e.g. src/app.html)' : framework === 'astro' ? 'Layout (e.g. src/layouts/Layout.astro)' : 'HTML or layout';
1487
+ const snippetBody = [
1488
+ 'Add to ' + where + ':',
1489
+ '',
1490
+ ' <link rel="stylesheet" href="' + linkHref + '" />',
1491
+ '',
1492
+ 'On <html>: data-theme="' + theme + '"',
1493
+ 'Themes: ' + cliExample,
1494
+ ].join('\n');
1495
+ writeFileSync(join(cwd, RIZZO_SNIPPET_FILE), snippetBody + '\n', 'utf8');
1496
+ }
1497
+ if (options.writeReadme) {
1498
+ const readmePath = join(getPackageRoot(), 'scaffold', 'vanilla', SCAFFOLD_README_FILENAME);
1499
+ if (existsSync(readmePath)) {
1500
+ copyFileSync(readmePath, join(cwd, SCAFFOLD_README_FILENAME));
1501
+ }
1502
+ }
1361
1503
  console.log('\n✓ Rizzo CSS added to your existing project');
1362
1504
  console.log(' - ' + cssTarget);
1363
1505
  console.log(' - Wrote ' + RIZZO_CONFIG_FILE);
1506
+ if (writeSnippet) console.log(' - Wrote ' + RIZZO_SNIPPET_FILE + ' (copy-paste link + theme)');
1507
+ if (options.writeReadme) console.log(' - Wrote ' + SCAFFOLD_README_FILENAME);
1364
1508
  console.log('\nYou must add the stylesheet link yourself — it is not added automatically.');
1365
- if (framework === 'svelte') {
1509
+ if (selectedComponents.length === 0) {
1510
+ console.log('\n <link rel="stylesheet" href="' + linkHref + '" />');
1511
+ console.log(' data-theme="' + theme + '" on <html> — list themes: ' + cliExample);
1512
+ } else if (framework === 'svelte') {
1366
1513
  console.log('\nIn your root layout (e.g. src/app.html), add:');
1367
1514
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
1368
- console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: ' + cliExample + ')');
1369
- console.log(' For theme "system": default dark ' + defaultDark + ', default light ' + defaultLight);
1370
- if (selectedComponents.length > 0) {
1371
- console.log(' Components are in src/lib/rizzo — import from \'$lib/rizzo\'.');
1372
- }
1515
+ console.log(' data-theme="' + theme + '" on <html> (themes: ' + cliExample + ')');
1516
+ console.log(' Components: src/lib/rizzo import from \'$lib/rizzo\'.');
1373
1517
  } else if (framework === 'astro') {
1374
1518
  console.log('\nIn your layout (e.g. src/layouts/Layout.astro), add:');
1375
1519
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
1376
- console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: ' + cliExample + ')');
1377
- console.log(' For theme "system": default dark ' + defaultDark + ', default light ' + defaultLight);
1378
- if (selectedComponents.length > 0) {
1379
- console.log(' Components are in src/components/rizzo — import from there.');
1380
- }
1520
+ console.log(' data-theme="' + theme + '" on <html> (themes: ' + cliExample + ')');
1521
+ console.log(' Components: src/components/rizzo import from there.');
1381
1522
  } else {
1382
1523
  console.log('\nIn your HTML or layout, add:');
1383
1524
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
1384
- console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: ' + cliExample + ')');
1385
- console.log(' For theme "system": default dark ' + defaultDark + ', default light ' + defaultLight);
1386
- if (selectedComponents.length > 0) {
1387
- console.log(' Component HTML files are in components/.');
1525
+ console.log(' data-theme="' + theme + '" on <html> (themes: ' + cliExample + ')');
1526
+ console.log(' Component HTML files are in components/.');
1527
+ if (options._vanillaJsHint) {
1528
+ console.log(' For interactive components (modal, dropdown, tabs, toast, theme switcher), add js/main.js — run again with --vanilla-js or copy from a Full scaffold.');
1388
1529
  }
1389
1530
  }
1390
- console.log('\nTo install the package (CLI + components): ' + pm.add('rizzo-css'));
1391
- console.log('\nDocs: https://rizzo-css.vercel.app\n');
1531
+ console.log('\nTo install the package: ' + pm.add('rizzo-css'));
1532
+ console.log('\nNext: add the link above, then run your dev server. Docs: https://rizzo-css.vercel.app\n');
1392
1533
  }
1393
1534
 
1394
1535
  async function cmdInit(argv) {
@@ -1412,7 +1553,8 @@ async function cmdInit(argv) {
1412
1553
  framework = (frameworkArg && FRAMEWORKS.includes(frameworkArg.toLowerCase())) ? frameworkArg.toLowerCase() : (config && config.framework) || 'astro';
1413
1554
  initMode = 'new';
1414
1555
  const templateArg = getFlagValue(argv, '--template');
1415
- selectedTemplate = (templateArg && (templateArg === 'full' || templateArg === 'minimal' || templateArg === 'manual')) ? templateArg : 'full';
1556
+ const defaultTemplate = framework === 'vanilla' ? 'minimal' : 'full';
1557
+ selectedTemplate = (templateArg && (templateArg === 'full' || templateArg === 'minimal' || templateArg === 'manual')) ? templateArg : defaultTemplate;
1416
1558
  if (selectedTemplate === 'full' && (framework === 'astro' || framework === 'svelte')) {
1417
1559
  selectedComponents = framework === 'svelte' ? [...SVELTE_COMPONENTS] : [...ASTRO_COMPONENTS];
1418
1560
  } else if (selectedTemplate === 'minimal' && (framework === 'astro' || framework === 'svelte')) {
@@ -1489,6 +1631,13 @@ async function cmdInit(argv) {
1489
1631
  }
1490
1632
 
1491
1633
  const projectDir = name ? join(cwd, name) : cwd;
1634
+ if (projectDir === cwd && isDirNonEmpty(cwd) && !yes) {
1635
+ const ok = await confirmNonEmptyDir(projectDir);
1636
+ if (!ok) {
1637
+ console.log('Aborted.');
1638
+ return;
1639
+ }
1640
+ }
1492
1641
  const cssSource = getCssPath();
1493
1642
 
1494
1643
  if (!existsSync(cssSource)) {
@@ -1742,7 +1891,7 @@ async function cmdInit(argv) {
1742
1891
 
1743
1892
  // Always write rizzo-css.json for new projects (targetDir, framework, packageManager).
1744
1893
  const pathsForConfig = getFrameworkCssPaths(framework);
1745
- writeRizzoConfig(projectDir, { targetDir: pathsForConfig.targetDir, framework, packageManager: selectedPm });
1894
+ writeRizzoConfig(projectDir, { targetDir: pathsForConfig.targetDir, framework, packageManager: selectedPm, theme });
1746
1895
  console.log(' - Wrote ' + RIZZO_CONFIG_FILE);
1747
1896
 
1748
1897
  if (runInstallAfterScaffold && !noInstall && hasPackageJson) {
@@ -1779,6 +1928,8 @@ async function cmdInit(argv) {
1779
1928
  const createExample = getCreateProjectExample(pm, framework);
1780
1929
  console.log('\n - Minimal template (CSS + index). To get a full app: ' + createExample + ', then cd into the project and run ' + pm.dlx('rizzo-css add') + '.');
1781
1930
  }
1931
+ if (hasPackageJson) console.log('\nNext: ' + runPrefix + nextStep);
1932
+ else if (framework === 'vanilla') console.log('\nNext: open index.html or serve the folder.');
1782
1933
  console.log('\nDocs: https://rizzo-css.vercel.app\n');
1783
1934
  }
1784
1935
 
@@ -1803,6 +1954,11 @@ function main() {
1803
1954
  return;
1804
1955
  }
1805
1956
 
1957
+ if (command === 'doctor') {
1958
+ cmdDoctor();
1959
+ return;
1960
+ }
1961
+
1806
1962
  if (command === 'add') {
1807
1963
  cmdAdd(argv).catch((err) => {
1808
1964
  console.error(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rizzo-css",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "scripts": {
5
5
  "prepublishOnly": "cd ../.. && pnpm run lint:css:fix && pnpm run build:css && node scripts/copy-scaffold.js && node scripts/prepare-vanilla-scaffold.js"
6
6
  },
@@ -0,0 +1,24 @@
1
+ # Astro default .gitignore (same as npm create astro@latest)
2
+ # build output
3
+ dist/
4
+ # generated types
5
+ .astro/
6
+
7
+ # dependencies
8
+ node_modules/
9
+
10
+ # logs
11
+ npm-debug.log*
12
+ yarn-debug.log*
13
+ yarn-error.log*
14
+ pnpm-debug.log*
15
+
16
+ # environment variables
17
+ .env
18
+ .env.production
19
+
20
+ # macOS-specific files
21
+ .DS_Store
22
+
23
+ # jetbrains setting folder
24
+ .idea/
@@ -0,0 +1,10 @@
1
+ node_modules
2
+ .output
3
+ .vercel
4
+ .netlify
5
+ /.svelte-kit
6
+ /build
7
+ .DS_Store
8
+ .env
9
+ .env.*
10
+ !.env.example
@@ -13,7 +13,7 @@ If you prefer to load CSS from a CDN instead of the local file, replace the `<li
13
13
  - `<link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css" />`
14
14
  - Or jsDelivr: `https://cdn.jsdelivr.net/npm/rizzo-css@latest/dist/rizzo.min.css`
15
15
 
16
- (Replace `@latest` with a specific version, e.g. `@0.0.27`, in production.)
16
+ (Replace `@latest` with a specific version, e.g. `@0.0.28`, in production.)
17
17
 
18
18
  The CLI replaces placeholders in `index.html` (e.g. `{{DATA_THEME}}`, `{{TITLE}}`) when you run `rizzo-css init`. The theme selected during init is used on first load when you have no saved preference in the browser.
19
19
 
@@ -0,0 +1,27 @@
1
+ # Vanilla / static site default .gitignore (Rizzo CSS scaffold)
2
+
3
+ # OS files
4
+ .DS_Store
5
+ Thumbs.db
6
+
7
+ # Editor / IDE
8
+ .idea/
9
+ .vscode/
10
+ *.swp
11
+ *.swo
12
+ *~
13
+
14
+ # Environment
15
+ .env
16
+ .env.*
17
+ !.env.example
18
+
19
+ # Logs
20
+ *.log
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
24
+ pnpm-debug.log*
25
+
26
+ # Optional: if you add Node/npm later
27
+ node_modules/