@axis-ds/cli 1.6.0 → 1.6.2
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 +604 -260
- package/dist/registry/agentic-agent-avatar.json +1 -1
- package/dist/registry/agentic-approval-card.json +1 -1
- package/dist/registry/agentic-attachment-card.json +1 -1
- package/dist/registry/agentic-code-block.json +1 -1
- package/dist/registry/agentic-context-panel.json +1 -1
- package/dist/registry/agentic-diff-viewer.json +1 -1
- package/dist/registry/agentic-feedback-buttons.json +1 -1
- package/dist/registry/agentic-message-bubble.json +1 -1
- package/dist/registry/agentic-plan-card.json +1 -1
- package/dist/registry/agentic-recovery-banner.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-token-usage-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 +23 -23
- package/dist/registry/input.json +1 -1
- package/dist/registry/registry.json +23 -23
- package/dist/registry/select.json +1 -1
- package/dist/registry/toast.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1106,17 +1106,59 @@ function toSearchItem(c) {
|
|
|
1106
1106
|
url: `/library/${c.category}/${c.slug}`
|
|
1107
1107
|
};
|
|
1108
1108
|
}
|
|
1109
|
+
var sourceTypeOf = (item) => typeof item.source === "string" ? item.source : item.source.type;
|
|
1110
|
+
function resolveRouteSlugs(items) {
|
|
1111
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1112
|
+
for (const item of items) {
|
|
1113
|
+
const key = `${item.category}/${item.slug}`;
|
|
1114
|
+
if (!groups.has(key)) groups.set(key, []);
|
|
1115
|
+
groups.get(key).push(item);
|
|
1116
|
+
}
|
|
1117
|
+
const result = /* @__PURE__ */ new Map();
|
|
1118
|
+
for (const [key, group] of groups) {
|
|
1119
|
+
if (group.length === 1) {
|
|
1120
|
+
result.set(group[0].id, group[0].slug);
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
const axis = group.filter((i) => sourceTypeOf(i) === "axis");
|
|
1124
|
+
if (axis.length > 1) {
|
|
1125
|
+
throw new Error(`\uC0C1\uC138 \uC8FC\uC18C /library/${key} \uB97C AXIS \uD56D\uBAA9 ${axis.map((i) => i.id).join(", ")} \uAC00 \uD568\uAED8 \uC501\uB2C8\uB2E4`);
|
|
1126
|
+
}
|
|
1127
|
+
const keeper = axis[0] || group[0];
|
|
1128
|
+
for (const item of group) {
|
|
1129
|
+
result.set(item.id, item === keeper ? item.slug : `${sourceTypeOf(item)}-${item.slug}`);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1133
|
+
for (const item of items) {
|
|
1134
|
+
const key = `${item.category}/${result.get(item.id)}`;
|
|
1135
|
+
const other = seen.get(key);
|
|
1136
|
+
if (other !== void 0 && other !== item.id) {
|
|
1137
|
+
throw new Error(`slug \uB97C \uBC14\uAFBC \uB4A4\uC5D0\uB3C4 \uC0C1\uC138 \uC8FC\uC18C /library/${key} \uAC00 ${other}, ${item.id} \uC5D0\uC11C \uACB9\uCE69\uB2C8\uB2E4`);
|
|
1138
|
+
}
|
|
1139
|
+
seen.set(key, item.id);
|
|
1140
|
+
}
|
|
1141
|
+
return result;
|
|
1142
|
+
}
|
|
1143
|
+
function withRouteSlugs(items) {
|
|
1144
|
+
const slugs = resolveRouteSlugs(items);
|
|
1145
|
+
return items.map((item) => slugs.get(item.id) === item.slug ? item : { ...item, slug: slugs.get(item.id) });
|
|
1146
|
+
}
|
|
1147
|
+
function componentFileOf(item) {
|
|
1148
|
+
return `components/${item.id}.json`;
|
|
1149
|
+
}
|
|
1109
1150
|
var Publisher = class {
|
|
1110
1151
|
defaultOutputDir = "apps/web/public/library";
|
|
1111
1152
|
/**
|
|
1112
1153
|
* 라이브러리 인덱스를 사이트에 배치
|
|
1113
1154
|
*/
|
|
1114
|
-
async publish(
|
|
1155
|
+
async publish(input, options = {}) {
|
|
1115
1156
|
const outputDir = options.outputDir || this.defaultOutputDir;
|
|
1116
1157
|
const files = [];
|
|
1117
1158
|
const errors = [];
|
|
1118
1159
|
const spinner = ora("\uB77C\uC774\uBE0C\uB7EC\uB9AC \uBC30\uCE58 \uC911...").start();
|
|
1119
1160
|
try {
|
|
1161
|
+
const index = { ...input, components: withRouteSlugs(input.components) };
|
|
1120
1162
|
await fs3.ensureDir(outputDir);
|
|
1121
1163
|
const indexPath = path3.join(outputDir, "index.json");
|
|
1122
1164
|
await this.writeJson(indexPath, this.createPublicIndex(index), options.minify);
|
|
@@ -1143,7 +1185,7 @@ var Publisher = class {
|
|
|
1143
1185
|
const componentsDir = path3.join(outputDir, "components");
|
|
1144
1186
|
await fs3.ensureDir(componentsDir);
|
|
1145
1187
|
for (const component of index.components) {
|
|
1146
|
-
const componentPath = path3.join(
|
|
1188
|
+
const componentPath = path3.join(outputDir, componentFileOf(component));
|
|
1147
1189
|
await this.writeJson(componentPath, this.createPublicComponent(component), options.minify);
|
|
1148
1190
|
files.push(componentPath);
|
|
1149
1191
|
}
|
|
@@ -1400,6 +1442,25 @@ async function refreshAxisLibrary(options) {
|
|
|
1400
1442
|
}
|
|
1401
1443
|
for (const f of existingFiles.values()) if (f.data.source?.type === AXIS) oldAxisIds.add(f.data.id);
|
|
1402
1444
|
const removed = [...oldAxisIds].filter((id) => !axisIds.has(id)).sort();
|
|
1445
|
+
const routeSlugs = resolveRouteSlugs([...extOrder.map((id) => extCategory.get(id)), ...axisComponents]);
|
|
1446
|
+
const renamedSlugs = {};
|
|
1447
|
+
const renamedFrom = {};
|
|
1448
|
+
for (const id of extOrder) {
|
|
1449
|
+
const slug = routeSlugs.get(id);
|
|
1450
|
+
const full = extCategory.get(id);
|
|
1451
|
+
if (slug === full.slug) continue;
|
|
1452
|
+
renamedSlugs[id] = slug;
|
|
1453
|
+
renamedFrom[id] = full.slug;
|
|
1454
|
+
extCategory.set(id, { ...full, slug });
|
|
1455
|
+
extIndex.set(id, { ...extIndex.get(id), slug });
|
|
1456
|
+
const s = extSearch.get(id);
|
|
1457
|
+
extSearch.set(id, { ...s, slug, url: `/library/${s.category}/${slug}` });
|
|
1458
|
+
}
|
|
1459
|
+
for (const c of axisComponents) {
|
|
1460
|
+
const slug = routeSlugs.get(c.id);
|
|
1461
|
+
if (slug === c.slug) continue;
|
|
1462
|
+
throw new Error(`AXIS \uD56D\uBAA9 ${c.id} \uC758 slug \uAC00 ${slug} \uB85C \uBC14\uB00C\uC5B4\uC57C \uD569\uB2C8\uB2E4. \uC218\uC9D1 \uACB0\uACFC\uB97C \uD655\uC778\uD558\uC138\uC694`);
|
|
1463
|
+
}
|
|
1403
1464
|
const indexEntries = [
|
|
1404
1465
|
...extOrder.map((id) => extIndex.get(id)),
|
|
1405
1466
|
...axisComponents.map((c) => toIndexEntry(c))
|
|
@@ -1457,24 +1518,18 @@ async function refreshAxisLibrary(options) {
|
|
|
1457
1518
|
})
|
|
1458
1519
|
);
|
|
1459
1520
|
}
|
|
1460
|
-
const
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
const existing = existingFiles.get(slug);
|
|
1467
|
-
const extForSlug = extOrder.map((id) => extCategory.get(id)).filter((c) => c.slug === slug);
|
|
1468
|
-
const existingIsExternal = !!existing && extForSlug.some((c) => c.id === existing.data.id);
|
|
1469
|
-
if (existingIsExternal) {
|
|
1470
|
-
if (axis) shadowedAxis.push(axis.id);
|
|
1471
|
-
continue;
|
|
1472
|
-
}
|
|
1473
|
-
if (axis) {
|
|
1474
|
-
outputs.set(`components/${slug}.json`, serialize(axis));
|
|
1521
|
+
const finalFiles = /* @__PURE__ */ new Set();
|
|
1522
|
+
for (const c of allPublic) {
|
|
1523
|
+
const rel3 = componentFileOf(c);
|
|
1524
|
+
finalFiles.add(rel3);
|
|
1525
|
+
if (c.source.type === AXIS) {
|
|
1526
|
+
outputs.set(rel3, serialize(c));
|
|
1475
1527
|
continue;
|
|
1476
1528
|
}
|
|
1477
|
-
|
|
1529
|
+
const same = (f) => f.data?.id === c.id && isDeepStrictEqual(f.data, c);
|
|
1530
|
+
const atKey = existingFiles.get(c.id);
|
|
1531
|
+
const kept = atKey && same(atKey) ? atKey : [...existingFiles.values()].find(same);
|
|
1532
|
+
outputs.set(rel3, kept ? kept.raw : serialize(c));
|
|
1478
1533
|
}
|
|
1479
1534
|
const writtenFiles = [];
|
|
1480
1535
|
for (const [rel3, content] of outputs) {
|
|
@@ -1485,13 +1540,13 @@ async function refreshAxisLibrary(options) {
|
|
|
1485
1540
|
if (!options.dryRun) await fs4.writeFile(file, content, "utf-8");
|
|
1486
1541
|
}
|
|
1487
1542
|
const removedFiles = [];
|
|
1488
|
-
for (const
|
|
1489
|
-
|
|
1490
|
-
|
|
1543
|
+
for (const key of existingFiles.keys()) {
|
|
1544
|
+
const rel3 = `components/${key}.json`;
|
|
1545
|
+
if (finalFiles.has(rel3)) continue;
|
|
1491
1546
|
removedFiles.push(rel3);
|
|
1492
1547
|
if (!options.dryRun) await fs4.remove(path4.join(libraryDir, rel3));
|
|
1493
1548
|
}
|
|
1494
|
-
return { added, changed, unchanged, removed,
|
|
1549
|
+
return { added, changed, unchanged, removed, renamedSlugs, renamedFrom, writtenFiles, removedFiles, stats };
|
|
1495
1550
|
}
|
|
1496
1551
|
function registerRefreshAxisCommand(libraryCmd2) {
|
|
1497
1552
|
libraryCmd2.command("refresh-axis").description("AXIS \uD56D\uBAA9\uB9CC \uC800\uC7A5\uC18C \uC18C\uC2A4\uC5D0\uC11C \uB2E4\uC2DC \uB9CC\uB4E6 (\uC678\uBD80 \uC18C\uC2A4 \uD56D\uBAA9\uC740 \uADF8\uB300\uB85C, \uB124\uD2B8\uC6CC\uD06C \uC5C6\uC74C)").option("--root <dir>", "\uC800\uC7A5\uC18C \uB8E8\uD2B8", process.cwd()).option("-o, --output <dir>", "library \uB514\uB809\uD130\uB9AC (\uB8E8\uD2B8 \uAE30\uC900)", "apps/web/public/library").option("--updated-at <iso>", "\uBC14\uB010 \uD56D\uBAA9\uC5D0 \uAE30\uB85D\uD560 \uC2DC\uAC01 (\uAE30\uBCF8: \uC624\uB298 KST \uB0A0\uC9DC\uC758 00:00:00.000Z)").option("--dry-run", "\uD30C\uC77C\uC744 \uC4F0\uC9C0 \uC54A\uACE0 \uBC14\uB014 \uB0B4\uC6A9\uB9CC \uCD9C\uB825").action(async (opts) => {
|
|
@@ -1511,9 +1566,12 @@ ${head}AXIS library \uC7AC\uC0DD\uC131`));
|
|
|
1511
1566
|
for (const id of result.added) console.log(chalk2.green(` + ${id}`));
|
|
1512
1567
|
for (const id of result.changed) console.log(chalk2.yellow(` ~ ${id}`));
|
|
1513
1568
|
for (const id of result.removed) console.log(chalk2.red(` - ${id}`));
|
|
1514
|
-
|
|
1569
|
+
const renamed = Object.entries(result.renamedSlugs);
|
|
1570
|
+
if (renamed.length > 0) {
|
|
1515
1571
|
console.log(
|
|
1516
|
-
chalk2.yellow(
|
|
1572
|
+
chalk2.yellow(
|
|
1573
|
+
` \uC0C1\uC138 \uC8FC\uC18C\uAC00 \uACB9\uCCD0 slug \uB97C \uBC14\uAFC8(WI-0060): ${renamed.map(([id, slug]) => `${id}: ${result.renamedFrom[id] ?? id} \u2192 ${slug}`).join(", ")}`
|
|
1574
|
+
)
|
|
1517
1575
|
);
|
|
1518
1576
|
}
|
|
1519
1577
|
console.log(` \uD30C\uC77C \uC4F0\uAE30 ${result.writtenFiles.length}\uAC1C \xB7 \uC0AD\uC81C ${result.removedFiles.length}\uAC1C`);
|
|
@@ -1745,7 +1803,7 @@ import ora5 from "ora";
|
|
|
1745
1803
|
|
|
1746
1804
|
// src/template/template-apply.ts
|
|
1747
1805
|
import fs8 from "fs-extra";
|
|
1748
|
-
import
|
|
1806
|
+
import path9 from "path";
|
|
1749
1807
|
import chalk5 from "chalk";
|
|
1750
1808
|
import ora3 from "ora";
|
|
1751
1809
|
import prompts from "prompts";
|
|
@@ -1843,8 +1901,18 @@ async function readAxisConfig(baseDir) {
|
|
|
1843
1901
|
}
|
|
1844
1902
|
|
|
1845
1903
|
// ../axis-registry-core/src/template/tailwind-core.ts
|
|
1846
|
-
import { existsSync, lstatSync, readdirSync, readFileSync } from "fs";
|
|
1847
|
-
import { join, resolve } from "path";
|
|
1904
|
+
import { existsSync as existsSync2, lstatSync, readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
1905
|
+
import { extname, join, resolve } from "path";
|
|
1906
|
+
|
|
1907
|
+
// ../axis-registry-core/src/project.ts
|
|
1908
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
1909
|
+
import path8 from "path";
|
|
1910
|
+
function detectInstallCommand(baseDir) {
|
|
1911
|
+
if (existsSync(path8.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
1912
|
+
if (existsSync(path8.join(baseDir, "yarn.lock"))) return "yarn install";
|
|
1913
|
+
if (existsSync(path8.join(baseDir, "package-lock.json"))) return "npm install";
|
|
1914
|
+
return "pnpm install";
|
|
1915
|
+
}
|
|
1848
1916
|
function hasDependency(pkg, name) {
|
|
1849
1917
|
for (const field of ["dependencies", "devDependencies"]) {
|
|
1850
1918
|
const deps = pkg[field];
|
|
@@ -1857,6 +1925,134 @@ function hasDependency(pkg, name) {
|
|
|
1857
1925
|
function isPlainObject(value) {
|
|
1858
1926
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1859
1927
|
}
|
|
1928
|
+
function addCommandFor(installCommand, deps) {
|
|
1929
|
+
const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
|
|
1930
|
+
if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
|
|
1931
|
+
if (installCommand.startsWith("npm")) return `npm install ${specs}`;
|
|
1932
|
+
return `pnpm add ${specs}`;
|
|
1933
|
+
}
|
|
1934
|
+
var GLOBAL_CSS_CANDIDATES = [
|
|
1935
|
+
"app/globals.css",
|
|
1936
|
+
"src/app/globals.css",
|
|
1937
|
+
"styles/globals.css",
|
|
1938
|
+
"src/styles/globals.css",
|
|
1939
|
+
"globals.css"
|
|
1940
|
+
];
|
|
1941
|
+
var TAILWIND_CONFIG_CANDIDATES = [
|
|
1942
|
+
"tailwind.config.ts",
|
|
1943
|
+
"tailwind.config.js",
|
|
1944
|
+
"tailwind.config.mjs",
|
|
1945
|
+
"tailwind.config.cjs"
|
|
1946
|
+
];
|
|
1947
|
+
function isFile(file) {
|
|
1948
|
+
try {
|
|
1949
|
+
return statSync(file).isFile();
|
|
1950
|
+
} catch {
|
|
1951
|
+
return false;
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
function isDirectory(dir) {
|
|
1955
|
+
try {
|
|
1956
|
+
return statSync(dir).isDirectory();
|
|
1957
|
+
} catch {
|
|
1958
|
+
return false;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
function findFirstFile(baseDir, candidates) {
|
|
1962
|
+
return candidates.find((c) => isFile(path8.join(baseDir, c)));
|
|
1963
|
+
}
|
|
1964
|
+
function detectProjectPaths(baseDirInput) {
|
|
1965
|
+
const baseDir = path8.resolve(baseDirInput);
|
|
1966
|
+
const hasSrc = isDirectory(path8.join(baseDir, "src"));
|
|
1967
|
+
const css = findFirstFile(baseDir, GLOBAL_CSS_CANDIDATES);
|
|
1968
|
+
const tw = findFirstFile(baseDir, TAILWIND_CONFIG_CANDIDATES);
|
|
1969
|
+
return {
|
|
1970
|
+
componentsDir: hasSrc ? "./src/components/ui" : "./components/ui",
|
|
1971
|
+
globalCss: css !== void 0 ? `./${css}` : hasSrc ? "./src/app/globals.css" : "./app/globals.css",
|
|
1972
|
+
globalCssSource: css !== void 0 ? "found" : "default",
|
|
1973
|
+
tailwindConfig: tw !== void 0 ? `./${tw}` : "./tailwind.config.ts",
|
|
1974
|
+
tailwindConfigSource: tw !== void 0 ? "found" : "default"
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
function projectFileExists(baseDir, relPath) {
|
|
1978
|
+
return isFile(path8.resolve(baseDir, relPath));
|
|
1979
|
+
}
|
|
1980
|
+
var ROOT_LAYOUT_FILES = [
|
|
1981
|
+
"app/layout.tsx",
|
|
1982
|
+
"app/layout.jsx",
|
|
1983
|
+
"app/layout.js",
|
|
1984
|
+
"src/app/layout.tsx",
|
|
1985
|
+
"src/app/layout.jsx",
|
|
1986
|
+
"src/app/layout.js",
|
|
1987
|
+
"pages/_app.tsx",
|
|
1988
|
+
"pages/_app.jsx",
|
|
1989
|
+
"pages/_document.tsx",
|
|
1990
|
+
"pages/_document.jsx",
|
|
1991
|
+
"src/pages/_app.tsx",
|
|
1992
|
+
"src/pages/_app.jsx",
|
|
1993
|
+
"src/pages/_document.tsx",
|
|
1994
|
+
"src/pages/_document.jsx"
|
|
1995
|
+
];
|
|
1996
|
+
function exactVersionOf(version) {
|
|
1997
|
+
if (typeof version !== "string") return void 0;
|
|
1998
|
+
const v = version.trim();
|
|
1999
|
+
if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
|
|
2000
|
+
return v;
|
|
2001
|
+
}
|
|
2002
|
+
function findInstalledPackage(baseDirInput, name) {
|
|
2003
|
+
let dir = path8.resolve(baseDirInput);
|
|
2004
|
+
for (; ; ) {
|
|
2005
|
+
const pkgDir = path8.join(dir, "node_modules", ...name.split("/"));
|
|
2006
|
+
const file = path8.join(pkgDir, "package.json");
|
|
2007
|
+
if (isFile(file)) {
|
|
2008
|
+
let version;
|
|
2009
|
+
try {
|
|
2010
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
2011
|
+
version = isPlainObject(parsed) ? exactVersionOf(parsed.version) : void 0;
|
|
2012
|
+
} catch {
|
|
2013
|
+
version = void 0;
|
|
2014
|
+
}
|
|
2015
|
+
return { dir: pkgDir, version };
|
|
2016
|
+
}
|
|
2017
|
+
const parent = path8.dirname(dir);
|
|
2018
|
+
if (parent === dir) return void 0;
|
|
2019
|
+
dir = parent;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function isPnpProject(baseDirInput) {
|
|
2023
|
+
let dir = path8.resolve(baseDirInput);
|
|
2024
|
+
for (; ; ) {
|
|
2025
|
+
if (isFile(path8.join(dir, ".pnp.cjs")) || isFile(path8.join(dir, ".pnp.js"))) return true;
|
|
2026
|
+
const parent = path8.dirname(dir);
|
|
2027
|
+
if (parent === dir) return false;
|
|
2028
|
+
dir = parent;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
function compareExactVersions(a, b) {
|
|
2032
|
+
const parse = (v) => {
|
|
2033
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?/.exec(v.trim());
|
|
2034
|
+
return m ? { core: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] !== void 0 } : void 0;
|
|
2035
|
+
};
|
|
2036
|
+
const x = parse(a);
|
|
2037
|
+
const y = parse(b);
|
|
2038
|
+
if (!x || !y) return void 0;
|
|
2039
|
+
for (let i = 0; i < 3; i++) if (x.core[i] !== y.core[i]) return x.core[i] - y.core[i];
|
|
2040
|
+
return Number(y.pre) - Number(x.pre);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
// ../axis-registry-core/src/template/tailwind-core.ts
|
|
2044
|
+
function hasDependency2(pkg, name) {
|
|
2045
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
2046
|
+
const deps = pkg[field];
|
|
2047
|
+
if (typeof deps === "object" && deps !== null && name in deps) {
|
|
2048
|
+
return String(deps[name]);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
return void 0;
|
|
2052
|
+
}
|
|
2053
|
+
function isPlainObject2(value) {
|
|
2054
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2055
|
+
}
|
|
1860
2056
|
var VERSION = String.raw`v?(\d+)(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
|
|
1861
2057
|
function versionParts(token) {
|
|
1862
2058
|
const m = new RegExp(`^${VERSION}$`).exec(token);
|
|
@@ -1930,12 +2126,12 @@ function majorFromVersion(version) {
|
|
|
1930
2126
|
function detectTailwind(baseDirInput, pkg) {
|
|
1931
2127
|
const baseDir = resolve(baseDirInput);
|
|
1932
2128
|
const installedFile = join(baseDir, "node_modules", "tailwindcss", "package.json");
|
|
1933
|
-
const declared = pkg ?
|
|
2129
|
+
const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
|
|
1934
2130
|
const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
|
|
1935
2131
|
const declaredMajor = bounds?.lower;
|
|
1936
2132
|
try {
|
|
1937
|
-
const installed = JSON.parse(
|
|
1938
|
-
const version =
|
|
2133
|
+
const installed = JSON.parse(readFileSync2(installedFile, "utf8"));
|
|
2134
|
+
const version = isPlainObject2(installed) ? installed.version : void 0;
|
|
1939
2135
|
const major = majorFromVersion(version);
|
|
1940
2136
|
if (major !== void 0) {
|
|
1941
2137
|
const found = { major, source: "installed", value: String(version) };
|
|
@@ -1982,18 +2178,57 @@ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/s
|
|
|
1982
2178
|
function findTokensCssImport(css) {
|
|
1983
2179
|
return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
|
|
1984
2180
|
}
|
|
2181
|
+
var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
|
|
2182
|
+
var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
|
|
2183
|
+
function findLayoutTokensCssImport(baseDirInput) {
|
|
2184
|
+
const baseDir = resolve(baseDirInput);
|
|
2185
|
+
for (const candidate of ROOT_LAYOUT_FILES) {
|
|
2186
|
+
const file = join(baseDir, candidate);
|
|
2187
|
+
if (!existsSync2(file)) continue;
|
|
2188
|
+
let text;
|
|
2189
|
+
try {
|
|
2190
|
+
text = readFileSync2(file, "utf8");
|
|
2191
|
+
} catch {
|
|
2192
|
+
continue;
|
|
2193
|
+
}
|
|
2194
|
+
const m = TOKENS_CSS_JS_IMPORT.exec(stripJsComments(text));
|
|
2195
|
+
if (m) return { file: candidate, spec: m[2] };
|
|
2196
|
+
}
|
|
2197
|
+
return void 0;
|
|
2198
|
+
}
|
|
1985
2199
|
function checkGlobalsCss(baseDirInput) {
|
|
1986
2200
|
const baseDir = resolve(baseDirInput);
|
|
1987
2201
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
1988
2202
|
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
|
-
}
|
|
2203
|
+
if (!existsSync2(file)) continue;
|
|
2204
|
+
const content = readFileSync2(file, "utf8");
|
|
2205
|
+
const css = stripCssComments(content);
|
|
1994
2206
|
const imported = findTokensCssImport(content);
|
|
1995
|
-
|
|
1996
|
-
|
|
2207
|
+
let pass;
|
|
2208
|
+
if (imported !== void 0) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
|
|
2209
|
+
else if (AXIS_VARIABLE_DEFINITION.test(css)) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218(--axis-*)\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`;
|
|
2210
|
+
else {
|
|
2211
|
+
const layout = findLayoutTokensCssImport(baseDir);
|
|
2212
|
+
if (layout) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${layout.file}\uC758 ${layout.spec} import)`;
|
|
2213
|
+
}
|
|
2214
|
+
if (pass !== void 0) {
|
|
2215
|
+
const tailwind = detectTailwind(baseDir, readPackageJson(baseDir));
|
|
2216
|
+
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
2217
|
+
if (!tailwind4 && findCreateNextAppDefaults(content).some((d) => d.includes("font-family: Arial"))) {
|
|
2218
|
+
return {
|
|
2219
|
+
name: "globals.css",
|
|
2220
|
+
severity: "warn",
|
|
2221
|
+
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)`
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
return { name: "globals.css", severity: "pass", message: pass };
|
|
2225
|
+
}
|
|
2226
|
+
if (css.includes("--background") && css.includes("--primary")) {
|
|
2227
|
+
return {
|
|
2228
|
+
name: "globals.css",
|
|
2229
|
+
severity: "warn",
|
|
2230
|
+
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`
|
|
2231
|
+
};
|
|
1997
2232
|
}
|
|
1998
2233
|
return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
|
|
1999
2234
|
}
|
|
@@ -2056,8 +2291,8 @@ function exactVersion(version) {
|
|
|
2056
2291
|
}
|
|
2057
2292
|
function installedVersion(baseDir, name) {
|
|
2058
2293
|
try {
|
|
2059
|
-
const parsed = JSON.parse(
|
|
2060
|
-
return
|
|
2294
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
|
|
2295
|
+
return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
|
|
2061
2296
|
} catch {
|
|
2062
2297
|
return void 0;
|
|
2063
2298
|
}
|
|
@@ -2068,7 +2303,7 @@ function axisPackagesBelowTailwind4(pkg, baseDirInput) {
|
|
|
2068
2303
|
const out = [];
|
|
2069
2304
|
const min = lowerOf(TAILWIND4_MIN_AXIS_VERSION);
|
|
2070
2305
|
for (const name of TAILWIND4_AXIS_PACKAGES) {
|
|
2071
|
-
const range =
|
|
2306
|
+
const range = hasDependency2(pkg, name);
|
|
2072
2307
|
if (range === void 0 || range.trim().startsWith("workspace:")) continue;
|
|
2073
2308
|
const installed = baseDir !== void 0 ? installedVersion(baseDir, name) : void 0;
|
|
2074
2309
|
const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
|
|
@@ -2125,8 +2360,10 @@ var CREATE_NEXT_APP_DEFAULTS = [
|
|
|
2125
2360
|
},
|
|
2126
2361
|
{
|
|
2127
2362
|
prefix: "body",
|
|
2128
|
-
|
|
2129
|
-
|
|
2363
|
+
// WI-0070: create-next-app 의 body `font-family: Arial, Helvetica, sans-serif` 도 같은 특징으로 봅니다. 레이어 밖 규칙이라
|
|
2364
|
+
// AXIS 글꼴(Pretendard, html 에 적용)을 이기고 Button 등이 `font-family: inherit` 로 Arial 을 물려받습니다.
|
|
2365
|
+
pattern: /(?<![\w-])(?:(background|background-color|color)\s*:\s*var\(\s*(--(?:background|foreground))\s*\)|font-family\s*:\s*Arial\b)/g,
|
|
2366
|
+
item: (m) => m[1] !== void 0 ? `${m[1]}: var(${m[2]})` : "font-family: Arial"
|
|
2130
2367
|
}
|
|
2131
2368
|
];
|
|
2132
2369
|
function findCreateNextAppDefaults(css) {
|
|
@@ -2182,10 +2419,55 @@ function hasTokensPresetReference(source) {
|
|
|
2182
2419
|
return PRESET_REFERENCE.test(stripJsComments(source));
|
|
2183
2420
|
}
|
|
2184
2421
|
var PRESET_PASS_SUFFIX = `\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${TOKENS_TAILWIND3_PRESET} preset)`;
|
|
2422
|
+
var TOKENS_CJS_PRESET_FIXED_VERSION = "1.7.0";
|
|
2423
|
+
var TOKENS_TAILWIND3_CJS_REQUIRE = `require("${TOKENS_TAILWIND3_PRESET}").default`;
|
|
2424
|
+
var PRESET_REQUIRE_CALL = /\brequire\s*\(\s*(["'])@axis-ds\/tokens\/tailwind\1\s*\)/g;
|
|
2425
|
+
var DEFAULT_ACCESS_AHEAD = /^\s*(?:\.\s*default\b|\[\s*["']default["']\s*\])/;
|
|
2426
|
+
function hasBareCjsPresetRequire(code) {
|
|
2427
|
+
for (const m of code.matchAll(PRESET_REQUIRE_CALL)) {
|
|
2428
|
+
const start = m.index ?? 0;
|
|
2429
|
+
const end = start + m[0].length;
|
|
2430
|
+
if (DEFAULT_ACCESS_AHEAD.test(code.slice(end))) continue;
|
|
2431
|
+
const before = code.slice(0, start);
|
|
2432
|
+
if (/\b(?:const|let|var)\s*\{[^{}]*\}\s*=\s*$/.test(before)) continue;
|
|
2433
|
+
const bound = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*$/.exec(before);
|
|
2434
|
+
if (!bound) return true;
|
|
2435
|
+
const ident = escapeRegExp(bound[1]);
|
|
2436
|
+
const rest = code.slice(0, bound.index) + code.slice(end);
|
|
2437
|
+
const bareUse = new RegExp(`(?<![\\w$.])${ident}(?![\\w$])(?!\\s*(?:\\.\\s*default\\b|\\[\\s*["']default["']\\s*\\]))`);
|
|
2438
|
+
if (bareUse.test(rest)) return true;
|
|
2439
|
+
}
|
|
2440
|
+
return false;
|
|
2441
|
+
}
|
|
2442
|
+
function isCommonJsConfig(file, source) {
|
|
2443
|
+
return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
|
|
2444
|
+
}
|
|
2445
|
+
function packageVersionGate(baseDirInput, pkg, name, min) {
|
|
2446
|
+
const baseDir = resolve(baseDirInput);
|
|
2447
|
+
if (!isPnpProject(baseDir)) {
|
|
2448
|
+
const installed = findInstalledPackage(baseDir, name)?.version;
|
|
2449
|
+
if (installed !== void 0) {
|
|
2450
|
+
const cmp = compareExactVersions(installed, min);
|
|
2451
|
+
if (cmp !== void 0) return { status: cmp >= 0 ? "ok" : "below", source: "installed", value: installed };
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
const declared = pkg ? hasDependency2(pkg, name) : void 0;
|
|
2455
|
+
if (declared !== void 0) {
|
|
2456
|
+
const atLeast = rangeLowerAtLeast(declared, min);
|
|
2457
|
+
if (atLeast !== void 0) return { status: atLeast ? "ok" : "below", source: "declared", value: declared };
|
|
2458
|
+
return { status: "unknown", source: "declared", value: declared };
|
|
2459
|
+
}
|
|
2460
|
+
return { status: "unknown", source: "none" };
|
|
2461
|
+
}
|
|
2462
|
+
function versionGateLabel(gate) {
|
|
2463
|
+
if (gate.source === "installed") return `\uC124\uCE58\uBCF8 ${gate.value}`;
|
|
2464
|
+
if (gate.source === "declared") return `\uC120\uC5B8 ${gate.value}`;
|
|
2465
|
+
return "\uC124\uCE58\uBCF8 \xB7 \uC120\uC5B8 \uC5C6\uC74C";
|
|
2466
|
+
}
|
|
2185
2467
|
function readPackageJson(baseDir) {
|
|
2186
2468
|
try {
|
|
2187
|
-
const parsed = JSON.parse(
|
|
2188
|
-
return
|
|
2469
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "package.json"), "utf8"));
|
|
2470
|
+
return isPlainObject2(parsed) ? parsed : void 0;
|
|
2189
2471
|
} catch {
|
|
2190
2472
|
return void 0;
|
|
2191
2473
|
}
|
|
@@ -2195,7 +2477,7 @@ function tailwind4Issues(css, pkg, versions) {
|
|
|
2195
2477
|
const hasEntry = hasTokensTailwind4Import(css);
|
|
2196
2478
|
if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
|
|
2197
2479
|
const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
|
|
2198
|
-
(name) => pkg !== void 0 &&
|
|
2480
|
+
(name) => pkg !== void 0 && hasDependency2(pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
|
|
2199
2481
|
);
|
|
2200
2482
|
if (missing.length > 0) {
|
|
2201
2483
|
issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
|
|
@@ -2222,8 +2504,8 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2222
2504
|
const label = `Tailwind ${tailwind.major}`;
|
|
2223
2505
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
2224
2506
|
const file = join(baseDir, candidate);
|
|
2225
|
-
if (!
|
|
2226
|
-
const css =
|
|
2507
|
+
if (!existsSync2(file)) continue;
|
|
2508
|
+
const css = readFileSync2(file, "utf8");
|
|
2227
2509
|
if (!hasTailwindImport(css)) {
|
|
2228
2510
|
return {
|
|
2229
2511
|
name: "tailwind.config",
|
|
@@ -2254,9 +2536,21 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2254
2536
|
}
|
|
2255
2537
|
for (const file of TAILWIND_CONFIG_FILES) {
|
|
2256
2538
|
const path18 = join(baseDir, file);
|
|
2257
|
-
if (!
|
|
2258
|
-
const content =
|
|
2539
|
+
if (!existsSync2(path18)) continue;
|
|
2540
|
+
const content = readFileSync2(path18, "utf8");
|
|
2259
2541
|
if (hasTokensPresetReference(content)) {
|
|
2542
|
+
const code = stripJsComments(content);
|
|
2543
|
+
if (isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code)) {
|
|
2544
|
+
const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION);
|
|
2545
|
+
if (gate.status !== "ok") {
|
|
2546
|
+
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`;
|
|
2547
|
+
return {
|
|
2548
|
+
name: "tailwind.config",
|
|
2549
|
+
severity: "warn",
|
|
2550
|
+
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`
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2260
2554
|
return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
|
|
2261
2555
|
}
|
|
2262
2556
|
const ownMapping = content.includes("--background") || content.includes("hsl(var(");
|
|
@@ -2270,8 +2564,8 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2270
2564
|
}
|
|
2271
2565
|
function readAxisConfigLike(baseDir) {
|
|
2272
2566
|
try {
|
|
2273
|
-
const parsed = JSON.parse(
|
|
2274
|
-
return
|
|
2567
|
+
const parsed = JSON.parse(readFileSync2(join(baseDir, "axis.config.json"), "utf8"));
|
|
2568
|
+
return isPlainObject2(parsed) ? parsed : void 0;
|
|
2275
2569
|
} catch {
|
|
2276
2570
|
return void 0;
|
|
2277
2571
|
}
|
|
@@ -2358,7 +2652,7 @@ function inspectTailwindContent(baseDirInput) {
|
|
|
2358
2652
|
const pkg = readPackageJson(baseDir);
|
|
2359
2653
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
2360
2654
|
if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
|
|
2361
|
-
const configFile = TAILWIND_CONFIG_FILES.find((f) =>
|
|
2655
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
|
|
2362
2656
|
if (configFile === void 0) return null;
|
|
2363
2657
|
const targets = [];
|
|
2364
2658
|
const componentsDir = readAxisConfigLike(baseDir)?.componentsDir;
|
|
@@ -2367,12 +2661,12 @@ function inspectTailwindContent(baseDirInput) {
|
|
|
2367
2661
|
targets.push({ label: `componentsDir(${componentsDir})`, sample: `${rel3}/button.tsx`, suggest: `./${rel3}/**/*.{ts,tsx}` });
|
|
2368
2662
|
}
|
|
2369
2663
|
for (const name of TAILWIND4_COMPONENT_PACKAGES) {
|
|
2370
|
-
if (pkg !== void 0 &&
|
|
2664
|
+
if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
|
|
2371
2665
|
targets.push({ label: name, sample: `node_modules/${name}/dist/index.js`, suggest: `./node_modules/${name}/dist/**/*.{js,mjs}` });
|
|
2372
2666
|
}
|
|
2373
2667
|
}
|
|
2374
2668
|
if (targets.length === 0) return null;
|
|
2375
|
-
const read = readTailwindContent(
|
|
2669
|
+
const read = readTailwindContent(readFileSync2(join(baseDir, configFile), "utf8"));
|
|
2376
2670
|
const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
|
|
2377
2671
|
return {
|
|
2378
2672
|
configFile,
|
|
@@ -2437,7 +2731,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
|
|
|
2437
2731
|
if (st.isDirectory()) {
|
|
2438
2732
|
if (name !== "node_modules" && depth < ANIMATION_SCAN_DEPTH_LIMIT) stack.push([p, depth + 1]);
|
|
2439
2733
|
} else if (st.isFile() && st.size <= ANIMATION_SCAN_FILE_BYTES && /\.(tsx|ts|jsx|js)$/.test(name)) {
|
|
2440
|
-
if (/\banimate-(?:in|out)\b/.test(
|
|
2734
|
+
if (/\banimate-(?:in|out)\b/.test(readFileSync2(p, "utf8"))) return true;
|
|
2441
2735
|
}
|
|
2442
2736
|
}
|
|
2443
2737
|
}
|
|
@@ -2447,14 +2741,14 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2447
2741
|
const baseDir = resolve(baseDirInput);
|
|
2448
2742
|
const pkg = readPackageJson(baseDir);
|
|
2449
2743
|
const config = readAxisConfigLike(baseDir);
|
|
2450
|
-
const declared = pkg !== void 0 &&
|
|
2744
|
+
const declared = pkg !== void 0 && hasDependency2(pkg, "@axis-ds/ui-react") !== void 0;
|
|
2451
2745
|
const copied = typeof config?.componentsDir === "string" && componentsUseAnimation(baseDir, config.componentsDir);
|
|
2452
2746
|
if (!declared && !copied) return null;
|
|
2453
2747
|
const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
|
|
2454
2748
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
2455
2749
|
if (tailwind.major !== void 0 && tailwind.major >= 4) {
|
|
2456
|
-
const file = TAILWIND_CSS_CANDIDATES.find((c) =>
|
|
2457
|
-
const css = file !== void 0 ? stripCssComments(
|
|
2750
|
+
const file = TAILWIND_CSS_CANDIDATES.find((c) => existsSync2(join(baseDir, c)));
|
|
2751
|
+
const css = file !== void 0 ? stripCssComments(readFileSync2(join(baseDir, file), "utf8")) : "";
|
|
2458
2752
|
const ok = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`).test(css) || new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(css);
|
|
2459
2753
|
return ok ? { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` } : {
|
|
2460
2754
|
name: "animation",
|
|
@@ -2462,25 +2756,91 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2462
2756
|
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
2757
|
};
|
|
2464
2758
|
}
|
|
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
|
-
|
|
2759
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
|
|
2760
|
+
const source = configFile !== void 0 ? stripJsComments(readFileSync2(join(baseDir, configFile), "utf8")) : "";
|
|
2761
|
+
const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
|
|
2762
|
+
const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
|
|
2763
|
+
const pluginInstalled = pluginDeclared && (isPnpProject(baseDir) || findInstalledPackage(baseDir, ANIMATION_PLUGIN_TAILWIND3) !== void 0);
|
|
2764
|
+
if (plugins === "found" && pluginDeclared && pluginInstalled) {
|
|
2765
|
+
return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
2766
|
+
}
|
|
2767
|
+
const cfg = configFile ?? "tailwind.config";
|
|
2768
|
+
const reasons = [];
|
|
2769
|
+
if (!pluginDeclared) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uC120\uC5B8 \uC5C6\uC74C`);
|
|
2770
|
+
else if (!pluginInstalled) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`);
|
|
2771
|
+
if (plugins === "dynamic") reasons.push(`${cfg} plugins \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD568`);
|
|
2772
|
+
else if (plugins !== "found") reasons.push(`${cfg} plugins \uC5D0 \uC5C6\uC74C`);
|
|
2473
2773
|
return {
|
|
2474
2774
|
name: "animation",
|
|
2475
2775
|
severity: "warn",
|
|
2476
|
-
message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${
|
|
2776
|
+
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
2777
|
};
|
|
2478
2778
|
}
|
|
2779
|
+
function readAnimationPluginUse(source) {
|
|
2780
|
+
const name = escapeRegExp(ANIMATION_PLUGIN_TAILWIND3);
|
|
2781
|
+
const idents = /* @__PURE__ */ new Set();
|
|
2782
|
+
for (const m of source.matchAll(new RegExp(`\\bimport\\s+([A-Za-z_$][\\w$]*)\\s+from\\s*(["'])${name}\\2`, "g"))) idents.add(m[1]);
|
|
2783
|
+
for (const m of source.matchAll(
|
|
2784
|
+
new RegExp(`\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*require\\s*\\(\\s*(["'])${name}\\2\\s*\\)`, "g")
|
|
2785
|
+
)) {
|
|
2786
|
+
idents.add(m[1]);
|
|
2787
|
+
}
|
|
2788
|
+
const requireCall = new RegExp(`^require\\s*\\(\\s*(["'])${name}\\1\\s*\\)(?:\\s*\\.\\s*default)?$`);
|
|
2789
|
+
let sawDynamic = false;
|
|
2790
|
+
for (const m of source.matchAll(/\bplugins\b\s*(:)?\s*/g)) {
|
|
2791
|
+
if (m[1] === void 0) {
|
|
2792
|
+
const before = source.slice(Math.max(0, (m.index ?? 0) - 1), m.index ?? 0);
|
|
2793
|
+
if (/[{,\s]/.test(before) || before === "") sawDynamic = true;
|
|
2794
|
+
continue;
|
|
2795
|
+
}
|
|
2796
|
+
const at = (m.index ?? 0) + m[0].length;
|
|
2797
|
+
if (source[at] !== "[") {
|
|
2798
|
+
sawDynamic = true;
|
|
2799
|
+
continue;
|
|
2800
|
+
}
|
|
2801
|
+
const block = balancedSlice(source, at);
|
|
2802
|
+
if (block === void 0) {
|
|
2803
|
+
sawDynamic = true;
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
const elements = splitTopLevel(block.slice(1, -1));
|
|
2807
|
+
for (const el of elements) {
|
|
2808
|
+
const e = el.trim();
|
|
2809
|
+
if (e === "") continue;
|
|
2810
|
+
if (requireCall.test(e) || idents.has(e) || idents.has(e.replace(/\(\s*\)$/, ""))) return "found";
|
|
2811
|
+
if (/^require\s*\(\s*(["'])[^"']+\1\s*\)(?:\s*\.\s*default)?$/.test(e)) continue;
|
|
2812
|
+
sawDynamic = true;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
return sawDynamic ? "dynamic" : "absent";
|
|
2816
|
+
}
|
|
2817
|
+
function splitTopLevel(body) {
|
|
2818
|
+
const out = [];
|
|
2819
|
+
let depth = 0;
|
|
2820
|
+
let start = 0;
|
|
2821
|
+
for (let i = 0; i < body.length; i++) {
|
|
2822
|
+
const c = body[i];
|
|
2823
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2824
|
+
let j = i + 1;
|
|
2825
|
+
while (j < body.length && body[j] !== c) j += body[j] === "\\" ? 2 : 1;
|
|
2826
|
+
i = j;
|
|
2827
|
+
continue;
|
|
2828
|
+
}
|
|
2829
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2830
|
+
else if (c === ")" || c === "]" || c === "}") depth--;
|
|
2831
|
+
else if (c === "," && depth === 0) {
|
|
2832
|
+
out.push(body.slice(start, i));
|
|
2833
|
+
start = i + 1;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
out.push(body.slice(start));
|
|
2837
|
+
return out;
|
|
2838
|
+
}
|
|
2479
2839
|
|
|
2480
2840
|
// src/template/template-apply.ts
|
|
2481
2841
|
async function templateApplyWarnings(baseDir, detail) {
|
|
2482
2842
|
const warnings = [];
|
|
2483
|
-
const pkgPath =
|
|
2843
|
+
const pkgPath = path9.join(baseDir, "package.json");
|
|
2484
2844
|
const templateRange = detail.devDependencies?.tailwindcss ?? detail.dependencies?.tailwindcss;
|
|
2485
2845
|
const templateMajor = templateRange !== void 0 ? tailwindMajorFromRange(templateRange) : void 0;
|
|
2486
2846
|
if (templateMajor !== void 0 && await fs8.pathExists(pkgPath)) {
|
|
@@ -2498,7 +2858,7 @@ async function templateApplyWarnings(baseDir, detail) {
|
|
|
2498
2858
|
}
|
|
2499
2859
|
}
|
|
2500
2860
|
const usesRootApp = detail.files.some((f) => f.path.startsWith("app/"));
|
|
2501
|
-
if (usesRootApp && await fs8.pathExists(
|
|
2861
|
+
if (usesRootApp && await fs8.pathExists(path9.join(baseDir, "src", "app"))) {
|
|
2502
2862
|
warnings.push(
|
|
2503
2863
|
"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
2864
|
);
|
|
@@ -2515,13 +2875,13 @@ async function applyTemplate(slug, options) {
|
|
|
2515
2875
|
spinner.fail(err.message);
|
|
2516
2876
|
process.exit(1);
|
|
2517
2877
|
}
|
|
2518
|
-
const baseDir =
|
|
2878
|
+
const baseDir = path9.resolve(options.dir || ".");
|
|
2519
2879
|
for (const w of await templateApplyWarnings(baseDir, detail)) {
|
|
2520
2880
|
console.log(chalk5.yellow(`! ${w}`));
|
|
2521
2881
|
}
|
|
2522
2882
|
const conflicts = [];
|
|
2523
2883
|
for (const file of detail.files) {
|
|
2524
|
-
const dest =
|
|
2884
|
+
const dest = path9.join(baseDir, file.path);
|
|
2525
2885
|
if (await fs8.pathExists(dest)) {
|
|
2526
2886
|
conflicts.push(file.path);
|
|
2527
2887
|
}
|
|
@@ -2546,7 +2906,7 @@ async function applyTemplate(slug, options) {
|
|
|
2546
2906
|
if (options.dryRun) {
|
|
2547
2907
|
console.log(chalk5.blue("\n[\uBBF8\uB9AC\uBCF4\uAE30] \uC0DD\uC131\uB420 \uD30C\uC77C:"));
|
|
2548
2908
|
for (const file of detail.files) {
|
|
2549
|
-
const dest =
|
|
2909
|
+
const dest = path9.join(baseDir, file.path);
|
|
2550
2910
|
const exists = conflicts.includes(file.path);
|
|
2551
2911
|
const label = exists ? chalk5.yellow("\uB36E\uC5B4\uC4F0\uAE30") : chalk5.green("\uC0DD\uC131");
|
|
2552
2912
|
console.log(` ${label} ${dest}`);
|
|
@@ -2561,8 +2921,8 @@ async function applyTemplate(slug, options) {
|
|
|
2561
2921
|
}
|
|
2562
2922
|
const writeSpinner = ora3("\uD30C\uC77C \uC0DD\uC131 \uC911...").start();
|
|
2563
2923
|
for (const file of detail.files) {
|
|
2564
|
-
const dest =
|
|
2565
|
-
await fs8.ensureDir(
|
|
2924
|
+
const dest = path9.join(baseDir, file.path);
|
|
2925
|
+
await fs8.ensureDir(path9.dirname(dest));
|
|
2566
2926
|
await fs8.writeFile(dest, file.content);
|
|
2567
2927
|
}
|
|
2568
2928
|
writeSpinner.succeed(`${detail.files.length}\uAC1C \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC`);
|
|
@@ -2623,7 +2983,7 @@ async function initTemplate(slug, options) {
|
|
|
2623
2983
|
}
|
|
2624
2984
|
targetDir = dir;
|
|
2625
2985
|
}
|
|
2626
|
-
const resolved =
|
|
2986
|
+
const resolved = path9.resolve(targetDir);
|
|
2627
2987
|
if (await fs8.pathExists(resolved)) {
|
|
2628
2988
|
const entries = await fs8.readdir(resolved);
|
|
2629
2989
|
if (entries.length > 0) {
|
|
@@ -2639,7 +2999,7 @@ async function initTemplate(slug, options) {
|
|
|
2639
2999
|
await fs8.ensureDir(resolved);
|
|
2640
3000
|
}
|
|
2641
3001
|
await applyTemplate(selectedSlug, { dir: targetDir, yes: true });
|
|
2642
|
-
const configPath =
|
|
3002
|
+
const configPath = path9.join(resolved, "axis.config.json");
|
|
2643
3003
|
if (!await fs8.pathExists(configPath)) {
|
|
2644
3004
|
const axisConfig = createTemplateConfig(selectedSlug);
|
|
2645
3005
|
await fs8.writeJSON(configPath, axisConfig, { spaces: 2 });
|
|
@@ -2654,7 +3014,7 @@ async function initTemplate(slug, options) {
|
|
|
2654
3014
|
|
|
2655
3015
|
// src/template/template-diff.ts
|
|
2656
3016
|
import fs9 from "fs-extra";
|
|
2657
|
-
import
|
|
3017
|
+
import path10 from "path";
|
|
2658
3018
|
import chalk6 from "chalk";
|
|
2659
3019
|
import ora4 from "ora";
|
|
2660
3020
|
async function diffTemplate(slug, options) {
|
|
@@ -2667,10 +3027,10 @@ async function diffTemplate(slug, options) {
|
|
|
2667
3027
|
spinner.fail(err.message);
|
|
2668
3028
|
process.exit(1);
|
|
2669
3029
|
}
|
|
2670
|
-
const baseDir =
|
|
3030
|
+
const baseDir = path10.resolve(options.dir || ".");
|
|
2671
3031
|
const entries = [];
|
|
2672
3032
|
for (const file of detail.files) {
|
|
2673
|
-
const localPath =
|
|
3033
|
+
const localPath = path10.join(baseDir, file.path);
|
|
2674
3034
|
if (!await fs9.pathExists(localPath)) {
|
|
2675
3035
|
entries.push({ path: file.path, status: "added" });
|
|
2676
3036
|
continue;
|
|
@@ -2751,12 +3111,12 @@ async function collectLocalFiles(dir, base) {
|
|
|
2751
3111
|
}
|
|
2752
3112
|
for (const entry of entries) {
|
|
2753
3113
|
if (ignore.has(entry.name)) continue;
|
|
2754
|
-
const fullPath =
|
|
3114
|
+
const fullPath = path10.join(dir, entry.name);
|
|
2755
3115
|
if (entry.isDirectory()) {
|
|
2756
3116
|
const nested = await collectLocalFiles(fullPath, root);
|
|
2757
3117
|
results.push(...nested);
|
|
2758
3118
|
} else {
|
|
2759
|
-
results.push(
|
|
3119
|
+
results.push(path10.relative(root, fullPath).replace(/\\/g, "/"));
|
|
2760
3120
|
}
|
|
2761
3121
|
}
|
|
2762
3122
|
return results;
|
|
@@ -2768,85 +3128,9 @@ import path11 from "path";
|
|
|
2768
3128
|
import chalk7 from "chalk";
|
|
2769
3129
|
|
|
2770
3130
|
// src/theme/brand-core.ts
|
|
2771
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3131
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
2772
3132
|
import { createRequire } from "module";
|
|
2773
3133
|
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
3134
|
var TOKENS_PACKAGE = "@axis-ds/tokens";
|
|
2851
3135
|
var BRAND_NAME_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
2852
3136
|
var MIN_BRAND_TOKENS_VERSION = "1.3.0";
|
|
@@ -2867,7 +3151,7 @@ var KEY_TOKENS = [
|
|
|
2867
3151
|
];
|
|
2868
3152
|
var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
|
|
2869
3153
|
function readJsonFile(file) {
|
|
2870
|
-
return JSON.parse(
|
|
3154
|
+
return JSON.parse(readFileSync3(file, "utf8"));
|
|
2871
3155
|
}
|
|
2872
3156
|
function errorCode(err) {
|
|
2873
3157
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
@@ -2943,7 +3227,7 @@ var AXIS_CONFIG_FILE_NAME = "axis.config.json";
|
|
|
2943
3227
|
function readBrandConfig(baseDir) {
|
|
2944
3228
|
let parsed;
|
|
2945
3229
|
try {
|
|
2946
|
-
parsed = JSON.parse(
|
|
3230
|
+
parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
|
|
2947
3231
|
} catch {
|
|
2948
3232
|
return null;
|
|
2949
3233
|
}
|
|
@@ -2962,7 +3246,7 @@ function inspectBrandImport(baseDir) {
|
|
|
2962
3246
|
return { ...base, state: "css-missing", imports: [] };
|
|
2963
3247
|
}
|
|
2964
3248
|
const cssFile = relative(root, location.path).split(sep).join("/");
|
|
2965
|
-
const imports = [...new Set(findBrandImports(
|
|
3249
|
+
const imports = [...new Set(findBrandImports(readFileSync3(location.path, "utf8")))];
|
|
2966
3250
|
let state;
|
|
2967
3251
|
if (imports.includes(brand)) state = "match";
|
|
2968
3252
|
else if (imports.length === 0) state = "import-missing";
|
|
@@ -3046,34 +3330,23 @@ function pickKeyTokens(decls) {
|
|
|
3046
3330
|
}
|
|
3047
3331
|
return out;
|
|
3048
3332
|
}
|
|
3333
|
+
var THEME_MARKUP_BRAND_MIN_VERSION = "1.7.0";
|
|
3049
3334
|
function providerExample(name) {
|
|
3050
3335
|
return [
|
|
3051
|
-
"// 1)
|
|
3336
|
+
"// 1) \uB8E8\uD2B8 \uB808\uC774\uC544\uC6C3(app/layout.tsx)\uC758 <html> \uC5D0 \uBD99\uC785\uB2C8\uB2E4(\uCCAB \uD654\uBA74\uBD80\uD130 \uC801\uC6A9)",
|
|
3337
|
+
`// 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
3338
|
`<html lang="ko" data-brand="${name}">`,
|
|
3053
3339
|
"",
|
|
3054
|
-
|
|
3340
|
+
`// 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
3341
|
'import { useTheme } from "@axis-ds/theme";',
|
|
3056
3342
|
"const { setBrand } = useTheme();",
|
|
3057
3343
|
`setBrand("${name}");`
|
|
3058
3344
|
].join("\n");
|
|
3059
3345
|
}
|
|
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
|
-
];
|
|
3346
|
+
var BRAND_ACTIVATION_FILES = ROOT_LAYOUT_FILES;
|
|
3076
3347
|
var BRAND_ACTIVATION_PATTERN = /data-brand|setBrand\s*\(|defaultBrand\s*=/;
|
|
3348
|
+
var PROVIDER_ACTIVATION_PATTERN = /setBrand\s*\(|defaultBrand\s*=/;
|
|
3349
|
+
var THEME_PROVIDER_PATTERN = /<ThemeProvider\b/;
|
|
3077
3350
|
function stripJsLikeComments(src) {
|
|
3078
3351
|
return src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`])\/\/[^\n]*/g, "$1");
|
|
3079
3352
|
}
|
|
@@ -3084,15 +3357,23 @@ function findBrandActivation(baseDir) {
|
|
|
3084
3357
|
const file = join2(root, candidate);
|
|
3085
3358
|
if (!isFile2(file)) continue;
|
|
3086
3359
|
layoutFiles.push(candidate);
|
|
3087
|
-
const text = stripJsLikeComments(
|
|
3088
|
-
|
|
3360
|
+
const text = stripJsLikeComments(readFileSync3(file, "utf8"));
|
|
3361
|
+
const providerTexts = [];
|
|
3089
3362
|
for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
|
|
3090
3363
|
for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
|
|
3091
3364
|
const rel3 = `${dirname(candidate)}/${m[1]}${ext}`;
|
|
3092
3365
|
const p = join2(root, rel3);
|
|
3093
|
-
if (isFile2(p)
|
|
3094
|
-
|
|
3095
|
-
|
|
3366
|
+
if (isFile2(p)) providerTexts.push({ rel: rel3, text: stripJsLikeComments(readFileSync3(p, "utf8")) });
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
const all = [text, ...providerTexts.map((x) => x.text)];
|
|
3370
|
+
const markupWithProvider = !all.some((t) => PROVIDER_ACTIVATION_PATTERN.test(t)) && all.some((t) => THEME_PROVIDER_PATTERN.test(t));
|
|
3371
|
+
if (BRAND_ACTIVATION_PATTERN.test(text)) {
|
|
3372
|
+
return markupWithProvider ? { found: candidate, layoutFiles, markupWithProvider } : { found: candidate, layoutFiles };
|
|
3373
|
+
}
|
|
3374
|
+
for (const x of providerTexts) {
|
|
3375
|
+
if (BRAND_ACTIVATION_PATTERN.test(x.text)) {
|
|
3376
|
+
return markupWithProvider ? { found: x.rel, layoutFiles, markupWithProvider } : { found: x.rel, layoutFiles };
|
|
3096
3377
|
}
|
|
3097
3378
|
}
|
|
3098
3379
|
}
|
|
@@ -3102,7 +3383,18 @@ function inspectBrandActivation(baseDir) {
|
|
|
3102
3383
|
const config = readBrandConfig(baseDir);
|
|
3103
3384
|
const brand = config?.brand;
|
|
3104
3385
|
if (typeof brand !== "string" || brand.trim() === "") return null;
|
|
3105
|
-
|
|
3386
|
+
const location = findBrandActivation(baseDir);
|
|
3387
|
+
if (!location.markupWithProvider) return { brand, ...location };
|
|
3388
|
+
return { brand, ...location, theme: packageVersionGate(baseDir, readProjectPackageJson(baseDir), THEME_PACKAGE, THEME_MARKUP_BRAND_MIN_VERSION) };
|
|
3389
|
+
}
|
|
3390
|
+
var THEME_PACKAGE = "@axis-ds/theme";
|
|
3391
|
+
function readProjectPackageJson(baseDir) {
|
|
3392
|
+
try {
|
|
3393
|
+
const parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), "package.json"), "utf8"));
|
|
3394
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
|
|
3395
|
+
} catch {
|
|
3396
|
+
return void 0;
|
|
3397
|
+
}
|
|
3106
3398
|
}
|
|
3107
3399
|
function getBrand(baseDir, name) {
|
|
3108
3400
|
const tokens = resolveTokens(baseDir);
|
|
@@ -3120,7 +3412,7 @@ function getBrand(baseDir, name) {
|
|
|
3120
3412
|
try {
|
|
3121
3413
|
summary = readSummary(baseDir, entry);
|
|
3122
3414
|
const cssPath = projectRequire(baseDir).resolve(summary.importPath);
|
|
3123
|
-
parsed = parseBrandCss(
|
|
3415
|
+
parsed = parseBrandCss(readFileSync3(cssPath, "utf8"), name);
|
|
3124
3416
|
} catch (err) {
|
|
3125
3417
|
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
|
|
3126
3418
|
throw err;
|
|
@@ -3138,6 +3430,57 @@ function getBrand(baseDir, name) {
|
|
|
3138
3430
|
};
|
|
3139
3431
|
}
|
|
3140
3432
|
|
|
3433
|
+
// ../axis-registry-core/src/template/dependencies-core.ts
|
|
3434
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3435
|
+
import { join as join3, resolve as resolve3 } from "path";
|
|
3436
|
+
var REQUIRED_DEPENDENCIES = ["tailwindcss"];
|
|
3437
|
+
var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
|
|
3438
|
+
function declaredAxisPackages(pkg) {
|
|
3439
|
+
const out = [];
|
|
3440
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
3441
|
+
const deps = pkg[field];
|
|
3442
|
+
if (!isPlainObject(deps)) continue;
|
|
3443
|
+
for (const name of Object.keys(deps)) if (name.startsWith("@axis-ds/") && !out.includes(name)) out.push(name);
|
|
3444
|
+
}
|
|
3445
|
+
return out;
|
|
3446
|
+
}
|
|
3447
|
+
function checkDependencies(baseDirInput) {
|
|
3448
|
+
const baseDir = resolve3(baseDirInput);
|
|
3449
|
+
let pkg;
|
|
3450
|
+
try {
|
|
3451
|
+
const parsed = JSON.parse(readFileSync4(join3(baseDir, "package.json"), "utf8"));
|
|
3452
|
+
if (!isPlainObject(parsed)) throw new Error("not object");
|
|
3453
|
+
pkg = parsed;
|
|
3454
|
+
} catch (err) {
|
|
3455
|
+
if (err?.code === "ENOENT") {
|
|
3456
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
|
|
3457
|
+
}
|
|
3458
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
|
|
3459
|
+
}
|
|
3460
|
+
const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
3461
|
+
if (missingRequired.length > 0) {
|
|
3462
|
+
return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
|
|
3463
|
+
}
|
|
3464
|
+
const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
3465
|
+
const targets = [
|
|
3466
|
+
...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0),
|
|
3467
|
+
...declaredAxisPackages(pkg)
|
|
3468
|
+
];
|
|
3469
|
+
const pnp = isPnpProject(baseDir);
|
|
3470
|
+
const notInstalled = pnp ? [] : targets.filter((d) => findInstalledPackage(baseDir, d) === void 0);
|
|
3471
|
+
const problems = [];
|
|
3472
|
+
if (missingRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`);
|
|
3473
|
+
if (notInstalled.length > 0) {
|
|
3474
|
+
problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalled.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
|
|
3475
|
+
}
|
|
3476
|
+
if (problems.length > 0) return { name: "dependencies", severity: "warn", message: problems.join(" / ") };
|
|
3477
|
+
return {
|
|
3478
|
+
name: "dependencies",
|
|
3479
|
+
severity: "pass",
|
|
3480
|
+
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)`
|
|
3481
|
+
};
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3141
3484
|
// src/template/template-check.ts
|
|
3142
3485
|
var SEVERITY_ICON = {
|
|
3143
3486
|
pass: chalk7.green("PASS"),
|
|
@@ -3151,7 +3494,7 @@ async function collectCheckResults(dir) {
|
|
|
3151
3494
|
results.push(checkTailwindSetup(baseDir));
|
|
3152
3495
|
results.push(checkGlobalsCss(baseDir));
|
|
3153
3496
|
results.push(await checkUtils(baseDir));
|
|
3154
|
-
results.push(
|
|
3497
|
+
results.push(checkDependencies(baseDir));
|
|
3155
3498
|
const brand = checkBrand(baseDir);
|
|
3156
3499
|
if (brand) results.push(brand);
|
|
3157
3500
|
const activation = inspectBrandActivation(baseDir);
|
|
@@ -3229,41 +3572,6 @@ async function checkUtils(baseDir) {
|
|
|
3229
3572
|
message: "utils.ts\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC2DC \uD544\uC694)"
|
|
3230
3573
|
};
|
|
3231
3574
|
}
|
|
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
3575
|
function checkBrand(baseDir) {
|
|
3268
3576
|
const check = inspectBrandImport(baseDir);
|
|
3269
3577
|
return check ? brandCheckResult(check) : null;
|
|
@@ -3299,6 +3607,15 @@ function brandCheckResult(check) {
|
|
|
3299
3607
|
}
|
|
3300
3608
|
}
|
|
3301
3609
|
function brandActivationResult(check) {
|
|
3610
|
+
if (check.found && check.theme && check.theme.status !== "ok") {
|
|
3611
|
+
const label = versionGateLabel(check.theme);
|
|
3612
|
+
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`;
|
|
3613
|
+
return {
|
|
3614
|
+
name: "brand.activation",
|
|
3615
|
+
severity: "warn",
|
|
3616
|
+
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}")`
|
|
3617
|
+
};
|
|
3618
|
+
}
|
|
3302
3619
|
if (check.found) {
|
|
3303
3620
|
return {
|
|
3304
3621
|
name: "brand.activation",
|
|
@@ -3422,14 +3739,13 @@ import chalk9 from "chalk";
|
|
|
3422
3739
|
import path13 from "path";
|
|
3423
3740
|
|
|
3424
3741
|
// src/theme/theme-add.ts
|
|
3425
|
-
import { accessSync, constants, existsSync as existsSync4, readFileSync as
|
|
3742
|
+
import { accessSync, constants, existsSync as existsSync4, readFileSync as readFileSync5, realpathSync, unlinkSync, writeFileSync } from "fs";
|
|
3426
3743
|
import path12 from "path";
|
|
3427
3744
|
var TOKENS_DEPENDENCY_RANGE = `^${TOKENS_DEPENDENCY_MIN_VERSION}`;
|
|
3428
3745
|
var TAILWIND3_BASE_IMPORTS = [`${TOKENS_PACKAGE}/css`, `${TOKENS_PACKAGE}/css/shadcn`];
|
|
3429
|
-
var THEME_PACKAGE = "@axis-ds/theme";
|
|
3430
3746
|
var THEME_MIN_VERSION = "1.3.0";
|
|
3431
3747
|
function readText(file) {
|
|
3432
|
-
return existsSync4(file) ?
|
|
3748
|
+
return existsSync4(file) ? readFileSync5(file, "utf8") : null;
|
|
3433
3749
|
}
|
|
3434
3750
|
function eolOf(text) {
|
|
3435
3751
|
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -3551,7 +3867,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3551
3867
|
let config;
|
|
3552
3868
|
try {
|
|
3553
3869
|
const parsed = JSON.parse(configText);
|
|
3554
|
-
if (!
|
|
3870
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3555
3871
|
config = parsed;
|
|
3556
3872
|
} catch (err) {
|
|
3557
3873
|
plan.errors.push({ kind: "invalid-config", message: err.message });
|
|
@@ -3563,7 +3879,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3563
3879
|
}
|
|
3564
3880
|
plan.tokens = resolveTokens(baseDir);
|
|
3565
3881
|
if (plan.tokens.status === "ok" && plan.tokens.indexPath) {
|
|
3566
|
-
const data = JSON.parse(
|
|
3882
|
+
const data = JSON.parse(readFileSync5(plan.tokens.indexPath, "utf8"));
|
|
3567
3883
|
const entries = Array.isArray(data.brands) ? data.brands : [];
|
|
3568
3884
|
const entry = entries.find((e) => e.name === brand);
|
|
3569
3885
|
if (!entry) {
|
|
@@ -3585,7 +3901,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3585
3901
|
if (pkgText !== null) {
|
|
3586
3902
|
try {
|
|
3587
3903
|
const parsed = JSON.parse(pkgText);
|
|
3588
|
-
if (!
|
|
3904
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
3589
3905
|
pkg = parsed;
|
|
3590
3906
|
} catch (err) {
|
|
3591
3907
|
plan.errors.push({ kind: "invalid-package-json", message: err.message });
|
|
@@ -3597,7 +3913,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3597
3913
|
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
3598
3914
|
const requiredBaseImports = tailwind4 ? [
|
|
3599
3915
|
TOKENS_TAILWIND4_ENTRY,
|
|
3600
|
-
...TAILWIND4_COMPONENT_PACKAGES.filter((n) => pkg !== void 0 &&
|
|
3916
|
+
...TAILWIND4_COMPONENT_PACKAGES.filter((n) => pkg !== void 0 && hasDependency(pkg, n) !== void 0).map(
|
|
3601
3917
|
(n) => `${n}/tailwind.css`
|
|
3602
3918
|
)
|
|
3603
3919
|
] : [...TAILWIND3_BASE_IMPORTS];
|
|
@@ -3614,7 +3930,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3614
3930
|
plan.writes = [];
|
|
3615
3931
|
return plan;
|
|
3616
3932
|
}
|
|
3617
|
-
const before =
|
|
3933
|
+
const before = readFileSync5(location.path, "utf8");
|
|
3618
3934
|
const imported = findBrandImports(before);
|
|
3619
3935
|
const otherBrands = [...new Set(imported.filter((n) => n !== brand))];
|
|
3620
3936
|
const brandAdded = !imported.includes(brand);
|
|
@@ -3651,7 +3967,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3651
3967
|
const content = inspectTailwindContent(baseDir);
|
|
3652
3968
|
plan.tailwindConfig = {
|
|
3653
3969
|
configFile: configFile2,
|
|
3654
|
-
presetMissing: configFile2 === void 0 || !hasTokensPresetReference(
|
|
3970
|
+
presetMissing: configFile2 === void 0 || !hasTokensPresetReference(readFileSync5(path12.join(baseDir, configFile2), "utf8")),
|
|
3655
3971
|
contentMissing: content?.targets.filter((t) => !t.covered) ?? [],
|
|
3656
3972
|
contentUnknown: content !== null && (content.unreadable || content.dynamic)
|
|
3657
3973
|
};
|
|
@@ -3664,12 +3980,12 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3664
3980
|
if (pkgText === null || pkg === void 0) {
|
|
3665
3981
|
plan.dependency = { action: "no-package-json", upgrade, themeMissing: false, tokensAddCommand, themeAddCommand };
|
|
3666
3982
|
} else {
|
|
3667
|
-
const themeMissing =
|
|
3668
|
-
const declared =
|
|
3983
|
+
const themeMissing = hasDependency(pkg, THEME_PACKAGE) === void 0;
|
|
3984
|
+
const declared = hasDependency(pkg, TOKENS_PACKAGE);
|
|
3669
3985
|
if (declared !== void 0) {
|
|
3670
3986
|
plan.dependency = { action: "present", declaredRange: declared, upgrade, themeMissing, tokensAddCommand, themeAddCommand };
|
|
3671
3987
|
} else {
|
|
3672
|
-
const deps =
|
|
3988
|
+
const deps = isPlainObject(pkg.dependencies) ? { ...pkg.dependencies } : {};
|
|
3673
3989
|
deps[TOKENS_PACKAGE] = TOKENS_DEPENDENCY_RANGE;
|
|
3674
3990
|
const next = { ...pkg, dependencies: deps };
|
|
3675
3991
|
plan.dependency = { action: "add", upgrade, themeMissing, tokensAddCommand, themeAddCommand };
|
|
@@ -3754,6 +4070,25 @@ function applyThemeAdd(plan) {
|
|
|
3754
4070
|
}
|
|
3755
4071
|
|
|
3756
4072
|
// src/theme/index.ts
|
|
4073
|
+
function importOffset(css, spec) {
|
|
4074
|
+
const escaped = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4075
|
+
const m = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${escaped}["']`).exec(css);
|
|
4076
|
+
return m ? m.index : -1;
|
|
4077
|
+
}
|
|
4078
|
+
function baseImportLines(after, spec, brandImportPath2, file) {
|
|
4079
|
+
if (spec.endsWith("/tailwind.css")) {
|
|
4080
|
+
return [` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C, \uC704\uCE58 \uBB34\uAD00)`];
|
|
4081
|
+
}
|
|
4082
|
+
const at = importOffset(after, spec);
|
|
4083
|
+
const brandAt = importOffset(after, brandImportPath2);
|
|
4084
|
+
if (brandAt === -1 || at !== -1 && at < brandAt) {
|
|
4085
|
+
return [` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uAE30\uBCF8 \uD1A0\uD070 CSS, \uBE0C\uB79C\uB4DC \uC55E)`];
|
|
4086
|
+
}
|
|
4087
|
+
return [
|
|
4088
|
+
` ${chalk9.green("\u2713")} ${file}: @import "${spec}"; \uCD94\uAC00(\uAE30\uBCF8 \uD1A0\uD070 CSS)`,
|
|
4089
|
+
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`)
|
|
4090
|
+
];
|
|
4091
|
+
}
|
|
3757
4092
|
function tokensInstallCommand(baseDir) {
|
|
3758
4093
|
return addCommandFor(detectInstallCommand(baseDir), { [TOKENS_PACKAGE]: TOKENS_DEPENDENCY_RANGE });
|
|
3759
4094
|
}
|
|
@@ -3941,8 +4276,9 @@ function renderThemeAdd(plan, written) {
|
|
|
3941
4276
|
}
|
|
3942
4277
|
const brandLine = `@import "${plan.importPath}";`;
|
|
3943
4278
|
if (css?.action === "add" && css.file) {
|
|
4279
|
+
const after = plan.writes.find((w) => w.file === css.file)?.after ?? "";
|
|
3944
4280
|
for (const spec of css.baseImports) {
|
|
3945
|
-
lines.push(
|
|
4281
|
+
lines.push(...baseImportLines(after, spec, plan.importPath, rel(plan, css.file)));
|
|
3946
4282
|
}
|
|
3947
4283
|
if (css.brandAdded) lines.push(` ${chalk9.green("\u2713")} ${rel(plan, css.file)}: ${brandLine} \uCD94\uAC00`);
|
|
3948
4284
|
else lines.push(` ${chalk9.gray("-")} ${rel(plan, css.file)}: \uBE0C\uB79C\uB4DC import \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uAC74\uB108\uB700`);
|
|
@@ -4002,7 +4338,8 @@ function renderThemeAdd(plan, written) {
|
|
|
4002
4338
|
lines.push("", chalk9.bold(`Tailwind \uC124\uC815 (${tw.configFile ?? "tailwind.config"}, \uD30C\uC77C\uC740 \uACE0\uCE58\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4)`));
|
|
4003
4339
|
if (tw.presetMissing) {
|
|
4004
4340
|
lines.push(
|
|
4005
|
-
|
|
4341
|
+
// WI-0072: CommonJS 는 모든 tokens 버전에서 동작하는 `.default` 형태로 안내합니다(1.6.2 이하의 bare require 는 preset 이 빠짐)
|
|
4342
|
+
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
4343
|
);
|
|
4007
4344
|
}
|
|
4008
4345
|
for (const t of tw.contentMissing) {
|
|
@@ -4017,6 +4354,13 @@ function renderThemeAdd(plan, written) {
|
|
|
4017
4354
|
lines.push("", chalk9.bold(`\uBE0C\uB79C\uB4DC \uCF1C\uAE30 (ThemeProvider \uB294 ${THEME_PACKAGE} ${THEME_MIN_VERSION} \uC774\uC0C1)`));
|
|
4018
4355
|
if (act?.found) {
|
|
4019
4356
|
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.`);
|
|
4357
|
+
if (act.markupWithProvider) {
|
|
4358
|
+
lines.push(
|
|
4359
|
+
chalk9.yellow(
|
|
4360
|
+
` ! <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`
|
|
4361
|
+
)
|
|
4362
|
+
);
|
|
4363
|
+
}
|
|
4020
4364
|
} else {
|
|
4021
4365
|
lines.push(
|
|
4022
4366
|
...providerExample(plan.brand).split("\n").map((l) => l ? ` ${l}` : ""),
|
|
@@ -4387,7 +4731,7 @@ async function fetchRegistryJson(url, options = {}) {
|
|
|
4387
4731
|
}
|
|
4388
4732
|
|
|
4389
4733
|
// src/init/init.ts
|
|
4390
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as
|
|
4734
|
+
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
4735
|
import path15 from "path";
|
|
4392
4736
|
import chalk10 from "chalk";
|
|
4393
4737
|
import fs12 from "fs-extra";
|
|
@@ -4644,7 +4988,7 @@ async function resolveInitAnswers(baseDirInput, tailwind4) {
|
|
|
4644
4988
|
}
|
|
4645
4989
|
function animationGuideLine(pkg, tailwind4, installCommand) {
|
|
4646
4990
|
const name = tailwind4 ? ANIMATION_PLUGIN_TAILWIND4 : ANIMATION_PLUGIN_TAILWIND3;
|
|
4647
|
-
if (pkg !== void 0 && (
|
|
4991
|
+
if (pkg !== void 0 && (hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0 || hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND4) !== void 0)) {
|
|
4648
4992
|
return void 0;
|
|
4649
4993
|
}
|
|
4650
4994
|
const add = `${addCommandFor(installCommand, {}).trimEnd()} ${name}`;
|
|
@@ -4659,15 +5003,15 @@ var TAILWIND4_TOKENS_VERSION = TAILWIND4_MIN_AXIS_VERSION;
|
|
|
4659
5003
|
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
5004
|
function readPackageJsonSafe(baseDir) {
|
|
4661
5005
|
try {
|
|
4662
|
-
const text =
|
|
5006
|
+
const text = readFileSync6(path15.join(baseDir, "package.json"), "utf8");
|
|
4663
5007
|
const parsed = JSON.parse(text.startsWith(BOM) ? text.slice(1) : text);
|
|
4664
|
-
return
|
|
5008
|
+
return isPlainObject(parsed) ? parsed : void 0;
|
|
4665
5009
|
} catch {
|
|
4666
5010
|
return void 0;
|
|
4667
5011
|
}
|
|
4668
5012
|
}
|
|
4669
5013
|
function tailwind4GuideLines(pkg, installCommand, globalCss, baseDir) {
|
|
4670
|
-
const used = TAILWIND4_COMPONENT_PACKAGES.filter((name) => pkg !== void 0 &&
|
|
5014
|
+
const used = TAILWIND4_COMPONENT_PACKAGES.filter((name) => pkg !== void 0 && hasDependency(pkg, name) !== void 0);
|
|
4671
5015
|
const lines = [
|
|
4672
5016
|
`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
5017
|
' @import "tailwindcss";',
|
|
@@ -4680,7 +5024,7 @@ function tailwind4GuideLines(pkg, installCommand, globalCss, baseDir) {
|
|
|
4680
5024
|
);
|
|
4681
5025
|
}
|
|
4682
5026
|
lines.push(TAILWIND4_CONFLICT_LINE);
|
|
4683
|
-
if (pkg === void 0 ||
|
|
5027
|
+
if (pkg === void 0 || hasDependency(pkg, TOKENS_PACKAGE) === void 0) {
|
|
4684
5028
|
const add = addCommandFor(installCommand, { [TOKENS_PACKAGE]: `^${TAILWIND4_TOKENS_VERSION}` });
|
|
4685
5029
|
lines.push(` ${TOKENS_PACKAGE} \uC124\uCE58: ${add}`);
|
|
4686
5030
|
}
|
|
@@ -4743,7 +5087,7 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4743
5087
|
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
5088
|
let text;
|
|
4745
5089
|
try {
|
|
4746
|
-
text =
|
|
5090
|
+
text = readFileSync6(pkgFile, "utf8");
|
|
4747
5091
|
} catch (err) {
|
|
4748
5092
|
return unwritable(err.message);
|
|
4749
5093
|
}
|
|
@@ -4752,7 +5096,7 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4752
5096
|
let pkg;
|
|
4753
5097
|
try {
|
|
4754
5098
|
const parsed = JSON.parse(body);
|
|
4755
|
-
if (!
|
|
5099
|
+
if (!isPlainObject(parsed)) throw new Error("\uCD5C\uC0C1\uC704\uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
4756
5100
|
pkg = parsed;
|
|
4757
5101
|
} catch (err) {
|
|
4758
5102
|
return unwritable(`JSON \uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${err.message}`);
|
|
@@ -4762,14 +5106,14 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
4762
5106
|
plan.addCommand = addCommandFor(installCommand, plan.ranges);
|
|
4763
5107
|
const missing = {};
|
|
4764
5108
|
for (const [name, range] of Object.entries(plan.ranges)) {
|
|
4765
|
-
const declared =
|
|
5109
|
+
const declared = hasDependency(pkg, name);
|
|
4766
5110
|
if (declared !== void 0) plan.present.push({ name, range: declared });
|
|
4767
5111
|
else missing[name] = range;
|
|
4768
5112
|
}
|
|
4769
5113
|
plan.added = Object.keys(missing);
|
|
4770
5114
|
plan.addCommand = addCommandFor(installCommand, plan.added.length > 0 ? missing : plan.ranges);
|
|
4771
5115
|
if (plan.added.length === 0) return { ...plan, action: "present" };
|
|
4772
|
-
if (pkg.dependencies !== void 0 && !
|
|
5116
|
+
if (pkg.dependencies !== void 0 && !isPlainObject(pkg.dependencies)) {
|
|
4773
5117
|
return unwritable("dependencies \uAC00 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
|
|
4774
5118
|
}
|
|
4775
5119
|
try {
|
|
@@ -4786,7 +5130,7 @@ function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile
|
|
|
4786
5130
|
const w = plan.write;
|
|
4787
5131
|
if (plan.action !== "add" || !w) return false;
|
|
4788
5132
|
const baseDir = path15.resolve(baseDirInput);
|
|
4789
|
-
const current = existsSync6(w.file) ?
|
|
5133
|
+
const current = existsSync6(w.file) ? readFileSync6(w.file, "utf8") : null;
|
|
4790
5134
|
if (current !== w.before) {
|
|
4791
5135
|
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
4792
5136
|
}
|
|
@@ -4802,7 +5146,7 @@ function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile
|
|
|
4802
5146
|
let restored;
|
|
4803
5147
|
try {
|
|
4804
5148
|
writeFile(w.file, w.before);
|
|
4805
|
-
if (
|
|
5149
|
+
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
5150
|
restored = "\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4";
|
|
4807
5151
|
} catch (restoreErr) {
|
|
4808
5152
|
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 +5184,7 @@ function reportDependencies(plan, log) {
|
|
|
4840
5184
|
async function existingConfig(baseDir) {
|
|
4841
5185
|
try {
|
|
4842
5186
|
const parsed = await readAxisConfig(baseDir);
|
|
4843
|
-
return
|
|
5187
|
+
return isPlainObject(parsed) ? parsed : null;
|
|
4844
5188
|
} catch {
|
|
4845
5189
|
return null;
|
|
4846
5190
|
}
|
|
@@ -4913,7 +5257,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
4913
5257
|
if (!target.isFile()) return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4` };
|
|
4914
5258
|
let content2;
|
|
4915
5259
|
try {
|
|
4916
|
-
content2 =
|
|
5260
|
+
content2 = readFileSync6(utilsPath, "utf8");
|
|
4917
5261
|
} catch (e) {
|
|
4918
5262
|
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
5263
|
}
|
|
@@ -4928,7 +5272,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
4928
5272
|
if (!st.isFile()) return { action: "reject", reason: `${shown} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` };
|
|
4929
5273
|
let content;
|
|
4930
5274
|
try {
|
|
4931
|
-
content =
|
|
5275
|
+
content = readFileSync6(utilsPath, "utf8");
|
|
4932
5276
|
} catch (e) {
|
|
4933
5277
|
return { action: "reject", reason: `\uAE30\uC874 ${shown} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4934
5278
|
}
|
|
@@ -5129,12 +5473,12 @@ import chalk12 from "chalk";
|
|
|
5129
5473
|
import prompts3 from "prompts";
|
|
5130
5474
|
|
|
5131
5475
|
// ../axis-registry-core/src/add/add.ts
|
|
5132
|
-
import { existsSync as existsSync8, readFileSync as
|
|
5476
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
|
|
5133
5477
|
import path17 from "path";
|
|
5134
5478
|
import fs13 from "fs-extra";
|
|
5135
5479
|
|
|
5136
5480
|
// ../axis-registry-core/src/registry/bundled.ts
|
|
5137
|
-
import { existsSync as existsSync7, readFileSync as
|
|
5481
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
|
|
5138
5482
|
import path16 from "path";
|
|
5139
5483
|
import { fileURLToPath } from "url";
|
|
5140
5484
|
function findBundledRegistryDir(moduleUrl = import.meta.url) {
|
|
@@ -5148,7 +5492,7 @@ function readBundledJson(dir, fileName) {
|
|
|
5148
5492
|
const file = path16.join(dir, fileName);
|
|
5149
5493
|
let text;
|
|
5150
5494
|
try {
|
|
5151
|
-
text =
|
|
5495
|
+
text = readFileSync7(file, "utf8");
|
|
5152
5496
|
} catch {
|
|
5153
5497
|
throw new Error(`\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 ${fileName} \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(${dir})`);
|
|
5154
5498
|
}
|
|
@@ -5336,7 +5680,7 @@ function createPinnedFetch(options = {}) {
|
|
|
5336
5680
|
const judge = options.judge ?? blockedAddressReason;
|
|
5337
5681
|
const send = options.request ?? httpsRequest;
|
|
5338
5682
|
const maxBytes = options.maxBytes ?? PINNED_FETCH_MAX_BYTES;
|
|
5339
|
-
return (input, init) => new Promise((
|
|
5683
|
+
return (input, init) => new Promise((resolve4, reject) => {
|
|
5340
5684
|
let url;
|
|
5341
5685
|
try {
|
|
5342
5686
|
url = new URL(input);
|
|
@@ -5377,7 +5721,7 @@ function createPinnedFetch(options = {}) {
|
|
|
5377
5721
|
if (failed) return;
|
|
5378
5722
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
5379
5723
|
const status = res.statusCode ?? 0;
|
|
5380
|
-
|
|
5724
|
+
resolve4({ ok: status >= 200 && status < 300, status, text: async () => body });
|
|
5381
5725
|
});
|
|
5382
5726
|
}
|
|
5383
5727
|
);
|
|
@@ -5863,9 +6207,9 @@ function missingDependencies(root, items) {
|
|
|
5863
6207
|
const installCommand = detectInstallCommand(root);
|
|
5864
6208
|
let pkg;
|
|
5865
6209
|
try {
|
|
5866
|
-
const text =
|
|
6210
|
+
const text = readFileSync8(path17.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
|
|
5867
6211
|
const parsed = JSON.parse(text);
|
|
5868
|
-
pkg =
|
|
6212
|
+
pkg = isPlainObject(parsed) ? parsed : void 0;
|
|
5869
6213
|
} catch {
|
|
5870
6214
|
pkg = void 0;
|
|
5871
6215
|
}
|
|
@@ -5874,7 +6218,7 @@ function missingDependencies(root, items) {
|
|
|
5874
6218
|
for (const item of items) {
|
|
5875
6219
|
for (const dep of item.dependencies) {
|
|
5876
6220
|
const name = dependencyName(dep);
|
|
5877
|
-
if (pkg !== void 0 &&
|
|
6221
|
+
if (pkg !== void 0 && hasDependency(pkg, name) !== void 0) continue;
|
|
5878
6222
|
if (name in specs) continue;
|
|
5879
6223
|
const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
|
|
5880
6224
|
specs[name] = explicit ?? ranges[name];
|
|
@@ -5984,7 +6328,7 @@ async function runAdd(cwd, requested, options, ctx) {
|
|
|
5984
6328
|
continue;
|
|
5985
6329
|
}
|
|
5986
6330
|
try {
|
|
5987
|
-
existing.set(file,
|
|
6331
|
+
existing.set(file, readFileSync8(file.target, "utf8"));
|
|
5988
6332
|
} catch (e) {
|
|
5989
6333
|
readErrors.push(
|
|
5990
6334
|
`${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})`
|