@axis-ds/cli 1.1.4 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/{chunk-GCOWKKXG.js → chunk-AHQT77FJ.js} +4 -4
- package/dist/{chunk-D26GW2HO.js → chunk-QORBOSUA.js} +1 -1
- package/dist/{chunk-WRDOGNSG.js → chunk-ZVVACWEW.js} +3 -3
- package/dist/index.js +1314 -145
- package/dist/monet.d.ts +3 -3
- package/dist/monet.js +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/v0.d.ts +3 -3
- package/dist/v0.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
MonetClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZVVACWEW.js";
|
|
5
5
|
import {
|
|
6
6
|
V0Client
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-AHQT77FJ.js";
|
|
8
8
|
import {
|
|
9
9
|
registerSyncCommand
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QORBOSUA.js";
|
|
11
11
|
import {
|
|
12
12
|
fetchTemplateDetail,
|
|
13
13
|
fetchTemplateIndex
|
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
|
|
16
16
|
// src/index.ts
|
|
17
17
|
import { Command } from "commander";
|
|
18
|
-
import
|
|
18
|
+
import chalk11 from "chalk";
|
|
19
19
|
import ora6 from "ora";
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
20
|
+
import fs11 from "fs-extra";
|
|
21
|
+
import path12 from "path";
|
|
22
|
+
import { createRequire as createRequire2 } from "module";
|
|
23
|
+
import prompts3 from "prompts";
|
|
23
24
|
|
|
24
25
|
// src/library/base-collector.ts
|
|
25
26
|
import crypto from "crypto";
|
|
@@ -483,11 +484,11 @@ var ShadcnCollector = class extends BaseCollector {
|
|
|
483
484
|
/**
|
|
484
485
|
* 파일 타입 추론
|
|
485
486
|
*/
|
|
486
|
-
getFileType(
|
|
487
|
-
if (
|
|
488
|
-
if (
|
|
489
|
-
if (
|
|
490
|
-
if (
|
|
487
|
+
getFileType(path13) {
|
|
488
|
+
if (path13.includes("hook") || path13.startsWith("use")) return "hook";
|
|
489
|
+
if (path13.includes("util") || path13.includes("lib")) return "util";
|
|
490
|
+
if (path13.endsWith(".css")) return "style";
|
|
491
|
+
if (path13.endsWith(".d.ts") || path13.includes("types")) return "type";
|
|
491
492
|
return "component";
|
|
492
493
|
}
|
|
493
494
|
};
|
|
@@ -1167,8 +1168,8 @@ var Publisher = class {
|
|
|
1167
1168
|
};
|
|
1168
1169
|
} catch (error) {
|
|
1169
1170
|
spinner.fail("\uB77C\uC774\uBE0C\uB7EC\uB9AC \uBC30\uCE58 \uC2E4\uD328");
|
|
1170
|
-
const
|
|
1171
|
-
errors.push(
|
|
1171
|
+
const errorMessage2 = error instanceof Error ? error.message : "Unknown error";
|
|
1172
|
+
errors.push(errorMessage2);
|
|
1172
1173
|
return {
|
|
1173
1174
|
success: false,
|
|
1174
1175
|
outputDir,
|
|
@@ -1473,7 +1474,7 @@ var LibraryCurator = class {
|
|
|
1473
1474
|
const index = await this.loadIndex();
|
|
1474
1475
|
if (!index) {
|
|
1475
1476
|
console.log(chalk2.yellow("\n\u26A0\uFE0F \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC778\uB371\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
1476
|
-
console.log(chalk2.gray(" axis-cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
1477
|
+
console.log(chalk2.gray(" npx @axis-ds/cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
1477
1478
|
return;
|
|
1478
1479
|
}
|
|
1479
1480
|
console.log(chalk2.blue("\n\u{1F4CA} Library Curator - \uD1B5\uACC4\n"));
|
|
@@ -1503,7 +1504,7 @@ import chalk7 from "chalk";
|
|
|
1503
1504
|
import ora5 from "ora";
|
|
1504
1505
|
|
|
1505
1506
|
// src/template/template-apply.ts
|
|
1506
|
-
import
|
|
1507
|
+
import fs7 from "fs-extra";
|
|
1507
1508
|
import path6 from "path";
|
|
1508
1509
|
import chalk4 from "chalk";
|
|
1509
1510
|
import ora3 from "ora";
|
|
@@ -1571,6 +1572,29 @@ function deepMerge(target, source) {
|
|
|
1571
1572
|
}
|
|
1572
1573
|
}
|
|
1573
1574
|
|
|
1575
|
+
// src/config/axis-config.ts
|
|
1576
|
+
import fs6 from "fs-extra";
|
|
1577
|
+
var AXIS_CONFIG_SCHEMA_URL = "https://axis.minu.best/schema.json";
|
|
1578
|
+
var AXIS_CONFIG_FILE = "axis.config.json";
|
|
1579
|
+
function createInitConfig(answers, registry) {
|
|
1580
|
+
return {
|
|
1581
|
+
$schema: AXIS_CONFIG_SCHEMA_URL,
|
|
1582
|
+
componentsDir: answers.componentsDir,
|
|
1583
|
+
tailwindConfig: answers.tailwindConfig,
|
|
1584
|
+
globalCss: answers.globalCss,
|
|
1585
|
+
registry
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
function createTemplateConfig(template) {
|
|
1589
|
+
return {
|
|
1590
|
+
$schema: AXIS_CONFIG_SCHEMA_URL,
|
|
1591
|
+
template,
|
|
1592
|
+
componentsDir: "./components/ui",
|
|
1593
|
+
tailwindConfig: "./tailwind.config.ts",
|
|
1594
|
+
globalCss: "./globals.css"
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1574
1598
|
// src/template/template-apply.ts
|
|
1575
1599
|
async function applyTemplate(slug, options) {
|
|
1576
1600
|
const spinner = ora3(`'${slug}' \uD15C\uD50C\uB9BF \uAC00\uC838\uC624\uB294 \uC911...`).start();
|
|
@@ -1586,7 +1610,7 @@ async function applyTemplate(slug, options) {
|
|
|
1586
1610
|
const conflicts = [];
|
|
1587
1611
|
for (const file of detail.files) {
|
|
1588
1612
|
const dest = path6.join(baseDir, file.path);
|
|
1589
|
-
if (await
|
|
1613
|
+
if (await fs7.pathExists(dest)) {
|
|
1590
1614
|
conflicts.push(file.path);
|
|
1591
1615
|
}
|
|
1592
1616
|
}
|
|
@@ -1626,8 +1650,8 @@ async function applyTemplate(slug, options) {
|
|
|
1626
1650
|
const writeSpinner = ora3("\uD30C\uC77C \uC0DD\uC131 \uC911...").start();
|
|
1627
1651
|
for (const file of detail.files) {
|
|
1628
1652
|
const dest = path6.join(baseDir, file.path);
|
|
1629
|
-
await
|
|
1630
|
-
await
|
|
1653
|
+
await fs7.ensureDir(path6.dirname(dest));
|
|
1654
|
+
await fs7.writeFile(dest, file.content);
|
|
1631
1655
|
}
|
|
1632
1656
|
writeSpinner.succeed(`${detail.files.length}\uAC1C \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC`);
|
|
1633
1657
|
if (detail.postInstall?.length) {
|
|
@@ -1688,8 +1712,8 @@ async function initTemplate(slug, options) {
|
|
|
1688
1712
|
targetDir = dir;
|
|
1689
1713
|
}
|
|
1690
1714
|
const resolved = path6.resolve(targetDir);
|
|
1691
|
-
if (await
|
|
1692
|
-
const entries = await
|
|
1715
|
+
if (await fs7.pathExists(resolved)) {
|
|
1716
|
+
const entries = await fs7.readdir(resolved);
|
|
1693
1717
|
if (entries.length > 0) {
|
|
1694
1718
|
const { proceed } = await prompts({
|
|
1695
1719
|
type: "confirm",
|
|
@@ -1700,19 +1724,13 @@ async function initTemplate(slug, options) {
|
|
|
1700
1724
|
if (!proceed) return;
|
|
1701
1725
|
}
|
|
1702
1726
|
} else {
|
|
1703
|
-
await
|
|
1727
|
+
await fs7.ensureDir(resolved);
|
|
1704
1728
|
}
|
|
1705
1729
|
await applyTemplate(selectedSlug, { dir: targetDir, yes: true });
|
|
1706
1730
|
const configPath = path6.join(resolved, "axis.config.json");
|
|
1707
|
-
if (!await
|
|
1708
|
-
const axisConfig =
|
|
1709
|
-
|
|
1710
|
-
template: selectedSlug,
|
|
1711
|
-
componentsDir: "./components/ui",
|
|
1712
|
-
tailwindConfig: "./tailwind.config.ts",
|
|
1713
|
-
globalCss: "./globals.css"
|
|
1714
|
-
};
|
|
1715
|
-
await fs6.writeJSON(configPath, axisConfig, { spaces: 2 });
|
|
1731
|
+
if (!await fs7.pathExists(configPath)) {
|
|
1732
|
+
const axisConfig = createTemplateConfig(selectedSlug);
|
|
1733
|
+
await fs7.writeJSON(configPath, axisConfig, { spaces: 2 });
|
|
1716
1734
|
console.log(chalk4.green("axis.config.json \uC0DD\uC131 \uC644\uB8CC"));
|
|
1717
1735
|
}
|
|
1718
1736
|
console.log(chalk4.blue(`
|
|
@@ -1723,7 +1741,7 @@ async function initTemplate(slug, options) {
|
|
|
1723
1741
|
}
|
|
1724
1742
|
|
|
1725
1743
|
// src/template/template-diff.ts
|
|
1726
|
-
import
|
|
1744
|
+
import fs8 from "fs-extra";
|
|
1727
1745
|
import path7 from "path";
|
|
1728
1746
|
import chalk5 from "chalk";
|
|
1729
1747
|
import ora4 from "ora";
|
|
@@ -1741,11 +1759,11 @@ async function diffTemplate(slug, options) {
|
|
|
1741
1759
|
const entries = [];
|
|
1742
1760
|
for (const file of detail.files) {
|
|
1743
1761
|
const localPath = path7.join(baseDir, file.path);
|
|
1744
|
-
if (!await
|
|
1762
|
+
if (!await fs8.pathExists(localPath)) {
|
|
1745
1763
|
entries.push({ path: file.path, status: "added" });
|
|
1746
1764
|
continue;
|
|
1747
1765
|
}
|
|
1748
|
-
const localContent = await
|
|
1766
|
+
const localContent = await fs8.readFile(localPath, "utf-8");
|
|
1749
1767
|
if (localContent === file.content) {
|
|
1750
1768
|
entries.push({ path: file.path, status: "unchanged" });
|
|
1751
1769
|
} else {
|
|
@@ -1815,7 +1833,7 @@ async function collectLocalFiles(dir, base) {
|
|
|
1815
1833
|
const results = [];
|
|
1816
1834
|
let entries;
|
|
1817
1835
|
try {
|
|
1818
|
-
entries = await
|
|
1836
|
+
entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
1819
1837
|
} catch {
|
|
1820
1838
|
return results;
|
|
1821
1839
|
}
|
|
@@ -1833,15 +1851,261 @@ async function collectLocalFiles(dir, base) {
|
|
|
1833
1851
|
}
|
|
1834
1852
|
|
|
1835
1853
|
// src/template/template-check.ts
|
|
1836
|
-
import
|
|
1854
|
+
import fs9 from "fs-extra";
|
|
1837
1855
|
import path8 from "path";
|
|
1838
1856
|
import chalk6 from "chalk";
|
|
1857
|
+
|
|
1858
|
+
// src/theme/brand-core.ts
|
|
1859
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
1860
|
+
import { createRequire } from "module";
|
|
1861
|
+
import { dirname, join, relative, resolve, sep } from "path";
|
|
1862
|
+
var TOKENS_PACKAGE = "@axis-ds/tokens";
|
|
1863
|
+
var BRAND_NAME_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
1864
|
+
var MIN_BRAND_TOKENS_VERSION = "1.3.0";
|
|
1865
|
+
var KEY_TOKENS = [
|
|
1866
|
+
"--primary",
|
|
1867
|
+
"--primary-foreground",
|
|
1868
|
+
"--background",
|
|
1869
|
+
"--foreground",
|
|
1870
|
+
"--ring",
|
|
1871
|
+
"--radius",
|
|
1872
|
+
"--axis-surface-default",
|
|
1873
|
+
"--axis-text-primary",
|
|
1874
|
+
"--axis-text-brand",
|
|
1875
|
+
"--axis-button-bg-default",
|
|
1876
|
+
"--axis-border-focus",
|
|
1877
|
+
"--axis-font-family-sans"
|
|
1878
|
+
];
|
|
1879
|
+
var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
|
|
1880
|
+
function readJsonFile(file) {
|
|
1881
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
1882
|
+
}
|
|
1883
|
+
function errorCode(err) {
|
|
1884
|
+
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
1885
|
+
}
|
|
1886
|
+
function findTokensPackageJson(baseDir) {
|
|
1887
|
+
let dir = resolve(baseDir);
|
|
1888
|
+
for (; ; ) {
|
|
1889
|
+
const candidate = join(dir, "node_modules", TOKENS_PACKAGE, "package.json");
|
|
1890
|
+
if (existsSync(candidate)) return candidate;
|
|
1891
|
+
const parent = dirname(dir);
|
|
1892
|
+
if (parent === dir) return void 0;
|
|
1893
|
+
dir = parent;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
function projectRequire(baseDir) {
|
|
1897
|
+
return createRequire(join(resolve(baseDir), "package.json"));
|
|
1898
|
+
}
|
|
1899
|
+
function tokensSpecifier(subpath) {
|
|
1900
|
+
return `${TOKENS_PACKAGE}/${subpath.replace(/^\.\//, "")}`;
|
|
1901
|
+
}
|
|
1902
|
+
function resolveTokens(baseDir) {
|
|
1903
|
+
const pkgJson = findTokensPackageJson(baseDir);
|
|
1904
|
+
if (!pkgJson) return { status: "not-installed" };
|
|
1905
|
+
const pkg = readJsonFile(pkgJson);
|
|
1906
|
+
const version = typeof pkg.version === "string" ? pkg.version : void 0;
|
|
1907
|
+
try {
|
|
1908
|
+
const indexPath = projectRequire(baseDir).resolve(tokensSpecifier("./brands"));
|
|
1909
|
+
return { status: "ok", version, indexPath };
|
|
1910
|
+
} catch (err) {
|
|
1911
|
+
const code = errorCode(err);
|
|
1912
|
+
if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return { status: "unsupported", version };
|
|
1913
|
+
if (code === "MODULE_NOT_FOUND") return { status: "not-built", version };
|
|
1914
|
+
throw err;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
function brandImportPath(entry) {
|
|
1918
|
+
return tokensSpecifier(entry.css);
|
|
1919
|
+
}
|
|
1920
|
+
var GLOBAL_CSS_CANDIDATES = ["app/globals.css", "src/app/globals.css", "globals.css"];
|
|
1921
|
+
function isFile(file) {
|
|
1922
|
+
try {
|
|
1923
|
+
return statSync(file).isFile();
|
|
1924
|
+
} catch {
|
|
1925
|
+
return false;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
function findGlobalCss(baseDir, config) {
|
|
1929
|
+
const root = resolve(baseDir);
|
|
1930
|
+
const result = {};
|
|
1931
|
+
const configured = config?.globalCss;
|
|
1932
|
+
if (typeof configured === "string" && configured.trim() !== "") {
|
|
1933
|
+
const file = resolve(root, configured);
|
|
1934
|
+
if (isFile(file)) return { path: file };
|
|
1935
|
+
result.configuredMissing = configured;
|
|
1936
|
+
}
|
|
1937
|
+
for (const candidate of GLOBAL_CSS_CANDIDATES) {
|
|
1938
|
+
const file = join(root, candidate);
|
|
1939
|
+
if (isFile(file)) {
|
|
1940
|
+
result.path = file;
|
|
1941
|
+
break;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
return result;
|
|
1945
|
+
}
|
|
1946
|
+
function findBrandImports(css) {
|
|
1947
|
+
const names = [];
|
|
1948
|
+
const pattern = /@import\s+(?:url\(\s*)?["']?@axis-ds\/tokens\/css\/brands\/([a-z][a-z0-9-]*)(?:\.css)?["']?\s*\)?\s*(?=[;\s]|$)/g;
|
|
1949
|
+
for (const m of stripComments(css).matchAll(pattern)) {
|
|
1950
|
+
names.push(m[1]);
|
|
1951
|
+
}
|
|
1952
|
+
return names;
|
|
1953
|
+
}
|
|
1954
|
+
var AXIS_CONFIG_FILE_NAME = "axis.config.json";
|
|
1955
|
+
function readBrandConfig(baseDir) {
|
|
1956
|
+
let parsed;
|
|
1957
|
+
try {
|
|
1958
|
+
parsed = JSON.parse(readFileSync(join(resolve(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
|
|
1959
|
+
} catch {
|
|
1960
|
+
return null;
|
|
1961
|
+
}
|
|
1962
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
|
|
1963
|
+
return parsed;
|
|
1964
|
+
}
|
|
1965
|
+
function inspectBrandImport(baseDir) {
|
|
1966
|
+
const config = readBrandConfig(baseDir);
|
|
1967
|
+
const brand = config?.brand;
|
|
1968
|
+
if (typeof brand !== "string" || brand.trim() === "") return null;
|
|
1969
|
+
const root = resolve(baseDir);
|
|
1970
|
+
const location = findGlobalCss(root, config);
|
|
1971
|
+
const base = { brand };
|
|
1972
|
+
if (location.configuredMissing !== void 0) base.configuredMissing = location.configuredMissing;
|
|
1973
|
+
if (!location.path) {
|
|
1974
|
+
return { ...base, state: "css-missing", imports: [] };
|
|
1975
|
+
}
|
|
1976
|
+
const cssFile = relative(root, location.path).split(sep).join("/");
|
|
1977
|
+
const imports = [...new Set(findBrandImports(readFileSync(location.path, "utf8")))];
|
|
1978
|
+
let state;
|
|
1979
|
+
if (imports.includes(brand)) state = "match";
|
|
1980
|
+
else if (imports.length === 0) state = "import-missing";
|
|
1981
|
+
else state = "other-brand";
|
|
1982
|
+
return { ...base, state, cssFile, imports };
|
|
1983
|
+
}
|
|
1984
|
+
function isMissingBuildFile(err) {
|
|
1985
|
+
const code = errorCode(err);
|
|
1986
|
+
return code === "MODULE_NOT_FOUND" || code === "ENOENT";
|
|
1987
|
+
}
|
|
1988
|
+
function readBrandIndex(indexPath) {
|
|
1989
|
+
const data = readJsonFile(indexPath);
|
|
1990
|
+
if (!Array.isArray(data.brands)) {
|
|
1991
|
+
throw new Error(`${indexPath}: "brands" \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
1992
|
+
}
|
|
1993
|
+
return data.brands;
|
|
1994
|
+
}
|
|
1995
|
+
function readSummary(baseDir, entry) {
|
|
1996
|
+
const metaPath = projectRequire(baseDir).resolve(tokensSpecifier(entry.meta));
|
|
1997
|
+
const meta = readJsonFile(metaPath);
|
|
1998
|
+
return {
|
|
1999
|
+
name: entry.name,
|
|
2000
|
+
description: typeof meta.description === "string" ? meta.description : "",
|
|
2001
|
+
themes: Array.isArray(meta.themes) ? meta.themes.map(String) : [],
|
|
2002
|
+
a11y: typeof meta.a11y === "object" && meta.a11y !== null ? meta.a11y : {},
|
|
2003
|
+
importPath: brandImportPath(entry)
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
function listBrands(baseDir) {
|
|
2007
|
+
const tokens = resolveTokens(baseDir);
|
|
2008
|
+
if (tokens.status !== "ok" || !tokens.indexPath) {
|
|
2009
|
+
return { status: tokens.status, version: tokens.version, brands: [] };
|
|
2010
|
+
}
|
|
2011
|
+
const entries = readBrandIndex(tokens.indexPath);
|
|
2012
|
+
let brands;
|
|
2013
|
+
try {
|
|
2014
|
+
brands = entries.map((entry) => readSummary(baseDir, entry));
|
|
2015
|
+
} catch (err) {
|
|
2016
|
+
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
|
|
2017
|
+
throw err;
|
|
2018
|
+
}
|
|
2019
|
+
return { status: "ok", version: tokens.version, brands };
|
|
2020
|
+
}
|
|
2021
|
+
function stripComments(css) {
|
|
2022
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
2023
|
+
}
|
|
2024
|
+
function parseDeclarations(body) {
|
|
2025
|
+
const out = {};
|
|
2026
|
+
for (const m of body.matchAll(/(--[A-Za-z0-9_-]+)\s*:\s*([^;]+);/g)) {
|
|
2027
|
+
out[m[1]] = m[2].trim();
|
|
2028
|
+
}
|
|
2029
|
+
return out;
|
|
2030
|
+
}
|
|
2031
|
+
function isDarkSelector(selector) {
|
|
2032
|
+
return /\.dark\b/.test(selector) || /\[data-theme=["']?dark["']?\]/.test(selector);
|
|
2033
|
+
}
|
|
2034
|
+
function parseBrandCss(css, name) {
|
|
2035
|
+
const result = { light: {}, dark: {} };
|
|
2036
|
+
let lightFound = false;
|
|
2037
|
+
let darkFound = false;
|
|
2038
|
+
const brandAttr = new RegExp(`\\[data-brand=["']?${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']?\\]`);
|
|
2039
|
+
for (const m of stripComments(css).matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
|
|
2040
|
+
const selectors = m[1].split(",").map((s) => s.trim());
|
|
2041
|
+
if (!selectors.some((s) => brandAttr.test(s))) continue;
|
|
2042
|
+
if (selectors.some(isDarkSelector)) {
|
|
2043
|
+
if (!darkFound) {
|
|
2044
|
+
result.dark = parseDeclarations(m[2]);
|
|
2045
|
+
darkFound = true;
|
|
2046
|
+
}
|
|
2047
|
+
} else if (!lightFound) {
|
|
2048
|
+
result.light = parseDeclarations(m[2]);
|
|
2049
|
+
lightFound = true;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
return result;
|
|
2053
|
+
}
|
|
2054
|
+
function pickKeyTokens(decls) {
|
|
2055
|
+
const out = {};
|
|
2056
|
+
for (const key of KEY_TOKENS) {
|
|
2057
|
+
if (Object.prototype.hasOwnProperty.call(decls, key)) out[key] = decls[key];
|
|
2058
|
+
}
|
|
2059
|
+
return out;
|
|
2060
|
+
}
|
|
2061
|
+
function providerExample(name) {
|
|
2062
|
+
return [
|
|
2063
|
+
'import { ThemeProvider } from "@axis-ds/theme";',
|
|
2064
|
+
"",
|
|
2065
|
+
`<ThemeProvider defaultBrand="${name}">{children}</ThemeProvider>`
|
|
2066
|
+
].join("\n");
|
|
2067
|
+
}
|
|
2068
|
+
function getBrand(baseDir, name) {
|
|
2069
|
+
const tokens = resolveTokens(baseDir);
|
|
2070
|
+
if (tokens.status !== "ok" || !tokens.indexPath) {
|
|
2071
|
+
return { status: tokens.status, version: tokens.version, brand: null, available: [] };
|
|
2072
|
+
}
|
|
2073
|
+
const entries = readBrandIndex(tokens.indexPath);
|
|
2074
|
+
const available = entries.map((e) => e.name);
|
|
2075
|
+
const entry = entries.find((e) => e.name === name);
|
|
2076
|
+
if (!entry) {
|
|
2077
|
+
return { status: "ok", version: tokens.version, brand: null, available };
|
|
2078
|
+
}
|
|
2079
|
+
let summary;
|
|
2080
|
+
let parsed;
|
|
2081
|
+
try {
|
|
2082
|
+
summary = readSummary(baseDir, entry);
|
|
2083
|
+
const cssPath = projectRequire(baseDir).resolve(summary.importPath);
|
|
2084
|
+
parsed = parseBrandCss(readFileSync(cssPath, "utf8"), name);
|
|
2085
|
+
} catch (err) {
|
|
2086
|
+
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
|
|
2087
|
+
throw err;
|
|
2088
|
+
}
|
|
2089
|
+
return {
|
|
2090
|
+
status: "ok",
|
|
2091
|
+
version: tokens.version,
|
|
2092
|
+
available,
|
|
2093
|
+
brand: {
|
|
2094
|
+
...summary,
|
|
2095
|
+
tokens: { light: pickKeyTokens(parsed.light), dark: pickKeyTokens(parsed.dark) },
|
|
2096
|
+
providerExample: providerExample(name),
|
|
2097
|
+
adjustments: { a11y: summary.a11y, reference: BRAND_ADJUSTMENT_REFERENCE }
|
|
2098
|
+
}
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// src/template/template-check.ts
|
|
1839
2103
|
var SEVERITY_ICON = {
|
|
1840
2104
|
pass: chalk6.green("PASS"),
|
|
1841
2105
|
warn: chalk6.yellow("WARN"),
|
|
1842
2106
|
fail: chalk6.red("FAIL")
|
|
1843
2107
|
};
|
|
1844
|
-
async function
|
|
2108
|
+
async function collectCheckResults(dir) {
|
|
1845
2109
|
const baseDir = path8.resolve(dir || ".");
|
|
1846
2110
|
const results = [];
|
|
1847
2111
|
results.push(await checkFileExists(baseDir, "axis.config.json", "axis.config.json"));
|
|
@@ -1849,6 +2113,12 @@ async function runCheck(dir) {
|
|
|
1849
2113
|
results.push(await checkGlobalsCss(baseDir));
|
|
1850
2114
|
results.push(await checkUtils(baseDir));
|
|
1851
2115
|
results.push(await checkDependencies(baseDir));
|
|
2116
|
+
const brand = checkBrand(baseDir);
|
|
2117
|
+
if (brand) results.push(brand);
|
|
2118
|
+
return results;
|
|
2119
|
+
}
|
|
2120
|
+
async function runCheck(dir) {
|
|
2121
|
+
const results = await collectCheckResults(dir);
|
|
1852
2122
|
console.log(chalk6.blue("\nAXIS \uD504\uB85C\uC81D\uD2B8 \uAC80\uC99D \uACB0\uACFC:\n"));
|
|
1853
2123
|
let passCount = 0;
|
|
1854
2124
|
let warnCount = 0;
|
|
@@ -1880,7 +2150,7 @@ async function runCheck(dir) {
|
|
|
1880
2150
|
}
|
|
1881
2151
|
}
|
|
1882
2152
|
async function checkFileExists(baseDir, fileName, label) {
|
|
1883
|
-
const exists = await
|
|
2153
|
+
const exists = await fs9.pathExists(path8.join(baseDir, fileName));
|
|
1884
2154
|
return {
|
|
1885
2155
|
name: label,
|
|
1886
2156
|
severity: exists ? "pass" : "fail",
|
|
@@ -1890,8 +2160,8 @@ async function checkFileExists(baseDir, fileName, label) {
|
|
|
1890
2160
|
async function checkTailwindConfig(baseDir) {
|
|
1891
2161
|
const tsPath = path8.join(baseDir, "tailwind.config.ts");
|
|
1892
2162
|
const jsPath = path8.join(baseDir, "tailwind.config.js");
|
|
1893
|
-
if (await
|
|
1894
|
-
const content = await
|
|
2163
|
+
if (await fs9.pathExists(tsPath)) {
|
|
2164
|
+
const content = await fs9.readFile(tsPath, "utf-8");
|
|
1895
2165
|
const hasTokens = content.includes("--background") || content.includes("hsl(var(");
|
|
1896
2166
|
return {
|
|
1897
2167
|
name: "tailwind.config",
|
|
@@ -1899,7 +2169,7 @@ async function checkTailwindConfig(baseDir) {
|
|
|
1899
2169
|
message: hasTokens ? "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4" : "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
|
|
1900
2170
|
};
|
|
1901
2171
|
}
|
|
1902
|
-
if (await
|
|
2172
|
+
if (await fs9.pathExists(jsPath)) {
|
|
1903
2173
|
return {
|
|
1904
2174
|
name: "tailwind.config",
|
|
1905
2175
|
severity: "warn",
|
|
@@ -1922,8 +2192,8 @@ async function checkGlobalsCss(baseDir) {
|
|
|
1922
2192
|
];
|
|
1923
2193
|
for (const candidate of candidates) {
|
|
1924
2194
|
const fullPath = path8.join(baseDir, candidate);
|
|
1925
|
-
if (await
|
|
1926
|
-
const content = await
|
|
2195
|
+
if (await fs9.pathExists(fullPath)) {
|
|
2196
|
+
const content = await fs9.readFile(fullPath, "utf-8");
|
|
1927
2197
|
const hasTokens = content.includes("--background") && content.includes("--primary");
|
|
1928
2198
|
return {
|
|
1929
2199
|
name: "globals.css",
|
|
@@ -1948,8 +2218,8 @@ async function checkUtils(baseDir) {
|
|
|
1948
2218
|
];
|
|
1949
2219
|
for (const candidate of candidates) {
|
|
1950
2220
|
const fullPath = path8.join(baseDir, candidate);
|
|
1951
|
-
if (await
|
|
1952
|
-
const content = await
|
|
2221
|
+
if (await fs9.pathExists(fullPath)) {
|
|
2222
|
+
const content = await fs9.readFile(fullPath, "utf-8");
|
|
1953
2223
|
const hasCn = content.includes("function cn");
|
|
1954
2224
|
return {
|
|
1955
2225
|
name: "utils.ts",
|
|
@@ -1966,14 +2236,14 @@ async function checkUtils(baseDir) {
|
|
|
1966
2236
|
}
|
|
1967
2237
|
async function checkDependencies(baseDir) {
|
|
1968
2238
|
const pkgPath = path8.join(baseDir, "package.json");
|
|
1969
|
-
if (!await
|
|
2239
|
+
if (!await fs9.pathExists(pkgPath)) {
|
|
1970
2240
|
return {
|
|
1971
2241
|
name: "package.json",
|
|
1972
2242
|
severity: "fail",
|
|
1973
2243
|
message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
|
|
1974
2244
|
};
|
|
1975
2245
|
}
|
|
1976
|
-
const pkg = await
|
|
2246
|
+
const pkg = await fs9.readJSON(pkgPath);
|
|
1977
2247
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1978
2248
|
const required = ["tailwindcss"];
|
|
1979
2249
|
const recommended = ["clsx", "tailwind-merge"];
|
|
@@ -1999,6 +2269,40 @@ async function checkDependencies(baseDir) {
|
|
|
1999
2269
|
message: "\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uBAA8\uB450 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4"
|
|
2000
2270
|
};
|
|
2001
2271
|
}
|
|
2272
|
+
function checkBrand(baseDir) {
|
|
2273
|
+
const check = inspectBrandImport(baseDir);
|
|
2274
|
+
return check ? brandCheckResult(check) : null;
|
|
2275
|
+
}
|
|
2276
|
+
function brandCheckResult(check) {
|
|
2277
|
+
const { brand } = check;
|
|
2278
|
+
const suffix = check.configuredMissing !== void 0 ? ` (globalCss ${check.configuredMissing} \uC5C6\uC74C)` : "";
|
|
2279
|
+
switch (check.state) {
|
|
2280
|
+
case "match":
|
|
2281
|
+
return {
|
|
2282
|
+
name: "brand",
|
|
2283
|
+
severity: "pass",
|
|
2284
|
+
message: `brand "${brand}" import \uAC00 ${check.cssFile}\uC5D0 \uC788\uC2B5\uB2C8\uB2E4${suffix}`
|
|
2285
|
+
};
|
|
2286
|
+
case "css-missing":
|
|
2287
|
+
return {
|
|
2288
|
+
name: "brand",
|
|
2289
|
+
severity: "warn",
|
|
2290
|
+
message: `brand "${brand}" \uAC00 \uC124\uC815\uB410\uC9C0\uB9CC CSS \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4${suffix}`
|
|
2291
|
+
};
|
|
2292
|
+
case "import-missing":
|
|
2293
|
+
return {
|
|
2294
|
+
name: "brand",
|
|
2295
|
+
severity: "warn",
|
|
2296
|
+
message: `brand "${brand}" import \uAC00 ${check.cssFile}\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 'axis theme add ${brand}'${suffix}`
|
|
2297
|
+
};
|
|
2298
|
+
case "other-brand":
|
|
2299
|
+
return {
|
|
2300
|
+
name: "brand",
|
|
2301
|
+
severity: "warn",
|
|
2302
|
+
message: `brand "${brand}" \uC640 import(${check.imports.join(", ")})\uAC00 \uB2E4\uB985\uB2C8\uB2E4${suffix}`
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2002
2306
|
|
|
2003
2307
|
// src/template/index.ts
|
|
2004
2308
|
function registerTemplateCommand(program2) {
|
|
@@ -2102,72 +2406,936 @@ function registerCheckCommand(program2) {
|
|
|
2102
2406
|
});
|
|
2103
2407
|
}
|
|
2104
2408
|
|
|
2105
|
-
// src/index.ts
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
const
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2409
|
+
// src/theme/index.ts
|
|
2410
|
+
import chalk8 from "chalk";
|
|
2411
|
+
import path10 from "path";
|
|
2412
|
+
|
|
2413
|
+
// src/theme/theme-add.ts
|
|
2414
|
+
import { accessSync, constants, existsSync as existsSync2, readFileSync as readFileSync2, realpathSync, unlinkSync, writeFileSync } from "fs";
|
|
2415
|
+
import path9 from "path";
|
|
2416
|
+
var TOKENS_DEPENDENCY_RANGE = `^${MIN_BRAND_TOKENS_VERSION}`;
|
|
2417
|
+
var THEME_PACKAGE = "@axis-ds/theme";
|
|
2418
|
+
function readText(file) {
|
|
2419
|
+
return existsSync2(file) ? readFileSync2(file, "utf8") : null;
|
|
2420
|
+
}
|
|
2421
|
+
function eolOf(text) {
|
|
2422
|
+
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
2423
|
+
}
|
|
2424
|
+
function indentOf(text) {
|
|
2425
|
+
const m = /\n([ \t]+)\S/.exec(text);
|
|
2426
|
+
if (!m) return 2;
|
|
2427
|
+
return m[1].includes(" ") ? " " : m[1].length;
|
|
2428
|
+
}
|
|
2429
|
+
function formatJsonLike(original, value) {
|
|
2430
|
+
const eol = eolOf(original);
|
|
2431
|
+
const endsWithNewline = /\r?\n$/.test(original);
|
|
2432
|
+
let out = JSON.stringify(value, null, indentOf(original));
|
|
2433
|
+
if (eol === "\r\n") out = out.replace(/\n/g, "\r\n");
|
|
2434
|
+
return endsWithNewline ? out + eol : out;
|
|
2435
|
+
}
|
|
2436
|
+
function insertImportLine(css, line) {
|
|
2437
|
+
const bom = css.startsWith("\uFEFF") ? "\uFEFF" : "";
|
|
2438
|
+
const body = bom ? css.slice(1) : css;
|
|
2439
|
+
const eol = eolOf(body);
|
|
2440
|
+
const lines = body.split(/\r?\n/);
|
|
2441
|
+
let insertAt = 0;
|
|
2442
|
+
let inComment = false;
|
|
2443
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2444
|
+
let rest = lines[i].trim();
|
|
2445
|
+
if (inComment) {
|
|
2446
|
+
const end = rest.indexOf("*/");
|
|
2447
|
+
if (end === -1) continue;
|
|
2448
|
+
inComment = false;
|
|
2449
|
+
rest = rest.slice(end + 2).trim();
|
|
2450
|
+
}
|
|
2451
|
+
while (rest.startsWith("/*")) {
|
|
2452
|
+
const end = rest.indexOf("*/", 2);
|
|
2453
|
+
if (end === -1) {
|
|
2454
|
+
inComment = true;
|
|
2455
|
+
rest = "";
|
|
2456
|
+
break;
|
|
2457
|
+
}
|
|
2458
|
+
rest = rest.slice(end + 2).trim();
|
|
2459
|
+
}
|
|
2460
|
+
if (rest === "") continue;
|
|
2461
|
+
if (/^@(charset|import)\b/i.test(rest)) {
|
|
2462
|
+
insertAt = i + 1;
|
|
2463
|
+
continue;
|
|
2464
|
+
}
|
|
2465
|
+
break;
|
|
2466
|
+
}
|
|
2467
|
+
lines.splice(insertAt, 0, line);
|
|
2468
|
+
return bom + lines.join(eol);
|
|
2469
|
+
}
|
|
2470
|
+
function compareVersions(a, b) {
|
|
2471
|
+
const parse = (v) => {
|
|
2472
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(v.trim());
|
|
2473
|
+
return m ? { nums: [Number(m[1]), Number(m[2]), Number(m[3])], pre: Boolean(m[4]) } : void 0;
|
|
2474
|
+
};
|
|
2475
|
+
const pa = parse(a);
|
|
2476
|
+
const pb = parse(b);
|
|
2477
|
+
if (!pa || !pb) return void 0;
|
|
2478
|
+
for (let i = 0; i < 3; i++) {
|
|
2479
|
+
if (pa.nums[i] !== pb.nums[i]) return pa.nums[i] < pb.nums[i] ? -1 : 1;
|
|
2480
|
+
}
|
|
2481
|
+
if (pa.pre !== pb.pre) return pa.pre ? -1 : 1;
|
|
2482
|
+
return 0;
|
|
2483
|
+
}
|
|
2484
|
+
function realPathInside(baseDir, file) {
|
|
2485
|
+
const realBase = realpathSync(baseDir);
|
|
2486
|
+
const realPath = realpathSync(file);
|
|
2487
|
+
const relPath = path9.relative(realBase, realPath);
|
|
2488
|
+
const inside = relPath !== "" && !relPath.startsWith("..") && !path9.isAbsolute(relPath);
|
|
2489
|
+
return { inside, realPath };
|
|
2490
|
+
}
|
|
2491
|
+
function isStylesheet(realPath) {
|
|
2492
|
+
return path9.extname(realPath).toLowerCase() === ".css";
|
|
2493
|
+
}
|
|
2494
|
+
function detectInstallCommand(baseDir) {
|
|
2495
|
+
if (existsSync2(path9.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
2496
|
+
if (existsSync2(path9.join(baseDir, "yarn.lock"))) return "yarn install";
|
|
2497
|
+
if (existsSync2(path9.join(baseDir, "package-lock.json"))) return "npm install";
|
|
2498
|
+
return "pnpm install";
|
|
2499
|
+
}
|
|
2500
|
+
function hasDependency(pkg, name) {
|
|
2501
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
2502
|
+
const deps = pkg[field];
|
|
2503
|
+
if (typeof deps === "object" && deps !== null && name in deps) {
|
|
2504
|
+
return String(deps[name]);
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
return void 0;
|
|
2508
|
+
}
|
|
2509
|
+
function isPlainObject(value) {
|
|
2510
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2511
|
+
}
|
|
2512
|
+
function planThemeAdd(baseDirInput, brand) {
|
|
2513
|
+
const baseDir = path9.resolve(baseDirInput);
|
|
2514
|
+
const plan = {
|
|
2515
|
+
baseDir,
|
|
2516
|
+
brand,
|
|
2517
|
+
importPath: brandImportPath({ css: `./css/brands/${brand}` }),
|
|
2518
|
+
tokens: { status: "not-installed" },
|
|
2519
|
+
errors: [],
|
|
2520
|
+
unverifiedBrand: false,
|
|
2521
|
+
configChanged: false,
|
|
2522
|
+
installCommand: detectInstallCommand(baseDir),
|
|
2523
|
+
writes: []
|
|
2141
2524
|
};
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2525
|
+
const configFile = path9.join(baseDir, AXIS_CONFIG_FILE);
|
|
2526
|
+
const configText = readText(configFile);
|
|
2527
|
+
if (configText === null) {
|
|
2528
|
+
plan.errors.push({ kind: "no-config" });
|
|
2529
|
+
return plan;
|
|
2530
|
+
}
|
|
2531
|
+
let config;
|
|
2532
|
+
try {
|
|
2533
|
+
const parsed = JSON.parse(configText);
|
|
2534
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
2535
|
+
config = parsed;
|
|
2536
|
+
} catch (err) {
|
|
2537
|
+
plan.errors.push({ kind: "invalid-config", message: err.message });
|
|
2538
|
+
return plan;
|
|
2539
|
+
}
|
|
2540
|
+
if (!BRAND_NAME_PATTERN.test(brand)) {
|
|
2541
|
+
plan.errors.push({ kind: "invalid-name", brand });
|
|
2542
|
+
return plan;
|
|
2543
|
+
}
|
|
2544
|
+
plan.tokens = resolveTokens(baseDir);
|
|
2545
|
+
if (plan.tokens.status === "ok" && plan.tokens.indexPath) {
|
|
2546
|
+
const data = JSON.parse(readFileSync2(plan.tokens.indexPath, "utf8"));
|
|
2547
|
+
const entries = Array.isArray(data.brands) ? data.brands : [];
|
|
2548
|
+
const entry = entries.find((e) => e.name === brand);
|
|
2549
|
+
if (!entry) {
|
|
2550
|
+
plan.errors.push({
|
|
2551
|
+
kind: "unknown-brand",
|
|
2552
|
+
brand,
|
|
2553
|
+
available: entries.map((e) => e.name),
|
|
2554
|
+
version: plan.tokens.version
|
|
2555
|
+
});
|
|
2556
|
+
return plan;
|
|
2557
|
+
}
|
|
2558
|
+
plan.importPath = brandImportPath(entry);
|
|
2559
|
+
} else {
|
|
2560
|
+
plan.unverifiedBrand = true;
|
|
2561
|
+
}
|
|
2562
|
+
const location = findGlobalCss(baseDir, config);
|
|
2563
|
+
if (location.path) {
|
|
2564
|
+
const where = realPathInside(baseDir, location.path);
|
|
2565
|
+
if (!where.inside) {
|
|
2566
|
+
plan.errors.push({ kind: "css-outside-project", file: location.path, realPath: where.realPath });
|
|
2567
|
+
plan.writes = [];
|
|
2568
|
+
return plan;
|
|
2569
|
+
}
|
|
2570
|
+
if (!isStylesheet(where.realPath)) {
|
|
2571
|
+
plan.errors.push({ kind: "css-not-stylesheet", file: location.path, realPath: where.realPath });
|
|
2572
|
+
plan.writes = [];
|
|
2573
|
+
return plan;
|
|
2574
|
+
}
|
|
2575
|
+
const before = readFileSync2(location.path, "utf8");
|
|
2576
|
+
const imported = findBrandImports(before);
|
|
2577
|
+
const otherBrands = [...new Set(imported.filter((n) => n !== brand))];
|
|
2578
|
+
if (imported.includes(brand)) {
|
|
2579
|
+
plan.css = { file: location.path, configuredMissing: location.configuredMissing, action: "exists", otherBrands };
|
|
2580
|
+
} else {
|
|
2581
|
+
plan.css = { file: location.path, configuredMissing: location.configuredMissing, action: "add", otherBrands };
|
|
2582
|
+
plan.writes.push({
|
|
2583
|
+
file: location.path,
|
|
2584
|
+
before,
|
|
2585
|
+
after: insertImportLine(before, `@import "${plan.importPath}";`)
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
} else {
|
|
2589
|
+
plan.css = { configuredMissing: location.configuredMissing, action: "manual", otherBrands: [] };
|
|
2590
|
+
}
|
|
2591
|
+
const pkgFile = path9.join(baseDir, "package.json");
|
|
2592
|
+
const pkgText = readText(pkgFile);
|
|
2593
|
+
const installed = plan.tokens.version;
|
|
2594
|
+
const upgrade = installed !== void 0 && (compareVersions(installed, MIN_BRAND_TOKENS_VERSION) ?? 0) < 0;
|
|
2595
|
+
if (pkgText === null) {
|
|
2596
|
+
plan.dependency = { action: "no-package-json", upgrade, themeMissing: false };
|
|
2597
|
+
} else {
|
|
2598
|
+
let pkg;
|
|
2599
|
+
try {
|
|
2600
|
+
const parsed = JSON.parse(pkgText);
|
|
2601
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
2602
|
+
pkg = parsed;
|
|
2603
|
+
} catch (err) {
|
|
2604
|
+
plan.errors.push({ kind: "invalid-package-json", message: err.message });
|
|
2605
|
+
plan.writes = [];
|
|
2606
|
+
return plan;
|
|
2607
|
+
}
|
|
2608
|
+
const themeMissing = hasDependency(pkg, THEME_PACKAGE) === void 0;
|
|
2609
|
+
const declared = hasDependency(pkg, TOKENS_PACKAGE);
|
|
2610
|
+
if (declared !== void 0) {
|
|
2611
|
+
plan.dependency = { action: "present", declaredRange: declared, upgrade, themeMissing };
|
|
2612
|
+
} else {
|
|
2613
|
+
const deps = isPlainObject(pkg.dependencies) ? { ...pkg.dependencies } : {};
|
|
2614
|
+
deps[TOKENS_PACKAGE] = TOKENS_DEPENDENCY_RANGE;
|
|
2615
|
+
const next = { ...pkg, dependencies: deps };
|
|
2616
|
+
plan.dependency = { action: "add", upgrade, themeMissing };
|
|
2617
|
+
plan.writes.push({ file: pkgFile, before: pkgText, after: formatJsonLike(pkgText, next) });
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
if (config.brand !== brand) {
|
|
2621
|
+
plan.configChanged = true;
|
|
2622
|
+
plan.writes.push({
|
|
2623
|
+
file: configFile,
|
|
2624
|
+
before: configText,
|
|
2625
|
+
after: formatJsonLike(configText, { ...config, brand })
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
return plan;
|
|
2629
|
+
}
|
|
2630
|
+
var ThemeApplyError = class extends Error {
|
|
2631
|
+
constructor(message, failedFile, restored, restoreFailed) {
|
|
2632
|
+
super(message);
|
|
2633
|
+
this.failedFile = failedFile;
|
|
2634
|
+
this.restored = restored;
|
|
2635
|
+
this.restoreFailed = restoreFailed;
|
|
2636
|
+
this.name = "ThemeApplyError";
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
function errorMessage(err) {
|
|
2640
|
+
return err instanceof Error ? err.message : String(err);
|
|
2641
|
+
}
|
|
2642
|
+
function applyThemeAdd(plan) {
|
|
2643
|
+
if (plan.errors.length > 0) {
|
|
2644
|
+
throw new Error("\uC624\uB958\uAC00 \uC788\uB294 \uACC4\uD68D\uC740 \uC801\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
2645
|
+
}
|
|
2646
|
+
for (const w of plan.writes) {
|
|
2647
|
+
const current = readText(w.file);
|
|
2648
|
+
if (current !== w.before) {
|
|
2649
|
+
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
2650
|
+
}
|
|
2651
|
+
const where = realPathInside(plan.baseDir, w.before === null ? path9.dirname(w.file) : w.file);
|
|
2652
|
+
if (!where.inside && !(w.before === null && path9.dirname(w.file) === plan.baseDir)) {
|
|
2653
|
+
throw new Error(`${w.file} \uC758 \uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`);
|
|
2654
|
+
}
|
|
2655
|
+
if (!w.file.endsWith(".json") && !isStylesheet(where.realPath)) {
|
|
2656
|
+
throw new Error(`${w.file} \uC758 \uC2E4\uC81C \uB300\uC0C1(${where.realPath})\uC774 CSS \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`);
|
|
2657
|
+
}
|
|
2658
|
+
if (w.file.endsWith(".json")) {
|
|
2659
|
+
JSON.parse(w.after);
|
|
2660
|
+
} else if (findBrandImports(w.after).filter((n) => n === plan.brand).length !== 1) {
|
|
2661
|
+
throw new Error(`${w.file}: \uBE0C\uB79C\uB4DC import \uAC00 \uC815\uD655\uD788 1\uC904\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
2662
|
+
}
|
|
2663
|
+
try {
|
|
2664
|
+
accessSync(w.before === null ? path9.dirname(w.file) : w.file, constants.W_OK);
|
|
2665
|
+
} catch (err) {
|
|
2666
|
+
throw new Error(`${w.file} \uC5D0 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errorMessage(err)}).`);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
const done = [];
|
|
2670
|
+
for (const w of plan.writes) {
|
|
2671
|
+
try {
|
|
2672
|
+
writeFileSync(w.file, w.after);
|
|
2673
|
+
done.push(w);
|
|
2674
|
+
} catch (err) {
|
|
2675
|
+
const restored = [];
|
|
2676
|
+
const restoreFailed = [];
|
|
2677
|
+
for (const d of done.reverse()) {
|
|
2678
|
+
try {
|
|
2679
|
+
if (d.before === null) unlinkSync(d.file);
|
|
2680
|
+
else writeFileSync(d.file, d.before);
|
|
2681
|
+
restored.push(d.file);
|
|
2682
|
+
} catch {
|
|
2683
|
+
restoreFailed.push(d.file);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
throw new ThemeApplyError(
|
|
2687
|
+
`${w.file} \uB97C \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${errorMessage(err)}).`,
|
|
2688
|
+
w.file,
|
|
2689
|
+
restored,
|
|
2690
|
+
restoreFailed
|
|
2691
|
+
);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
return done.map((w) => w.file);
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
// src/theme/index.ts
|
|
2698
|
+
var TOKENS_INSTALL_COMMAND = `pnpm add ${TOKENS_PACKAGE}@^${MIN_BRAND_TOKENS_VERSION}`;
|
|
2699
|
+
function tokensStatusGuide(status, version) {
|
|
2700
|
+
switch (status) {
|
|
2701
|
+
case "not-installed":
|
|
2702
|
+
return [
|
|
2703
|
+
chalk8.yellow(`${TOKENS_PACKAGE} \uAC00 \uC124\uCE58\uB3FC \uC788\uC9C0 \uC54A\uC544 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`),
|
|
2704
|
+
` \uC124\uCE58: ${chalk8.cyan(TOKENS_INSTALL_COMMAND)}`
|
|
2705
|
+
];
|
|
2706
|
+
case "unsupported":
|
|
2707
|
+
return [
|
|
2708
|
+
chalk8.yellow(
|
|
2709
|
+
`${TOKENS_PACKAGE} ${version ?? "(\uBC84\uC804 \uBAA8\uB984)"} \uC740 \uBE0C\uB79C\uB4DC\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1 \uD544\uC694).`
|
|
2710
|
+
),
|
|
2711
|
+
` \uC5C5\uADF8\uB808\uC774\uB4DC: ${chalk8.cyan(TOKENS_INSTALL_COMMAND)}`
|
|
2712
|
+
];
|
|
2713
|
+
case "not-built":
|
|
2714
|
+
return [
|
|
2715
|
+
chalk8.yellow(
|
|
2716
|
+
`${TOKENS_PACKAGE}${version ? ` ${version}` : ""} \uB294 \uC788\uC9C0\uB9CC \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C\uC774 \uC5C6\uC5B4 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`
|
|
2717
|
+
),
|
|
2718
|
+
` \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 ${chalk8.cyan(`pnpm --filter ${TOKENS_PACKAGE} build`)}, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: ${chalk8.cyan(TOKENS_INSTALL_COMMAND)}`
|
|
2719
|
+
];
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
function renderThemeList(result) {
|
|
2723
|
+
if (result.status !== "ok") {
|
|
2724
|
+
return { lines: ["", ...tokensStatusGuide(result.status, result.version), ""], exitCode: 1 };
|
|
2725
|
+
}
|
|
2726
|
+
if (result.brands.length === 0) {
|
|
2727
|
+
return {
|
|
2728
|
+
lines: ["", chalk8.yellow(`\uC124\uCE58\uB41C ${TOKENS_PACKAGE} ${result.version ?? ""} \uC5D0 \uBE0C\uB79C\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`), ""],
|
|
2729
|
+
exitCode: 0
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
const width = Math.max(...result.brands.map((b) => b.name.length));
|
|
2733
|
+
const lines = [
|
|
2734
|
+
"",
|
|
2735
|
+
chalk8.blue(`AXIS \uBE0C\uB79C\uB4DC (${result.brands.length}\uAC1C, ${TOKENS_PACKAGE} ${result.version ?? ""})`),
|
|
2736
|
+
""
|
|
2737
|
+
];
|
|
2738
|
+
for (const b of result.brands) {
|
|
2739
|
+
lines.push(
|
|
2740
|
+
` ${chalk8.cyan(b.name.padEnd(width))} ${b.description} ${chalk8.gray(`(${b.themes.join(" \xB7 ")})`)}`
|
|
2741
|
+
);
|
|
2742
|
+
}
|
|
2743
|
+
lines.push("", chalk8.gray("\uC0AC\uC6A9\uBC95: axis theme info <brand>"), "");
|
|
2744
|
+
return { lines, exitCode: 0 };
|
|
2745
|
+
}
|
|
2746
|
+
function a11yValue(value) {
|
|
2747
|
+
return value === null || value === void 0 || value === "" ? "-" : String(value);
|
|
2748
|
+
}
|
|
2749
|
+
function tokenTable(brand) {
|
|
2750
|
+
const rows = KEY_TOKENS.filter(
|
|
2751
|
+
(k) => k in brand.tokens.light || k in brand.tokens.dark
|
|
2752
|
+
).map((k) => [k, brand.tokens.light[k] ?? "-", brand.tokens.dark[k] ?? "-"]);
|
|
2753
|
+
const missing = KEY_TOKENS.filter((k) => !(k in brand.tokens.light) && !(k in brand.tokens.dark));
|
|
2754
|
+
const lines = [];
|
|
2755
|
+
if (rows.length > 0) {
|
|
2756
|
+
const header = ["\uD1A0\uD070", "\uB77C\uC774\uD2B8", "\uB2E4\uD06C"];
|
|
2757
|
+
const w0 = Math.max(header[0].length, ...rows.map((r) => r[0].length));
|
|
2758
|
+
const w1 = Math.max(header[1].length, ...rows.map((r) => r[1].length));
|
|
2759
|
+
lines.push(chalk8.gray(` ${header[0].padEnd(w0)} ${header[1].padEnd(w1)} ${header[2]}`));
|
|
2760
|
+
for (const [k, l, d] of rows) {
|
|
2761
|
+
lines.push(` ${k.padEnd(w0)} ${l.padEnd(w1)} ${d}`);
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
if (missing.length > 0) {
|
|
2765
|
+
lines.push(chalk8.gray(` \uBE0C\uB79C\uB4DC\uAC00 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC74C: ${missing.join(", ")}`));
|
|
2766
|
+
}
|
|
2767
|
+
return lines;
|
|
2768
|
+
}
|
|
2769
|
+
function renderThemeInfo(result, name) {
|
|
2770
|
+
if (result.status !== "ok") {
|
|
2771
|
+
return { lines: ["", ...tokensStatusGuide(result.status, result.version), ""], exitCode: 1 };
|
|
2772
|
+
}
|
|
2773
|
+
const brand = result.brand;
|
|
2774
|
+
if (!brand) {
|
|
2775
|
+
return {
|
|
2776
|
+
lines: [
|
|
2777
|
+
"",
|
|
2778
|
+
chalk8.red(`\uBE0C\uB79C\uB4DC '${name}' \uAC00 \uC124\uCE58\uB41C ${TOKENS_PACKAGE} ${result.version ?? ""} \uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4.`),
|
|
2779
|
+
` \uC124\uCE58\uB41C \uBE0C\uB79C\uB4DC: ${result.available.length > 0 ? result.available.join(", ") : "(\uC5C6\uC74C)"}`,
|
|
2780
|
+
chalk8.gray(" \uBAA9\uB85D: axis theme list"),
|
|
2781
|
+
""
|
|
2782
|
+
],
|
|
2783
|
+
exitCode: 1
|
|
2784
|
+
};
|
|
2785
|
+
}
|
|
2786
|
+
const lines = [
|
|
2787
|
+
"",
|
|
2788
|
+
chalk8.blue(`\uBE0C\uB79C\uB4DC ${brand.name}`),
|
|
2789
|
+
` \uC124\uBA85: ${brand.description}`,
|
|
2790
|
+
` \uD14C\uB9C8: ${brand.themes.join(" \xB7 ")}`,
|
|
2791
|
+
"",
|
|
2792
|
+
chalk8.bold("Import (globals.css, @charset \xB7 \uB2E4\uB978 @import \uB2E4\uC74C)"),
|
|
2793
|
+
` @import "${brand.importPath}";`,
|
|
2794
|
+
"",
|
|
2795
|
+
chalk8.bold("Provider (@axis-ds/theme 1.3.0 \uC774\uC0C1)"),
|
|
2796
|
+
...brand.providerExample.split("\n").map((l) => l ? ` ${l}` : ""),
|
|
2797
|
+
chalk8.gray(
|
|
2798
|
+
` ThemeProvider \uB098 <html data-brand="${brand.name}"> \uAC00 \uC5C6\uC73C\uBA74 import \uB9CC\uC73C\uB85C\uB294 \uD654\uBA74\uC774 \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`
|
|
2799
|
+
),
|
|
2800
|
+
"",
|
|
2801
|
+
chalk8.bold("\uC8FC\uC694 \uD1A0\uD070"),
|
|
2802
|
+
...tokenTable(brand),
|
|
2803
|
+
"",
|
|
2804
|
+
chalk8.bold("\uBCF4\uC815 \uB0B4\uC5ED"),
|
|
2805
|
+
` a11y \uC0C1\uD0DC: ${a11yValue(brand.adjustments.a11y.status)}`,
|
|
2806
|
+
` \uC810\uAC80\uC77C: ${a11yValue(brand.adjustments.a11y.checkedAt)}`,
|
|
2807
|
+
` \uAC8C\uC774\uD2B8: ${a11yValue(brand.adjustments.a11y.gate)}`,
|
|
2808
|
+
` \uADFC\uAC70 \uBB38\uC11C: ${brand.adjustments.reference}`,
|
|
2809
|
+
chalk8.gray(" \uBCF4\uC815 \uC804 \xB7 \uD6C4 \uAC12\uC740 \uC774 \uBC84\uC804\uC5D0\uC11C \uCD9C\uB825\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."),
|
|
2810
|
+
""
|
|
2811
|
+
];
|
|
2812
|
+
return { lines, exitCode: 0 };
|
|
2813
|
+
}
|
|
2814
|
+
function rel(plan, file) {
|
|
2815
|
+
return path10.relative(plan.baseDir, file) || file;
|
|
2816
|
+
}
|
|
2817
|
+
function renderThemeAdd(plan, written) {
|
|
2818
|
+
const error = plan.errors[0];
|
|
2819
|
+
if (error) {
|
|
2820
|
+
const lines2 = [""];
|
|
2821
|
+
switch (error.kind) {
|
|
2822
|
+
case "no-config":
|
|
2823
|
+
lines2.push(
|
|
2824
|
+
chalk8.red("axis.config.json \uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."),
|
|
2825
|
+
` \uBA3C\uC800 ${chalk8.cyan("axis init")} \uC744 \uC2E4\uD589\uD558\uC138\uC694.`
|
|
2826
|
+
);
|
|
2827
|
+
break;
|
|
2828
|
+
case "invalid-config":
|
|
2829
|
+
lines2.push(chalk8.red(`axis.config.json \uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${error.message}). \uC544\uBB34\uAC83\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`));
|
|
2830
|
+
break;
|
|
2831
|
+
case "invalid-package-json":
|
|
2832
|
+
lines2.push(chalk8.red(`package.json \uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${error.message}). \uC544\uBB34\uAC83\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`));
|
|
2833
|
+
break;
|
|
2834
|
+
case "invalid-name":
|
|
2835
|
+
lines2.push(
|
|
2836
|
+
chalk8.red(`\uBE0C\uB79C\uB4DC \uC774\uB984 '${error.brand}' \uAC00 \uADDC\uCE59(\uC18C\uBB38\uC790 \xB7 \uC22B\uC790 \xB7 \uD558\uC774\uD508, \uC608: ontology)\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`)
|
|
2837
|
+
);
|
|
2838
|
+
break;
|
|
2839
|
+
case "css-outside-project":
|
|
2840
|
+
lines2.push(
|
|
2841
|
+
chalk8.red(
|
|
2842
|
+
`CSS \uD30C\uC77C ${error.file} \uC758 \uC2E4\uC81C \uC704\uCE58(${error.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`
|
|
2843
|
+
),
|
|
2844
|
+
` axis.config.json \uC758 globalCss \uB97C \uD504\uB85C\uC81D\uD2B8 \uC548 \uD30C\uC77C\uB85C \uACE0\uCE58\uAC70\uB098, \uADF8 \uD30C\uC77C\uC5D0 \uC9C1\uC811 \uB123\uC73C\uC138\uC694: @import "${plan.importPath}";`
|
|
2845
|
+
);
|
|
2846
|
+
break;
|
|
2847
|
+
case "css-not-stylesheet":
|
|
2848
|
+
lines2.push(
|
|
2849
|
+
chalk8.red(`${error.file} \uC758 \uC2E4\uC81C \uB300\uC0C1(${error.realPath})\uC774 CSS \uD30C\uC77C(.css)\uC774 \uC544\uB2D9\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`),
|
|
2850
|
+
` axis.config.json \uC758 globalCss \uB97C \uC804\uC5ED CSS \uD30C\uC77C\uB85C \uACE0\uCE58\uAC70\uB098, \uADF8 \uD30C\uC77C\uC5D0 \uC9C1\uC811 \uB123\uC73C\uC138\uC694: @import "${plan.importPath}";`
|
|
2851
|
+
);
|
|
2852
|
+
break;
|
|
2853
|
+
case "unknown-brand":
|
|
2854
|
+
lines2.push(
|
|
2855
|
+
chalk8.red(`\uBE0C\uB79C\uB4DC '${error.brand}' \uAC00 \uC124\uCE58\uB41C ${TOKENS_PACKAGE} ${error.version ?? ""} \uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4.`),
|
|
2856
|
+
` \uC124\uCE58\uB41C \uBE0C\uB79C\uB4DC: ${error.available.length > 0 ? error.available.join(", ") : "(\uC5C6\uC74C)"}`,
|
|
2857
|
+
chalk8.gray(" \uBAA9\uB85D: axis theme list")
|
|
2858
|
+
);
|
|
2859
|
+
break;
|
|
2860
|
+
}
|
|
2861
|
+
lines2.push("");
|
|
2862
|
+
return { lines: lines2, exitCode: 1 };
|
|
2863
|
+
}
|
|
2864
|
+
const lines = ["", chalk8.blue(`\uBE0C\uB79C\uB4DC ${plan.brand} \uC801\uC6A9`), ""];
|
|
2865
|
+
if (plan.unverifiedBrand) {
|
|
2866
|
+
lines.push(
|
|
2867
|
+
chalk8.yellow(
|
|
2868
|
+
` ! ${TOKENS_PACKAGE} \uB97C \uC77D\uC744 \uC218 \uC5C6\uC5B4(${plan.tokens.status}) \uC774\uB984 \uADDC\uCE59\uB9CC \uD655\uC778\uD588\uC2B5\uB2C8\uB2E4. \uC124\uCE58 \uD6C4 axis theme list \uB85C '${plan.brand}' \uAC00 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.`
|
|
2869
|
+
)
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2872
|
+
const css = plan.css;
|
|
2873
|
+
if (css?.configuredMissing) {
|
|
2874
|
+
lines.push(
|
|
2875
|
+
chalk8.yellow(
|
|
2876
|
+
css.file ? ` ! axis.config.json \uC758 globalCss(${css.configuredMissing})\uAC00 \uC5C6\uC5B4 ${rel(plan, css.file)} \uC5D0 \uCD94\uAC00\uD569\uB2C8\uB2E4.` : ` ! axis.config.json \uC758 globalCss(${css.configuredMissing})\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`
|
|
2877
|
+
)
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2880
|
+
if (css?.action === "add" && css.file) {
|
|
2881
|
+
lines.push(` ${chalk8.green("\u2713")} ${rel(plan, css.file)}: @import "${plan.importPath}"; \uCD94\uAC00`);
|
|
2882
|
+
} else if (css?.action === "exists" && css.file) {
|
|
2883
|
+
lines.push(` ${chalk8.gray("-")} ${rel(plan, css.file)}: import \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uAC74\uB108\uB700`);
|
|
2884
|
+
} else {
|
|
2885
|
+
lines.push(
|
|
2886
|
+
chalk8.yellow(" ! CSS \uC9C4\uC785\uC810(globalCss \xB7 app/globals.css \xB7 src/app/globals.css \xB7 globals.css)\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4."),
|
|
2887
|
+
` \uC804\uC5ED CSS \uB9E8 \uC55E(@charset \xB7 \uB2E4\uB978 @import \uB2E4\uC74C)\uC5D0 \uC9C1\uC811 \uB123\uC73C\uC138\uC694: @import "${plan.importPath}";`
|
|
2888
|
+
);
|
|
2889
|
+
}
|
|
2890
|
+
if (css && css.otherBrands.length > 0) {
|
|
2891
|
+
lines.push(
|
|
2892
|
+
chalk8.yellow(
|
|
2893
|
+
` ! \uB2E4\uB978 \uBE0C\uB79C\uB4DC import(${css.otherBrands.join(", ")})\uB294 \uADF8\uB300\uB85C \uB450\uC5C8\uC2B5\uB2C8\uB2E4. \uC4F0\uC9C0 \uC54A\uC73C\uBA74 \uC774\uC804 \uBE0C\uB79C\uB4DC import \uB97C \uC9C0\uC6CC\uB3C4 \uB429\uB2C8\uB2E4.`
|
|
2894
|
+
)
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
const dep = plan.dependency;
|
|
2898
|
+
if (dep?.action === "add") {
|
|
2899
|
+
lines.push(
|
|
2900
|
+
` ${chalk8.green("\u2713")} package.json: dependencies \uC5D0 "${TOKENS_PACKAGE}": "${TOKENS_DEPENDENCY_RANGE}" \uCD94\uAC00`,
|
|
2901
|
+
` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk8.cyan(plan.installCommand)}`
|
|
2902
|
+
);
|
|
2903
|
+
} else if (dep?.action === "present") {
|
|
2904
|
+
lines.push(` ${chalk8.gray("-")} package.json: ${TOKENS_PACKAGE} ${dep.declaredRange} \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uBC94\uC704\uB97C \uBC14\uAFB8\uC9C0 \uC54A\uC74C`);
|
|
2905
|
+
} else if (dep?.action === "no-package-json") {
|
|
2906
|
+
lines.push(
|
|
2907
|
+
chalk8.yellow(` ! package.json \uC774 \uC5C6\uC5B4 \uC758\uC874\uC131\uC744 \uCD94\uAC00\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${TOKENS_INSTALL_COMMAND}`)
|
|
2908
|
+
);
|
|
2909
|
+
}
|
|
2910
|
+
if (dep?.upgrade) {
|
|
2911
|
+
lines.push(
|
|
2912
|
+
chalk8.yellow(
|
|
2913
|
+
` ! \uC124\uCE58\uB41C ${TOKENS_PACKAGE} ${plan.tokens.version} \uC740 \uBE0C\uB79C\uB4DC\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1 \uD544\uC694).`
|
|
2914
|
+
),
|
|
2915
|
+
` \uC5C5\uADF8\uB808\uC774\uB4DC: ${chalk8.cyan(TOKENS_INSTALL_COMMAND)}`
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
if (plan.configChanged) {
|
|
2919
|
+
lines.push(` ${chalk8.green("\u2713")} axis.config.json: "brand": "${plan.brand}" \uAE30\uB85D`);
|
|
2920
|
+
} else {
|
|
2921
|
+
lines.push(` ${chalk8.gray("-")} axis.config.json: brand \uAC00 \uC774\uBBF8 "${plan.brand}"`);
|
|
2922
|
+
}
|
|
2923
|
+
lines.push(
|
|
2924
|
+
"",
|
|
2925
|
+
chalk8.bold(`Provider (${THEME_PACKAGE} 1.3.0 \uC774\uC0C1)`),
|
|
2926
|
+
...providerExample(plan.brand).split("\n").map((l) => l ? ` ${l}` : ""),
|
|
2927
|
+
chalk8.gray(
|
|
2928
|
+
` ThemeProvider \uB098 <html data-brand="${plan.brand}"> \uAC00 \uC5C6\uC73C\uBA74 import \uB9CC\uC73C\uB85C\uB294 \uD654\uBA74\uC774 \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`
|
|
2929
|
+
)
|
|
2930
|
+
);
|
|
2931
|
+
if (dep?.themeMissing) {
|
|
2932
|
+
lines.push(` ${THEME_PACKAGE} \uC124\uCE58: ${chalk8.cyan(`pnpm add ${THEME_PACKAGE}@^1.3.0`)}`);
|
|
2933
|
+
}
|
|
2934
|
+
lines.push("", chalk8.gray(written.length > 0 ? `\uD30C\uC77C ${written.length}\uAC1C\uB97C \uBC14\uAFE8\uC2B5\uB2C8\uB2E4.` : "\uBC14\uAFBC \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."), "");
|
|
2935
|
+
return { lines, exitCode: 0 };
|
|
2936
|
+
}
|
|
2937
|
+
function renderThemeAddFailure(plan, err) {
|
|
2938
|
+
const lines = [""];
|
|
2939
|
+
if (err instanceof ThemeApplyError) {
|
|
2940
|
+
lines.push(chalk8.red(err.message));
|
|
2941
|
+
if (err.restored.length > 0) {
|
|
2942
|
+
lines.push(` \uBA3C\uC800 \uC4F4 \uD30C\uC77C\uC740 \uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4: ${err.restored.map((f) => rel(plan, f)).join(", ")}`);
|
|
2943
|
+
}
|
|
2944
|
+
if (err.restoreFailed.length > 0) {
|
|
2945
|
+
lines.push(
|
|
2946
|
+
chalk8.red(` \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD574 \uBC14\uB010 \uCC44 \uB0A8\uC740 \uD30C\uC77C: ${err.restoreFailed.map((f) => rel(plan, f)).join(", ")}`)
|
|
2947
|
+
);
|
|
2948
|
+
}
|
|
2949
|
+
if (err.restored.length === 0 && err.restoreFailed.length === 0) {
|
|
2950
|
+
lines.push(" \uBC14\uB010 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
2951
|
+
}
|
|
2952
|
+
} else {
|
|
2953
|
+
lines.push(chalk8.red(err instanceof Error ? err.message : String(err)), " \uBC14\uB010 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
2954
|
+
}
|
|
2955
|
+
lines.push("");
|
|
2956
|
+
return { lines, exitCode: 1 };
|
|
2957
|
+
}
|
|
2958
|
+
function print(output) {
|
|
2959
|
+
for (const line of output.lines) console.log(line);
|
|
2960
|
+
if (output.exitCode !== 0) process.exitCode = output.exitCode;
|
|
2961
|
+
}
|
|
2962
|
+
function registerThemeCommand(program2) {
|
|
2963
|
+
const themeCmd = program2.command("theme").description("\uBE0C\uB79C\uB4DC \uD14C\uB9C8 (@axis-ds/tokens \uBE0C\uB79C\uB4DC)");
|
|
2964
|
+
themeCmd.command("list").alias("ls").description("\uC124\uCE58\uB41C @axis-ds/tokens \uC758 \uBE0C\uB79C\uB4DC \uBAA9\uB85D").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((options) => {
|
|
2965
|
+
const baseDir = path10.resolve(options.dir || ".");
|
|
2966
|
+
print(renderThemeList(listBrands(baseDir)));
|
|
2967
|
+
});
|
|
2968
|
+
themeCmd.command("info <brand>").description("\uBE0C\uB79C\uB4DC \uC0C1\uC138: import \uACBD\uB85C \xB7 Provider \uC608\uC2DC \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((name, options) => {
|
|
2969
|
+
const baseDir = path10.resolve(options.dir || ".");
|
|
2970
|
+
print(renderThemeInfo(getBrand(baseDir, name), name));
|
|
2971
|
+
});
|
|
2972
|
+
themeCmd.command("add <brand>").description("\uBE0C\uB79C\uB4DC \uC801\uC6A9: CSS import \xB7 package.json \uC758\uC874\uC131 \xB7 axis.config.json brand (\uC124\uCE58\uB294 \uC548\uB0B4\uB9CC)").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((name, options) => {
|
|
2973
|
+
const baseDir = path10.resolve(options.dir || ".");
|
|
2974
|
+
const plan = planThemeAdd(baseDir, name);
|
|
2975
|
+
let written = [];
|
|
2976
|
+
if (plan.errors.length === 0) {
|
|
2977
|
+
try {
|
|
2978
|
+
written = applyThemeAdd(plan);
|
|
2979
|
+
} catch (err) {
|
|
2980
|
+
print(renderThemeAddFailure(plan, err));
|
|
2981
|
+
return;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
print(renderThemeAdd(plan, written));
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
// src/init/index.ts
|
|
2989
|
+
import chalk10 from "chalk";
|
|
2990
|
+
import prompts2 from "prompts";
|
|
2991
|
+
|
|
2992
|
+
// src/init/init.ts
|
|
2993
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
2994
|
+
import path11 from "path";
|
|
2995
|
+
import chalk9 from "chalk";
|
|
2996
|
+
import fs10 from "fs-extra";
|
|
2997
|
+
var CLSX_RANGE = "^2.1.1";
|
|
2998
|
+
var TAILWIND_MERGE_RANGES = {
|
|
2999
|
+
tailwind4: "^3.4.0",
|
|
3000
|
+
tailwind3: "^2.6.0"
|
|
3001
|
+
};
|
|
3002
|
+
var VERSION = String.raw`v?(\d+)(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
|
|
3003
|
+
function versionParts(token) {
|
|
3004
|
+
const m = new RegExp(`^${VERSION}$`).exec(token);
|
|
3005
|
+
if (!m) return void 0;
|
|
3006
|
+
if (/^v?0\.0\.0-/.test(token)) return void 0;
|
|
3007
|
+
return { major: Number(m[1]), minor: m[2], patch: m[3] };
|
|
3008
|
+
}
|
|
3009
|
+
var isWild = (part) => part === void 0 || /^[xX*]$/.test(part);
|
|
3010
|
+
function comparatorBounds(op, v) {
|
|
3011
|
+
switch (op) {
|
|
3012
|
+
case ">=":
|
|
3013
|
+
return { lower: v.major };
|
|
3014
|
+
case ">":
|
|
3015
|
+
return { lower: isWild(v.minor) ? v.major + 1 : v.major };
|
|
3016
|
+
case "<=":
|
|
3017
|
+
return { upper: v.major };
|
|
3018
|
+
case "<": {
|
|
3019
|
+
const zeroOrWild = (part) => isWild(part) || Number(part) === 0;
|
|
3020
|
+
return { upper: zeroOrWild(v.minor) && zeroOrWild(v.patch) ? v.major - 1 : v.major };
|
|
3021
|
+
}
|
|
3022
|
+
default:
|
|
3023
|
+
return { lower: v.major, upper: v.major };
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
function tailwindMajorBounds(range) {
|
|
3027
|
+
const r = range.trim();
|
|
3028
|
+
if (r === "" || r.includes("||")) return void 0;
|
|
3029
|
+
const simple = new RegExp(`^(?:\\^|~|=)?\\s*(${VERSION})$`).exec(r);
|
|
3030
|
+
if (simple) {
|
|
3031
|
+
const v = versionParts(simple[1]);
|
|
3032
|
+
return v ? { lower: v.major, upper: v.major } : void 0;
|
|
3033
|
+
}
|
|
3034
|
+
const hyphen = new RegExp(`^(${VERSION})\\s+-\\s+(${VERSION})$`).exec(r);
|
|
3035
|
+
if (hyphen) {
|
|
3036
|
+
const tokens2 = r.split(/\s+-\s+/);
|
|
3037
|
+
const a = versionParts(tokens2[0]);
|
|
3038
|
+
const b = versionParts(tokens2[1]);
|
|
3039
|
+
return a && b && a.major <= b.major ? { lower: a.major, upper: b.major } : void 0;
|
|
3040
|
+
}
|
|
3041
|
+
const tokens = r.replace(/(>=|<=|>|<|=)\s+/g, "$1").split(/\s+/);
|
|
3042
|
+
const lowers = [];
|
|
3043
|
+
const uppers = [];
|
|
3044
|
+
for (const t of tokens) {
|
|
3045
|
+
const c = /^(>=|<=|>|<|=)(.+)$/.exec(t);
|
|
3046
|
+
if (!c) return void 0;
|
|
3047
|
+
const v = versionParts(c[2]);
|
|
3048
|
+
if (v === void 0) return void 0;
|
|
3049
|
+
const b = comparatorBounds(c[1], v);
|
|
3050
|
+
if (b.lower !== void 0) lowers.push(b.lower);
|
|
3051
|
+
if (b.upper !== void 0) uppers.push(b.upper);
|
|
3052
|
+
}
|
|
3053
|
+
if (lowers.length === 0) return void 0;
|
|
3054
|
+
const lower = Math.max(...lowers);
|
|
3055
|
+
const upper = uppers.length > 0 ? Math.min(...uppers) : void 0;
|
|
3056
|
+
if (upper !== void 0 && upper < lower) return void 0;
|
|
3057
|
+
return upper !== void 0 ? { lower, upper } : { lower };
|
|
3058
|
+
}
|
|
3059
|
+
function majorWithin(major, bounds) {
|
|
3060
|
+
return major >= bounds.lower && (bounds.upper === void 0 || major <= bounds.upper);
|
|
3061
|
+
}
|
|
3062
|
+
function majorFromVersion(version) {
|
|
3063
|
+
if (typeof version !== "string") return void 0;
|
|
3064
|
+
const v = version.trim();
|
|
3065
|
+
const m = /^v?(\d+)\.\d+\.\d+(?:[-+][0-9A-Za-z.+-]*)?$/.exec(v);
|
|
3066
|
+
if (!m || /^v?0\.0\.0-/.test(v)) return void 0;
|
|
3067
|
+
return Number(m[1]);
|
|
3068
|
+
}
|
|
3069
|
+
function detectTailwind(baseDirInput, pkg) {
|
|
3070
|
+
const baseDir = path11.resolve(baseDirInput);
|
|
3071
|
+
const installedFile = path11.join(baseDir, "node_modules", "tailwindcss", "package.json");
|
|
3072
|
+
const declared = pkg ? hasDependency(pkg, "tailwindcss") : void 0;
|
|
3073
|
+
const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
|
|
3074
|
+
const declaredMajor = bounds?.lower;
|
|
3075
|
+
try {
|
|
3076
|
+
const installed = JSON.parse(readFileSync3(installedFile, "utf8"));
|
|
3077
|
+
const version = isPlainObject(installed) ? installed.version : void 0;
|
|
3078
|
+
const major = majorFromVersion(version);
|
|
3079
|
+
if (major !== void 0) {
|
|
3080
|
+
const found = { major, source: "installed", value: String(version) };
|
|
3081
|
+
if (declared !== void 0 && bounds !== void 0 && !majorWithin(major, bounds)) {
|
|
3082
|
+
found.mismatch = { declared, declaredMajor: bounds.lower };
|
|
3083
|
+
}
|
|
3084
|
+
return found;
|
|
3085
|
+
}
|
|
3086
|
+
} catch {
|
|
3087
|
+
}
|
|
3088
|
+
if (declared !== void 0) {
|
|
3089
|
+
if (declaredMajor !== void 0) return { major: declaredMajor, source: "declared", value: declared };
|
|
3090
|
+
return { source: "none", value: declared };
|
|
3091
|
+
}
|
|
3092
|
+
return { source: "none" };
|
|
3093
|
+
}
|
|
3094
|
+
function selectUtilsDependencies(tailwind) {
|
|
3095
|
+
return {
|
|
3096
|
+
clsx: CLSX_RANGE,
|
|
3097
|
+
"tailwind-merge": tailwind.major !== void 0 && tailwind.major >= 4 ? TAILWIND_MERGE_RANGES.tailwind4 : TAILWIND_MERGE_RANGES.tailwind3
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
function tailwindWarnings(tailwind, installCommand) {
|
|
3101
|
+
const out = [];
|
|
3102
|
+
if (tailwind.source === "none" && tailwind.value !== void 0) {
|
|
3103
|
+
out.push(
|
|
3104
|
+
`! tailwindcss \uC120\uC5B8(${tailwind.value})\uC740 \uD310\uC815 \uBD88\uAC00 - \uAE30\uBCF8\uAC12 \uC0AC\uC6A9(Tailwind 3, tailwind-merge ${TAILWIND_MERGE_RANGES.tailwind3}). Tailwind 4 \uC774\uC0C1\uC774\uBA74 tailwind-merge \uB97C ${TAILWIND_MERGE_RANGES.tailwind4} \uC73C\uB85C \uBC14\uAFB8\uC138\uC694.`
|
|
3105
|
+
);
|
|
3106
|
+
}
|
|
3107
|
+
if (tailwind.mismatch) {
|
|
3108
|
+
out.push(
|
|
3109
|
+
`! \uC124\uCE58\uBCF8 tailwindcss ${tailwind.value}(major ${tailwind.major})\uC640 package.json \uC120\uC5B8 ${tailwind.mismatch.declared}(major ${tailwind.mismatch.declaredMajor})\uAC00 \uB2E4\uB984 - \uC124\uCE58\uBCF8\uC744 \uB530\uB790\uC2B5\uB2C8\uB2E4. ${installCommand} \uB4A4 tailwind-merge \uBC94\uC704\uB97C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.`
|
|
3110
|
+
);
|
|
3111
|
+
}
|
|
3112
|
+
return out;
|
|
3113
|
+
}
|
|
3114
|
+
function describeTailwindBasis(tailwind) {
|
|
3115
|
+
if (tailwind.source === "installed") return `\uC124\uCE58\uB41C tailwindcss ${tailwind.value}`;
|
|
3116
|
+
if (tailwind.source === "declared") return `package.json \uC758 tailwindcss ${tailwind.value}`;
|
|
3117
|
+
if (tailwind.value !== void 0) {
|
|
3118
|
+
return `package.json \uC758 tailwindcss ${tailwind.value} \uB85C \uBC84\uC804\uC744 \uD310\uC815\uD558\uC9C0 \uBABB\uD574 \uAE30\uBCF8\uAC12(Tailwind 3)`;
|
|
3119
|
+
}
|
|
3120
|
+
return "tailwindcss \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uAE30\uBCF8\uAC12(Tailwind 3)";
|
|
3121
|
+
}
|
|
3122
|
+
var UTILS_TS_CONTENT = `import { type ClassValue, clsx } from "clsx";
|
|
2149
3123
|
import { twMerge } from "tailwind-merge";
|
|
2150
3124
|
|
|
2151
3125
|
export function cn(...inputs: ClassValue[]) {
|
|
2152
3126
|
return twMerge(clsx(inputs));
|
|
2153
3127
|
}
|
|
2154
|
-
|
|
3128
|
+
`;
|
|
3129
|
+
var INIT_DEFAULTS = {
|
|
3130
|
+
componentsDir: "./src/components/ui",
|
|
3131
|
+
tailwindConfig: "./tailwind.config.ts",
|
|
3132
|
+
globalCss: "./src/app/globals.css"
|
|
3133
|
+
};
|
|
3134
|
+
var INIT_NEXT_STEP_COMMAND = "npx @axis-ds/cli add button";
|
|
3135
|
+
var BOM = "\uFEFF";
|
|
3136
|
+
function addCommandFor(installCommand, deps) {
|
|
3137
|
+
const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
|
|
3138
|
+
if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
|
|
3139
|
+
if (installCommand.startsWith("npm")) return `npm install ${specs}`;
|
|
3140
|
+
return `pnpm add ${specs}`;
|
|
3141
|
+
}
|
|
3142
|
+
function planUtilsDependencies(baseDirInput) {
|
|
3143
|
+
const baseDir = path11.resolve(baseDirInput);
|
|
3144
|
+
const installCommand = detectInstallCommand(baseDir);
|
|
3145
|
+
const tailwind0 = detectTailwind(baseDir);
|
|
3146
|
+
const ranges0 = selectUtilsDependencies(tailwind0);
|
|
3147
|
+
const plan = {
|
|
3148
|
+
action: "no-package-json",
|
|
3149
|
+
added: [],
|
|
3150
|
+
present: [],
|
|
3151
|
+
ranges: ranges0,
|
|
3152
|
+
tailwind: tailwind0,
|
|
3153
|
+
installCommand,
|
|
3154
|
+
addCommand: addCommandFor(installCommand, ranges0)
|
|
3155
|
+
};
|
|
3156
|
+
const pkgFile = path11.join(baseDir, "package.json");
|
|
3157
|
+
if (!existsSync3(pkgFile)) return plan;
|
|
3158
|
+
const unwritable = (reason) => ({ ...plan, action: "unwritable", reason });
|
|
3159
|
+
let where;
|
|
3160
|
+
try {
|
|
3161
|
+
where = realPathInside(baseDir, pkgFile);
|
|
3162
|
+
} catch (err) {
|
|
3163
|
+
return unwritable(err.message);
|
|
3164
|
+
}
|
|
3165
|
+
if (!where.inside) return unwritable(`\uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`);
|
|
3166
|
+
let text;
|
|
3167
|
+
try {
|
|
3168
|
+
text = readFileSync3(pkgFile, "utf8");
|
|
3169
|
+
} catch (err) {
|
|
3170
|
+
return unwritable(err.message);
|
|
3171
|
+
}
|
|
3172
|
+
const bom = text.startsWith(BOM) ? BOM : "";
|
|
3173
|
+
const body = bom ? text.slice(1) : text;
|
|
3174
|
+
let pkg;
|
|
3175
|
+
try {
|
|
3176
|
+
const parsed = JSON.parse(body);
|
|
3177
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3178
|
+
pkg = parsed;
|
|
3179
|
+
} catch (err) {
|
|
3180
|
+
return unwritable(`JSON \uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${err.message}`);
|
|
3181
|
+
}
|
|
3182
|
+
plan.tailwind = detectTailwind(baseDir, pkg);
|
|
3183
|
+
plan.ranges = selectUtilsDependencies(plan.tailwind);
|
|
3184
|
+
plan.addCommand = addCommandFor(installCommand, plan.ranges);
|
|
3185
|
+
const missing = {};
|
|
3186
|
+
for (const [name, range] of Object.entries(plan.ranges)) {
|
|
3187
|
+
const declared = hasDependency(pkg, name);
|
|
3188
|
+
if (declared !== void 0) plan.present.push({ name, range: declared });
|
|
3189
|
+
else missing[name] = range;
|
|
3190
|
+
}
|
|
3191
|
+
plan.added = Object.keys(missing);
|
|
3192
|
+
plan.addCommand = addCommandFor(installCommand, plan.added.length > 0 ? missing : plan.ranges);
|
|
3193
|
+
if (plan.added.length === 0) return { ...plan, action: "present" };
|
|
3194
|
+
if (pkg.dependencies !== void 0 && !isPlainObject(pkg.dependencies)) {
|
|
3195
|
+
return unwritable("dependencies \uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3196
|
+
}
|
|
3197
|
+
try {
|
|
3198
|
+
accessSync2(pkgFile, constants2.W_OK);
|
|
3199
|
+
} catch (err) {
|
|
3200
|
+
return unwritable(`\uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${err.message})`);
|
|
3201
|
+
}
|
|
3202
|
+
const deps = { ...pkg.dependencies ?? {}, ...missing };
|
|
3203
|
+
const after = bom + formatJsonLike(body, { ...pkg, dependencies: deps });
|
|
3204
|
+
return { ...plan, action: "add", write: { file: pkgFile, before: text, after } };
|
|
3205
|
+
}
|
|
3206
|
+
var defaultWriteFile = (file, data) => writeFileSync2(file, data);
|
|
3207
|
+
function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile) {
|
|
3208
|
+
const w = plan.write;
|
|
3209
|
+
if (plan.action !== "add" || !w) return false;
|
|
3210
|
+
const baseDir = path11.resolve(baseDirInput);
|
|
3211
|
+
const current = existsSync3(w.file) ? readFileSync3(w.file, "utf8") : null;
|
|
3212
|
+
if (current !== w.before) {
|
|
3213
|
+
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
3214
|
+
}
|
|
3215
|
+
const where = realPathInside(baseDir, w.file);
|
|
3216
|
+
if (!where.inside) {
|
|
3217
|
+
throw new Error(`${w.file} \uC758 \uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4. \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`);
|
|
3218
|
+
}
|
|
3219
|
+
JSON.parse(w.after.startsWith(BOM) ? w.after.slice(1) : w.after);
|
|
3220
|
+
try {
|
|
3221
|
+
writeFile(w.file, w.after);
|
|
3222
|
+
} catch (err) {
|
|
3223
|
+
const cause = err.message;
|
|
3224
|
+
let restored;
|
|
3225
|
+
try {
|
|
3226
|
+
writeFile(w.file, w.before);
|
|
3227
|
+
if (readFileSync3(w.file, "utf8") !== w.before) throw new Error("\uB418\uB3CC\uB9B0 \uB0B4\uC6A9\uC774 \uC6D0\uB798 \uB0B4\uC6A9\uACFC \uB2E4\uB985\uB2C8\uB2E4");
|
|
3228
|
+
restored = "\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4";
|
|
3229
|
+
} catch (restoreErr) {
|
|
3230
|
+
restored = `\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${restoreErr.message}). \uD30C\uC77C\uC774 \uC798\uB838\uAC70\uB098 \uBE44\uC5C8\uC744 \uC218 \uC788\uC73C\uB2C8 \uBC84\uC804 \uAD00\uB9AC \uB3C4\uAD6C \uB4F1\uC73C\uB85C \uBCF5\uAD6C\uD558\uC138\uC694`;
|
|
3231
|
+
}
|
|
3232
|
+
throw new Error(`${w.file} \uC744 \uC4F0\uB294 \uB3C4\uC911 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4(${cause}). ${restored}.`);
|
|
3233
|
+
}
|
|
3234
|
+
return true;
|
|
3235
|
+
}
|
|
3236
|
+
function reportDependencies(plan, log) {
|
|
3237
|
+
const presentText = plan.present.map((p) => `${p.name} (${p.range})`).join(", ");
|
|
3238
|
+
const basis = ` tailwind-merge \uBC94\uC704 \uAE30\uC900: ${describeTailwindBasis(plan.tailwind)}`;
|
|
3239
|
+
const logBasis = () => {
|
|
3240
|
+
log(chalk9.gray(basis));
|
|
3241
|
+
for (const w of tailwindWarnings(plan.tailwind, plan.installCommand)) log(chalk9.yellow(` ${w}`));
|
|
3242
|
+
};
|
|
3243
|
+
if (plan.action === "add") {
|
|
3244
|
+
const addedText = plan.added.map((n) => `${n}@${plan.ranges[n]}`).join(", ");
|
|
3245
|
+
log(chalk9.green(`\u2713 package.json dependencies \uC5D0 \uCD94\uAC00: ${addedText}`));
|
|
3246
|
+
if (plan.present.length > 0) log(chalk9.gray(` \uC774\uBBF8 \uC788\uC74C(\uBC84\uC804 \uC720\uC9C0): ${presentText}`));
|
|
3247
|
+
if (plan.added.includes("tailwind-merge")) logBasis();
|
|
3248
|
+
log(chalk9.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk9.cyan(plan.installCommand)}`));
|
|
3249
|
+
} else if (plan.action === "present") {
|
|
3250
|
+
log(chalk9.green(`\u2713 utils.ts \uC758\uC874\uC131\uC774 package.json \uC5D0 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4(\uBC84\uC804 \uC720\uC9C0): ${presentText}`));
|
|
3251
|
+
log(chalk9.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk9.cyan(plan.installCommand)}`));
|
|
3252
|
+
} else if (plan.action === "no-package-json") {
|
|
3253
|
+
log(chalk9.yellow("! package.json \uC774 \uC5C6\uC5B4 utils.ts \uC758\uC874\uC131(clsx, tailwind-merge)\uC744 \uCD94\uAC00\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."));
|
|
3254
|
+
log(chalk9.yellow(` \uC124\uCE58: ${chalk9.cyan(plan.addCommand)}`));
|
|
3255
|
+
logBasis();
|
|
3256
|
+
} else {
|
|
3257
|
+
log(chalk9.yellow(`! package.json \uC744 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(${plan.reason}).`));
|
|
3258
|
+
log(chalk9.yellow(` utils.ts \uC758\uC874\uC131 \uC124\uCE58: ${chalk9.cyan(plan.addCommand)}`));
|
|
3259
|
+
if (plan.addCommand.includes('"tailwind-merge@')) logBasis();
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
|
|
3263
|
+
const baseDir = path11.resolve(baseDirInput);
|
|
3264
|
+
const axisConfig = createInitConfig(
|
|
3265
|
+
{
|
|
3266
|
+
componentsDir: answers.componentsDir,
|
|
3267
|
+
tailwindConfig: answers.tailwindConfig,
|
|
3268
|
+
globalCss: answers.globalCss
|
|
3269
|
+
},
|
|
3270
|
+
registryUrl
|
|
2155
3271
|
);
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
3272
|
+
await fs10.writeJSON(path11.join(baseDir, "axis.config.json"), axisConfig, { spaces: 2 });
|
|
3273
|
+
log(chalk9.green("\u2713 axis.config.json \uC0DD\uC131 \uC644\uB8CC"));
|
|
3274
|
+
const utilsPath = path11.resolve(baseDir, answers.componentsDir, "utils.ts");
|
|
3275
|
+
await fs10.ensureDir(path11.dirname(utilsPath));
|
|
3276
|
+
await fs10.writeFile(utilsPath, UTILS_TS_CONTENT);
|
|
3277
|
+
log(chalk9.green("\u2713 utils.ts \uC0DD\uC131 \uC644\uB8CC"));
|
|
3278
|
+
const plan = planUtilsDependencies(baseDir);
|
|
3279
|
+
try {
|
|
3280
|
+
applyUtilsDependencies(baseDir, plan);
|
|
3281
|
+
} catch (err) {
|
|
3282
|
+
log(chalk9.red(`\u2717 package.json \uC744 \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${err.message}`));
|
|
3283
|
+
log(chalk9.yellow(" axis.config.json \uACFC utils.ts \uB294 \uC774\uBBF8 \uB9CC\uB4E4\uC5B4\uC84C\uC2B5\uB2C8\uB2E4."));
|
|
3284
|
+
log(chalk9.yellow(` utils.ts \uC758\uC874\uC131 \uC124\uCE58: ${chalk9.cyan(plan.addCommand)}`));
|
|
3285
|
+
process.exitCode = 1;
|
|
3286
|
+
return;
|
|
3287
|
+
}
|
|
3288
|
+
reportDependencies(plan, log);
|
|
3289
|
+
log(chalk9.blue("\n\uCD08\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C \uB2E4\uC74C \uBA85\uB839\uC5B4\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uCD94\uAC00\uD558\uC138\uC694:"));
|
|
3290
|
+
log(chalk9.cyan(` ${INIT_NEXT_STEP_COMMAND}
|
|
3291
|
+
`));
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
// src/init/index.ts
|
|
3295
|
+
function registerInitCommand(program2, registryUrl) {
|
|
3296
|
+
program2.command("init").description("\uD504\uB85C\uC81D\uD2B8\uC5D0 AXIS Design System \uCD08\uAE30\uD654").option("-y, --yes", "\uAE30\uBCF8\uAC12\uC73C\uB85C \uC790\uB3D9 \uC124\uC815").action(async (options) => {
|
|
3297
|
+
console.log(chalk10.blue("\n\u{1F3A8} AXIS Design System \uCD08\uAE30\uD654\n"));
|
|
3298
|
+
const config = options.yes ? { ...INIT_DEFAULTS } : await prompts2([
|
|
3299
|
+
{
|
|
3300
|
+
type: "text",
|
|
3301
|
+
name: "componentsDir",
|
|
3302
|
+
message: "\uCEF4\uD3EC\uB10C\uD2B8 \uB514\uB809\uD1A0\uB9AC:",
|
|
3303
|
+
initial: INIT_DEFAULTS.componentsDir
|
|
3304
|
+
},
|
|
3305
|
+
{
|
|
3306
|
+
type: "text",
|
|
3307
|
+
name: "tailwindConfig",
|
|
3308
|
+
message: "Tailwind \uC124\uC815 \uD30C\uC77C:",
|
|
3309
|
+
initial: INIT_DEFAULTS.tailwindConfig
|
|
3310
|
+
},
|
|
3311
|
+
{
|
|
3312
|
+
type: "text",
|
|
3313
|
+
name: "globalCss",
|
|
3314
|
+
message: "\uAE00\uB85C\uBC8C CSS \uD30C\uC77C:",
|
|
3315
|
+
initial: INIT_DEFAULTS.globalCss
|
|
3316
|
+
}
|
|
3317
|
+
]);
|
|
3318
|
+
await runInit(process.cwd(), config, registryUrl);
|
|
3319
|
+
});
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
// src/index.ts
|
|
3323
|
+
var { version: CLI_VERSION } = createRequire2(import.meta.url)("../package.json");
|
|
3324
|
+
var REGISTRY_URL = process.env.AXIS_REGISTRY_URL || "https://axis.minu.best/r";
|
|
3325
|
+
var program = new Command();
|
|
3326
|
+
program.name("axis").description("AXIS Design System CLI - shadcn \uD638\uD658 \uCEF4\uD3EC\uB10C\uD2B8 \uC124\uCE58 \uB3C4\uAD6C").version(CLI_VERSION);
|
|
3327
|
+
registerInitCommand(program, REGISTRY_URL);
|
|
2160
3328
|
program.command("add <component>").description("\uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uAC00").option("--agentic", "Agentic UI \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uAC00").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uB36E\uC5B4\uC4F0\uAE30").action(async (component, options) => {
|
|
2161
3329
|
const spinner = ora6(`${component} \uCEF4\uD3EC\uB10C\uD2B8 \uAC00\uC838\uC624\uB294 \uC911...`).start();
|
|
2162
3330
|
try {
|
|
2163
|
-
const configPath =
|
|
2164
|
-
if (!await
|
|
3331
|
+
const configPath = path12.resolve("axis.config.json");
|
|
3332
|
+
if (!await fs11.pathExists(configPath)) {
|
|
2165
3333
|
spinner.fail(
|
|
2166
3334
|
"axis.config.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.\n \uD574\uACB0: \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0\uC11C 'npx @axis-ds/cli init'\uC744 \uC2E4\uD589\uD558\uC138\uC694.\n \uCC38\uACE0: https://axis.minu.best/docs/guides/quick-start"
|
|
2167
3335
|
);
|
|
2168
3336
|
process.exit(1);
|
|
2169
3337
|
}
|
|
2170
|
-
const config = await
|
|
3338
|
+
const config = await fs11.readJSON(configPath);
|
|
2171
3339
|
const category = options.agentic ? "agentic" : "ui";
|
|
2172
3340
|
const componentInfo = await getComponentInfo(component, category);
|
|
2173
3341
|
if (!componentInfo) {
|
|
@@ -2180,10 +3348,10 @@ program.command("add <component>").description("\uCEF4\uD3EC\uB10C\uD2B8 \uCD94\
|
|
|
2180
3348
|
}
|
|
2181
3349
|
spinner.text = `${component} \uCEF4\uD3EC\uB10C\uD2B8 \uC124\uCE58 \uC911...`;
|
|
2182
3350
|
for (const file of componentInfo.files) {
|
|
2183
|
-
const filePath =
|
|
2184
|
-
if (await
|
|
3351
|
+
const filePath = path12.join(config.componentsDir, file.path);
|
|
3352
|
+
if (await fs11.pathExists(filePath)) {
|
|
2185
3353
|
if (!options.yes) {
|
|
2186
|
-
const { overwrite } = await
|
|
3354
|
+
const { overwrite } = await prompts3({
|
|
2187
3355
|
type: "confirm",
|
|
2188
3356
|
name: "overwrite",
|
|
2189
3357
|
message: `${file.path}\uC774(\uAC00) \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`,
|
|
@@ -2192,13 +3360,13 @@ program.command("add <component>").description("\uCEF4\uD3EC\uB10C\uD2B8 \uCD94\
|
|
|
2192
3360
|
if (!overwrite) continue;
|
|
2193
3361
|
}
|
|
2194
3362
|
}
|
|
2195
|
-
await
|
|
2196
|
-
await
|
|
3363
|
+
await fs11.ensureDir(path12.dirname(filePath));
|
|
3364
|
+
await fs11.writeFile(filePath, file.content);
|
|
2197
3365
|
}
|
|
2198
|
-
spinner.succeed(
|
|
3366
|
+
spinner.succeed(chalk11.green(`${component} \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uAC00 \uC644\uB8CC`));
|
|
2199
3367
|
if (componentInfo.dependencies.length > 0) {
|
|
2200
|
-
console.log(
|
|
2201
|
-
console.log(
|
|
3368
|
+
console.log(chalk11.yellow("\n\uD544\uC694\uD55C \uC758\uC874\uC131:"));
|
|
3369
|
+
console.log(chalk11.cyan(` pnpm add ${componentInfo.dependencies.join(" ")}`));
|
|
2202
3370
|
}
|
|
2203
3371
|
} catch (error) {
|
|
2204
3372
|
spinner.fail(
|
|
@@ -2210,7 +3378,7 @@ program.command("add <component>").description("\uCEF4\uD3EC\uB10C\uD2B8 \uCD94\
|
|
|
2210
3378
|
}
|
|
2211
3379
|
});
|
|
2212
3380
|
program.command("list").description("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uCEF4\uD3EC\uB10C\uD2B8 \uBAA9\uB85D").option("--category <type>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130 (ui, agentic)").action(async (options) => {
|
|
2213
|
-
console.log(
|
|
3381
|
+
console.log(chalk11.blue("\n\u{1F4E6} AXIS Design System \uCEF4\uD3EC\uB10C\uD2B8\n"));
|
|
2214
3382
|
const components = {
|
|
2215
3383
|
ui: [
|
|
2216
3384
|
{ name: "button", description: "\uAE30\uBCF8 \uBC84\uD2BC \uCEF4\uD3EC\uB10C\uD2B8" },
|
|
@@ -2238,9 +3406,9 @@ program.command("list").description("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uCEF4\uD3E
|
|
|
2238
3406
|
]
|
|
2239
3407
|
};
|
|
2240
3408
|
const showCategory = (category, items) => {
|
|
2241
|
-
console.log(
|
|
3409
|
+
console.log(chalk11.bold(category === "ui" ? "Core UI" : "Agentic UI"));
|
|
2242
3410
|
items.forEach((c) => {
|
|
2243
|
-
console.log(` ${
|
|
3411
|
+
console.log(` ${chalk11.cyan(c.name.padEnd(20))} ${chalk11.gray(c.description)}`);
|
|
2244
3412
|
});
|
|
2245
3413
|
console.log();
|
|
2246
3414
|
};
|
|
@@ -2250,8 +3418,8 @@ program.command("list").description("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uCEF4\uD3E
|
|
|
2250
3418
|
if (!options.category || options.category === "agentic") {
|
|
2251
3419
|
showCategory("agentic", components.agentic);
|
|
2252
3420
|
}
|
|
2253
|
-
console.log(
|
|
2254
|
-
console.log(
|
|
3421
|
+
console.log(chalk11.gray("\uC0AC\uC6A9\uBC95: npx @axis-ds/cli add <component-name>"));
|
|
3422
|
+
console.log(chalk11.gray("Agentic: npx @axis-ds/cli add <component-name> --agentic\n"));
|
|
2255
3423
|
});
|
|
2256
3424
|
var monetCmd = program.command("monet").description("Monet Design \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC (https://monet.design)");
|
|
2257
3425
|
monetCmd.command("list").alias("ls").description("Monet \uCE74\uD14C\uACE0\uB9AC \uBAA9\uB85D").action(async () => {
|
|
@@ -2271,24 +3439,24 @@ monetCmd.command("import").alias("i").description("\uD074\uB9BD\uBCF4\uB4DC\uC5D
|
|
|
2271
3439
|
await client.importFromClipboard();
|
|
2272
3440
|
});
|
|
2273
3441
|
monetCmd.command("setup").description("Monet MCP \uC11C\uBC84 \uC124\uC815 \uC548\uB0B4").action(() => {
|
|
2274
|
-
console.log(
|
|
2275
|
-
console.log(
|
|
2276
|
-
console.log(
|
|
2277
|
-
console.log(
|
|
2278
|
-
console.log(
|
|
2279
|
-
console.log(
|
|
2280
|
-
console.log(
|
|
2281
|
-
console.log(
|
|
3442
|
+
console.log(chalk11.blue("\n\u{1F527} Monet MCP \uC11C\uBC84 \uC124\uC815\n"));
|
|
3443
|
+
console.log(chalk11.bold("1. API \uD0A4 \uBC1C\uAE09:"));
|
|
3444
|
+
console.log(chalk11.cyan(" https://monet.design/mcp\n"));
|
|
3445
|
+
console.log(chalk11.bold("2. \uD658\uACBD \uBCC0\uC218 \uC124\uC815:"));
|
|
3446
|
+
console.log(chalk11.gray(" .env \uD30C\uC77C\uC5D0 \uCD94\uAC00:"));
|
|
3447
|
+
console.log(chalk11.cyan(" MONET_API_KEY=your-api-key-here\n"));
|
|
3448
|
+
console.log(chalk11.bold("3. Claude Code MCP \uC124\uC815:"));
|
|
3449
|
+
console.log(chalk11.gray(" .claude/mcp.json\uC5D0\uC11C monet \uC11C\uBC84 \uD65C\uC131\uD654:\n"));
|
|
2282
3450
|
console.log(
|
|
2283
|
-
|
|
3451
|
+
chalk11.cyan(` "monet": {
|
|
2284
3452
|
"url": "https://www.monet.design/api/remote/mcp",
|
|
2285
3453
|
"headers": { "Authorization": "Bearer \${MONET_API_KEY}" },
|
|
2286
3454
|
"disabled": false
|
|
2287
3455
|
}
|
|
2288
3456
|
`)
|
|
2289
3457
|
);
|
|
2290
|
-
console.log(
|
|
2291
|
-
console.log(
|
|
3458
|
+
console.log(chalk11.bold("4. Claude Code \uC7AC\uC2DC\uC791 \uD6C4 \uC0AC\uC6A9:"));
|
|
3459
|
+
console.log(chalk11.gray(' "monet\uC5D0\uC11C hero \uCEF4\uD3EC\uB10C\uD2B8 \uCC3E\uC544\uC918"\n'));
|
|
2292
3460
|
});
|
|
2293
3461
|
var v0Cmd = program.command("v0").description("V0 (v0.app) \uCF54\uB4DC \uBCC0\uD658 \uBC0F \uD1B5\uD569");
|
|
2294
3462
|
v0Cmd.command("convert <file>").alias("c").description("V0 \uCF54\uB4DC\uB97C AXIS \uC2A4\uD0C0\uC77C\uB85C \uBCC0\uD658").option("-o, --output <path>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C").action(async (file, options) => {
|
|
@@ -2325,18 +3493,18 @@ libraryCmd.command("collect").alias("c").description("\uC678\uBD80 \uC18C\uC2A4\
|
|
|
2325
3493
|
total += result.collected;
|
|
2326
3494
|
failed += result.failed;
|
|
2327
3495
|
}
|
|
2328
|
-
console.log(
|
|
3496
|
+
console.log(chalk11.blue(`
|
|
2329
3497
|
\u{1F4CA} \uC218\uC9D1 \uC644\uB8CC: ${total}\uAC1C \uCEF4\uD3EC\uB10C\uD2B8`));
|
|
2330
3498
|
if (failed > 0) {
|
|
2331
|
-
console.log(
|
|
3499
|
+
console.log(chalk11.yellow(` \uC2E4\uD328: ${failed}\uAC1C`));
|
|
2332
3500
|
}
|
|
2333
3501
|
});
|
|
2334
3502
|
libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9AC \uCEF4\uD3EC\uB10C\uD2B8 \uBAA9\uB85D").option("-c, --category <category>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130").option("-s, --source <source>", "\uC18C\uC2A4 \uD544\uD130").action(async (options) => {
|
|
2335
3503
|
const curator = new LibraryCurator();
|
|
2336
3504
|
const index = await curator.loadIndex();
|
|
2337
3505
|
if (!index) {
|
|
2338
|
-
console.log(
|
|
2339
|
-
console.log(
|
|
3506
|
+
console.log(chalk11.yellow("\n\u26A0\uFE0F \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC778\uB371\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
3507
|
+
console.log(chalk11.gray(" \uD574\uACB0: npx @axis-ds/cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
2340
3508
|
return;
|
|
2341
3509
|
}
|
|
2342
3510
|
let components = index.components;
|
|
@@ -2346,7 +3514,7 @@ libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9
|
|
|
2346
3514
|
if (options.source) {
|
|
2347
3515
|
components = components.filter((c) => c.source.type === options.source);
|
|
2348
3516
|
}
|
|
2349
|
-
console.log(
|
|
3517
|
+
console.log(chalk11.blue(`
|
|
2350
3518
|
\u{1F4E6} Library Components (${components.length}\uAC1C)
|
|
2351
3519
|
`));
|
|
2352
3520
|
const byCategory = /* @__PURE__ */ new Map();
|
|
@@ -2358,14 +3526,14 @@ libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9
|
|
|
2358
3526
|
byCategory.get(cat).push(comp);
|
|
2359
3527
|
}
|
|
2360
3528
|
for (const [category, items] of byCategory) {
|
|
2361
|
-
console.log(
|
|
3529
|
+
console.log(chalk11.bold(`${category} (${items.length})`));
|
|
2362
3530
|
for (const item of items.slice(0, 10)) {
|
|
2363
3531
|
console.log(
|
|
2364
|
-
` ${
|
|
3532
|
+
` ${chalk11.cyan(item.name.padEnd(25))} ${chalk11.gray(item.source.type.padEnd(8))} ${chalk11.gray(item.description.slice(0, 40))}`
|
|
2365
3533
|
);
|
|
2366
3534
|
}
|
|
2367
3535
|
if (items.length > 10) {
|
|
2368
|
-
console.log(
|
|
3536
|
+
console.log(chalk11.gray(` ... \uC678 ${items.length - 10}\uAC1C`));
|
|
2369
3537
|
}
|
|
2370
3538
|
console.log();
|
|
2371
3539
|
}
|
|
@@ -2377,21 +3545,21 @@ libraryCmd.command("search <query>").alias("s").description("\uCEF4\uD3EC\uB10C\
|
|
|
2377
3545
|
source: options.source
|
|
2378
3546
|
});
|
|
2379
3547
|
if (results.length === 0) {
|
|
2380
|
-
console.log(
|
|
3548
|
+
console.log(chalk11.yellow(`
|
|
2381
3549
|
'${query}'\uC5D0 \uB300\uD55C \uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
2382
3550
|
`));
|
|
2383
3551
|
return;
|
|
2384
3552
|
}
|
|
2385
|
-
console.log(
|
|
3553
|
+
console.log(chalk11.blue(`
|
|
2386
3554
|
\u{1F50D} '${query}' \uAC80\uC0C9 \uACB0\uACFC (${results.length}\uAC1C)
|
|
2387
3555
|
`));
|
|
2388
3556
|
for (const comp of results.slice(0, 20)) {
|
|
2389
3557
|
console.log(
|
|
2390
|
-
` ${
|
|
3558
|
+
` ${chalk11.cyan(comp.name.padEnd(25))} ${chalk11.gray(comp.source.type.padEnd(8))} ${chalk11.gray(comp.category.padEnd(12))} ${chalk11.gray(comp.description.slice(0, 30))}`
|
|
2391
3559
|
);
|
|
2392
3560
|
}
|
|
2393
3561
|
if (results.length > 20) {
|
|
2394
|
-
console.log(
|
|
3562
|
+
console.log(chalk11.gray(`
|
|
2395
3563
|
... \uC678 ${results.length - 20}\uAC1C`));
|
|
2396
3564
|
}
|
|
2397
3565
|
console.log();
|
|
@@ -2405,12 +3573,12 @@ libraryCmd.command("publish").description("\uC0AC\uC774\uD2B8\uC5D0 \uB77C\uC774
|
|
|
2405
3573
|
const publisher2 = new Publisher();
|
|
2406
3574
|
const index = await curator.loadIndex();
|
|
2407
3575
|
if (!index) {
|
|
2408
|
-
console.log(
|
|
2409
|
-
console.log(
|
|
3576
|
+
console.log(chalk11.yellow("\n\u26A0\uFE0F \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC778\uB371\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
3577
|
+
console.log(chalk11.gray(" \uD574\uACB0: npx @axis-ds/cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
2410
3578
|
return;
|
|
2411
3579
|
}
|
|
2412
|
-
console.log(
|
|
2413
|
-
console.log(
|
|
3580
|
+
console.log(chalk11.blue("\n\u{1F4E4} Library \uBC30\uCE58\n"));
|
|
3581
|
+
console.log(chalk11.gray(`\uCD1D ${index.stats.total}\uAC1C \uCEF4\uD3EC\uB10C\uD2B8
|
|
2414
3582
|
`));
|
|
2415
3583
|
if (options.clean) {
|
|
2416
3584
|
await publisher2.clean(options.output);
|
|
@@ -2421,17 +3589,17 @@ libraryCmd.command("publish").description("\uC0AC\uC774\uD2B8\uC5D0 \uB77C\uC774
|
|
|
2421
3589
|
generateSearchIndex: true
|
|
2422
3590
|
});
|
|
2423
3591
|
if (result.success) {
|
|
2424
|
-
console.log(
|
|
3592
|
+
console.log(chalk11.green(`
|
|
2425
3593
|
\u2713 \uBC30\uCE58 \uC644\uB8CC`));
|
|
2426
|
-
console.log(
|
|
2427
|
-
console.log(
|
|
2428
|
-
console.log(
|
|
2429
|
-
console.log(
|
|
3594
|
+
console.log(chalk11.gray(` - \uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC: ${result.outputDir}`));
|
|
3595
|
+
console.log(chalk11.gray(` - \uC0DD\uC131\uB41C \uD30C\uC77C: ${result.files.length}\uAC1C`));
|
|
3596
|
+
console.log(chalk11.gray(` - \uCE74\uD14C\uACE0\uB9AC: ${result.stats.categoriesPublished}\uAC1C`));
|
|
3597
|
+
console.log(chalk11.gray(` - \uAC80\uC0C9 \uC778\uB371\uC2A4: ${result.stats.searchIndexSize}\uAC1C \uD56D\uBAA9`));
|
|
2430
3598
|
} else {
|
|
2431
|
-
console.log(
|
|
3599
|
+
console.log(chalk11.red(`
|
|
2432
3600
|
\u2717 \uBC30\uCE58 \uC2E4\uD328`));
|
|
2433
3601
|
for (const error of result.errors) {
|
|
2434
|
-
console.log(
|
|
3602
|
+
console.log(chalk11.red(` - ${error}`));
|
|
2435
3603
|
}
|
|
2436
3604
|
}
|
|
2437
3605
|
console.log();
|
|
@@ -2439,6 +3607,7 @@ libraryCmd.command("publish").description("\uC0AC\uC774\uD2B8\uC5D0 \uB77C\uC774
|
|
|
2439
3607
|
registerSyncCommand(program);
|
|
2440
3608
|
registerTemplateCommand(program);
|
|
2441
3609
|
registerCheckCommand(program);
|
|
3610
|
+
registerThemeCommand(program);
|
|
2442
3611
|
async function getComponentInfo(name, category) {
|
|
2443
3612
|
const localComponents = {
|
|
2444
3613
|
button: {
|