@shortwind/cli 0.1.0-beta.12 → 0.1.0-beta.13

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.
@@ -436,6 +436,34 @@ async function scaffoldTheme(cwd) {
436
436
  };
437
437
  }
438
438
  const THEME_COLOR_TOKENS = new Set([...THEME_BLOCK.matchAll(/--color-([\w-]+)\s*:/g)].map((m) => m[1] ?? ""));
439
+ const THEME_SUPPLEMENT_MARKER = "/* shortwind:theme-supplement";
440
+ function blockSectionValues(selector) {
441
+ const m = THEME_BLOCK.match(new RegExp(`${selector.replace(".", "\\.")}\\s*\\{([^}]*)\\}`));
442
+ const out = /* @__PURE__ */ new Map();
443
+ for (const decl of (m?.[1] ?? "").matchAll(/--([\w-]+)\s*:\s*([^;]+);/g)) out.set(decl[1], decl[2].trim());
444
+ return out;
445
+ }
446
+ const THEME_LIGHT_VALUES = blockSectionValues(":root");
447
+ const THEME_DARK_VALUES = blockSectionValues(".dark");
448
+ function buildThemeSupplement(css, missing) {
449
+ const tokens = missing.filter((t) => THEME_LIGHT_VALUES.has(t));
450
+ if (tokens.length === 0) return null;
451
+ const light = tokens.map((t) => ` --${t}: ${THEME_LIGHT_VALUES.get(t)};`);
452
+ const dark = tokens.filter((t) => THEME_DARK_VALUES.has(t)).map((t) => ` --${t}: ${THEME_DARK_VALUES.get(t)};`);
453
+ const mapping = tokens.map((t) => ` --color-${t}: var(--${t});`);
454
+ const lines = [
455
+ `${THEME_SUPPLEMENT_MARKER} — placeholder values for tokens your theme didn't define. Tune them to your palette. */`,
456
+ ":root {",
457
+ ...light,
458
+ "}"
459
+ ];
460
+ if (dark.length > 0) {
461
+ if (/@custom-variant\s+dark|\.dark\s*\{/.test(css)) lines.push(".dark {", ...dark, "}");
462
+ else if (/@media\s*\(\s*prefers-color-scheme\s*:\s*dark\s*\)/.test(css)) lines.push("@media (prefers-color-scheme: dark) {", " :root {", ...dark.map((l) => ` ${l}`), " }", "}");
463
+ }
464
+ lines.push("@theme inline {", ...mapping, "}", "/* end shortwind theme-supplement */");
465
+ return lines.join("\n");
466
+ }
439
467
  const COLOR_UTILITY_RE = /^(?:bg|text|border|ring|outline|fill|stroke|divide|accent|caret|decoration|shadow|from|via|to|placeholder)-(.+)$/;
440
468
  function referencedThemeTokens(flattened) {
441
469
  const out = /* @__PURE__ */ new Set();
@@ -618,8 +646,20 @@ async function init(options) {
618
646
  const skillPath = path.join(cwd, "skills", "shortwind", "SKILL.md");
619
647
  const skillRegistry = await writeSkillMd(skillPath, recipesDir, families, shape.bundler);
620
648
  const theme = await scaffoldTheme(cwd);
649
+ let themeAction = theme.action;
621
650
  let missingThemeTokens = [];
622
- if (theme.action === "skipped" && theme.themePath && skillRegistry) missingThemeTokens = findMissingThemeTokens(await readFile(theme.themePath, "utf8"), skillRegistry.flattened);
651
+ let supplementedThemeTokens = [];
652
+ if (theme.action === "skipped" && theme.themePath && skillRegistry) {
653
+ const css = await readFile(theme.themePath, "utf8");
654
+ missingThemeTokens = findMissingThemeTokens(css, skillRegistry.flattened);
655
+ const supplement = buildThemeSupplement(css, missingThemeTokens);
656
+ if (supplement) {
657
+ await writeFile(theme.themePath, `${css.replace(/\s*$/, "")}\n\n${supplement}\n`);
658
+ supplementedThemeTokens = missingThemeTokens;
659
+ missingThemeTokens = [];
660
+ themeAction = "supplemented";
661
+ }
662
+ }
623
663
  const safelistCssPaths = [];
624
664
  if (shape.bundler !== "vite" && shape.bundler !== "astro" && skillRegistry) for (const file of findTailwindEntryCssFiles(cwd)) {
625
665
  syncSourceDirectiveToFile(file, skillRegistry);
@@ -629,6 +669,7 @@ async function init(options) {
629
669
  const agentsFile = await wireAgentsInstructions(cwd, skillPath);
630
670
  return {
631
671
  packageManager: shape.packageManager,
672
+ bundler: shape.bundler,
632
673
  preset: options.preset,
633
674
  registry,
634
675
  families,
@@ -640,7 +681,8 @@ async function init(options) {
640
681
  huskyPath,
641
682
  skillPath,
642
683
  themePath: theme.themePath,
643
- themeAction: theme.action,
684
+ themeAction,
685
+ supplementedThemeTokens,
644
686
  safelistCssPaths,
645
687
  missingThemeTokens,
646
688
  bundlerConfigPath: bundlerConfig.configPath,
@@ -852,11 +894,16 @@ async function readConfig(cwd) {
852
894
  ...DEFAULT_CONFIG,
853
895
  ...parsed
854
896
  };
855
- return {
897
+ const config = {
856
898
  registry: assertConfigString(merged.registry, "registry", configPath),
857
899
  recipesDir: assertWithinCwd(cwd, assertConfigString(merged.recipesDir, "recipesDir", configPath), "recipesDir", configPath),
858
900
  outputPath: assertWithinCwd(cwd, assertConfigString(merged.outputPath, "outputPath", configPath), "outputPath", configPath)
859
901
  };
902
+ if (merged.content !== void 0) {
903
+ if (!Array.isArray(merged.content) || merged.content.some((g) => typeof g !== "string")) throw new Error(`${configPath}: "content" must be an array of glob strings`);
904
+ config.content = merged.content;
905
+ }
906
+ return config;
860
907
  }
861
908
  function installedFamilies(recipesDir) {
862
909
  if (!existsSync(recipesDir)) return [];
@@ -1752,7 +1799,7 @@ const ALL_RULES = [
1752
1799
  "recipe/no-sibling-overlap",
1753
1800
  "recipe/reserved-name"
1754
1801
  ];
1755
- const DEFAULT_CONTENT = ["src/**/*.{html,js,jsx,ts,tsx,vue,svelte,astro,md,mdx}"];
1802
+ const DEFAULT_CONTENT = ["{src,app,pages,components,lib}/**/*.{html,js,jsx,ts,tsx,vue,svelte,astro,md,mdx}"];
1756
1803
  async function lint(options) {
1757
1804
  const cwd = path.resolve(options.cwd);
1758
1805
  const config = await readConfig(cwd);
@@ -1763,7 +1810,7 @@ async function lint(options) {
1763
1810
  findings.push(...parseFindings);
1764
1811
  findings.push(...checkRecipeNames(registry, recipesDir, enabledRules));
1765
1812
  findings.push(...checkReservedNames(registry, recipesDir, enabledRules));
1766
- const files = await glob(options.content ?? DEFAULT_CONTENT, {
1813
+ const files = await glob(options.content ?? config.content ?? DEFAULT_CONTENT, {
1767
1814
  cwd,
1768
1815
  absolute: true,
1769
1816
  onlyFiles: true,
@@ -1807,7 +1854,7 @@ async function lint(options) {
1807
1854
  }
1808
1855
  }
1809
1856
  }
1810
- if (enabledRules.has("recipe/unused")) {
1857
+ if (enabledRules.has("recipe/unused") && files.length > 0) {
1811
1858
  const recipesByName = /* @__PURE__ */ new Map();
1812
1859
  for (const recs of Object.values(registry.families)) for (const r of recs) recipesByName.set(r.name, r);
1813
1860
  for (const name of Object.keys(registry.flattened)) {
@@ -1832,7 +1879,8 @@ async function lint(options) {
1832
1879
  return {
1833
1880
  ok: !findings.some((f) => f.severity === "error"),
1834
1881
  findings,
1835
- filesFixed
1882
+ filesFixed,
1883
+ scannedFiles: files.length
1836
1884
  };
1837
1885
  }
1838
1886
  function loadRegistry(recipesDir, rules) {
@@ -2445,6 +2493,6 @@ function formatBenchTable(result) {
2445
2493
  return lines.join("\n");
2446
2494
  }
2447
2495
  //#endregion
2448
- export { buildHeaderLine as A, cliVersion as C, createRegistrySource as D, writeLockfile as E, verifyFetchedFamily as F, extractHeader as M, rewriteHeaderSha as N, resolvePresetFamilies as O, sealRecipeFile as P, DEFAULT_REGISTRY as S, readLockfile as T, NewFamilyError as _, formatFindingsText as a, add as b, UpgradeError as c, BuildError as d, build as f, reseal as g, preset as h, extractClassUsages as i, computeBodySha as j, detectProject as k, upgrade as l, ls as m, formatBenchTable as n, lint as o, formatLsText as p, ALL_RULES as r, verify as s, bench as t, dev as u, newFamily as v, init as w, renameFamilyInSource as x, remove as y };
2496
+ export { createRegistrySource as A, readConfig as C, init as D, cliVersion as E, extractHeader as F, rewriteHeaderSha as I, sealRecipeFile as L, detectProject as M, buildHeaderLine as N, readLockfile as O, computeBodySha as P, verifyFetchedFamily as R, installedFamilies as S, DEFAULT_REGISTRY as T, reseal as _, extractClassUsages as a, remove as b, verify as c, dev as d, BuildError as f, preset as g, ls as h, DEFAULT_CONTENT as i, resolvePresetFamilies as j, writeLockfile as k, UpgradeError as l, formatLsText as m, formatBenchTable as n, formatFindingsText as o, build as p, ALL_RULES as r, lint as s, bench as t, upgrade as u, NewFamilyError as v, renameFamilyInSource as w, add as x, newFamily as y };
2449
2497
 
2450
- //# sourceMappingURL=bench-BGO3pupw.js.map
2498
+ //# sourceMappingURL=bench-B7SxNGiU.js.map