digdesign 0.3.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +520 -83
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20,6 +20,8 @@ function defaultConfig() {
20
20
  tsx: true,
21
21
  tailwind: {
22
22
  css: "src/app/globals.css",
23
+ theme: "src/app/dig-theme.css",
24
+ brand: "src/app/brand.css",
23
25
  baseColor: "neutral",
24
26
  cssVariables: true
25
27
  },
@@ -273,15 +275,23 @@ async function fetchFromRegistry(url, subject) {
273
275
  }
274
276
  throw new DigError(`\u062F\u0631\u06CC\u0627\u0641\u062A ${subject} \u0646\u0627\u0645\u0648\u0641\u0642 \u0628\u0648\u062F (${response.status}): ${url}`);
275
277
  }
278
+ function normalizeType(type) {
279
+ return type.startsWith("registry:") ? `dig:${type.slice("registry:".length)}` : type;
280
+ }
276
281
  async function fetchRegistryIndex(registryUrl) {
277
282
  const url = `${registryUrl}/r/registry.json`;
278
283
  const response = await fetchFromRegistry(url, "\u0641\u0647\u0631\u0633\u062A\u0650 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC");
279
- return await response.json();
284
+ const index = await response.json();
285
+ for (const item of index.items) item.type = normalizeType(item.type);
286
+ return index;
280
287
  }
281
288
  async function fetchRegistryItem(nameOrUrl, registryUrl) {
282
289
  const url = resolveUrl(nameOrUrl, registryUrl);
283
290
  const response = await fetchFromRegistry(url, `\xAB${nameOrUrl}\xBB`);
284
- return await response.json();
291
+ const item = await response.json();
292
+ item.type = normalizeType(item.type);
293
+ for (const file of item.files ?? []) file.type = normalizeType(file.type);
294
+ return item;
285
295
  }
286
296
  async function resolveRegistryTree(names, registryUrl) {
287
297
  const resolved = /* @__PURE__ */ new Map();
@@ -369,9 +379,12 @@ import path5 from "path";
369
379
  function toPosixPath(relativePath) {
370
380
  return relativePath.split(path5.sep).join("/");
371
381
  }
382
+ function targetPathOptions(config) {
383
+ return { tailwindCss: config.tailwind.css, themeCss: config.tailwind.theme };
384
+ }
372
385
  function resolveTargetPath(filePath, aliases, options = {}) {
373
386
  if (/(?:^|\/)app\/globals\.css$/.test(filePath)) {
374
- return options.tailwindCss ?? "src/app/globals.css";
387
+ return options.themeCss ?? options.tailwindCss ?? "src/app/globals.css";
375
388
  }
376
389
  const match = filePath.match(/(?:^|\/)(components|lib|hooks)\/(.*)$/);
377
390
  const cleaned = match ? `${match[1]}/${match[2]}` : filePath;
@@ -406,7 +419,7 @@ async function pickComponents(registryUrl) {
406
419
  );
407
420
  }
408
421
  const index = await fetchRegistryIndex(registryUrl);
409
- const choices = index.items.filter((item) => item.type === "registry:ui").map((item) => ({
422
+ const choices = index.items.filter((item) => item.type === "dig:ui").map((item) => ({
410
423
  value: item.name,
411
424
  label: item.title ? `${item.name} \u2014 ${item.title}` : item.name
412
425
  }));
@@ -435,9 +448,7 @@ async function addCommand(components, options) {
435
448
  const existing = [];
436
449
  for (const item of items.values()) {
437
450
  for (const file of item.files) {
438
- const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, {
439
- tailwindCss: config.tailwind.css
440
- }));
451
+ const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, targetPathOptions(config)));
441
452
  if (await pathExists(target)) existing.push(path6.relative(cwd, target));
442
453
  }
443
454
  }
@@ -459,12 +470,10 @@ ${existing.length} \u0641\u0627\u06CC\u0644 \u0627\u0632 \u0642\u0628\u0644 \u06
459
470
  for (const item of items.values()) {
460
471
  for (const dep of item.dependencies ?? []) npmDeps.add(dep);
461
472
  for (const file of item.files) {
462
- const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, {
463
- tailwindCss: config.tailwind.css
464
- }));
465
- const exists = await pathExists(target);
466
- const mark = exists ? overwrite ? "~" : "-" : "+";
467
- const note = exists ? overwrite ? " (\u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC)" : " (\u0631\u062F \u0645\u06CC\u200C\u0634\u0648\u062F\u060C \u0648\u062C\u0648\u062F \u062F\u0627\u0631\u062F)" : "";
473
+ const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, targetPathOptions(config)));
474
+ const exists2 = await pathExists(target);
475
+ const mark = exists2 ? overwrite ? "~" : "-" : "+";
476
+ const note = exists2 ? overwrite ? " (\u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC)" : " (\u0631\u062F \u0645\u06CC\u200C\u0634\u0648\u062F\u060C \u0648\u062C\u0648\u062F \u062F\u0627\u0631\u062F)" : "";
468
477
  console.log(`${mark} ${path6.relative(cwd, target)}${note}`);
469
478
  }
470
479
  }
@@ -488,9 +497,7 @@ ${items.size} \u0622\u06CC\u062A\u0645 \u0627\u0632 \u0631\u062C\u06CC\u0633\u06
488
497
  const writtenFiles = {};
489
498
  const writtenContents = {};
