@axis-ds/cli 1.6.0 → 1.6.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 +7 -4
- package/dist/index.js +522 -236
- package/dist/registry/agentic-message-bubble.json +1 -1
- package/dist/registry/agentic-plan-card.json +1 -1
- package/dist/registry/agentic-run-progress.json +1 -1
- package/dist/registry/agentic-step-timeline.json +1 -1
- package/dist/registry/agentic-streaming-text.json +1 -1
- package/dist/registry/agentic-thinking-indicator.json +1 -1
- package/dist/registry/agentic-tool-call-card.json +1 -1
- package/dist/registry/button.json +1 -1
- package/dist/registry/card.json +1 -1
- package/dist/registry/dialog.json +1 -1
- package/dist/registry/index.json +13 -13
- package/dist/registry/input.json +1 -1
- package/dist/registry/registry.json +13 -13
- package/dist/registry/select.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1745,7 +1745,7 @@ import ora5 from "ora";
|
|
|
1745
1745
|
|
|
1746
1746
|
// src/template/template-apply.ts
|
|
1747
1747
|
import fs8 from "fs-extra";
|
|
1748
|
-
import
|
|
1748
|
+
import path9 from "path";
|
|
1749
1749
|
import chalk5 from "chalk";
|
|
1750
1750
|
import ora3 from "ora";
|
|
1751
1751
|
import prompts from "prompts";
|
|
@@ -1843,8 +1843,18 @@ async function readAxisConfig(baseDir) {
|
|
|
1843
1843
|
}
|
|
1844
1844
|
|
|
1845
1845
|
// ../axis-registry-core/src/template/tailwind-core.ts
|
|
1846
|
-
import { existsSync, lstatSync, readdirSync, readFileSync } from "fs";
|
|
1847
|
-
import { join, resolve } from "path";
|
|
1846
|
+
import { existsSync as existsSync2, lstatSync, readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
1847
|
+
import { extname, join, resolve } from "path";
|
|
1848
|
+
|
|
1849
|
+
// ../axis-registry-core/src/project.ts
|
|
1850
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
1851
|
+
import path8 from "path";
|
|
1852
|
+
function detectInstallCommand(baseDir) {
|
|
1853
|
+
if (existsSync(path8.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
1854
|
+
if (existsSync(path8.join(baseDir, "yarn.lock"))) return "yarn install";
|
|
1855
|
+
if (existsSync(path8.join(baseDir, "package-lock.json"))) return "npm install";
|
|
1856
|
+
return "pnpm install";
|
|
1857
|
+
}
|
|
1848
1858
|
function hasDependency(pkg, name) {
|
|
1849
1859
|
for (const field of ["dependencies", "devDependencies"]) {
|
|
1850
1860
|
const deps = pkg[field];
|
|
@@ -1857,6 +1867,134 @@ function hasDependency(pkg, name) {
|
|
|
1857
1867
|
function isPlainObject(value) {
|
|
1858
1868
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1859
1869
|
}
|
|
1870
|
+
function addCommandFor(installCommand, deps) {
|
|
1871
|
+
const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
|
|
1872
|
+
if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
|
|
1873
|
+
if (installCommand.startsWith("npm")) return `npm install ${specs}`;
|
|
1874
|
+
return `pnpm add ${specs}`;
|
|
1875
|
+
}
|
|
1876
|
+
var GLOBAL_CSS_CANDIDATES = [
|
|
1877
|
+
"app/globals.css",
|
|
1878
|
+
"src/app/globals.css",
|
|
1879
|
+
"styles/globals.css",
|
|
1880
|
+
"src/styles/globals.css",
|
|
1881
|
+
"globals.css"
|
|
1882
|
+
];
|
|
1883
|
+
var TAILWIND_CONFIG_CANDIDATES = [
|
|
1884
|
+
"tailwind.config.ts",
|
|
1885
|
+
"tailwind.config.js",
|
|
1886
|
+
"tailwind.config.mjs",
|
|
1887
|
+
"tailwind.config.cjs"
|
|
1888
|
+
];
|
|
1889
|
+
function isFile(file) {
|
|
1890
|
+
try {
|
|
1891
|
+
return statSync(file).isFile();
|
|
1892
|
+
} catch {
|
|
1893
|
+
return false;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
function isDirectory(dir) {
|
|
1897
|
+
try {
|
|
1898
|
+
return statSync(dir).isDirectory();
|
|
1899
|
+
} catch {
|
|
1900
|
+
return false;
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
function findFirstFile(baseDir, candidates) {
|
|
1904
|
+
return candidates.find((c) => isFile(path8.join(baseDir, c)));
|
|
1905
|
+
}
|
|
1906
|
+
function detectProjectPaths(baseDirInput) {
|
|
1907
|
+
const baseDir = path8.resolve(baseDirInput);
|
|
1908
|
+
const hasSrc = isDirectory(path8.join(baseDir, "src"));
|
|
1909
|
+
const css = findFirstFile(baseDir, GLOBAL_CSS_CANDIDATES);
|
|
1910
|
+
const tw = findFirstFile(baseDir, TAILWIND_CONFIG_CANDIDATES);
|
|
1911
|
+
return {
|
|
1912
|
+
componentsDir: hasSrc ? "./src/components/ui" : "./components/ui",
|
|
1913
|
+
globalCss: css !== void 0 ? `./${css}` : hasSrc ? "./src/app/globals.css" : "./app/globals.css",
|
|
1914
|
+
globalCssSource: css !== void 0 ? "found" : "default",
|
|
1915
|
+
tailwindConfig: tw !== void 0 ? `./${tw}` : "./tailwind.config.ts",
|
|
1916
|
+
tailwindConfigSource: tw !== void 0 ? "found" : "default"
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
function projectFileExists(baseDir, relPath) {
|
|
1920
|
+
return isFile(path8.resolve(baseDir, relPath));
|
|
1921
|
+
}
|
|
1922
|
+
var ROOT_LAYOUT_FILES = [
|
|
1923
|
+
"app/layout.tsx",
|
|
1924
|
+
"app/layout.jsx",
|
|
1925
|
+
"app/layout.js",
|
|
1926
|
+
"src/app/layout.tsx",
|
|
1927
|
+
"src/app/layout.jsx",
|
|
1928
|
+
"src/app/layout.js",
|
|
1929
|
+
"pages/_app.tsx",
|
|
1930
|
+
"pages/_app.jsx",
|
|
1931
|
+
"pages/_document.tsx",
|
|
1932
|
+
"pages/_document.jsx",
|
|
1933
|
+
"src/pages/_app.tsx",
|
|
1934
|
+
"src/pages/_app.jsx",
|
|
1935
|
+
"src/pages/_document.tsx",
|
|
1936
|
+
"src/pages/_document.jsx"
|
|
1937
|
+
];
|
|
1938
|
+
function exactVersionOf(version) {
|
|
1939
|
+
if (typeof version !== "string") return void 0;
|
|
1940
|
+
const v = version.trim();
|
|
1941
|
+
if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
|
|
1942
|
+
return v;
|
|
1943
|
+
}
|
|
1944
|
+
function findInstalledPackage(baseDirInput, name) {
|
|
1945
|
+
let dir = path8.resolve(baseDirInput);
|
|
1946
|
+
for (; ; ) {
|
|
1947
|
+
const pkgDir = path8.join(dir, "node_modules", ...name.split("/"));
|
|
1948
|
+
const file = path8.join(pkgDir, "package.json");
|
|
1949
|
+
if (isFile(file)) {
|
|
1950
|
+
let version;
|
|
1951
|
+
try {
|
|
1952
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
1953
|
+
version = isPlainObject(parsed) ? exactVersionOf(parsed.version) : void 0;
|
|
1954
|
+
} catch {
|
|
1955
|
+
version = void 0;
|
|
1956
|
+
}
|
|
1957
|
+
return { dir: pkgDir, version };
|
|
1958
|
+
}
|
|
1959
|
+
const parent = path8.dirname(dir);
|
|
1960
|
+
if (parent === dir) return void 0;
|
|
1961
|
+
dir = parent;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
function isPnpProject(baseDirInput) {
|
|
1965
|
+
let dir = path8.resolve(baseDirInput);
|
|
1966
|
+
for (; ; ) {
|
|
1967
|
+
if (isFile(path8.join(dir, ".pnp.cjs")) || isFile(path8.join(dir, ".pnp.js"))) return true;
|
|
1968
|
+
const parent = path8.dirname(dir);
|
|
1969
|
+
if (parent === dir) return false;
|
|
1970
|
+
dir = parent;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
function compareExactVersions(a, b) {
|
|
1974
|
+
const parse = (v) => {
|
|
1975
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?/.exec(v.trim());
|
|
1976
|
+
return m ? { core: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] !== void 0 } : void 0;
|
|
1977
|
+
};
|
|
1978
|
+
const x = parse(a);
|
|
1979
|
+
const y = parse(b);
|
|
1980
|
+
if (!x || !y) return void 0;
|
|
1981
|
+
for (let i = 0; i < 3; i++) if (x.core[i] !== y.core[i]) return x.core[i] - y.core[i];
|
|
1982
|
+
return Number(y.pre) - Number(x.pre);
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
// ../axis-registry-core/src/template/tailwind-core.ts
|
|
1986
|
+
function hasDependency2(pkg, name) {
|
|
1987
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
1988
|
+
const deps = pkg[field];
|
|
1989
|
+
if (typeof deps === "object" && deps !== null && name in deps) {
|
|
1990
|
+
return String(deps[name]);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
return void 0;
|
|
1994
|
+
}
|
|
1995
|
+
function isPlainObject2(value) {
|
|
1996
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1997
|
+
}
|
|
1860
1998
|
var VERSION = String.raw`v?(\d+)(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
|
|
1861
1999
|
function versionParts(token) {
|
|
1862
2000
|
const m = new RegExp(`^${VERSION}$`).exec(token);
|
|
@@ -1930,12 +2068,12 @@ function majorFromVersion(version) {
|
|
|
1930
2068
|
function detectTailwind(baseDirInput, pkg) {
|
|
1931
2069
|
const baseDir = resolve(baseDirInput);
|
|
1932
2070
|
const installedFile = join(baseDir, "node_modules", "tailwindcss", "package.json");
|
|
1933
|
-
const declared = pkg ?
|
|
2071
|
+
const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
|
|
1934
2072
|
const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
|
|
1935
2073
|
const declaredMajor = bounds?.lower;
|
|
1936
2074
|
try {
|
|
1937
|
-
const installed = JSON.parse(
|
|
1938
|
-
const version =
|
|
2075
|
+
const installed = JSON.parse(readFileSync2(installedFile, "utf8"));
|
|
2076
|
+
const version = isPlainObject2(installed) ? installed.version : void 0;
|
|
1939
2077
|
const major = majorFromVersion(version);
|
|
1940
2078
|
if (major !== void 0) {
|
|
1941
2079
|
const found = { major, source: "installed", value: String(version) };
|
|
@@ -1982,18 +2120,57 @@ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/s
|
|
|
1982
2120
|
function findTokensCssImport(css) {
|
|
1983
2121
|
return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
|
|
1984
2122
|
}
|
|
2123
|
+
var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
|
|
2124
|
+
var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
|
|
2125
|
+
function findLayoutTokensCssImport(baseDirInput) {
|
|
2126
|
+
const baseDir = resolve(baseDirInput);
|
|
2127
|
+
for (const candidate of ROOT_LAYOUT_FILES) {
|
|
2128
|
+
const file = join(baseDir, candidate);
|
|
2129
|
+
if (!existsSync2(file)) continue;
|
|
2130
|
+
let text;
|
|
2131
|
+
try {
|
|
2132
|
+
text = readFileSync2(file, "utf8");
|
|
2133
|
+
} catch {
|
|
2134
|
+
continue;
|
|
2135
|
+
}
|
|
2136
|
+
const m = TOKENS_CSS_JS_IMPORT.exec(stripJsComments(text));
|
|
2137
|
+
if (m) return { file: candidate, spec: m[2] };
|
|
2138
|
+
}
|
|
2139
|
+
return void 0;
|
|
2140
|
+
}
|
|
1985
2141
|
function checkGlobalsCss(baseDirInput) {
|
|
1986
2142
|
const baseDir = resolve(baseDirInput);
|
|
1987
2143
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
1988
2144
|
const file = join(baseDir, candidate);
|
|
1989
|
-
if (!
|
|
1990
|
-
const content =
|
|
1991
|
-
|
|
1992
|
-
return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
1993
|
-
}
|
|
2145
|
+
if (!existsSync2(file)) continue;
|
|
2146
|
+
const content = readFileSync2(file, "utf8");
|
|
2147
|
+
const css = stripCssComments(content);
|
|
1994
2148
|
const imported = findTokensCssImport(content);
|
|
1995
|
-
|
|
1996
|
-
|
|
2149
|
+
let pass;
|
|
2150
|
+
if (imported !== void 0) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
|
|
2151
|
+
else if (AXIS_VARIABLE_DEFINITION.test(css)) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218(--axis-*)\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`;
|
|
2152
|
+
else {
|
|
2153
|
+
const layout = findLayoutTokensCssImport(baseDir);
|
|
2154
|
+
if (layout) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${layout.file}\uC758 ${layout.spec} import)`;
|
|
2155
|
+
}
|
|
2156
|
+
if (pass !== void 0) {
|
|
2157
|
+
const tailwind = detectTailwind(baseDir, readPackageJson(baseDir));
|
|
2158
|
+
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
2159
|
+
if (!tailwind4 && findCreateNextAppDefaults(content).some((d) => d.includes("font-family: Arial"))) {
|
|
2160
|
+
return {
|
|
2161
|
+
name: "globals.css",
|
|
2162
|
+
severity: "warn",
|
|
2163
|
+
message: `${pass}. \uB2E4\uB9CC create-next-app \uAE30\uBCF8 body font-family: Arial \uC774 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2192 \uC9C0\uC6B0\uC138\uC694(AXIS \uAE00\uAF34 \uB300\uC2E0 Arial \uC774 \uC801\uC6A9\uB428)`
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
return { name: "globals.css", severity: "pass", message: pass };
|
|
2167
|
+
}
|
|
2168
|
+
if (css.includes("--background") && css.includes("--primary")) {
|
|
2169
|
+
return {
|
|
2170
|
+
name: "globals.css",
|
|
2171
|
+
severity: "warn",
|
|
2172
|
+
message: `${candidate}\uC5D0 \uC790\uCCB4 CSS \uBCC0\uC218(--background \xB7 --primary)\uB9CC \uC788\uACE0 AXIS \uD1A0\uD070\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 @axis-ds/tokens CSS \uB97C import \uD558\uC138\uC694`
|
|
2173
|
+
};
|
|
1997
2174
|
}
|
|
1998
2175
|
return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
|
|
1999
2176
|
}
|
|
@@ -2056,8 +2233,8 @@ function exactVersion(version) {
|
|
|
2056
2233
|
}
|
|
2057
2234
|
function installedVersion(baseDir, name) {
|
|
2058
2235
|
try {
|
|
2059
|
-
const parsed = JSON.parse(
|
|
2060
|
-
return
|
|
2236
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
|
|
2237
|
+
return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
|
|
2061
2238
|
} catch {
|
|
2062
2239
|
return void 0;
|
|
2063
2240
|
}
|
|
@@ -2068,7 +2245,7 @@ function axisPackagesBelowTailwind4(pkg, baseDirInput) {
|
|
|
2068
2245
|
const out = [];
|
|
2069
2246
|
const min = lowerOf(TAILWIND4_MIN_AXIS_VERSION);
|
|
2070
2247
|
for (const name of TAILWIND4_AXIS_PACKAGES) {
|
|
2071
|
-
const range =
|
|
2248
|
+
const range = hasDependency2(pkg, name);
|
|
2072
2249
|
if (range === void 0 || range.trim().startsWith("workspace:")) continue;
|
|
2073
2250
|
const installed = baseDir !== void 0 ? installedVersion(baseDir, name) : void 0;
|
|
2074
2251
|
const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
|
|
@@ -2125,8 +2302,10 @@ var CREATE_NEXT_APP_DEFAULTS = [
|
|
|
2125
2302
|
},
|
|
2126
2303
|
{
|
|
2127
2304
|
prefix: "body",
|
|
2128
|
-
|
|
2129
|
-
|
|
2305
|
+
// WI-0070: create-next-app 의 body `font-family: Arial, Helvetica, sans-serif` 도 같은 특징으로 봅니다. 레이어 밖 규칙이라
|
|
2306
|
+
// AXIS 글꼴(Pretendard, html 에 적용)을 이기고 Button 등이 `font-family: inherit` 로 Arial 을 물려받습니다.
|
|
2307
|
+
pattern: /(?<![\w-])(?:(background|background-color|color)\s*:\s*var\(\s*(--(?:background|foreground))\s*\)|font-family\s*:\s*Arial\b)/g,
|
|
2308
|
+
item: (m) => m[1] !== void 0 ? `${m[1]}: var(${m[2]})` : "font-family: Arial"
|
|
2130
2309
|
}
|
|
2131
2310
|
];
|
|
2132
2311
|
function findCreateNextAppDefaults(css) {
|
|
@@ -2182,10 +2361,55 @@ function hasTokensPresetReference(source) {
|
|
|
2182
2361
|
return PRESET_REFERENCE.test(stripJsComments(source));
|
|
2183
2362
|
}
|
|
2184
2363
|
var PRESET_PASS_SUFFIX = `\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${TOKENS_TAILWIND3_PRESET} preset)`;
|
|
2364
|
+
var TOKENS_CJS_PRESET_FIXED_VERSION = "1.7.0";
|
|
2365
|
+
var TOKENS_TAILWIND3_CJS_REQUIRE = `require("${TOKENS_TAILWIND3_PRESET}").default`;
|
|
2366
|
+
var PRESET_REQUIRE_CALL = /\brequire\s*\(\s*(["'])@axis-ds\/tokens\/tailwind\1\s*\)/g;
|
|
2367
|
+
var DEFAULT_ACCESS_AHEAD = /^\s*(?:\.\s*default\b|\[\s*["']default["']\s*\])/;
|
|
2368
|
+
function hasBareCjsPresetRequire(code) {
|
|
2369
|
+
for (const m of code.matchAll(PRESET_REQUIRE_CALL)) {
|
|
2370
|
+
const start = m.index ?? 0;
|
|
2371
|
+
const end = start + m[0].length;
|
|
2372
|
+
if (DEFAULT_ACCESS_AHEAD.test(code.slice(end))) continue;
|
|
2373
|
+
const before = code.slice(0, start);
|
|
2374
|
+
if (/\b(?:const|let|var)\s*\{[^{}]*\}\s*=\s*$/.test(before)) continue;
|
|
2375
|
+
const bound = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*$/.exec(before);
|
|
2376
|
+
if (!bound) return true;
|
|
2377
|
+
const ident = escapeRegExp(bound[1]);
|
|
2378
|
+
const rest = code.slice(0, bound.index) + code.slice(end);
|
|
2379
|
+
const bareUse = new RegExp(`(?<![\\w$.])${ident}(?![\\w$])(?!\\s*(?:\\.\\s*default\\b|\\[\\s*["']default["']\\s*\\]))`);
|
|
2380
|
+
if (bareUse.test(rest)) return true;
|
|
2381
|
+
}
|
|
2382
|
+
return false;
|
|
2383
|
+
}
|
|
2384
|
+
function isCommonJsConfig(file, source) {
|
|
2385
|
+
return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
|
|
2386
|
+
}
|
|
2387
|
+
function packageVersionGate(baseDirInput, pkg, name, min) {
|
|
2388
|
+
const baseDir = resolve(baseDirInput);
|
|
2389
|
+
if (!isPnpProject(baseDir)) {
|
|
2390
|
+
const installed = findInstalledPackage(baseDir, name)?.version;
|
|
2391
|
+
if (installed !== void 0) {
|
|
2392
|
+
const cmp = compareExactVersions(installed, min);
|
|
2393
|
+
if (cmp !== void 0) return { status: cmp >= 0 ? "ok" : "below", source: "installed", value: installed };
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
const declared = pkg ? hasDependency2(pkg, name) : void 0;
|
|
2397
|
+
if (declared !== void 0) {
|
|
2398
|
+
const atLeast = rangeLowerAtLeast(declared, min);
|
|
2399
|
+
if (atLeast !== void 0) return { status: atLeast ? "ok" : "below", source: "declared", value: declared };
|
|
2400
|
+
return { status: "unknown", source: "declared", value: declared };
|
|
2401
|
+
}
|
|
2402
|
+
return { status: "unknown", source: "none" };
|
|
2403
|
+
}
|
|
2404
|
+
function versionGateLabel(gate) {
|
|
2405
|
+
if (gate.source === "installed") return `\uC124\uCE58\uBCF8 ${gate.value}`;
|
|
2406
|
+
if (gate.source === "declared") return `\uC120\uC5B8 ${gate.value}`;
|
|
2407
|
+
return "\uC124\uCE58\uBCF8 \xB7 \uC120\uC5B8 \uC5C6\uC74C";
|
|
2408
|
+
}
|
|
2185
2409
|
function readPackageJson(baseDir) {
|
|
2186
2410
|
try {
|
|
2187
|
-
const parsed = JSON.parse(
|
|
2188
|
-
return
|
|
2411
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "package.json"), "utf8"));
|
|
2412
|
+
return isPlainObject2(parsed) ? parsed : void 0;
|
|
2189
2413
|
} catch {
|
|
2190
2414
|
return void 0;
|
|
2191
2415
|
}
|
|
@@ -2195,7 +2419,7 @@ function tailwind4Issues(css, pkg, versions) {
|
|
|
2195
2419
|
const hasEntry = hasTokensTailwind4Import(css);
|
|
2196
2420
|
if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
|
|
2197
2421
|
const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
|
|
2198
|
-
(name) => pkg !== void 0 &&
|
|
2422
|
+
(name) => pkg !== void 0 && hasDependency2(pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
|
|
2199
2423
|
);
|
|
2200
2424
|
if (missing.length > 0) {
|
|
2201
2425
|
issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
|
|
@@ -2222,8 +2446,8 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2222
2446
|
const label = `Tailwind ${tailwind.major}`;
|
|
2223
2447
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
2224
2448
|
const file = join(baseDir, candidate);
|
|
2225
|
-
if (!
|
|
2226
|
-
const css =
|
|
2449
|
+
if (!existsSync2(file)) continue;
|
|
2450
|
+
const css = readFileSync2(file, "utf8");
|
|
2227
2451
|
if (!hasTailwindImport(css)) {
|
|
2228
2452
|
return {
|
|
2229
2453
|
name: "tailwind.config",
|
|
@@ -2254,9 +2478,21 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2254
2478
|
}
|
|
2255
2479
|
for (const file of TAILWIND_CONFIG_FILES) {
|
|
2256
2480
|
const path18 = join(baseDir, file);
|
|
2257
|
-
if (!
|
|
2258
|
-
const content =
|
|
2481
|
+
if (!existsSync2(path18)) continue;
|
|
2482
|
+
const content = readFileSync2(path18, "utf8");
|
|
2259
2483
|
if (hasTokensPresetReference(content)) {
|
|
2484
|
+
const code = stripJsComments(content);
|
|
2485
|
+
if (isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code)) {
|
|
2486
|
+
const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION);
|
|
2487
|
+
if (gate.status !== "ok") {
|
|
2488
|
+
const why = gate.status === "below" ? `@axis-ds/tokens ${versionGateLabel(gate)} \uC5D0\uC11C\uB294 CommonJS \uC758 require("${TOKENS_TAILWIND3_PRESET}") \uAC00 preset \uC774 \uC544\uB2C8\uB77C { default } \uB97C \uB3CC\uB824\uC918 \uC0C9 \xB7 keyframes \uAC00 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` : `@axis-ds/tokens \uBC84\uC804\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${versionGateLabel(gate)}). ${TOKENS_CJS_PRESET_FIXED_VERSION} \uBBF8\uB9CC\uC774\uBA74 CommonJS \uC758 require("${TOKENS_TAILWIND3_PRESET}") \uB85C\uB294 preset \uC774 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`;
|
|
2489
|
+
return {
|
|
2490
|
+
name: "tailwind.config",
|
|
2491
|
+
severity: "warn",
|
|
2492
|
+
message: `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${why} \u2192 ${TOKENS_TAILWIND3_CJS_REQUIRE} \uB85C \uBC14\uAFB8\uAC70\uB098 @axis-ds/tokens ${TOKENS_CJS_PRESET_FIXED_VERSION} \uC774\uC0C1`
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2260
2496
|
return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
|
|
2261
2497
|
}
|
|
2262
2498
|
const ownMapping = content.includes("--background") || content.includes("hsl(var(");
|
|
@@ -2270,8 +2506,8 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2270
2506
|
}
|
|
2271
2507
|
function readAxisConfigLike(baseDir) {
|
|
2272
2508
|
try {
|
|
2273
|
-
const parsed = JSON.parse(
|
|
2274
|
-
return
|
|
2509
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "axis.config.json"), "utf8"));
|
|
2510
|
+
return isPlainObject2(parsed) ? parsed : void 0;
|
|
2275
2511
|
} catch {
|
|
2276
2512
|
return void 0;
|
|
2277
2513
|
}
|
|
@@ -2358,7 +2594,7 @@ function inspectTailwindContent(baseDirInput) {
|
|
|
2358
2594
|
const pkg = readPackageJson(baseDir);
|
|
2359
2595
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
2360
2596
|
if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
|
|
2361
|
-
const configFile = TAILWIND_CONFIG_FILES.find((f) =>
|
|
2597
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
|
|
2362
2598
|
if (configFile === void 0) return null;
|
|
2363
2599
|
const targets = [];
|
|
2364
2600
|
const componentsDir = readAxisConfigLike(baseDir)?.componentsDir;
|
|
@@ -2367,12 +2603,12 @@ function inspectTailwindContent(baseDirInput) {
|
|
|
2367
2603
|
targets.push({ label: `componentsDir(${componentsDir})`, sample: `${rel3}/button.tsx`, suggest: `./${rel3}/**/*.{ts,tsx}` });
|
|
2368
2604
|
}
|
|
2369
2605
|
for (const name of TAILWIND4_COMPONENT_PACKAGES) {
|
|
2370
|
-
if (pkg !== void 0 &&
|
|
2606
|
+
if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
|
|
2371
2607
|
targets.push({ label: name, sample: `node_modules/${name}/dist/index.js`, suggest: `./node_modules/${name}/dist/**/*.{js,mjs}` });
|
|
2372
2608
|
}
|
|
2373
2609
|
}
|
|
2374
2610
|
if (targets.length === 0) return null;
|
|
2375
|
-
const read = readTailwindContent(
|
|
2611
|
+
const read = readTailwindContent(readFileSync2(join(baseDir, configFile), "utf8"));
|
|
2376
2612
|
const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
|
|
2377
2613
|
return {
|
|
2378
2614
|
configFile,
|
|
@@ -2437,7 +2673,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
|
|
|
2437
2673
|
if (st.isDirectory()) {
|
|
2438
2674
|
if (name !== "node_modules" && depth < ANIMATION_SCAN_DEPTH_LIMIT) stack.push([p, depth + 1]);
|
|
2439
2675
|
} else if (st.isFile() && st.size <= ANIMATION_SCAN_FILE_BYTES && /\.(tsx|ts|jsx|js)$/.test(name)) {
|
|
2440
|
-
if (/\banimate-(?:in|out)\b/.test(
|
|
2676
|
+
if (/\banimate-(?:in|out)\b/.test(readFileSync2(p, "utf8"))) return true;
|
|
2441
2677
|
}
|
|
2442
2678
|
}
|
|
2443
2679
|
}
|
|
@@ -2447,14 +2683,14 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2447
2683
|
const baseDir = resolve(baseDirInput);
|
|
2448
2684
|
const pkg = readPackageJson(baseDir);
|
|
2449
2685
|
const config = readAxisConfigLike(baseDir);
|
|
2450
|
-
const declared = pkg !== void 0 &&
|
|
2686
|
+
const declared = pkg !== void 0 && hasDependency2(pkg, "@axis-ds/ui-react") !== void 0;
|
|
2451
2687
|
const copied = typeof config?.componentsDir === "string" && componentsUseAnimation(baseDir, config.componentsDir);
|
|
2452
2688
|
if (!declared && !copied) return null;
|
|
2453
2689
|
const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
|
|
2454
2690
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
2455
2691
|
if (tailwind.major !== void 0 && tailwind.major >= 4) {
|
|
2456
|
-
const file = TAILWIND_CSS_CANDIDATES.find((c) =>
|
|
2457
|
-
const css = file !== void 0 ? stripCssComments(
|
|
2692
|
+
const file = TAILWIND_CSS_CANDIDATES.find((c) => existsSync2(join(baseDir, c)));
|
|
2693
|
+
const css = file !== void 0 ? stripCssComments(readFileSync2(join(baseDir, file), "utf8")) : "";
|
|
2458
2694
|
const ok = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`).test(css) || new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(css);
|
|
2459
2695
|
return ok ? { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` } : {
|
|
2460
2696
|
name: "animation",
|
|
@@ -2462,25 +2698,91 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2462
2698
|
message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 ${ANIMATION_PLUGIN_TAILWIND4} \uC124\uCE58 \uB4A4 @import "${ANIMATION_PLUGIN_TAILWIND4}";`
|
|
2463
2699
|
};
|
|
2464
2700
|
}
|
|
2465
|
-
const configFile = TAILWIND_CONFIG_FILES.find((f) =>
|
|
2466
|
-
const source = configFile !== void 0 ? stripJsComments(
|
|
2467
|
-
const
|
|
2468
|
-
const pluginDeclared = pkg !== void 0 &&
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2701
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
|
|
2702
|
+
const source = configFile !== void 0 ? stripJsComments(readFileSync2(join(baseDir, configFile), "utf8")) : "";
|
|
2703
|
+
const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
|
|
2704
|
+
const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
|
|
2705
|
+
const pluginInstalled = pluginDeclared && (isPnpProject(baseDir) || findInstalledPackage(baseDir, ANIMATION_PLUGIN_TAILWIND3) !== void 0);
|
|
2706
|
+
if (plugins === "found" && pluginDeclared && pluginInstalled) {
|
|
2707
|
+
return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
2708
|
+
}
|
|
2709
|
+
const cfg = configFile ?? "tailwind.config";
|
|
2710
|
+
const reasons = [];
|
|
2711
|
+
if (!pluginDeclared) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uC120\uC5B8 \uC5C6\uC74C`);
|
|
2712
|
+
else if (!pluginInstalled) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`);
|
|
2713
|
+
if (plugins === "dynamic") reasons.push(`${cfg} plugins \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD568`);
|
|
2714
|
+
else if (plugins !== "found") reasons.push(`${cfg} plugins \uC5D0 \uC5C6\uC74C`);
|
|
2473
2715
|
return {
|
|
2474
2716
|
name: "animation",
|
|
2475
2717
|
severity: "warn",
|
|
2476
|
-
message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${
|
|
2718
|
+
message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${reasons.join(" \xB7 ")}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 ${ANIMATION_PLUGIN_TAILWIND3} \uC124\uCE58 \uB4A4 plugins \uC5D0 require("${ANIMATION_PLUGIN_TAILWIND3}")`
|
|
2477
2719
|
};
|
|
2478
2720
|
}
|
|
2721
|
+
function readAnimationPluginUse(source) {
|
|
2722
|
+
const name = escapeRegExp(ANIMATION_PLUGIN_TAILWIND3);
|
|
2723
|
+
const idents = /* @__PURE__ */ new Set();
|
|
2724
|
+
for (const m of source.matchAll(new RegExp(`\\bimport\\s+([A-Za-z_$][\\w$]*)\\s+from\\s*(["'])${name}\\2`, "g"))) idents.add(m[1]);
|
|
2725
|
+
for (const m of source.matchAll(
|
|
2726
|
+
new RegExp(`\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*require\\s*\\(\\s*(["'])${name}\\2\\s*\\)`, "g")
|
|
2727
|
+
)) {
|
|
2728
|
+
idents.add(m[1]);
|
|
2729
|
+
}
|
|
2730
|
+
const requireCall = new RegExp(`^require\\s*\\(\\s*(["'])${name}\\1\\s*\\)(?:\\s*\\.\\s*default)?$`);
|
|
2731
|
+
let sawDynamic = false;
|
|
2732
|
+
for (const m of source.matchAll(/\bplugins\b\s*(:)?\s*/g)) {
|
|
2733
|
+
if (m[1] === void 0) {
|
|
2734
|
+
const before = source.slice(Math.max(0, (m.index ?? 0) - 1), m.index ?? 0);
|
|
2735
|
+
if (/[{,\s]/.test(before) || before === "") sawDynamic = true;
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
const at = (m.index ?? 0) + m[0].length;
|
|
2739
|
+
if (source[at] !== "[") {
|
|
2740
|
+
sawDynamic = true;
|
|
2741
|
+
continue;
|
|
2742
|
+
}
|
|
2743
|
+
const block = balancedSlice(source, at);
|
|
2744
|
+
if (block === void 0) {
|
|
2745
|
+
sawDynamic = true;
|
|
2746
|
+
continue;
|
|
2747
|
+
}
|
|
2748
|
+
const elements = splitTopLevel(block.slice(1, -1));
|
|
2749
|
+
for (const el of elements) {
|
|
2750
|
+
const e = el.trim();
|
|
2751
|
+
if (e === "") continue;
|
|
2752
|
+
if (requireCall.test(e) || idents.has(e) || idents.has(e.replace(/\(\s*\)$/, ""))) return "found";
|
|
2753
|
+
if (/^require\s*\(\s*(["'])[^"']+\1\s*\)(?:\s*\.\s*default)?$/.test(e)) continue;
|
|
2754
|
+
sawDynamic = true;
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
return sawDynamic ? "dynamic" : "absent";
|
|
2758
|
+
}
|
|
2759
|
+
function splitTopLevel(body) {
|
|
2760
|
+
const out = [];
|
|
2761
|
+
let depth = 0;
|
|
2762
|
+
let start = 0;
|
|
2763
|
+
for (let i = 0; i < body.length; i++) {
|
|
2764
|
+
const c = body[i];
|
|
2765
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2766
|
+
let j = i + 1;
|
|
2767
|
+
while (j < body.length && body[j] !== c) j += body[j] === "\\" ? 2 : 1;
|
|
2768
|
+
i = j;
|
|
2769
|
+
continue;
|
|
2770
|
+
}
|
|
2771
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2772
|
+
else if (c === ")" || c === "]" || c === "}") depth--;
|
|
2773
|
+
else if (c === "," && depth === 0) {
|
|
2774
|
+
out.push(body.slice(start, i));
|
|
2775
|
+
start = i + 1;
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
out.push(body.slice(start));
|
|
2779
|
+
return out;
|
|
2780
|
+
}
|
|
2479
2781
|
|
|
2480
2782
|
// src/template/template-apply.ts
|
|
2481
2783
|
async function templateApplyWarnings(baseDir, detail) {
|
|
2482
2784
|
const warnings = [];
|
|
2483
|
-
const pkgPath =
|
|
2785
|
+
const pkgPath = path9.join(baseDir, "package.json");
|
|
2484
2786
|
const templateRange = detail.devDependencies?.tailwindcss ?? detail.dependencies?.tailwindcss;
|
|
2485
2787
|
const templateMajor = templateRange !== void 0 ? tailwindMajorFromRange(templateRange) : void 0;
|
|
2486
2788
|
if (templateMajor !== void 0 && await fs8.pathExists(pkgPath)) {
|
|
@@ -2498,7 +2800,7 @@ async function templateApplyWarnings(baseDir, detail) {
|
|
|
2498
2800
|
}
|
|
2499
2801
|
}
|
|
2500
2802
|
const usesRootApp = detail.files.some((f) => f.path.startsWith("app/"));
|
|
2501
|
-
if (usesRootApp && await fs8.pathExists(
|
|
2803
|
+
if (usesRootApp && await fs8.pathExists(path9.join(baseDir, "src", "app"))) {
|
|
2502
2804
|
warnings.push(
|
|
2503
2805
|
"src/app \uC774 \uC788\uB294\uB370 \uD15C\uD50C\uB9BF\uC740 \uB8E8\uD2B8 app/ \uC744 \uC501\uB2C8\uB2E4. Next.js \uB294 \uB8E8\uD2B8 app/ \uC774 \uC788\uC73C\uBA74 src/app \uC744 \uC4F0\uC9C0 \uC54A\uC544 \uAE30\uC874 \uB77C\uC6B0\uD2B8\uAC00 \uBE60\uC9D1\uB2C8\uB2E4."
|
|
2504
2806
|
);
|
|
@@ -2515,13 +2817,13 @@ async function applyTemplate(slug, options) {
|
|
|
2515
2817
|
spinner.fail(err.message);
|
|
2516
2818
|
process.exit(1);
|
|
2517
2819
|
}
|
|
2518
|
-
const baseDir =
|
|
2820
|
+
const baseDir = path9.resolve(options.dir || ".");
|
|
2519
2821
|
for (const w of await templateApplyWarnings(baseDir, detail)) {
|
|
2520
2822
|
console.log(chalk5.yellow(`! ${w}`));
|
|
2521
2823
|
}
|
|
2522
2824
|
const conflicts = [];
|
|
2523
2825
|
for (const file of detail.files) {
|
|
2524
|
-
const dest =
|
|
2826
|
+
const dest = path9.join(baseDir, file.path);
|
|
2525
2827
|
if (await fs8.pathExists(dest)) {
|
|
2526
2828
|
conflicts.push(file.path);
|
|
2527
2829
|
}
|
|
@@ -2546,7 +2848,7 @@ async function applyTemplate(slug, options) {
|
|
|
2546
2848
|
if (options.dryRun) {
|
|
2547
2849
|
console.log(chalk5.blue("\n[\uBBF8\uB9AC\uBCF4\uAE30] \uC0DD\uC131\uB420 \uD30C\uC77C:"));
|
|
2548
2850
|
for (const file of detail.files) {
|
|
2549
|
-
const dest =
|
|
2851
|
+
const dest = path9.join(baseDir, file.path);
|
|
2550
2852
|
const exists = conflicts.includes(file.path);
|
|
2551
2853
|
const label = exists ? chalk5.yellow("\uB36E\uC5B4\uC4F0\uAE30") : chalk5.green("\uC0DD\uC131");
|
|
2552
2854
|
console.log(` ${label} ${dest}`);
|
|
@@ -2561,8 +2863,8 @@ async function applyTemplate(slug, options) {
|
|
|
2561
2863
|
}
|
|
2562
2864
|
const writeSpinner = ora3("\uD30C\uC77C \uC0DD\uC131 \uC911...").start();
|
|
2563
2865
|
for (const file of detail.files) {
|
|
2564
|
-
const dest =
|
|
2565
|
-
await fs8.ensureDir(
|
|
2866
|
+
const dest = path9.join(baseDir, file.path);
|
|
2867
|
+
await fs8.ensureDir(path9.dirname(dest));
|
|
2566
2868
|
await fs8.writeFile(dest, file.content);
|
|
2567
2869
|
}
|
|
2568
2870
|
writeSpinner.succeed(`${detail.files.length}\uAC1C \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC`);
|
|
@@ -2623,7 +2925,7 @@ async function initTemplate(slug, options) {
|
|
|
2623
2925
|
}
|
|
2624
2926
|
targetDir = dir;
|
|
2625
2927
|
}
|
|
2626
|
-
const resolved =
|
|
2928
|
+
const resolved = path9.resolve(targetDir);
|
|
2627
2929
|
if (await fs8.pathExists(resolved)) {
|
|
2628
2930
|
const entries = await fs8.readdir(resolved);
|
|
2629
2931
|
if (entries.length > 0) {
|
|
@@ -2639,7 +2941,7 @@ async function initTemplate(slug, options) {
|
|
|
2639
2941
|
await fs8.ensureDir(resolved);
|
|
2640
2942
|
}
|
|
2641
2943
|
await applyTemplate(selectedSlug, { dir: targetDir, yes: true });
|
|
2642
|
-
const configPath =
|
|
2944
|
+
const configPath = path9.join(resolved, "axis.config.json");
|
|
2643
2945
|
if (!await fs8.pathExists(configPath)) {
|
|
2644
2946
|
const axisConfig = createTemplateConfig(selectedSlug);
|
|
2645
2947
|
await fs8.writeJSON(configPath, axisConfig, { spaces: 2 });
|
|
@@ -2654,7 +2956,7 @@ async function initTemplate(slug, options) {
|
|
|
2654
2956
|
|
|
2655
2957
|
// src/template/template-diff.ts
|
|
2656
2958
|
import fs9 from "fs-extra";
|
|
2657
|
-
import
|
|
2959
|
+
import path10 from "path";
|
|
2658
2960
|
import chalk6 from "chalk";
|
|
2659
2961
|
import ora4 from "ora";
|
|
2660
2962
|
async function diffTemplate(slug, options) {
|
|
@@ -2667,10 +2969,10 @@ async function diffTemplate(slug, options) {
|
|
|
2667
2969
|
spinner.fail(err.message);
|
|
2668
2970
|
process.exit(1);
|
|
2669
2971
|
}
|
|
2670
|
-
const baseDir =
|
|
2972
|
+
const baseDir = path10.resolve(options.dir || ".");
|
|
2671
2973
|
const entries = [];
|
|
2672
2974
|
for (const file of detail.files) {
|
|
2673
|
-
const localPath =
|
|
2975
|
+
const localPath = path10.join(baseDir, file.path);
|
|
2674
2976
|
if (!await fs9.pathExists(localPath)) {
|
|
2675
2977
|
entries.push({ path: file.path, status: "added" });
|
|
2676
2978
|
continue;
|
|
@@ -2751,12 +3053,12 @@ async function collectLocalFiles(dir, base) {
|
|
|
2751
3053
|
}
|
|
2752
3054
|
for (const entry of entries) {
|
|
2753
3055
|
if (ignore.has(entry.name)) continue;
|
|
2754
|
-
const fullPath =
|
|
3056
|
+
const fullPath = path10.join(dir, entry.name);
|
|
2755
3057
|
if (entry.isDirectory()) {
|
|
2756
3058
|
const nested = await collectLocalFiles(fullPath, root);
|
|
2757
3059
|
results.push(...nested);
|
|
2758
3060
|
} else {
|
|
2759
|
-
results.push(
|
|
3061
|
+
results.push(path10.relative(root, fullPath).replace(/\\/g, "/"));
|
|
2760
3062
|
}
|
|
2761
3063
|
}
|
|
2762
3064
|
return results;
|
|
@@ -2768,85 +3070,9 @@ import path11 from "path";
|
|
|
2768
3070
|
import chalk7 from "chalk";
|
|
2769
3071
|
|
|
2770
3072
|
// src/theme/brand-core.ts
|
|
2771
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3073
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
2772
3074
|
import { createRequire } from "module";
|
|
2773
3075
|
import { dirname, join as join2, relative, resolve as resolve2, sep } from "path";
|
|
2774
|
-
|
|
2775
|
-
// ../axis-registry-core/src/project.ts
|
|
2776
|
-
import { existsSync as existsSync2, statSync } from "fs";
|
|
2777
|
-
import path10 from "path";
|
|
2778
|
-
function detectInstallCommand(baseDir) {
|
|
2779
|
-
if (existsSync2(path10.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
2780
|
-
if (existsSync2(path10.join(baseDir, "yarn.lock"))) return "yarn install";
|
|
2781
|
-
if (existsSync2(path10.join(baseDir, "package-lock.json"))) return "npm install";
|
|
2782
|
-
return "pnpm install";
|
|
2783
|
-
}
|
|
2784
|
-
function hasDependency2(pkg, name) {
|
|
2785
|
-
for (const field of ["dependencies", "devDependencies"]) {
|
|
2786
|
-
const deps = pkg[field];
|
|
2787
|
-
if (typeof deps === "object" && deps !== null && name in deps) {
|
|
2788
|
-
return String(deps[name]);
|
|
2789
|
-
}
|
|
2790
|
-
}
|
|
2791
|
-
return void 0;
|
|
2792
|
-
}
|
|
2793
|
-
function isPlainObject2(value) {
|
|
2794
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2795
|
-
}
|
|
2796
|
-
function addCommandFor(installCommand, deps) {
|
|
2797
|
-
const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
|
|
2798
|
-
if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
|
|
2799
|
-
if (installCommand.startsWith("npm")) return `npm install ${specs}`;
|
|
2800
|
-
return `pnpm add ${specs}`;
|
|
2801
|
-
}
|
|
2802
|
-
var GLOBAL_CSS_CANDIDATES = [
|
|
2803
|
-
"app/globals.css",
|
|
2804
|
-
"src/app/globals.css",
|
|
2805
|
-
"styles/globals.css",
|
|
2806
|
-
"src/styles/globals.css",
|
|
2807
|
-
"globals.css"
|
|
2808
|
-
];
|
|
2809
|
-
var TAILWIND_CONFIG_CANDIDATES = [
|
|
2810
|
-
"tailwind.config.ts",
|
|
2811
|
-
"tailwind.config.js",
|
|
2812
|
-
"tailwind.config.mjs",
|
|
2813
|
-
"tailwind.config.cjs"
|
|
2814
|
-
];
|
|
2815
|
-
function isFile(file) {
|
|
2816
|
-
try {
|
|
2817
|
-
return statSync(file).isFile();
|
|
2818
|
-
} catch {
|
|
2819
|
-
return false;
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
function isDirectory(dir) {
|
|
2823
|
-
try {
|
|
2824
|
-
return statSync(dir).isDirectory();
|
|
2825
|
-
} catch {
|
|
2826
|
-
return false;
|
|
2827
|
-
}
|
|
2828
|
-
}
|
|
2829
|
-
function findFirstFile(baseDir, candidates) {
|
|
2830
|
-
return candidates.find((c) => isFile(path10.join(baseDir, c)));
|
|
2831
|
-
}
|
|
2832
|
-
function detectProjectPaths(baseDirInput) {
|
|
2833
|
-
const baseDir = path10.resolve(baseDirInput);
|
|
2834
|
-
const hasSrc = isDirectory(path10.join(baseDir, "src"));
|
|
2835
|
-
const css = findFirstFile(baseDir, GLOBAL_CSS_CANDIDATES);
|
|
2836
|
-
const tw = findFirstFile(baseDir, TAILWIND_CONFIG_CANDIDATES);
|
|
2837
|
-
return {
|
|
2838
|
-
componentsDir: hasSrc ? "./src/components/ui" : "./components/ui",
|
|
2839
|
-
globalCss: css !== void 0 ? `./${css}` : hasSrc ? "./src/app/globals.css" : "./app/globals.css",
|
|
2840
|
-
globalCssSource: css !== void 0 ? "found" : "default",
|
|
2841
|
-
tailwindConfig: tw !== void 0 ? `./${tw}` : "./tailwind.config.ts",
|
|
2842
|
-
tailwindConfigSource: tw !== void 0 ? "found" : "default"
|
|
2843
|
-
};
|
|
2844
|
-
}
|
|
2845
|
-
function projectFileExists(baseDir, relPath) {
|
|
2846
|
-
return isFile(path10.resolve(baseDir, relPath));
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
|
-
// src/theme/brand-core.ts
|
|
2850
3076
|
var TOKENS_PACKAGE = "@axis-ds/tokens";
|
|
2851
3077
|
var BRAND_NAME_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
2852
3078
|
var MIN_BRAND_TOKENS_VERSION = "1.3.0";
|
|
@@ -2867,7 +3093,7 @@ var KEY_TOKENS = [
|
|
|
2867
3093
|
];
|
|
2868
3094
|
var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
|
|
2869
3095
|
function readJsonFile(file) {
|
|
2870
|
-
return JSON.parse(
|
|
3096
|
+
return JSON.parse(readFileSync3(file, "utf8"));
|
|
2871
3097
|
}
|
|
2872
3098
|
function errorCode(err) {
|
|
2873
3099
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
@@ -2943,7 +3169,7 @@ var AXIS_CONFIG_FILE_NAME = "axis.config.json";
|
|
|
2943
3169
|
function readBrandConfig(baseDir) {
|
|
2944
3170
|
let parsed;
|
|
2945
3171
|
try {
|
|
2946
|
-
parsed = JSON.parse(
|
|
3172
|
+
parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
|
|
2947
3173
|
} catch {
|
|
2948
3174
|
return null;
|
|
2949
3175
|
}
|
|
@@ -2962,7 +3188,7 @@ function inspectBrandImport(baseDir) {
|
|
|
2962
3188
|
return { ...base, state: "css-missing", imports: [] };
|
|
2963
3189
|
}
|
|
2964
3190
|
const cssFile = relative(root, location.path).split(sep).join("/");
|
|
2965
|
-
const imports = [...new Set(findBrandImports(
|
|
3191
|
+
const imports = [...new Set(findBrandImports(readFileSync3(location.path, "utf8")))];
|
|
2966
3192
|
let state;
|
|
2967
3193
|
if (imports.includes(brand)) state = "match";
|
|
2968
3194
|
else if (imports.length === 0) state = "import-missing";
|
|
@@ -3046,34 +3272,23 @@ function pickKeyTokens(decls) {
|
|
|
3046
3272
|
}
|
|
3047
3273
|
return out;
|
|
3048
3274
|
}
|
|
3275
|
+
var THEME_MARKUP_BRAND_MIN_VERSION = "1.7.0";
|
|
3049
3276
|
function providerExample(name) {
|
|
3050
3277
|
return [
|
|
3051
|
-
"// 1)
|
|
3278
|
+
"// 1) \uB8E8\uD2B8 \uB808\uC774\uC544\uC6C3(app/layout.tsx)\uC758 <html> \uC5D0 \uBD99\uC785\uB2C8\uB2E4(\uCCAB \uD654\uBA74\uBD80\uD130 \uC801\uC6A9)",
|
|
3279
|
+
`// ThemeProvider \uB97C \uD568\uAED8 \uC4F0\uBA74 @axis-ds/theme ${THEME_MARKUP_BRAND_MIN_VERSION} \uC774\uC0C1\uC774 \uD544\uC694\uD569\uB2C8\uB2E4(\uADF8 \uC544\uB798\uB294 \uB9C8\uC6B4\uD2B8 \uB54C \uC18D\uC131\uC744 \uC9C0\uC6C0)`,
|
|
3052
3280
|
`<html lang="ko" data-brand="${name}">`,
|
|
3053
3281
|
"",
|
|
3054
|
-
|
|
3282
|
+
`// 2) \uC0AC\uC6A9\uC790\uAC00 \uACE0\uB974\uAC8C \uD558\uB824\uBA74 setBrand \uB85C \uCF1C\uACE0 \uB055\uB2C8\uB2E4(\uC800\uC7A5\uB3FC \uC720\uC9C0, setBrand(undefined) \uB85C \uB048 \uC0C1\uD0DC \uC720\uC9C0\uB294 ${THEME_MARKUP_BRAND_MIN_VERSION} \uC774\uC0C1)`,
|
|
3055
3283
|
'import { useTheme } from "@axis-ds/theme";',
|
|
3056
3284
|
"const { setBrand } = useTheme();",
|
|
3057
3285
|
`setBrand("${name}");`
|
|
3058
3286
|
].join("\n");
|
|
3059
3287
|
}
|
|
3060
|
-
var BRAND_ACTIVATION_FILES =
|
|
3061
|
-
"app/layout.tsx",
|
|
3062
|
-
"app/layout.jsx",
|
|
3063
|
-
"app/layout.js",
|
|
3064
|
-
"src/app/layout.tsx",
|
|
3065
|
-
"src/app/layout.jsx",
|
|
3066
|
-
"src/app/layout.js",
|
|
3067
|
-
"pages/_app.tsx",
|
|
3068
|
-
"pages/_app.jsx",
|
|
3069
|
-
"pages/_document.tsx",
|
|
3070
|
-
"pages/_document.jsx",
|
|
3071
|
-
"src/pages/_app.tsx",
|
|
3072
|
-
"src/pages/_app.jsx",
|
|
3073
|
-
"src/pages/_document.tsx",
|
|
3074
|
-
"src/pages/_document.jsx"
|
|
3075
|
-
];
|
|
3288
|
+
var BRAND_ACTIVATION_FILES = ROOT_LAYOUT_FILES;
|
|
3076
3289
|
var BRAND_ACTIVATION_PATTERN = /data-brand|setBrand\s*\(|defaultBrand\s*=/;
|
|
3290
|
+
var PROVIDER_ACTIVATION_PATTERN = /setBrand\s*\(|defaultBrand\s*=/;
|
|
3291
|
+
var THEME_PROVIDER_PATTERN = /<ThemeProvider\b/;
|
|
3077
3292
|
function stripJsLikeComments(src) {
|
|
3078
3293
|
return src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`])\/\/[^\n]*/g, "$1");
|
|
3079
3294
|
}
|
|
@@ -3084,15 +3299,23 @@ function findBrandActivation(baseDir) {
|
|
|
3084
3299
|
const file = join2(root, candidate);
|
|
3085
3300
|
if (!isFile2(file)) continue;
|
|
3086
3301
|
layoutFiles.push(candidate);
|
|
3087
|
-
const text = stripJsLikeComments(
|
|
3088
|
-
|
|
3302
|
+
const text = stripJsLikeComments(readFileSync3(file, "utf8"));
|
|
3303
|
+
const providerTexts = [];
|
|
3089
3304
|
for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
|
|
3090
3305
|
for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
|
|
3091
3306
|
const rel3 = `${dirname(candidate)}/${m[1]}${ext}`;
|
|
3092
3307
|
const p = join2(root, rel3);
|
|
3093
|
-
if (isFile2(p)
|
|
3094
|
-
|
|
3095
|
-
|
|
3308
|
+
if (isFile2(p)) providerTexts.push({ rel: rel3, text: stripJsLikeComments(readFileSync3(p, "utf8")) });
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
const all = [text, ...providerTexts.map((x) => x.text)];
|
|
3312
|
+
const markupWithProvider = !all.some((t) => PROVIDER_ACTIVATION_PATTERN.test(t)) && all.some((t) => THEME_PROVIDER_PATTERN.test(t));
|
|
3313
|
+
if (BRAND_ACTIVATION_PATTERN.test(text)) {
|
|
3314
|
+
return markupWithProvider ? { found: candidate, layoutFiles, markupWithProvider } : { found: candidate, layoutFiles };
|
|
3315
|
+
}
|
|
3316
|
+
for (const x of providerTexts) {
|
|
3317
|
+
if (BRAND_ACTIVATION_PATTERN.test(x.text)) {
|
|
3318
|
+
return markupWithProvider ? { found: x.rel, layoutFiles, markupWithProvider } : { found: x.rel, layoutFiles };
|
|
3096
3319
|
}
|
|
3097
3320
|
}
|
|
3098
3321
|
}
|
|
@@ -3102,7 +3325,18 @@ function inspectBrandActivation(baseDir) {
|
|
|
3102
3325
|
const config = readBrandConfig(baseDir);
|
|
3103
3326
|
const brand = config?.brand;
|
|
3104
3327
|
if (typeof brand !== "string" || brand.trim() === "") return null;
|
|
3105
|
-
|
|
3328
|
+
const location = findBrandActivation(baseDir);
|
|
3329
|
+
if (!location.markupWithProvider) return { brand, ...location };
|
|
3330
|
+
return { brand, ...location, theme: packageVersionGate(baseDir, readProjectPackageJson(baseDir), THEME_PACKAGE, THEME_MARKUP_BRAND_MIN_VERSION) };
|
|
3331
|
+
}
|
|
3332
|
+
var THEME_PACKAGE = "@axis-ds/theme";
|
|
3333
|
+
function readProjectPackageJson(baseDir) {
|
|
3334
|
+
try {
|
|
3335
|
+
const parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), "package.json"), "utf8"));
|
|
3336
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
|
|
3337
|
+
} catch {
|
|
3338
|
+
return void 0;
|
|
3339
|
+
}
|
|
3106
3340
|
}
|
|
3107
3341
|
function getBrand(baseDir, name) {
|
|
3108
3342
|
const tokens = resolveTokens(baseDir);
|
|
@@ -3120,7 +3354,7 @@ function getBrand(baseDir, name) {
|
|
|
3120
3354
|
try {
|
|
3121
3355
|
summary = readSummary(baseDir, entry);
|
|
3122
3356
|
const cssPath = projectRequire(baseDir).resolve(summary.importPath);
|
|
3123
|
-
parsed = parseBrandCss(
|
|
3357
|
+
parsed = parseBrandCss(readFileSync3(cssPath, "utf8"), name);
|
|
3124
3358
|
} catch (err) {
|
|
3125
3359
|
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
|
|
3126
3360
|
throw err;
|
|
@@ -3138,6 +3372,57 @@ function getBrand(baseDir, name) {
|
|
|
3138
3372
|
};
|
|
3139
3373
|
}
|
|
3140
3374
|
|
|
3375
|
+
// ../axis-registry-core/src/template/dependencies-core.ts
|
|
3376
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3377
|
+
import { join as join3, resolve as resolve3 } from "path";
|
|
3378
|
+
var REQUIRED_DEPENDENCIES = ["tailwindcss"];
|
|
3379
|
+
var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
|
|
3380
|
+
function declaredAxisPackages(pkg) {
|
|
3381
|
+
const out = [];
|
|
3382
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
3383
|
+
const deps = pkg[field];
|
|
3384
|
+
if (!isPlainObject(deps)) continue;
|
|
3385
|
+
for (const name of Object.keys(deps)) if (name.startsWith("@axis-ds/") && !out.includes(name)) out.push(name);
|
|
3386
|
+
}
|
|
3387
|
+
return out;
|
|
3388
|
+
}
|
|
3389
|
+
function checkDependencies(baseDirInput) {
|
|
3390
|
+
const baseDir = resolve3(baseDirInput);
|
|
3391
|
+
let pkg;
|
|
3392
|
+
try {
|
|
3393
|
+
const parsed = JSON.parse(readFileSync4(join3(baseDir, "package.json"), "utf8"));
|
|
3394
|
+
if (!isPlainObject(parsed)) throw new Error("not object");
|
|
3395
|
+
pkg = parsed;
|
|
3396
|
+
} catch (err) {
|
|
3397
|
+
if (err?.code === "ENOENT") {
|
|
3398
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
|
|
3399
|
+
}
|
|
3400
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
|
|
3401
|
+
}
|
|
3402
|
+
const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
3403
|
+
if (missingRequired.length > 0) {
|
|
3404
|
+
return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
|
|
3405
|
+
}
|
|
3406
|
+
const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
3407
|
+
const targets = [
|
|
3408
|
+
...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0),
|
|
3409
|
+
...declaredAxisPackages(pkg)
|
|
3410
|
+
];
|
|
3411
|
+
const pnp = isPnpProject(baseDir);
|
|
3412
|
+
const notInstalled = pnp ? [] : targets.filter((d) => findInstalledPackage(baseDir, d) === void 0);
|
|
3413
|
+
const problems = [];
|
|
3414
|
+
if (missingRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`);
|
|
3415
|
+
if (notInstalled.length > 0) {
|
|
3416
|
+
problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalled.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
|
|
3417
|
+
}
|
|
3418
|
+
if (problems.length > 0) return { name: "dependencies", severity: "warn", message: problems.join(" / ") };
|
|
3419
|
+
return {
|
|
3420
|
+
name: "dependencies",
|
|
3421
|
+
severity: "pass",
|
|
3422
|
+
message: pnp ? `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (Plug'n'Play \uB77C \uC124\uCE58\uBCF8\uC740 \uD655\uC778\uD558\uC9C0 \uC54A\uC74C, ${targets.length}\uAC1C)` : `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8 \xB7 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${targets.length}\uAC1C \uD655\uC778)`
|
|
3423
|
+
};
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3141
3426
|
// src/template/template-check.ts
|
|
3142
3427
|
var SEVERITY_ICON = {
|
|
3143
3428
|
pass: chalk7.green("PASS"),
|
|
@@ -3151,7 +3436,7 @@ async function collectCheckResults(dir) {
|
|
|
3151
3436
|
results.push(checkTailwindSetup(baseDir));
|
|
3152
3437
|
results.push(checkGlobalsCss(baseDir));
|
|
3153
3438
|
results.push(await checkUtils(baseDir));
|
|
3154
|
-
results.push(
|
|
3439
|
+
results.push(checkDependencies(baseDir));
|
|
3155
3440
|
const brand = checkBrand(baseDir);
|
|
3156
3441
|
if (brand) results.push(brand);
|
|
3157
3442
|
const activation = inspectBrandActivation(baseDir);
|
|
@@ -3229,41 +3514,6 @@ async function checkUtils(baseDir) {
|
|
|
3229
3514
|
message: "utils.ts\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC2DC \uD544\uC694)"
|
|
3230
3515
|
};
|
|
3231
3516
|
}
|
|
3232
|
-
async function checkDependencies(baseDir) {
|
|
3233
|
-
const pkgPath = path11.join(baseDir, "package.json");
|
|
3234
|
-
if (!await fs10.pathExists(pkgPath)) {
|
|
3235
|
-
return {
|
|
3236
|
-
name: "package.json",
|
|
3237
|
-
severity: "fail",
|
|
3238
|
-
message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
|
|
3239
|
-
};
|
|
3240
|
-
}
|
|
3241
|
-
const pkg = await fs10.readJSON(pkgPath);
|
|
3242
|
-
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
3243
|
-
const required = ["tailwindcss"];
|
|
3244
|
-
const recommended = ["clsx", "tailwind-merge"];
|
|
3245
|
-
const missingRequired = required.filter((d) => !allDeps[d]);
|
|
3246
|
-
const missingRecommended = recommended.filter((d) => !allDeps[d]);
|
|
3247
|
-
if (missingRequired.length > 0) {
|
|
3248
|
-
return {
|
|
3249
|
-
name: "dependencies",
|
|
3250
|
-
severity: "fail",
|
|
3251
|
-
message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}`
|
|
3252
|
-
};
|
|
3253
|
-
}
|
|
3254
|
-
if (missingRecommended.length > 0) {
|
|
3255
|
-
return {
|
|
3256
|
-
name: "dependencies",
|
|
3257
|
-
severity: "warn",
|
|
3258
|
-
message: `\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`
|
|
3259
|
-
};
|
|
3260
|
-
}
|
|
3261
|
-
return {
|
|
3262
|
-
name: "dependencies",
|
|
3263
|
-
severity: "pass",
|
|
3264
|
-
message: "\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uBAA8\uB450 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4"
|
|
3265
|
-
};
|
|
3266
|
-
}
|
|
3267
3517
|
function checkBrand(baseDir) {
|
|
3268
3518
|
const check = inspectBrandImport(baseDir);
|
|
3269
3519
|
return check ? brandCheckResult(check) : null;
|
|
@@ -3299,6 +3549,15 @@ function brandCheckResult(check) {
|
|
|
3299
3549
|
}
|
|
3300
3550
|
}
|
|
3301
3551
|
function brandActivationResult(check) {
|
|
3552
|
+
if (check.found && check.theme && check.theme.status !== "ok") {
|
|
3553
|
+
const label = versionGateLabel(check.theme);
|
|
3554
|
+
const why = check.theme.status === "below" ? `@axis-ds/theme ${label} \uC758 ThemeProvider \uAC00 \uB9C8\uC6B4\uD2B8 \uB54C \uC9C0\uC6C1\uB2C8\uB2E4` : `@axis-ds/theme \uBC84\uC804\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${label}). ${THEME_MARKUP_BRAND_MIN_VERSION} \uBBF8\uB9CC\uC774\uBA74 ThemeProvider \uAC00 \uB9C8\uC6B4\uD2B8 \uB54C \uC9C0\uC6C1\uB2C8\uB2E4`;
|
|
3555
|
+
return {
|
|
3556
|
+
name: "brand.activation",
|
|
3557
|
+
severity: "warn",
|
|
3558
|
+
message: `${check.found}\uC758 <html data-brand> \uB97C ${why} \u2192 @axis-ds/theme ${THEME_MARKUP_BRAND_MIN_VERSION} \uC774\uC0C1\uC73C\uB85C \uC62C\uB9AC\uAC70\uB098 setBrand("${check.brand}")`
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3302
3561
|
if (check.found) {
|
|
3303
3562
|
return {
|
|
3304
3563
|
name: "brand.activation",
|
|
@@ -3422,14 +3681,13 @@ import chalk9 from "chalk";
|
|
|
3422
3681
|
import path13 from "path";
|
|
3423
3682
|
|
|
3424
3683
|
// src/theme/theme-add.ts
|
|
3425
|
-
import { accessSync, constants, existsSync as existsSync4, readFileSync as
|
|
3684
|
+
import { accessSync, constants, existsSync as existsSync4, readFileSync as readFileSync5, realpathSync, unlinkSync, writeFileSync } from "fs";
|
|
3426
3685
|
import path12 from "path";
|
|
3427
3686
|
var TOKENS_DEPENDENCY_RANGE = `^${TOKENS_DEPENDENCY_MIN_VERSION}`;
|
|
3428
3687
|
var TAILWIND3_BASE_IMPORTS = [`${TOKENS_PACKAGE}/css`, `${TOKENS_PACKAGE}/css/shadcn`];
|
|
3429
|
-
var THEME_PACKAGE = "@axis-ds/theme";
|
|
3430
3688
|
var THEME_MIN_VERSION = "1.3.0";
|
|
3431
3689
|
function readText(file) {
|
|
3432
|
-
return existsSync4(file) ?
|
|
3690
|
+
return existsSync4(file) ? readFileSync5(file, "utf8") : null;
|
|
3433
3691
|
}
|
|
3434
3692
|
function eolOf(text) {
|
|
3435
3693
|
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -3551,7 +3809,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3551
3809
|
let config;
|
|
3552
3810
|
try {
|
|
3553
3811
|
const parsed = JSON.parse(configText);
|
|
3554
|
-
if (!
|
|
3812
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3555
3813
|
config = parsed;
|
|
3556
3814
|
} catch (err) {
|
|
3557
3815
|
plan.errors.push({ kind: "invalid-config", message: err.message });
|
|
@@ -3563,7 +3821,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3563
3821
|
}
|
|
3564
3822
|
plan.tokens = resolveTokens(baseDir);
|
|
3565
3823
|
if (plan.tokens.status === "ok" && plan.tokens.indexPath) {
|
|
3566
|
-
const data = JSON.parse(
|
|
3824
|
+
const data = JSON.parse(readFileSync5(plan.tokens.indexPath, "utf8"));
|
|
3567
3825
|
const entries = Array.isArray(data.brands) ? data.brands : [];
|
|
3568
3826
|
const entry = entries.find((e) => e.name === brand);
|
|
3569
3827
|
if (!entry) {
|
|
@@ -3585,7 +3843,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3585
3843
|
if (pkgText !== null) {
|
|
3586
3844
|
try {
|
|
3587
3845
|
const parsed = JSON.parse(pkgText);
|
|
3588
|
-
if (!
|
|
3846
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3589
3847
|
pkg = parsed;
|
|
3590
3848
|
} catch (err) {
|
|
3591
3849
|
plan.errors.push({ kind: "invalid-package-json", message: err.message });
|
|
@@ -3597,7 +3855,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3597
3855
|
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
3598
3856
|
const requiredBaseImports = tailwind4 ? [
|
|
3599
3857
|
TOKENS_TAILWIND4_ENTRY,
|
|
3600
|
-
...TAILWIND4_COMPONENT_PACKAGES.filter((n) => pkg !== void 0 &&
|
|
3858
|
+
...TAILWIND4_COMPONENT_PACKAGES.filter((n) => pkg !== void 0 && hasDependency(pkg, n) !== void 0).map(
|
|
3601
3859
|
(n) => `${n}/tailwind.css`
|
|
3602
3860
|
)
|
|
3603
3861
|
] : [...TAILWIND3_BASE_IMPORTS];
|
|
@@ -3614,7 +3872,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3614
3872
|
plan.writes = [];
|
|
3615
3873
|
return plan;
|
|
3616
3874
|
}
|
|
3617
|
-
const before =
|
|
3875
|
+
const before = readFileSync5(location.path, "utf8");
|
|
3618
3876
|
const imported = findBrandImports(before);
|
|
3619
3877
|
const otherBrands = [...new Set(imported.filter((n) => n !== brand))];
|
|
3620
3878
|
const brandAdded = !imported.includes(brand);
|
|
@@ -3651,7 +3909,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3651
3909
|
const content = inspectTailwindContent(baseDir);
|
|
3652
3910
|
plan.tailwindConfig = {
|
|
3653
3911
|
configFile: configFile2,
|
|
3654
|
-
presetMissing: configFile2 === void 0 || !hasTokensPresetReference(
|
|
3912
|
+
presetMissing: configFile2 === void 0 || !hasTokensPresetReference(readFileSync5(path12.join(baseDir, configFile2), "utf8")),
|
|
3655
3913
|
contentMissing: content?.targets.filter((t) => !t.covered) ?? [],
|
|
3656
3914
|
contentUnknown: content !== null && (content.unreadable || content.dynamic)
|
|
3657
3915
|
};
|
|
@@ -3664,12 +3922,12 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3664
3922
|
if (pkgText === null || pkg === void 0) {
|
|
3665
3923
|
plan.dependency = { action: "no-package-json", upgrade, themeMissing: false, tokensAddCommand, themeAddCommand };
|
|
3666
3924
|
} else {
|
|
3667
|
-
const themeMissing =
|
|
3668
|
-
const declared =
|
|
3925
|
+
const themeMissing = hasDependency(pkg, THEME_PACKAGE) === void 0;
|
|
3926
|
+
const declared = hasDependency(pkg, TOKENS_PACKAGE);
|
|
3669
3927
|
if (declared !== void 0) {
|
|
3670
3928
|
plan.dependency = { action: "present", declaredRange: declared, upgrade, themeMissing, tokensAddCommand, themeAddCommand };
|
|
3671
3929
|
} else {
|
|
3672
|
-
const deps =
|
|
3930
|
+
const deps = isPlainObject(pkg.dependencies) ? { ...pkg.dependencies } : {};
|
|
3673
3931
|
deps[TOKENS_PACKAGE] = TOKENS_DEPENDENCY_RANGE;
|
|
3674
3932
|
const next = { ...pkg, dependencies: deps };
|
|
3675
3933
|
plan.dependency = { action: "add", upgrade, themeMissing, tokensAddCommand, themeAddCommand };
|
|
@@ -3754,6 +4012,25 @@ function applyThemeAdd(plan) {
|
|
|
3754
4012
|
}
|
|
3755
4013
|
|
|
3756
4014
|
// src/theme/index.ts
|
|
4015
|
+
function importOffset(css, spec) {
|
|
4016
|
+
const escaped = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4017
|
+
const m = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${escaped}["']`).exec(css);
|
|
4018
|
+
return m ? m.index : -1;
|
|
4019
|
+
}
|
|
4020
|
+
function baseImportLines(after, spec, brandImportPath2, file) {
|
|
4021
|
+
if (spec.endsWith("/tailwind.css")) {
|
|
4022
|
+
return [` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C, \uC704\uCE58 \uBB34\uAD00)`];
|
|
4023
|
+
}
|
|
4024
|
+
const at = importOffset(after, spec);
|
|
4025
|
+
const brandAt = importOffset(after, brandImportPath2);
|
|
4026
|
+
if (brandAt === -1 || at !== -1 && at < brandAt) {
|
|
4027
|
+
return [` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uAE30\uBCF8 \uD1A0\uD070 CSS, \uBE0C\uB79C\uB4DC \uC55E)`];
|
|
4028
|
+
}
|
|
4029
|
+
return [
|
|
4030
|
+
` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uAE30\uBCF8 \uD1A0\uD070 CSS)`,
|
|
4031
|
+
chalk9.yellow(` ! \uC774 \uC904\uC774 \uBE0C\uB79C\uB4DC import \uB4A4\uC5D0 \uB4E4\uC5B4\uAC14\uC2B5\uB2C8\uB2E4. \uBE0C\uB79C\uB4DC \uAC12\uC774 \uAE30\uBCF8 \uD1A0\uD070\uC5D0 \uB36E\uC774\uBBC0\uB85C @import "${brandImportPath2}"; \uC55E\uC73C\uB85C \uC62E\uAE30\uC138\uC694`)
|
|
4032
|
+
];
|
|
4033
|
+
}
|
|
3757
4034
|
function tokensInstallCommand(baseDir) {
|
|
3758
4035
|
return addCommandFor(detectInstallCommand(baseDir), { [TOKENS_PACKAGE]: TOKENS_DEPENDENCY_RANGE });
|
|
3759
4036
|
}
|
|
@@ -3941,8 +4218,9 @@ function renderThemeAdd(plan, written) {
|
|
|
3941
4218
|
}
|
|
3942
4219
|
const brandLine = `@import "${plan.importPath}";`;
|
|
3943
4220
|
if (css?.action === "add" && css.file) {
|
|
4221
|
+
const after = plan.writes.find((w) => w.file === css.file)?.after ?? "";
|
|
3944
4222
|
for (const spec of css.baseImports) {
|
|
3945
|
-
lines.push(
|
|
4223
|
+
lines.push(...baseImportLines(after, spec, plan.importPath, rel(plan, css.file)));
|
|
3946
4224
|
}
|
|
3947
4225
|
if (css.brandAdded) lines.push(` ${chalk9.green("\u2713")} ${rel(plan, css.file)}: ${brandLine} \uCD94\uAC00`);
|
|
3948
4226
|
else lines.push(` ${chalk9.gray("-")} ${rel(plan, css.file)}: \uBE0C\uB79C\uB4DC import \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uAC74\uB108\uB700`);
|
|
@@ -4002,7 +4280,8 @@ function renderThemeAdd(plan, written) {
|
|
|
4002
4280
|
lines.push("", chalk9.bold(`Tailwind \uC124\uC815 (${tw.configFile ?? "tailwind.config"}, \uD30C\uC77C\uC740 \uACE0\uCE58\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4)`));
|
|
4003
4281
|
if (tw.presetMissing) {
|
|
4004
4282
|
lines.push(
|
|
4005
|
-
|
|
4283
|
+
// WI-0072: CommonJS 는 모든 tokens 버전에서 동작하는 `.default` 형태로 안내합니다(1.6.2 이하의 bare require 는 preset 이 빠짐)
|
|
4284
|
+
chalk9.yellow(` ! AXIS preset \uC774 \uC5C6\uC2B5\uB2C8\uB2E4. presets \uC5D0 \uB123\uC73C\uC138\uC694: presets: [${TOKENS_TAILWIND3_CJS_REQUIRE}]`) + chalk9.gray(` (ESM \xB7 TypeScript \uC774\uBA74 import axisPreset from "${TOKENS_TAILWIND3_PRESET}" \uB4A4 presets: [axisPreset])`)
|
|
4006
4285
|
);
|
|
4007
4286
|
}
|
|
4008
4287
|
for (const t of tw.contentMissing) {
|
|
@@ -4017,6 +4296,13 @@ function renderThemeAdd(plan, written) {
|
|
|
4017
4296
|
lines.push("", chalk9.bold(`\uBE0C\uB79C\uB4DC \uCF1C\uAE30 (ThemeProvider \uB294 ${THEME_PACKAGE} ${THEME_MIN_VERSION} \uC774\uC0C1)`));
|
|
4018
4297
|
if (act?.found) {
|
|
4019
4298
|
lines.push(` ${chalk9.gray("-")} ${act.found} \uC5D0 \uBE0C\uB79C\uB4DC\uB97C \uCF1C\uB294 \uCF54\uB4DC(data-brand \xB7 setBrand \uB4F1)\uAC00 \uC788\uC2B5\uB2C8\uB2E4. "${plan.brand}" \uB85C \uCF1C\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.`);
|
|
4299
|
+
if (act.markupWithProvider) {
|
|
4300
|
+
lines.push(
|
|
4301
|
+
chalk9.yellow(
|
|
4302
|
+
` ! <html data-brand> \uC640 ThemeProvider \uB97C \uD568\uAED8 \uC4F0\uBA74 ${THEME_PACKAGE} ${THEME_MARKUP_BRAND_MIN_VERSION} \uC774\uC0C1\uC774\uC5B4\uC57C \uB9C8\uC6B4\uD2B8 \uB54C \uC9C0\uC6CC\uC9C0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uBCF8 \uD655\uC778: axis check`
|
|
4303
|
+
)
|
|
4304
|
+
);
|
|
4305
|
+
}
|
|
4020
4306
|
} else {
|
|
4021
4307
|
lines.push(
|
|
4022
4308
|
...providerExample(plan.brand).split("\n").map((l) => l ? ` ${l}` : ""),
|
|
@@ -4387,7 +4673,7 @@ async function fetchRegistryJson(url, options = {}) {
|
|
|
4387
4673
|
}
|
|
4388
4674
|
|
|
4389
4675
|
// src/init/init.ts
|
|
4390
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as
|
|
4676
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
4391
4677
|
import path15 from "path";
|
|
4392
4678
|
import chalk10 from "chalk";
|
|
4393
4679
|
import fs12 from "fs-extra";
|
|
@@ -4644,7 +4930,7 @@ async function resolveInitAnswers(baseDirInput, tailwind4) {
|
|
|
4644
4930
|
}
|
|
4645
4931
|
function animationGuideLine(pkg, tailwind4, installCommand) {
|
|
4646
4932
|
const name = tailwind4 ? ANIMATION_PLUGIN_TAILWIND4 : ANIMATION_PLUGIN_TAILWIND3;
|
|
4647
|
-
if (pkg !== void 0 && (
|
|
4933
|
+
if (pkg !== void 0 && (hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0 || hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND4) !== void 0)) {
|
|
4648
4934
|
return void 0;
|
|
4649
4935
|
}
|
|
4650
4936
|
const add = `${addCommandFor(installCommand, {}).trimEnd()} ${name}`;
|
|
@@ -4659,15 +4945,15 @@ var TAILWIND4_TOKENS_VERSION = TAILWIND4_MIN_AXIS_VERSION;
|
|
|
4659
4945
|
var TAILWIND4_CONFLICT_LINE = " ! create-next-app \uAE30\uBCF8 globals.css \uC758 :root \xB7 @theme inline \xB7 @media (prefers-color-scheme: dark) \xB7 body \uBE14\uB85D\uC740 AXIS \uC640 \uAC19\uC740 \uC774\uB984(--background \xB7 --foreground \xB7 --color-background \xB7 --font-sans \xB7 --font-mono)\uC744 \uB2E4\uB978 \uAC12\uC73C\uB85C \uC815\uC758\uD569\uB2C8\uB2E4. \uC774 \uBE14\uB85D\uB4E4\uC744 \uC9C0\uC6B0\uC138\uC694.";
|
|
4660
4946
|
function readPackageJsonSafe(baseDir) {
|
|
4661
4947
|
try {
|
|
4662
|
-
const text =
|
|
4948
|
+
const text = readFileSync6(path15.join(baseDir, "package.json"), "utf8");
|
|
4663
4949
|
const parsed = JSON.parse(text.startsWith(BOM) ? text.slice(1) : text);
|
|
4664
|
-
return
|
|
4950
|
+
return isPlainObject(parsed) ? parsed : void 0;
|
|
4665
4951
|
} catch {
|
|
4666
4952
|
return void 0;
|
|
4667
4953
|
}
|
|
4668
4954
|
}
|
|
4669
4955
|
function tailwind4GuideLines(pkg, installCommand, globalCss, baseDir) {
|
|
4670
|
-
const used = TAILWIND4_COMPONENT_PACKAGES.filter((name) => pkg !== void 0 &&
|
|
4956
|
+
const used = TAILWIND4_COMPONENT_PACKAGES.filter((name) => pkg !== void 0 && hasDependency(pkg, name) !== void 0);
|
|
4671
4957
|
const lines = [
|
|
4672
4958
|
`Tailwind 4: \uC804\uC5ED CSS(${globalCss}) \uB9E8 \uC704\uC5D0 \uB2E4\uC74C \uC904\uC744 \uB123\uC73C\uC138\uC694(\uD30C\uC77C\uC740 \uACE0\uCE58\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4).`,
|
|
4673
4959
|
' @import "tailwindcss";',
|
|
@@ -4680,7 +4966,7 @@ function tailwind4GuideLines(pkg, installCommand, globalCss, baseDir) {
|
|
|
4680
4966
|
);
|
|
4681
4967
|
}
|
|
4682
4968
|
lines.push(TAILWIND4_CONFLICT_LINE);
|
|
4683
|
-
if (pkg === void 0 ||
|
|
4969
|
+
if (pkg === void 0 || hasDependency(pkg, TOKENS_PACKAGE) === void 0) {
|
|
4684
4970
|
const add = addCommandFor(installCommand, { [TOKENS_PACKAGE]: `^${TAILWIND4_TOKENS_VERSION}` });
|
|
4685
4971
|
lines.push(` ${TOKENS_PACKAGE} \uC124\uCE58: ${add}`);
|
|
4686
4972
|
}
|
|
@@ -4743,7 +5029,7 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4743
5029
|
if (!where.inside) return unwritable(`\uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`);
|
|
4744
5030
|
let text;
|
|
4745
5031
|
try {
|
|
4746
|
-
text =
|
|
5032
|
+
text = readFileSync6(pkgFile, "utf8");
|
|
4747
5033
|
} catch (err) {
|
|
4748
5034
|
return unwritable(err.message);
|
|
4749
5035
|
}
|
|
@@ -4752,7 +5038,7 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4752
5038
|
let pkg;
|
|
4753
5039
|
try {
|
|
4754
5040
|
const parsed = JSON.parse(body);
|
|
4755
|
-
if (!
|
|
5041
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
4756
5042
|
pkg = parsed;
|
|
4757
5043
|
} catch (err) {
|
|
4758
5044
|
return unwritable(`JSON \uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${err.message}`);
|
|
@@ -4762,14 +5048,14 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4762
5048
|
plan.addCommand = addCommandFor(installCommand, plan.ranges);
|
|
4763
5049
|
const missing = {};
|
|
4764
5050
|
for (const [name, range] of Object.entries(plan.ranges)) {
|
|
4765
|
-
const declared =
|
|
5051
|
+
const declared = hasDependency(pkg, name);
|
|
4766
5052
|
if (declared !== void 0) plan.present.push({ name, range: declared });
|
|
4767
5053
|
else missing[name] = range;
|
|
4768
5054
|
}
|
|
4769
5055
|
plan.added = Object.keys(missing);
|
|
4770
5056
|
plan.addCommand = addCommandFor(installCommand, plan.added.length > 0 ? missing : plan.ranges);
|
|
4771
5057
|
if (plan.added.length === 0) return { ...plan, action: "present" };
|
|
4772
|
-
if (pkg.dependencies !== void 0 && !
|
|
5058
|
+
if (pkg.dependencies !== void 0 && !isPlainObject(pkg.dependencies)) {
|
|
4773
5059
|
return unwritable("dependencies \uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
4774
5060
|
}
|
|
4775
5061
|
try {
|
|
@@ -4786,7 +5072,7 @@ function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile
|
|
|
4786
5072
|
const w = plan.write;
|
|
4787
5073
|
if (plan.action !== "add" || !w) return false;
|
|
4788
5074
|
const baseDir = path15.resolve(baseDirInput);
|
|
4789
|
-
const current = existsSync6(w.file) ?
|
|
5075
|
+
const current = existsSync6(w.file) ? readFileSync6(w.file, "utf8") : null;
|
|
4790
5076
|
if (current !== w.before) {
|
|
4791
5077
|
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
4792
5078
|
}
|
|
@@ -4802,7 +5088,7 @@ function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile
|
|
|
4802
5088
|
let restored;
|
|
4803
5089
|
try {
|
|
4804
5090
|
writeFile(w.file, w.before);
|
|
4805
|
-
if (
|
|
5091
|
+
if (readFileSync6(w.file, "utf8") !== w.before) throw new Error("\uB418\uB3CC\uB9B0 \uB0B4\uC6A9\uC774 \uC6D0\uB798 \uB0B4\uC6A9\uACFC \uB2E4\uB985\uB2C8\uB2E4");
|
|
4806
5092
|
restored = "\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4";
|
|
4807
5093
|
} catch (restoreErr) {
|
|
4808
5094
|
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`;
|
|
@@ -4840,7 +5126,7 @@ function reportDependencies(plan, log) {
|
|
|
4840
5126
|
async function existingConfig(baseDir) {
|
|
4841
5127
|
try {
|
|
4842
5128
|
const parsed = await readAxisConfig(baseDir);
|
|
4843
|
-
return
|
|
5129
|
+
return isPlainObject(parsed) ? parsed : null;
|
|
4844
5130
|
} catch {
|
|
4845
5131
|
return null;
|
|
4846
5132
|
}
|
|
@@ -4913,7 +5199,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
4913
5199
|
if (!target.isFile()) return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4` };
|
|
4914
5200
|
let content2;
|
|
4915
5201
|
try {
|
|
4916
|
-
content2 =
|
|
5202
|
+
content2 = readFileSync6(utilsPath, "utf8");
|
|
4917
5203
|
} catch (e) {
|
|
4918
5204
|
return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4919
5205
|
}
|
|
@@ -4928,7 +5214,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
4928
5214
|
if (!st.isFile()) return { action: "reject", reason: `${shown} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` };
|
|
4929
5215
|
let content;
|
|
4930
5216
|
try {
|
|
4931
|
-
content =
|
|
5217
|
+
content = readFileSync6(utilsPath, "utf8");
|
|
4932
5218
|
} catch (e) {
|
|
4933
5219
|
return { action: "reject", reason: `\uAE30\uC874 ${shown} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4934
5220
|
}
|
|
@@ -5129,12 +5415,12 @@ import chalk12 from "chalk";
|
|
|
5129
5415
|
import prompts3 from "prompts";
|
|
5130
5416
|
|
|
5131
5417
|
// ../axis-registry-core/src/add/add.ts
|
|
5132
|
-
import { existsSync as existsSync8, readFileSync as
|
|
5418
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
|
|
5133
5419
|
import path17 from "path";
|
|
5134
5420
|
import fs13 from "fs-extra";
|
|
5135
5421
|
|
|
5136
5422
|
// ../axis-registry-core/src/registry/bundled.ts
|
|
5137
|
-
import { existsSync as existsSync7, readFileSync as
|
|
5423
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
|
|
5138
5424
|
import path16 from "path";
|
|
5139
5425
|
import { fileURLToPath } from "url";
|
|
5140
5426
|
function findBundledRegistryDir(moduleUrl = import.meta.url) {
|
|
@@ -5148,7 +5434,7 @@ function readBundledJson(dir, fileName) {
|
|
|
5148
5434
|
const file = path16.join(dir, fileName);
|
|
5149
5435
|
let text;
|
|
5150
5436
|
try {
|
|
5151
|
-
text =
|
|
5437
|
+
text = readFileSync7(file, "utf8");
|
|
5152
5438
|
} catch {
|
|
5153
5439
|
throw new Error(`\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 ${fileName} \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(${dir})`);
|
|
5154
5440
|
}
|
|
@@ -5336,7 +5622,7 @@ function createPinnedFetch(options = {}) {
|
|
|
5336
5622
|
const judge = options.judge ?? blockedAddressReason;
|
|
5337
5623
|
const send = options.request ?? httpsRequest;
|
|
5338
5624
|
const maxBytes = options.maxBytes ?? PINNED_FETCH_MAX_BYTES;
|
|
5339
|
-
return (input, init) => new Promise((
|
|
5625
|
+
return (input, init) => new Promise((resolve4, reject) => {
|
|
5340
5626
|
let url;
|
|
5341
5627
|
try {
|
|
5342
5628
|
url = new URL(input);
|
|
@@ -5377,7 +5663,7 @@ function createPinnedFetch(options = {}) {
|
|
|
5377
5663
|
if (failed) return;
|
|
5378
5664
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
5379
5665
|
const status = res.statusCode ?? 0;
|
|
5380
|
-
|
|
5666
|
+
resolve4({ ok: status >= 200 && status < 300, status, text: async () => body });
|
|
5381
5667
|
});
|
|
5382
5668
|
}
|
|
5383
5669
|
);
|
|
@@ -5863,9 +6149,9 @@ function missingDependencies(root, items) {
|
|
|
5863
6149
|
const installCommand = detectInstallCommand(root);
|
|
5864
6150
|
let pkg;
|
|
5865
6151
|
try {
|
|
5866
|
-
const text =
|
|
6152
|
+
const text = readFileSync8(path17.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
|
|
5867
6153
|
const parsed = JSON.parse(text);
|
|
5868
|
-
pkg =
|
|
6154
|
+
pkg = isPlainObject(parsed) ? parsed : void 0;
|
|
5869
6155
|
} catch {
|
|
5870
6156
|
pkg = void 0;
|
|
5871
6157
|
}
|
|
@@ -5874,7 +6160,7 @@ function missingDependencies(root, items) {
|
|
|
5874
6160
|
for (const item of items) {
|
|
5875
6161
|
for (const dep of item.dependencies) {
|
|
5876
6162
|
const name = dependencyName(dep);
|
|
5877
|
-
if (pkg !== void 0 &&
|
|
6163
|
+
if (pkg !== void 0 && hasDependency(pkg, name) !== void 0) continue;
|
|
5878
6164
|
if (name in specs) continue;
|
|
5879
6165
|
const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
|
|
5880
6166
|
specs[name] = explicit ?? ranges[name];
|
|
@@ -5984,7 +6270,7 @@ async function runAdd(cwd, requested, options, ctx) {
|
|
|
5984
6270
|
continue;
|
|
5985
6271
|
}
|
|
5986
6272
|
try {
|
|
5987
|
-
existing.set(file,
|
|
6273
|
+
existing.set(file, readFileSync8(file.target, "utf8"));
|
|
5988
6274
|
} catch (e) {
|
|
5989
6275
|
readErrors.push(
|
|
5990
6276
|
`${file.item.name}: \uAE30\uC874 \uD30C\uC77C ${rel2(root, file.target)} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${e.code ?? e.message})`
|