490
499
  for (const file of item.files) {
491
- const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, {
492
- tailwindCss: config.tailwind.css
493
- }));
500
+ const target = path6.join(cwd, resolveTargetPath(file.path, config.aliases, targetPathOptions(config)));
494
501
  if (!overwrite && await pathExists(target)) {
495
502
  console.log(`- \u0631\u062F \u0634\u062F (\u0648\u062C\u0648\u062F \u062F\u0627\u0631\u062F): ${path6.relative(cwd, target)}`);
496
503
  skipped++;
@@ -589,9 +596,9 @@ function searchItems(items, query) {
589
596
 
590
597
  // src/commands/list.ts
591
598
  var TYPE_LABEL = {
592
- "registry:ui": "\u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A",
593
- "registry:lib": "\u0627\u0628\u0632\u0627\u0631",
594
- "registry:theme": "\u062A\u0645"
599
+ "dig:ui": "\u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A",
600
+ "dig:lib": "\u0627\u0628\u0632\u0627\u0631",
601
+ "dig:theme": "\u062A\u0645"
595
602
  };
596
603
  async function loadItems(cwd) {
597
604
  const config = await configExists(cwd) ? await readConfig(cwd) : defaultConfig();
@@ -600,7 +607,7 @@ async function loadItems(cwd) {
600
607
  }
601
608
  function matchesType(item, type) {
602
609
  if (!type) return true;
603
- const wanted = type.startsWith("registry:") ? type : `registry:${type}`;
610
+ const wanted = type.startsWith("dig:") ? type : `dig:${type}`;
604
611
  return item.type === wanted;
605
612
  }
606
613
  function printTable(items) {
@@ -685,8 +692,8 @@ async function readLocalHash(target) {
685
692
  throw error;
686
693
  }
687
694
  }
688
- async function computeFileDrift(cwd, aliases, lockEntry, file) {
689
- const target = path7.join(cwd, resolveTargetPath(file.path, aliases));
695
+ async function computeFileDrift(cwd, aliases, lockEntry, file, paths) {
696
+ const target = path7.join(cwd, resolveTargetPath(file.path, aliases, paths));
690
697
  const relPath = toPosixPath(path7.relative(cwd, target));
691
698
  const registryHash = file.hash ?? hashContent(file.content);
692
699
  const installedHash = lockEntry?.files[relPath];
@@ -700,9 +707,9 @@ async function computeFileDrift(cwd, aliases, lockEntry, file) {
700
707
  };
701
708
  }
702
709
  async function computeComponentDrift(params) {
703
- const { cwd, aliases, registryUrl, lockEntry, registryItem } = params;
710
+ const { cwd, aliases, registryUrl, lockEntry, registryItem, paths } = params;
704
711
  const files = await Promise.all(
705
- registryItem.files.map((file) => computeFileDrift(cwd, aliases, lockEntry, file))
712
+ registryItem.files.map((file) => computeFileDrift(cwd, aliases, lockEntry, file, paths))
706
713
  );
707
714
  return {
708
715
  name: registryItem.name,
@@ -850,7 +857,7 @@ function describeThreeWayConflict(baseContent, localContent, registryContent) {
850
857
  return `\u0646\u0633\u0628\u062A \u0628\u0647 \u0646\u0633\u062E\u0647\u0654 \u0646\u0635\u0628\u200C\u0634\u062F\u0647 (\u067E\u0627\u06CC\u0647): \u0634\u0645\u0627 ${local.added + local.removed} \u062E\u0637 \u062A\u063A\u06CC\u06CC\u0631 \u062F\u0627\u062F\u0647\u200C\u0627\u06CC\u062F (+${local.added}/-${local.removed})\u060C \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC ${registry.added + registry.removed} \u062E\u0637 \u062A\u063A\u06CC\u06CC\u0631 \u062F\u0627\u062F\u0647 (+${registry.added}/-${registry.removed}). \u062F\u06CC\u06AF \u062E\u0648\u062F\u06A9\u0627\u0631 \u0627\u062F\u063A\u0627\u0645 \u0646\u0645\u06CC\u200C\u06A9\u0646\u062F \u2014 \u062F\u0648 \u062F\u06CC\u0641\u0650 \u0628\u0627\u0644\u0627 \u0631\u0627 \u062F\u0633\u062A\u06CC \u0628\u0631\u0631\u0633\u06CC \u06A9\u0646\u06CC\u062F.`;
851
858
  }
852
859
  async function computeFileDiffDetails(params) {
853
- const { cwd, aliases, name, snapshotVersion, file, registryFile } = params;
860
+ const { cwd, aliases, name, snapshotVersion, file, registryFile, paths } = params;
854
861
  if (file.status === "up_to_date") return void 0;
855
862
  if (file.status === "new_upstream") {
856
863
  return {
@@ -866,7 +873,7 @@ async function computeFileDiffDetails(params) {
866
873
  note: file.registryHash === file.installedHash ? "\u0641\u0627\u06CC\u0644 \u0628\u0647\u200C\u0635\u0648\u0631\u062A \u0645\u062D\u0644\u06CC \u062D\u0630\u0641 \u0634\u062F\u0647\u061B \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u0627\u0632 \u0632\u0645\u0627\u0646 \u0646\u0635\u0628 \u062A\u063A\u06CC\u06CC\u0631\u06CC \u0646\u06A9\u0631\u062F\u0647." : "\u0641\u0627\u06CC\u0644 \u0628\u0647\u200C\u0635\u0648\u0631\u062A \u0645\u062D\u0644\u06CC \u062D\u0630\u0641 \u0634\u062F\u0647 \u0648 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u0647\u0645 \u062A\u063A\u06CC\u06CC\u0631 \u06A9\u0631\u062F\u0647 \u2014 \u0645\u0642\u0627\u06CC\u0633\u0647\u200C\u0627\u06CC \u0628\u0627 \u0641\u0627\u06CC\u0644 \u062D\u0630\u0641\u200C\u0634\u062F\u0647 \u0645\u0645\u06A9\u0646 \u0646\u06CC\u0633\u062A."
867
874
  };
868
875
  }
869
- const target = path8.join(cwd, resolveTargetPath(registryFile.path, aliases));
876
+ const target = path8.join(cwd, resolveTargetPath(registryFile.path, aliases, paths));
870
877
  const localContent = await readTextFileSafely(target);
871
878
  if (localContent === "binary") {
872
879
  return {
@@ -961,6 +968,7 @@ async function diffCommand(components, options) {
961
968
  const drift = await computeComponentDrift({
962
969
  cwd,
963
970
  aliases: config.aliases,
971
+ paths: targetPathOptions(config),
964
972
  registryUrl: config.registryUrl,
965
973
  lockEntry,
966
974
  registryItem
@@ -972,6 +980,7 @@ async function diffCommand(components, options) {
972
980
  (file, index) => file.status === "up_to_date" ? Promise.resolve(void 0) : computeFileDiffDetails({
973
981
  cwd,
974
982
  aliases: config.aliases,
983
+ paths: targetPathOptions(config),
975
984
  name,
976
985
  snapshotVersion: lockEntry?.snapshot?.version,
977
986
  file,
@@ -1655,7 +1664,7 @@ async function generateIntelligenceExport(params) {
1655
1664
  } catch {
1656
1665
  continue;
1657
1666
  }
1658
- if (item.type !== "registry:ui") continue;
1667
+ if (item.type !== "dig:ui") continue;
1659
1668
  const scan = await scanRepositoryForComponent({ projectRoot: cwd, component: name });
1660
1669
  installedComponents.push({
1661
1670
  name,
@@ -1874,7 +1883,7 @@ async function healthCommand(options) {
1874
1883
  } catch {
1875
1884
  continue;
1876
1885
  }
1877
- if (item.type !== "registry:ui") continue;
1886
+ if (item.type !== "dig:ui") continue;
1878
1887
  const scan = await scanRepositoryForComponent({ projectRoot: cwd, component: name });
1879
1888
  installedComponents.push({
1880
1889
  name,
@@ -1948,8 +1957,272 @@ async function impactCommand(name, options) {
1948
1957
  }
1949
1958
 
1950
1959
  // src/commands/init.ts
1951
- import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
1960
+ import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
1961
+ import path12 from "path";
1962
+
1963
+ // src/commands/theme.ts
1964
+ import { access as access5, mkdir as mkdir4, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
1965
+ import path11 from "path";
1966
+
1967
+ // src/lib/brand-ramp.ts
1968
+ var RAMP_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
1969
+ var REFERENCE_L = {
1970
+ 50: 96.6,
1971
+ 100: 93.1,
1972
+ 200: 87.6,
1973
+ 300: 79.7,
1974
+ 400: 69,
1975
+ 500: 60.4,
1976
+ 600: 52.9,
1977
+ 700: 47.3,
1978
+ 800: 41.1,
1979
+ 900: 36.9,
1980
+ 950: 26.9
1981
+ };
1982
+ var CHROMA_SHAPE = {
1983
+ 50: 0.07,
1984
+ 100: 0.13,
1985
+ 200: 0.25,
1986
+ 300: 0.44,
1987
+ 400: 0.69,
1988
+ 500: 0.89,
1989
+ 600: 1,
1990
+ 700: 0.92,
1991
+ 800: 0.74,
1992
+ 900: 0.55,
1993
+ 950: 0.34
1994
+ };
1995
+ function parseHex(hex) {
1996
+ const clean = hex.trim().replace(/^#/, "");
1997
+ const full = clean.length === 3 ? [...clean].map((ch) => ch + ch).join("") : clean;
1998
+ if (!/^[0-9a-fA-F]{6}$/.test(full)) {
1999
+ throw new DigError(`\xAB${hex}\xBB \u0631\u0646\u06AF\u0650 \u0647\u06AF\u0632\u0650 \u0645\u0639\u062A\u0628\u0631 \u0646\u06CC\u0633\u062A\u061B \u0645\u062B\u0644\u0627\u064B #2C4C5B \u0628\u062F\u0647\u06CC\u062F.`);
2000
+ }
2001
+ return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16) / 255);
2002
+ }
2003
+ var toLinear = (v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
2004
+ var fromLinear = (v) => v <= 31308e-7 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055;
2005
+ function hexToOklch(hex) {
2006
+ const [r, g, b] = parseHex(hex).map(toLinear);
2007
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
2008
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
2009
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
2010
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
2011
+ const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
2012
+ const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
2013
+ const c = Math.sqrt(A * A + B * B);
2014
+ const h = (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
2015
+ return { l: L * 100, c, h };
2016
+ }
2017
+ function oklchToSrgb({ l, c, h }) {
2018
+ const L = l / 100;
2019
+ const rad = h * Math.PI / 180;
2020
+ const A = c * Math.cos(rad);
2021
+ const B = c * Math.sin(rad);
2022
+ const l_ = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3;
2023
+ const m_ = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3;
2024
+ const s_ = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;
2025
+ return [
2026
+ fromLinear(4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_),
2027
+ fromLinear(-1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_),
2028
+ fromLinear(-0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_)
2029
+ ];
2030
+ }
2031
+ var inGamut = (rgb) => rgb.every((v) => v >= -5e-4 && v <= 1.0005);
2032
+ function fitGamut(color) {
2033
+ let { c } = color;
2034
+ while (c > 0 && !inGamut(oklchToSrgb({ ...color, c }))) c -= 2e-3;
2035
+ return { ...color, c: Math.max(0, c) };
2036
+ }
2037
+ function relativeLuminance(rgb) {
2038
+ const [r, g, b] = rgb.map((v) => toLinear(Math.min(1, Math.max(0, v))));
2039
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
2040
+ }
2041
+ function contrastWithWhite(color) {
2042
+ return 1.05 / (relativeLuminance(oklchToSrgb(color)) + 0.05);
2043
+ }
2044
+ function formatOklch({ l, c, h }) {
2045
+ return `oklch(${l.toFixed(1)}% ${c.toFixed(3)} ${h.toFixed(1)})`;
2046
+ }
2047
+ function buildBrandRamp(hex) {
2048
+ const base = hexToOklch(hex);
2049
+ const top = 97.5;
2050
+ const bottom = Math.min(26, Math.max(8, base.l * 0.55));
2051
+ const ref600 = REFERENCE_L[600];
2052
+ const steps = {};
2053
+ for (const step of RAMP_STEPS) {
2054
+ if (step === 600) {
2055
+ steps[step] = base;
2056
+ continue;
2057
+ }
2058
+ const ref = REFERENCE_L[step];
2059
+ const l = ref > ref600 ? base.l + (ref - ref600) / (REFERENCE_L[50] - ref600) * (top - base.l) : base.l - (ref600 - ref) / (ref600 - REFERENCE_L[950]) * (base.l - bottom);
2060
+ steps[step] = fitGamut({ l, c: base.c * CHROMA_SHAPE[step], h: base.h });
2061
+ }
2062
+ return { steps, primaryContrast: contrastWithWhite(base) };
2063
+ }
2064
+
2065
+ // src/lib/theme-files.ts
1952
2066
  import path10 from "path";
2067
+ function importPath(fromFile, toFile) {
2068
+ const rel = toPosixPath(path10.relative(path10.dirname(fromFile), toFile));
2069
+ return rel.startsWith(".") ? rel : `./${rel}`;
2070
+ }
2071
+ function globalsCss(paths, extraStatements = []) {
2072
+ const lines = [
2073
+ "/* \u0641\u0642\u0637 import. \u062A\u0645 \u062F\u0631 dig-theme.css (\u0645\u0627\u0644\u0650 \u062F\u06CC\u06AF) \u0648 \u0628\u0631\u0646\u062F \u062F\u0631 brand.css (\u0645\u0627\u0644\u0650",
2074
+ " \u067E\u0631\u0648\u0698\u0647) \u0627\u0633\u062A\u061B \u062A\u0631\u062A\u06CC\u0628 \u0645\u0647\u0645 \u0627\u0633\u062A: \u0628\u0631\u0646\u062F \u0628\u0639\u062F \u0627\u0632 \u062A\u0645 \u0645\u06CC\u200C\u0622\u06CC\u062F \u062A\u0627 \u0628\u0631\u0646\u062F\u0647 \u0628\u0627\u0634\u062F. */",
2075
+ `@import "${importPath(paths.css, paths.theme)}";`,
2076
+ ...extraStatements,
2077
+ `@import "${importPath(paths.css, paths.brand)}";`,
2078
+ ""
2079
+ ];
2080
+ return lines.join("\n");
2081
+ }
2082
+ var BRAND_HEADER = `/* ==================================================================== *
2083
+ * \u0628\u0631\u0646\u062F\u0650 \u067E\u0631\u0648\u0698\u0647
2084
+ *
2085
+ * \u0627\u06CC\u0646 \u0641\u0627\u06CC\u0644 \u0645\u0627\u0644\u0650 \u067E\u0631\u0648\u0698\u0647 \u0627\u0633\u062A \u0648 \u062F\u06CC\u06AF \u0647\u06CC\u0686\u200C\u0648\u0642\u062A \u0622\u0646 \u0631\u0627 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u0646\u0645\u06CC\u200C\u06A9\u0646\u062F\u061B \u062A\u0645\u0650 \u062F\u06CC\u06AF \u062F\u0631
2086
+ * dig-theme.css \u0627\u0633\u062A \u0648 \u0628\u0627 \xABdig update theme\xBB \u0628\u0647\u200C\u0631\u0648\u0632 \u0645\u06CC\u200C\u0634\u0648\u062F.
2087
+ *
2088
+ * \u0686\u0647 \u0686\u06CC\u0632\u06CC \u0627\u06CC\u0646\u062C\u0627 \u0645\u06CC\u200C\u0622\u06CC\u062F:
2089
+ * \u06F1) \u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F (--brand-*\u060C \u0644\u0627\u06CC\u0647\u0654 \u06F2)\u061B Shade \u06F6\u06F0\u06F0 \u0647\u0645\u0627\u0646 --primary \u0627\u0633\u062A.
2090
+ * \u06F2) \u0644\u0627\u06CC\u0647\u0654 \u0645\u062D\u0635\u0648\u0644: \u0641\u0642\u0637 \u062A\u0648\u06A9\u0646\u200C\u0647\u0627\u06CC \u0645\u0639\u0646\u0627\u06CC\u06CC\u200C\u0627\u06CC \u06A9\u0647 \u0628\u0627 \u067E\u06CC\u0634\u200C\u0641\u0631\u0636\u0650 \u062F\u06CC\u06AF \u0641\u0631\u0642 \u062F\u0627\u0631\u0646\u062F
2091
+ * (--background\u060C --foreground\u060C --radius\u060C --font-anchor\u060C \u0633\u0627\u06CC\u0647\u200C\u0647\u0627\u060C ...).
2092
+ * \u06F3) \u062A\u0648\u06A9\u0646\u200C\u0647\u0627\u06CC \u062A\u0627\u0632\u0647\u0654 \u062E\u0648\u062F\u0650 \u0645\u062D\u0635\u0648\u0644 \u062F\u0627\u062E\u0644 @theme inline.
2093
+ *
2094
+ * \u0631\u0645\u067E \u0631\u0627 \u0645\u06CC\u200C\u0634\u0648\u062F \u062F\u0648\u0628\u0627\u0631\u0647 \u0627\u0632 \u06CC\u06A9 \u0631\u0646\u06AF \u0633\u0627\u062E\u062A: npx digdesign theme brand "#2C4C5B"
2095
+ * ==================================================================== */
2096
+ `;
2097
+ function brandRampBlock(ramp, hex) {
2098
+ const lines = RAMP_STEPS.map((step) => ` --brand-${step}: ${formatOklch(ramp.steps[step])};`);
2099
+ return `/* dig:brand-ramp-start \u2014 \u0633\u0627\u062E\u062A\u0647\u200C\u0634\u062F\u0647 \u0627\u0632 ${hex.toUpperCase()}\u061B \xABdig theme brand\xBB \u0647\u0645\u06CC\u0646 \u0628\u0644\u0648\u06A9 \u0631\u0627 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u0645\u06CC\u200C\u06A9\u0646\u062F */
2100
+ :root {
2101
+ ${lines.join("\n")}
2102
+ }
2103
+ /* dig:brand-ramp-end */`;
2104
+ }
2105
+ function brandCss(options) {
2106
+ const parts = [BRAND_HEADER];
2107
+ if (options.ramp && options.hex) parts.push(brandRampBlock(options.ramp, options.hex));
2108
+ if (options.body?.trim()) parts.push(options.body.trim());
2109
+ if (!options.ramp && !options.body?.trim()) {
2110
+ parts.push(`/* \u0646\u0645\u0648\u0646\u0647:
2111
+ :root {
2112
+ --brand-600: #2c4c5b;
2113
+ --radius: 0.75rem;
2114
+ }
2115
+ */`);
2116
+ }
2117
+ return `${parts.join("\n\n")}
2118
+ `;
2119
+ }
2120
+ function replaceBrandRamp(existing, ramp, hex) {
2121
+ const block = brandRampBlock(ramp, hex);
2122
+ const pattern = /\/\* dig:brand-ramp-start[\s\S]*?\/\* dig:brand-ramp-end \*\//;
2123
+ if (pattern.test(existing)) return existing.replace(pattern, block);
2124
+ const headerEnd = existing.indexOf("* ==================================================================== */");
2125
+ if (existing.startsWith("/* ====") && headerEnd !== -1) {
2126
+ const cut = existing.indexOf("\n", headerEnd) + 1;
2127
+ return `${existing.slice(0, cut)}
2128
+ ${block}
2129
+ ${existing.slice(cut)}`;
2130
+ }
2131
+ return `${block}
2132
+
2133
+ ${existing}`;
2134
+ }
2135
+ function stripComments(css) {
2136
+ return css.replace(/\/\*[\s\S]*?\*\//g, "");
2137
+ }
2138
+ function parseCss(css) {
2139
+ const source = stripComments(css);
2140
+ const declarations = [];
2141
+ const statements = [];
2142
+ const stack = [];
2143
+ let buffer = "";
2144
+ let depthParen = 0;
2145
+ const flush = (terminator) => {
2146
+ const text = buffer.trim();
2147
+ buffer = "";
2148
+ if (!text) return;
2149
+ if (text.startsWith("@")) {
2150
+ statements.push({ context: [...stack], text: `${text};` });
2151
+ return;
2152
+ }
2153
+ const colon = text.indexOf(":");
2154
+ if (colon === -1) return;
2155
+ declarations.push({
2156
+ context: [...stack],
2157
+ property: text.slice(0, colon).trim(),
2158
+ value: text.slice(colon + 1).trim().replace(/\s+/g, " ")
2159
+ });
2160
+ void terminator;
2161
+ };
2162
+ for (const ch of source) {
2163
+ if (ch === "(") depthParen++;
2164
+ if (ch === ")") depthParen--;
2165
+ if (depthParen > 0) {
2166
+ buffer += ch;
2167
+ continue;
2168
+ }
2169
+ if (ch === "{") {
2170
+ stack.push(buffer.trim().replace(/\s+/g, " "));
2171
+ buffer = "";
2172
+ } else if (ch === ";") {
2173
+ flush(";");
2174
+ } else if (ch === "}") {
2175
+ flush("}");
2176
+ stack.pop();
2177
+ } else {
2178
+ buffer += ch;
2179
+ }
2180
+ }
2181
+ return { declarations, statements };
2182
+ }
2183
+ var key = (context, name) => `${context.join(" > ")}|${name}`;
2184
+ function splitTheme(projectCss, digThemeCss) {
2185
+ const project = parseCss(projectCss);
2186
+ const dig = parseCss(digThemeCss);
2187
+ const digValues = new Map(dig.declarations.map((d) => [key(d.context, d.property), d.value]));
2188
+ const digStatements = new Set(dig.statements.map((s) => key(s.context, s.text)));
2189
+ const overrides = /* @__PURE__ */ new Map();
2190
+ let changed = 0;
2191
+ let added = 0;
2192
+ for (const decl of project.declarations) {
2193
+ const k = key(decl.context, decl.property);
2194
+ const digValue = digValues.get(k);
2195
+ if (digValue === decl.value) {
2196
+ overrides.delete(k);
2197
+ continue;
2198
+ }
2199
+ overrides.set(k, decl);
2200
+ }
2201
+ for (const [k] of overrides) {
2202
+ if (digValues.has(k)) changed++;
2203
+ else added++;
2204
+ }
2205
+ const groups = /* @__PURE__ */ new Map();
2206
+ for (const decl of overrides.values()) {
2207
+ const ctx = decl.context.join(" > ");
2208
+ if (!groups.has(ctx)) groups.set(ctx, []);
2209
+ groups.get(ctx).push(decl);
2210
+ }
2211
+ const blocks = [];
2212
+ for (const [, decls] of groups) {
2213
+ const context = decls[0].context;
2214
+ const indent = (level) => " ".repeat(level);
2215
+ const lines = [];
2216
+ context.forEach((selector, level) => lines.push(`${indent(level)}${selector} {`));
2217
+ for (const d of decls) lines.push(`${indent(context.length)}${d.property}: ${d.value};`);
2218
+ for (let level = context.length - 1; level >= 0; level--) lines.push(`${indent(level)}}`);
2219
+ blocks.push(lines.join("\n"));
2220
+ }
2221
+ const extraStatements = project.statements.filter((s) => s.context.length === 0 && !digStatements.has(key(s.context, s.text))).map((s) => s.text);
2222
+ return { body: blocks.join("\n\n"), extraStatements, changed, added };
2223
+ }
2224
+
2225
+ // src/commands/theme.ts
1953
2226
  var THEME_ITEM = "theme";
1954
2227
  async function readIfExists(target) {
1955
2228
  try {
@@ -1958,36 +2231,192 @@ async function readIfExists(target) {
1958
2231
  return null;
1959
2232
  }
1960
2233
  }
1961
- async function writeTheme(config, cwd, options) {
2234
+ async function exists(target) {
2235
+ try {
2236
+ await access5(target);
2237
+ return true;
2238
+ } catch {
2239
+ return false;
2240
+ }
2241
+ }
2242
+ function themePaths(config) {
2243
+ const dir = path11.posix.dirname(toPosixPath(config.tailwind.css));
2244
+ return {
2245
+ css: config.tailwind.css,
2246
+ theme: config.tailwind.theme ?? `${dir}/dig-theme.css`,
2247
+ brand: config.tailwind.brand ?? `${dir}/brand.css`
2248
+ };
2249
+ }
2250
+ function isBoilerplateCss(content) {
2251
+ if (content === null) return true;
2252
+ const withoutComments = content.replace(/\/\*[\s\S]*?\*\//g, "");
2253
+ return withoutComments.split("\n").filter((line) => line.trim() && !line.trim().startsWith("@import")).length === 0;
2254
+ }
2255
+ async function fetchTheme(config) {
1962
2256
  const item = await fetchRegistryItem(THEME_ITEM, config.registryUrl);
1963
2257
  const file = item.files[0];
1964
- if (!file) {
1965
- throw new DigError("\u0622\u06CC\u062A\u0645\u0650 \xABtheme\xBB \u062F\u0631 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u0641\u0627\u06CC\u0644\u06CC \u0646\u062F\u0627\u0631\u062F.");
2258
+ if (!file) throw new DigError("\u0622\u06CC\u062A\u0645\u0650 \xABtheme\xBB \u062F\u0631 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u0641\u0627\u06CC\u0644\u06CC \u0646\u062F\u0627\u0631\u062F.");
2259
+ return { ...item, content: file.content };
2260
+ }
2261
+ async function recordTheme(cwd, config, themeRel, item) {
2262
+ const lock = await readLock(cwd);
2263
+ const version = item.version ?? "0.0.0";
2264
+ const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2265
+ const relPath = toPosixPath(themeRel);
2266
+ const snapshot = await writeComponentSnapshot(cwd, THEME_ITEM, version, { [relPath]: item.content });
2267
+ lock.components[THEME_ITEM] = mergeComponentEntry(lock.components[THEME_ITEM], {
2268
+ version: item.version,
2269
+ registryUrl: config.registryUrl,
2270
+ installedAt,
2271
+ writtenFiles: { [relPath]: item.files[0].hash ?? hashContent(item.content) },
2272
+ snapshot: "path" in snapshot ? { version, path: snapshot.path, installedAt } : void 0
2273
+ });
2274
+ await writeLock(lock, cwd);
2275
+ }
2276
+ async function writeText(cwd, rel, content) {
2277
+ const target = path11.join(cwd, rel);
2278
+ await mkdir4(path11.dirname(target), { recursive: true });
2279
+ await writeFile5(target, content, "utf8");
2280
+ }
2281
+ async function installTheme(cwd, config, options) {
2282
+ const paths = themePaths(config);
2283
+ const item = await fetchTheme(config);
2284
+ const ramp = options.brand ? buildBrandRamp(options.brand) : void 0;
2285
+ await writeText(cwd, paths.theme, item.content);
2286
+ console.log(`\u2713 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u062F\u0631 ${paths.theme} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F (\u0645\u0627\u0644\u0650 \u062F\u06CC\u06AF\u061B \u0628\u0627 \xABdig update theme\xBB \u0628\u0647\u200C\u0631\u0648\u0632 \u0645\u06CC\u200C\u0634\u0648\u062F).`);
2287
+ const existingBrand = await readIfExists(path11.join(cwd, paths.brand));
2288
+ if (existingBrand === null) {
2289
+ await writeText(cwd, paths.brand, brandCss({ ramp, hex: options.brand }));
2290
+ console.log(`\u2713 ${paths.brand} \u0633\u0627\u062E\u062A\u0647 \u0634\u062F (\u0645\u0627\u0644\u0650 \u067E\u0631\u0648\u0698\u0647\u061B \u062F\u06CC\u06AF \u0647\u0631\u06AF\u0632 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC\u200C\u0627\u0634 \u0646\u0645\u06CC\u200C\u06A9\u0646\u062F).`);
2291
+ } else if (ramp && options.brand) {
2292
+ await writeText(cwd, paths.brand, replaceBrandRamp(existingBrand, ramp, options.brand));
2293
+ console.log(`\u2713 \u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u062F\u0631 ${paths.brand} \u0627\u0632 ${options.brand} \u0628\u0627\u0632\u0633\u0627\u0632\u06CC \u0634\u062F\u061B \u0628\u0642\u06CC\u0647\u0654 \u0641\u0627\u06CC\u0644 \u062F\u0633\u062A \u0646\u062E\u0648\u0631\u062F.`);
2294
+ } else {
2295
+ console.log(`- ${paths.brand} \u0627\u0632 \u0642\u0628\u0644 \u0647\u0633\u062A\u061B \u062F\u0633\u062A \u0646\u062E\u0648\u0631\u062F.`);
2296
+ }
2297
+ if (ramp) reportContrast(ramp.primaryContrast);
2298
+ const cssTarget = path11.join(cwd, paths.css);
2299
+ const existingCss = await readIfExists(cssTarget);
2300
+ if (!isBoilerplateCss(existingCss) && existingCss !== null) {
2301
+ await writeFile5(`${cssTarget}.backup`, existingCss, "utf8");
2302
+ console.log(` \u0646\u0633\u062E\u0647\u0654 \u0642\u0628\u0644\u06CC\u0650 ${paths.css} \u062F\u0631 ${paths.css}.backup \u0646\u06AF\u0647 \u062F\u0627\u0634\u062A\u0647 \u0634\u062F.`);
2303
+ console.log(` \u0627\u06AF\u0631 \u0622\u0646 \u0641\u0627\u06CC\u0644 \u062A\u0645\u0650 \u0642\u062F\u06CC\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0628\u0648\u062F\u060C \u0628\u0647\u200C\u062C\u0627\u06CC init \u0627\u0632 \xABdig theme split\xBB \u0627\u0633\u062A\u0641\u0627\u062F\u0647 \u06A9\u0646\u06CC\u062F.`);
2304
+ }
2305
+ await writeText(cwd, paths.css, globalsCss(paths));
2306
+ console.log(`\u2713 ${paths.css} \u0641\u0642\u0637 import \u0634\u062F: \u062A\u0645\u060C \u0633\u067E\u0633 \u0628\u0631\u0646\u062F.`);
2307
+ await recordTheme(cwd, config, paths.theme, item);
2308
+ return item;
2309
+ }
2310
+ function reportContrast(contrast) {
2311
+ const ratio = contrast.toFixed(2);
2312
+ if (contrast >= 4.5) {
2313
+ console.log(` \u06A9\u0646\u062A\u0631\u0627\u0633\u062A\u0650 \u0645\u062A\u0646\u0650 \u0633\u0641\u06CC\u062F \u0631\u0648\u06CC \u0631\u0646\u06AF\u0650 \u0627\u0635\u0644\u06CC: ${ratio} (AA \u0631\u0627 \u0631\u062F \u0645\u06CC\u200C\u06A9\u0646\u062F).`);
2314
+ } else {
2315
+ console.log(
2316
+ ` \u26A0 \u06A9\u0646\u062A\u0631\u0627\u0633\u062A\u0650 \u0645\u062A\u0646\u0650 \u0633\u0641\u06CC\u062F \u0631\u0648\u06CC \u0631\u0646\u06AF\u0650 \u0627\u0635\u0644\u06CC ${ratio} \u0627\u0633\u062A\u060C \u06A9\u0645\u062A\u0631 \u0627\u0632 \u06F4.\u06F5 (AA). \u0645\u062A\u0646\u0650 \u062F\u06A9\u0645\u0647\u200C\u0647\u0627\u06CC \u0627\u0635\u0644\u06CC \u062E\u0648\u0627\u0646\u0627 \u0646\u06CC\u0633\u062A\u061B \u0631\u0646\u06AF\u06CC \u062A\u06CC\u0631\u0647\u200C\u062A\u0631 \u0628\u062F\u0647\u06CC\u062F \u06CC\u0627 --primary-foreground \u0631\u0627 \u062F\u0631 brand.css \u062A\u06CC\u0631\u0647 \u06A9\u0646\u06CC\u062F.`
2317
+ );
2318
+ }
2319
+ }
2320
+ async function requireConfig(cwd) {
2321
+ if (!await configExists(cwd)) {
2322
+ throw new DigError("dig.json \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F\u061B \u0627\u0648\u0644 \xABnpx digdesign init\xBB \u0631\u0627 \u0627\u062C\u0631\u0627 \u06A9\u0646\u06CC\u062F.");
1966
2323
  }
1967
- const target = path10.join(cwd, config.tailwind.css);
1968
- const existing = await readIfExists(target);
1969
- const isBoilerplate = existing === null || existing.split("\n").filter((line) => line.trim() && !line.trim().startsWith("@import")).length === 0;
1970
- if (!isBoilerplate && !options.yes) {
2324
+ return readConfig(cwd);
2325
+ }
2326
+ async function themeSplitCommand(options) {
2327
+ const cwd = process.cwd();
2328
+ const config = await requireConfig(cwd);
2329
+ if (config.tailwind.theme) {
2330
+ console.log(`\u067E\u0631\u0648\u0698\u0647 \u0627\u0632 \u0642\u0628\u0644 \u0633\u0627\u062E\u062A\u0627\u0631\u0650 \u062F\u0648\u0641\u0627\u06CC\u0644\u06CC \u062F\u0627\u0631\u062F (${config.tailwind.theme})\u061B \u06A9\u0627\u0631\u06CC \u0644\u0627\u0632\u0645 \u0646\u06CC\u0633\u062A.`);
2331
+ return;
2332
+ }
2333
+ const paths = themePaths(config);
2334
+ const current = await readIfExists(path11.join(cwd, paths.css));
2335
+ if (current === null || isBoilerplateCss(current)) {
2336
+ throw new DigError(`${paths.css} \u062A\u0645\u06CC \u0646\u062F\u0627\u0631\u062F\u061B \u0628\u0631\u0627\u06CC \u0646\u0635\u0628\u0650 \u062A\u0627\u0632\u0647 \xABdig init\xBB \u0631\u0627 \u0627\u062C\u0631\u0627 \u06A9\u0646\u06CC\u062F.`);
2337
+ }
2338
+ if (await exists(path11.join(cwd, paths.brand))) {
2339
+ throw new DigError(`${paths.brand} \u0627\u0632 \u0642\u0628\u0644 \u0648\u062C\u0648\u062F \u062F\u0627\u0631\u062F\u061B \u0628\u0631\u0627\u06CC \u062C\u0644\u0648\u06AF\u06CC\u0631\u06CC \u0627\u0632 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC\u060C \u0627\u0648\u0644 \u062C\u0627\u0628\u0647\u200C\u062C\u0627\u06CC\u0634 \u06A9\u0646\u06CC\u062F.`);
2340
+ }
2341
+ console.log(`\u062F\u0631\u06CC\u0627\u0641\u062A\u0650 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0627\u0632 ${config.registryUrl} \u2026`);
2342
+ const item = await fetchTheme(config);
2343
+ const split = splitTheme(current, item.content);
2344
+ console.log(`
2345
+ ${split.changed} \u062A\u0648\u06A9\u0646\u0650 \u0639\u0648\u0636\u200C\u0634\u062F\u0647 \u0648 ${split.added} \u062A\u0648\u06A9\u0646\u0650 \u062A\u0627\u0632\u0647 \u067E\u06CC\u062F\u0627 \u0634\u062F \u2192 ${paths.brand}`);
2346
+ if (split.extraStatements.length) {
2347
+ console.log(`${split.extraStatements.length} \u062F\u0633\u062A\u0648\u0631\u0650 \u0633\u0637\u062D\u0650 \u0628\u0627\u0644\u0627 \u062F\u0631 ${paths.css} \u0645\u06CC\u200C\u0645\u0627\u0646\u062F:`);
2348
+ for (const statement of split.extraStatements) console.log(` ${statement}`);
2349
+ }
2350
+ if (options.dryRun) {
1971
2351
  console.log(`
1972
- ${config.tailwind.css} \u0627\u0632 \u0642\u0628\u0644 \u0645\u062D\u062A\u0648\u0627 \u062F\u0627\u0631\u062F.`);
2352
+ \u067E\u06CC\u0634\u200C\u0646\u0645\u0627\u06CC\u0634\u0650 ${paths.brand} (\u0686\u06CC\u0632\u06CC \u0646\u0648\u0634\u062A\u0647 \u0646\u0634\u062F):
2353
+ `);
2354
+ console.log(split.body || "(\u062E\u0627\u0644\u06CC: \u067E\u0631\u0648\u0698\u0647 \u0686\u06CC\u0632\u06CC \u062F\u0631 \u062A\u0645 \u0639\u0648\u0636 \u0646\u06A9\u0631\u062F\u0647)");
2355
+ return;
2356
+ }
2357
+ await writeFile5(path11.join(cwd, `${paths.css}.backup`), current, "utf8");
2358
+ await writeText(cwd, paths.theme, item.content);
2359
+ await writeText(cwd, paths.brand, brandCss({ body: split.body }));
2360
+ await writeText(cwd, paths.css, globalsCss(paths, split.extraStatements));
2361
+ await writeConfig(
2362
+ { ...config, tailwind: { ...config.tailwind, theme: paths.theme, brand: paths.brand } },
2363
+ cwd
2364
+ );
2365
+ await recordTheme(cwd, config, paths.theme, item);
2366
+ console.log(`
2367
+ \u2713 ${paths.theme} (\u062A\u0645\u0650 \u062F\u06CC\u06AF)\u060C ${paths.brand} (\u0628\u0631\u0646\u062F) \u0648 ${paths.css} (\u0641\u0642\u0637 import) \u0646\u0648\u0634\u062A\u0647 \u0634\u062F.`);
2368
+ console.log(` \u0646\u0633\u062E\u0647\u0654 \u0642\u0628\u0644\u06CC: ${paths.css}.backup`);
2369
+ console.log(
2370
+ ` \u062A\u0641\u0627\u0648\u062A\u200C\u0647\u0627 \u0628\u0627 \u0622\u062E\u0631\u06CC\u0646 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0645\u0642\u0627\u06CC\u0633\u0647 \u0634\u062F\u0646\u062F\u061B \u0627\u06AF\u0631 \u067E\u0631\u0648\u0698\u0647 \u0646\u0633\u062E\u0647\u0654 \u0642\u062F\u06CC\u0645\u06CC\u200C\u062A\u0631\u06CC \u0627\u0632 \u062A\u0645 \u062F\u0627\u0634\u062A\u060C \u0645\u0645\u06A9\u0646 \u0627\u0633\u062A \u0686\u0646\u062F \u0645\u0642\u062F\u0627\u0631\u0650 \u0642\u062F\u06CC\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0647\u0645 \u0628\u0647 ${paths.brand} \u0631\u0641\u062A\u0647 \u0628\u0627\u0634\u062F. \u06CC\u06A9 \u0646\u06AF\u0627\u0647 \u0628\u0647 \u0622\u0646 \u0628\u06CC\u0646\u062F\u0627\u0632\u06CC\u062F.`
2371
+ );
2372
+ }
2373
+ async function themeBrandCommand(hex) {
2374
+ const cwd = process.cwd();
2375
+ const config = await requireConfig(cwd);
2376
+ if (!config.tailwind.theme) {
2377
+ throw new DigError("\u0627\u06CC\u0646 \u067E\u0631\u0648\u0698\u0647 \u0647\u0646\u0648\u0632 brand.css \u0646\u062F\u0627\u0631\u062F\u061B \u0627\u0648\u0644 \xABdig theme split\xBB \u0631\u0627 \u0627\u062C\u0631\u0627 \u06A9\u0646\u06CC\u062F.");
2378
+ }
2379
+ const paths = themePaths(config);
2380
+ const ramp = buildBrandRamp(hex);
2381
+ const existing = await readIfExists(path11.join(cwd, paths.brand)) ?? brandCss({});
2382
+ const next = replaceBrandRamp(existing, ramp, hex);
2383
+ await writeText(cwd, paths.brand, next);
2384
+ console.log(`\u2713 \u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u062F\u0631 ${paths.brand} \u0627\u0632 ${hex} \u0633\u0627\u062E\u062A\u0647 \u0634\u062F (Shade \u06F6\u06F0\u06F0 = \u0631\u0646\u06AF\u0650 \u062F\u0627\u062F\u0647\u200C\u0634\u062F\u0647).`);
2385
+ reportContrast(ramp.primaryContrast);
2386
+ const outside = next.replace(/\/\* dig:brand-ramp-start[\s\S]*?\/\* dig:brand-ramp-end \*\//, "");
2387
+ const shadowing = outside.match(/--brand-\d+\s*:/g);
2388
+ if (shadowing) {
2389
+ console.log(
2390
+ ` \u26A0 ${shadowing.length} \u0627\u0639\u0644\u0627\u0646\u0650 --brand-* \u0628\u06CC\u0631\u0648\u0646 \u0627\u0632 \u0628\u0644\u0648\u06A9\u0650 \u0631\u0645\u067E \u062F\u0631 ${paths.brand} \u0647\u0633\u062A \u0648 \u0628\u0631 \u0622\u0646 \u0628\u0631\u0646\u062F\u0647 \u0645\u06CC\u200C\u0634\u0648\u062F\u061B \u0627\u06AF\u0631 \u0631\u0645\u067E\u0650 \u062A\u0627\u0632\u0647 \u0631\u0627 \u0645\u06CC\u200C\u062E\u0648\u0627\u0647\u06CC\u062F\u060C \u0622\u0646\u200C\u0647\u0627 \u0631\u0627 \u067E\u0627\u06A9 \u06A9\u0646\u06CC\u062F.`
2391
+ );
2392
+ }
2393
+ }
2394
+
2395
+ // src/commands/init.ts
2396
+ async function readIfExists2(target) {
2397
+ try {
2398
+ return await readFile8(target, "utf8");
2399
+ } catch {
2400
+ return null;
2401
+ }
2402
+ }
2403
+ async function writeTheme(config, cwd, options) {
2404
+ const paths = themePaths(config);
2405
+ const existing = await readIfExists2(path12.join(cwd, paths.css));
2406
+ if (!isBoilerplateCss(existing) && !options.yes) {
2407
+ console.log(`
2408
+ ${paths.css} \u0627\u0632 \u0642\u0628\u0644 \u0645\u062D\u062A\u0648\u0627 \u062F\u0627\u0631\u062F.`);
2409
+ console.log(` \u0627\u06AF\u0631 \u062A\u0645\u0650 \u0642\u062F\u06CC\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0627\u0633\u062A\u060C \u0628\u0647\u200C\u062C\u0627\u06CC \u0627\u06CC\u0646 \u0627\u0632 \xABdig theme split\xBB \u0627\u0633\u062A\u0641\u0627\u062F\u0647 \u06A9\u0646\u06CC\u062F \u062A\u0627 \u0628\u0631\u0646\u062F\u062A\u0627\u0646 \u062D\u0641\u0638 \u0634\u0648\u062F.`);
1973
2410
  const overwrite = await confirm(
1974
- "\u0628\u0627 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u0634\u0648\u062F\u061F (\u0646\u0633\u062E\u0647\u0654 \u0641\u0639\u0644\u06CC \u06A9\u0646\u0627\u0631\u0634 \u0628\u0647\u200C\u0639\u0646\u0648\u0627\u0646 .backup \u0645\u06CC\u200C\u0645\u0627\u0646\u062F)",
2411
+ "\u0628\u0627 \u0633\u0627\u062E\u062A\u0627\u0631\u0650 \u062A\u0627\u0632\u0647 (\u0641\u0642\u0637 import) \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u0634\u0648\u062F\u061F (\u0646\u0633\u062E\u0647\u0654 \u0641\u0639\u0644\u06CC \u06A9\u0646\u0627\u0631\u0634 \u0628\u0647\u200C\u0639\u0646\u0648\u0627\u0646 .backup \u0645\u06CC\u200C\u0645\u0627\u0646\u062F)",
1975
2412
  false
1976
2413
  );
1977
2414
  if (!overwrite) {
1978
- console.log(
1979
- `- \u062A\u0645 \u0646\u0648\u0634\u062A\u0647 \u0646\u0634\u062F. \u0628\u0631\u0627\u06CC \u0646\u0648\u0634\u062A\u0646\u0634 \u0628\u0639\u062F\u0627\u064B: dig add ${THEME_ITEM} --overwrite`
1980
- );
2415
+ console.log(`- \u062A\u0645 \u0646\u0648\u0634\u062A\u0647 \u0646\u0634\u062F. \u0628\u0639\u062F\u0627\u064B: dig init \u06CC\u0627 dig theme split`);
1981
2416
  return "skipped";
1982
2417
  }
1983
2418
  }
1984
- if (!isBoilerplate && existing !== null) {
1985
- await writeFile5(`${target}.backup`, existing, "utf8");
1986
- console.log(` \u0646\u0633\u062E\u0647\u0654 \u0642\u0628\u0644\u06CC \u062F\u0631 ${config.tailwind.css}.backup \u0646\u06AF\u0647 \u062F\u0627\u0634\u062A\u0647 \u0634\u062F.`);
1987
- }
1988
- await mkdir4(path10.dirname(target), { recursive: true });
1989
- await writeFile5(target, file.content, "utf8");
1990
- console.log(`\u2713 \u062A\u0645 \u062F\u0631 ${config.tailwind.css} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F.`);
2419
+ const item = await installTheme(cwd, config, { brand: options.brand });
1991
2420
  if (item.dependencies?.length) {
1992
2421
  const pm = await detectPackageManager(cwd);
1993
2422
  console.log(`
@@ -1998,8 +2427,8 @@ ${config.tailwind.css} \u0627\u0632 \u0642\u0628\u0644 \u0645\u062D\u062A\u0648\
1998
2427
  }
1999
2428
  async function applyRtl(cwd) {
2000
2429
  for (const candidate of ["src/app/layout.tsx", "app/layout.tsx"]) {
2001
- const target = path10.join(cwd, candidate);
2002
- const source = await readIfExists(target);
2430
+ const target = path12.join(cwd, candidate);
2431
+ const source = await readIfExists2(target);
2003
2432
  if (source === null) continue;
2004
2433
  if (/<html[^>]*\sdir=/.test(source)) {
2005
2434
  console.log(`- ${candidate} \u0627\u0632 \u0642\u0628\u0644 dir \u062F\u0627\u0631\u062F\u061B \u062F\u0633\u062A \u0646\u062E\u0648\u0631\u062F.`);
@@ -2011,7 +2440,7 @@ async function applyRtl(cwd) {
2011
2440
  match[0],
2012
2441
  `<html${match[1]} dir="rtl">`.replace(/\s+dir="rtl">$/, ' dir="rtl">')
2013
2442
  );
2014
- await writeFile5(target, updated, "utf8");
2443
+ await writeFile6(target, updated, "utf8");
2015
2444
  console.log(`\u2713 dir="rtl" \u0628\u0647 ${candidate} \u0627\u0636\u0627\u0641\u0647 \u0634\u062F.`);
2016
2445
  return;
2017
2446
  }
@@ -2032,23 +2461,24 @@ async function initCommand(options) {
2032
2461
  const config = options.yes ? base : {
2033
2462
  ...base,
2034
2463
  rtl: await confirm("\u067E\u0631\u0648\u0698\u0647 \u0631\u0627\u0633\u062A\u200C\u0628\u0647\u200C\u0686\u067E (RTL) \u0627\u0633\u062A\u061F", base.rtl),
2035
- tailwind: {
2036
- ...base.tailwind,
2037
- css: await ask(
2038
- "\u0645\u0633\u06CC\u0631 \u0641\u0627\u06CC\u0644 CSS \u0627\u0635\u0644\u06CC \u062A\u06CC\u0644\u0648\u06CC\u0646\u062F\u061F",
2039
- base.tailwind.css
2040
- )
2041
- }
2464
+ tailwind: await (async () => {
2465
+ const css = await ask("\u0645\u0633\u06CC\u0631 \u0641\u0627\u06CC\u0644 CSS \u0627\u0635\u0644\u06CC \u062A\u06CC\u0644\u0648\u06CC\u0646\u062F\u061F", base.tailwind.css);
2466
+ const dir = path12.posix.dirname(css.split(path12.sep).join("/"));
2467
+ return { ...base.tailwind, css, theme: `${dir}/dig-theme.css`, brand: `${dir}/brand.css` };
2468
+ })()
2042
2469
  };
2043
2470
  await writeConfig(config, cwd);
2044
- console.log(`\u2713 ${path10.join(cwd, "dig.json")} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F.`);
2045
- const theme = await writeTheme(config, cwd, options);
2471
+ console.log(`\u2713 ${path12.join(cwd, "dig.json")} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F.`);
2472
+ const theme2 = await writeTheme(config, cwd, options);
2046
2473
  if (config.rtl) {
2047
2474
  await applyRtl(cwd);
2048
2475
  }
2049
2476
  console.log("\n\u0622\u0645\u0627\u062F\u0647 \u0627\u0633\u062A. \u0642\u062F\u0645 \u0628\u0639\u062F\u06CC:");
2050
2477
  console.log(" dig add button");
2051
- if (theme === "skipped") {
2478
+ if (theme2 === "written") {
2479
+ console.log("\n\u0628\u0631\u0646\u062F \u0648 \u0634\u062E\u0635\u06CC\u200C\u0633\u0627\u0632\u06CC \u0641\u0642\u0637 \u062F\u0631 brand.css\u061B \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0628\u0627 \xABdig update theme\xBB \u0628\u0647\u200C\u0631\u0648\u0632 \u0645\u06CC\u200C\u0634\u0648\u062F.");
2480
+ }
2481
+ if (theme2 === "skipped") {
2052
2482
  console.log(
2053
2483
  `
2054
2484
  \u26A0 \u0628\u062F\u0648\u0646 \u062A\u0645\u060C \u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A\u200C\u0647\u0627 \u0646\u0635\u0628 \u0645\u06CC\u200C\u0634\u0648\u0646\u062F \u0648\u0644\u06CC \u0628\u06CC\u200C\u0638\u0627\u0647\u0631 \u0645\u06CC\u200C\u0645\u0627\u0646\u0646\u062F (\u0631\u0646\u06AF\u060C \u0634\u0639\u0627\u0639 \u0648 \u0633\u0627\u06CC\u0647 \u0627\u0632 \u062A\u0648\u06A9\u0646 \u0645\u06CC\u200C\u0622\u06CC\u0646\u062F).`
@@ -2057,8 +2487,8 @@ async function initCommand(options) {
2057
2487
  }
2058
2488
 
2059
2489
  // src/lib/migration-apply.ts
2060
- import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
2061
- import path11 from "path";
2490
+ import { readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
2491
+ import path13 from "path";
2062
2492
 
2063
2493
  // src/lib/migration-strategy.ts
2064
2494
  var TextReplaceStrategy = class {
@@ -2135,7 +2565,7 @@ function looksBinary2(buffer) {
2135
2565
  async function readTextFileSafely2(target) {
2136
2566
  let buffer;
2137
2567
  try {
2138
- buffer = await readFile8(target);
2568
+ buffer = await readFile9(target);
2139
2569
  } catch (error) {
2140
2570
  if (error.code === "ENOENT") return void 0;
2141
2571
  throw error;
@@ -2157,7 +2587,7 @@ function summarizeMigration(migration) {
2157
2587
  return void 0;
2158
2588
  }
2159
2589
  async function planOrApplyMigrations(params) {
2160
- const { cwd, aliases, registryUrl, lock, registryItem, dryRun } = params;
2590
+ const { cwd, aliases, registryUrl, lock, registryItem, dryRun, paths } = params;
2161
2591
  const name = registryItem.name;
2162
2592
  const lockEntry = lock.components[name];
2163
2593
  if (!lockEntry) {
@@ -2180,8 +2610,8 @@ async function planOrApplyMigrations(params) {
2180
2610
  };
2181
2611
  }
2182
2612
  const fileTargets = registryItem.files.map((file) => {
2183
- const target = path11.join(cwd, resolveTargetPath(file.path, aliases));
2184
- return { relPath: toPosixPath(path11.relative(cwd, target)), target };
2613
+ const target = path13.join(cwd, resolveTargetPath(file.path, aliases, paths));
2614
+ return { relPath: toPosixPath(path13.relative(cwd, target)), target };
2185
2615
  });
2186
2616
  const currentContents = /* @__PURE__ */ new Map();
2187
2617
  for (const ft of fileTargets) {
@@ -2247,12 +2677,12 @@ async function planOrApplyMigrations(params) {
2247
2677
  const written = [];
2248
2678
  try {
2249
2679
  for (const item of pending) {
2250
- await writeFile6(item.target, item.newContent, "utf8");
2680
+ await writeFile7(item.target, item.newContent, "utf8");
2251
2681
  written.push(item);
2252
2682
  }
2253
2683
  } catch (error) {
2254
2684
  for (const item of written) {
2255
- await writeFile6(item.target, item.originalContent, "utf8");
2685
+ await writeFile7(item.target, item.originalContent, "utf8");
2256
2686
  }
2257
2687
  return {
2258
2688
  name,
@@ -2389,6 +2819,7 @@ async function runApplyOrDryRun(components, options, dryRun) {
2389
2819
  const result = await planOrApplyMigrations({
2390
2820
  cwd,
2391
2821
  aliases: config.aliases,
2822
+ paths: targetPathOptions(config),
2392
2823
  registryUrl: config.registryUrl,
2393
2824
  lock,
2394
2825
  registryItem,
@@ -2546,7 +2977,7 @@ ${message}`);
2546
2977
  }
2547
2978
  const summary = intelligence.components.find((c) => c.name === component);
2548
2979
  if (!summary) {
2549
- const message = `\xAB${component}\xBB \u062F\u0631 \u062F\u0627\u062F\u0647\u0654 \u0647\u0648\u0634\u0645\u0646\u062F\u06CC\u0650 \u0641\u0639\u0644\u06CC \u0646\u06CC\u0633\u062A (\u0634\u0627\u06CC\u062F \u0627\u0632 \u0646\u0648\u0639\u0650 registry:lib \u0628\u0627\u0634\u062F\u060C \u0646\u0647 UI).`;
2980
+ const message = `\xAB${component}\xBB \u062F\u0631 \u062F\u0627\u062F\u0647\u0654 \u0647\u0648\u0634\u0645\u0646\u062F\u06CC\u0650 \u0641\u0639\u0644\u06CC \u0646\u06CC\u0633\u062A (\u0634\u0627\u06CC\u062F \u0627\u0632 \u0646\u0648\u0639\u0650 dig:lib \u0628\u0627\u0634\u062F\u060C \u0646\u0647 UI).`;
2550
2981
  if (options.json) {
2551
2982
  console.log(JSON.stringify({ component, status: "no-data", message }, null, 2));
2552
2983
  } else {
@@ -2863,8 +3294,8 @@ ${entry.migrationHint}`);
2863
3294
  }
2864
3295
 
2865
3296
  // src/lib/update.ts
2866
- import { mkdir as mkdir5, readFile as readFile9, rm as rm2, writeFile as writeFile7 } from "fs/promises";
2867
- import path12 from "path";
3297
+ import { mkdir as mkdir5, readFile as readFile10, rm as rm2, writeFile as writeFile8 } from "fs/promises";
3298
+ import path14 from "path";
2868
3299
  function safeFileIndexes(drift) {
2869
3300
  const indexes = [];
2870
3301
  drift.files.forEach((file, index) => {
@@ -2873,7 +3304,7 @@ function safeFileIndexes(drift) {
2873
3304
  });
2874
3305
  return indexes;
2875
3306
  }
2876
- async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun) {
3307
+ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun, paths) {
2877
3308
  const actions = new Array(drift.files.length).fill("skipped");
2878
3309
  const safeIndexes = safeFileIndexes(drift);
2879
3310
  if (dryRun) {
@@ -2884,7 +3315,7 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun) {
2884
3315
  for (const index of safeIndexes) {
2885
3316
  const file = drift.files[index];
2886
3317
  const registryFile = registryItem.files[index];
2887
- const target = path12.join(cwd, resolveTargetPath(registryFile.path, aliases));
3318
+ const target = path14.join(cwd, resolveTargetPath(registryFile.path, aliases, paths));
2888
3319
  const isNewFile = file.status === "new_upstream";
2889
3320
  pending.push({
2890
3321
  index,
@@ -2892,14 +3323,14 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun) {
2892
3323
  newContent: registryFile.content,
2893
3324
  newHash: registryFile.hash ?? hashContent(registryFile.content),
2894
3325
  isNewFile,
2895
- originalContent: isNewFile ? void 0 : await readFile9(target, "utf8")
3326
+ originalContent: isNewFile ? void 0 : await readFile10(target, "utf8")
2896
3327
  });
2897
3328
  }
2898
3329
  const written = [];
2899
3330
  try {
2900
3331
  for (const item of pending) {
2901
- if (item.isNewFile) await mkdir5(path12.dirname(item.target), { recursive: true });
2902
- await writeFile7(item.target, item.newContent, "utf8");
3332
+ if (item.isNewFile) await mkdir5(path14.dirname(item.target), { recursive: true });
3333
+ await writeFile8(item.target, item.newContent, "utf8");
2903
3334
  written.push(item);
2904
3335
  }
2905
3336
  } catch (error) {
@@ -2907,7 +3338,7 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun) {
2907
3338
  if (item.isNewFile) {
2908
3339
  await rm2(item.target, { force: true });
2909
3340
  } else {
2910
- await writeFile7(item.target, item.originalContent, "utf8");
3341
+ await writeFile8(item.target, item.originalContent, "utf8");
2911
3342
  }
2912
3343
  }
2913
3344
  return { actions, writtenHashes: {}, rollbackError: error.message };
@@ -2932,7 +3363,7 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun) {
2932
3363
  return { actions, writtenHashes, snapshotPath: snapshotResult.path };
2933
3364
  }
2934
3365
  async function updateComponent(params) {
2935
- const { cwd, aliases, registryUrl, lock, registryItem, dryRun = false } = params;
3366
+ const { cwd, aliases, registryUrl, lock, registryItem, dryRun = false, paths } = params;
2936
3367
  const name = registryItem.name;
2937
3368
  const lockEntry = lock.components[name];
2938
3369
  if (!lockEntry) {
@@ -2943,9 +3374,10 @@ async function updateComponent(params) {
2943
3374
  aliases,
2944
3375
  registryUrl,
2945
3376
  lockEntry,
2946
- registryItem
3377
+ registryItem,
3378
+ paths
2947
3379
  });
2948
- const { actions, writtenHashes, rollbackError, snapshotPath, snapshotError } = await applySafeFiles(cwd, aliases, drift, registryItem, dryRun);
3380
+ const { actions, writtenHashes, rollbackError, snapshotPath, snapshotError } = await applySafeFiles(cwd, aliases, drift, registryItem, dryRun, paths);
2949
3381
  if (rollbackError) {
2950
3382
  return {
2951
3383
  name,
@@ -3009,6 +3441,7 @@ async function updateCommand(components, options) {
3009
3441
  const result = await updateComponent({
3010
3442
  cwd,
3011
3443
  aliases: config.aliases,
3444
+ paths: targetPathOptions(config),
3012
3445
  registryUrl: config.registryUrl,
3013
3446
  lock,
3014
3447
  registryItem,
@@ -3140,6 +3573,7 @@ ${result.name}`);
3140
3573
  const details = await computeFileDiffDetails({
3141
3574
  cwd,
3142
3575
  aliases: config.aliases,
3576
+ paths: targetPathOptions(config),
3143
3577
  name: result.name,
3144
3578
  snapshotVersion,
3145
3579
  file,
@@ -3196,14 +3630,17 @@ ${result.name}`);
3196
3630
  }
3197
3631
 
3198
3632
  // src/lib/version.ts
3199
- var CLI_VERSION = "0.3.0";
3633
+ var CLI_VERSION = "0.4.0";
3200
3634
 
3201
3635
  // src/index.ts
3202
3636
  var program = new Command();
3203
3637
  program.name("dig").description("CLI \u0631\u0633\u0645\u06CC \u062F\u06CC\u0632\u0627\u06CC\u0646 \u0633\u06CC\u0633\u062A\u0645 \u062F\u06CC\u06AF").version(CLI_VERSION);
3204
3638
  program.command("init").description(
3205
3639
  '\u0631\u0627\u0647\u200C\u0627\u0646\u062F\u0627\u0632\u06CC \u062F\u06CC\u06AF \u062F\u0631 \u067E\u0631\u0648\u0698\u0647: dig.json\u060C \u062A\u0645 \u0648 \u062A\u0648\u06A9\u0646\u200C\u0647\u0627\u060C \u0648 dir="rtl"'
3206
- ).option("--yes", "\u067E\u0627\u0633\u062E \u067E\u06CC\u0634\u200C\u0641\u0631\u0636 \u0628\u0647 \u0647\u0645\u0647\u0654 \u0633\u0648\u0627\u0644\u0627\u062A", false).action(initCommand);
3640
+ ).option("--yes", "\u067E\u0627\u0633\u062E \u067E\u06CC\u0634\u200C\u0641\u0631\u0636 \u0628\u0647 \u0647\u0645\u0647\u0654 \u0633\u0648\u0627\u0644\u0627\u062A", false).option("--brand <hex>", "\u0633\u0627\u062E\u062A\u0646\u0650 \u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u0627\u0632 \u06CC\u06A9 \u0631\u0646\u06AF (\u0631\u0648\u06CC Shade \u06F6\u06F0\u06F0 \u0645\u06CC\u200C\u0646\u0634\u06CC\u0646\u062F)\u060C \u0645\u062B\u0644 #2C4C5B").action(initCommand);
3641
+ var theme = program.command("theme").description("\u062A\u0645 \u0648 \u0628\u0631\u0646\u062F: \u062C\u062F\u0627 \u06A9\u0631\u062F\u0646\u0650 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0627\u0632 \u0628\u0631\u0646\u062F\u0650 \u067E\u0631\u0648\u0698\u0647");
3642
+ theme.command("split").description("\u067E\u0631\u0648\u0698\u0647\u0654 \u0642\u062F\u06CC\u0645\u06CC \u0631\u0627 \u0628\u0647 \u0633\u0627\u062E\u062A\u0627\u0631\u0650 \u062F\u0648\u0641\u0627\u06CC\u0644\u06CC \u0645\u06CC\u200C\u0628\u0631\u062F (dig-theme.css \u0645\u0627\u0644\u0650 \u062F\u06CC\u06AF\u060C brand.css \u0645\u0627\u0644\u0650 \u067E\u0631\u0648\u0698\u0647)").option("--dry-run", "\u0641\u0642\u0637 \u0646\u0634\u0627\u0646 \u0628\u062F\u0647 \u0686\u0647 \u0686\u06CC\u0632\u06CC \u0628\u0647 brand.css \u0645\u06CC\u200C\u0631\u0648\u062F\u060C \u0686\u06CC\u0632\u06CC \u0646\u0646\u0648\u06CC\u0633", false).action(themeSplitCommand);
3643
+ theme.command("brand").description("\u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u0631\u0627 \u062F\u0631 brand.css \u0627\u0632 \u06CC\u06A9 \u0631\u0646\u06AF \u0645\u06CC\u200C\u0633\u0627\u0632\u062F\u061B \u0628\u0642\u06CC\u0647\u0654 \u0641\u0627\u06CC\u0644 \u062F\u0633\u062A \u0646\u0645\u06CC\u200C\u062E\u0648\u0631\u062F").argument("<hex>", "\u0631\u0646\u06AF\u0650 \u0627\u0635\u0644\u06CC\u0650 \u0628\u0631\u0646\u062F\u060C \u0645\u062B\u0644 #2C4C5B").action(themeBrandCommand);
3207
3644
  program.command("add").description("\u0627\u0641\u0632\u0648\u062F\u0646 \u06CC\u06A9 \u06CC\u0627 \u0686\u0646\u062F \u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A \u0627\u0632 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u062F\u06CC\u06AF").argument("[components...]", "\u0646\u0627\u0645 \u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A\u200C\u0647\u0627 (\u0645\u062B\u0644 button) \u06CC\u0627 \u0622\u062F\u0631\u0633 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC\u061B \u0628\u062F\u0648\u0646 \u0622\u0631\u06AF\u0648\u0645\u0627\u0646 \u0641\u0647\u0631\u0633\u062A \u0631\u0627 \u0646\u0634\u0627\u0646 \u0645\u06CC\u200C\u062F\u0647\u062F").option("--overwrite", "\u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC \u0645\u0648\u062C\u0648\u062F", false).option("-y, --yes", "\u0628\u062F\u0648\u0646 \u067E\u0631\u0633\u0634\u060C \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC \u0645\u0648\u062C\u0648\u062F \u0631\u0627 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC \u06A9\u0646", false).option("--dry-run", "\u0641\u0642\u0637 \u0646\u0634\u0627\u0646 \u0628\u062F\u0647 \u0686\u0647 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC\u06CC \u0646\u0648\u0634\u062A\u0647 \u0645\u06CC\u200C\u0634\u0648\u062F\u060C \u0686\u06CC\u0632\u06CC \u0646\u0646\u0648\u06CC\u0633", false).option("--no-install", "\u0641\u0642\u0637 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627 \u0631\u0627 \u0628\u0646\u0648\u06CC\u0633\u060C \u0648\u0627\u0628\u0633\u062A\u06AF\u06CC\u200C\u0647\u0627 \u0631\u0627 \u0646\u0635\u0628 \u0646\u06A9\u0646").action(addCommand);
3208
3645
  program.command("list").description("\u0641\u0647\u0631\u0633\u062A \u0622\u06CC\u062A\u0645\u200C\u0647\u0627\u06CC \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC \u062F\u06CC\u06AF").option("--type <type>", "\u0641\u06CC\u0644\u062A\u0631 \u0646\u0648\u0639: ui\u060C lib \u06CC\u0627 theme").option("--json", "\u062E\u0631\u0648\u062C\u06CC JSON \u0628\u0631\u0627\u06CC \u0627\u0633\u06A9\u0631\u06CC\u067E\u062A/\u0627\u0628\u0632\u0627\u0631", false).action(listCommand);
3209
3646
  program.command("search").description("\u062C\u0633\u062A\u062C\u0648\u06CC \u06A9\u0627\u0645\u067E\u0648\u0646\u0646\u062A \u062F\u0631 \u0631\u062C\u06CC\u0633\u062A\u0631\u06CC\u060C \u0628\u0627 \u0646\u0627\u0645 \u0641\u0627\u0631\u0633\u06CC \u06CC\u0627 \u0627\u0646\u06AF\u0644\u06CC\u0633\u06CC").argument("<query>", "\u0639\u0628\u0627\u0631\u062A \u062C\u0633\u062A\u062C\u0648").option("--json", "\u062E\u0631\u0648\u062C\u06CC JSON \u0628\u0631\u0627\u06CC \u0627\u0633\u06A9\u0631\u06CC\u067E\u062A/\u0627\u0628\u0632\u0627\u0631", false).action(searchCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "digdesign",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI رسمی برای نصب کامپوننت‌های دیزاین سیستم دیگ",
5
5
  "type": "module",
6
6
  "license": "MIT",