@axis-ds/mcp 1.4.7 → 1.4.9
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 +2 -1
- package/dist/index.js +345 -81
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,8 @@ Claude Desktop 또는 기타 MCP 호환 클라이언트에서 설정:
|
|
|
41
41
|
- 이름은 레지스트리 이름 그대로입니다. Agentic UI 는 `agentic-` 접두를 붙입니다(예: `agentic-run-progress`). 의존 항목(`utils` · `agentic-a11y-labels`)은 함께 설치됩니다.
|
|
42
42
|
- `targetDir` 는 이미 있는 프로젝트 루트입니다(상대 경로는 서버의 현재 디렉터리 기준). `axis.config.json` 이 있으면 그 `componentsDir` · `agenticDir` 에, 없으면 `components/ui` · `components/agentic` 에 설치하고 그 사실을 알립니다. 프로젝트 밖으로 나가는 경로는 아무것도 쓰지 않고 실패합니다.
|
|
43
43
|
- 내용이 다른 기존 파일은 덮어쓰지 않고 건너뛰며 응답 첫머리에 건너뛴 수를 적습니다. `overwrite: true` 일 때만 덮어씁니다.
|
|
44
|
-
- 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
|
|
44
|
+
- 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. 워크스페이스 루트 `package.json` 에 선언된 의존성은 안내하지 않고, 1.4.8 다음 patch 부터(WI-0095) Yarn Plug'n'Play 에서는 루트에만 선언한 의존성도 앱이 해석하지 못하므로 안내 명령에 넣습니다(CLI `axis add` 와 같음). lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
|
|
45
|
+
- `axis.apply_template` 은 `targetDir` 에 이미 있는 `package.json` · `axis.config.json`(템플릿 루트의 것)을 덮어쓰지 않고 CLI `axis template apply` 와 같은 규칙으로 합칩니다(WI-0088). `packageManager` 등 사용자 필드가 남고, 결과의 파일 목록에 「합치기」로 표시합니다. 파일을 쓰는 도중 실패하면 건드린 파일을 되돌리고 오류로 응답합니다. 템플릿 경로가 `targetDir` 밖(절대 경로 · `..` · 밖을 가리키는 심볼릭 링크 경유)이면 `axis.apply_template` · `axis.diff_template` 은 아무 파일도 쓰거나 읽지 않고 오류로 응답합니다.
|
|
45
46
|
|
|
46
47
|
## 토큰 도구
|
|
47
48
|
|
package/dist/index.js
CHANGED
|
@@ -58,8 +58,8 @@ function listTokens(category) {
|
|
|
58
58
|
}
|
|
59
59
|
return tokens;
|
|
60
60
|
}
|
|
61
|
-
function getToken(
|
|
62
|
-
const q =
|
|
61
|
+
function getToken(path12) {
|
|
62
|
+
const q = path12.trim().toLowerCase();
|
|
63
63
|
return loadTokens().tokens.find(
|
|
64
64
|
(t) => t.path.toLowerCase() === q || (t.aliases ?? []).some((a) => a.toLowerCase() === q) || t.cssVariable.toLowerCase() === q
|
|
65
65
|
);
|
|
@@ -1020,6 +1020,9 @@ function dependencyInstallGuide(baseDirInput, name, range) {
|
|
|
1020
1020
|
...base
|
|
1021
1021
|
};
|
|
1022
1022
|
}
|
|
1023
|
+
function installCommandPhrase(installCommand, rootDeclared) {
|
|
1024
|
+
return rootDeclared && packageManagerOf(installCommand) === "npm" ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${installCommand}` : installCommand;
|
|
1025
|
+
}
|
|
1023
1026
|
function isPlainObject(value) {
|
|
1024
1027
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1025
1028
|
}
|
|
@@ -1195,20 +1198,20 @@ function splitPackageSpec(spec) {
|
|
|
1195
1198
|
if (parts.length < n || parts.slice(0, n).some((p) => p === "" || p === "." || p === "..")) return void 0;
|
|
1196
1199
|
return { name: parts.slice(0, n).join("/"), rest: parts.slice(n).join("/") };
|
|
1197
1200
|
}
|
|
1198
|
-
function resolveExportTarget(value) {
|
|
1201
|
+
function resolveExportTarget(value, conditions = CSS_EXPORT_CONDITIONS) {
|
|
1199
1202
|
if (typeof value === "string") return value;
|
|
1200
1203
|
if (Array.isArray(value)) {
|
|
1201
1204
|
for (const v of value) {
|
|
1202
|
-
const r = resolveExportTarget(v);
|
|
1205
|
+
const r = resolveExportTarget(v, conditions);
|
|
1203
1206
|
if (r !== void 0) return r;
|
|
1204
1207
|
}
|
|
1205
1208
|
return void 0;
|
|
1206
1209
|
}
|
|
1207
1210
|
if (isPlainObject(value)) {
|
|
1208
1211
|
for (const [key, v] of Object.entries(value)) {
|
|
1209
|
-
if (!
|
|
1212
|
+
if (!conditions.has(key)) continue;
|
|
1210
1213
|
if (v === null) return void 0;
|
|
1211
|
-
const r = resolveExportTarget(v);
|
|
1214
|
+
const r = resolveExportTarget(v, conditions);
|
|
1212
1215
|
if (r !== void 0) return r;
|
|
1213
1216
|
}
|
|
1214
1217
|
}
|
|
@@ -1217,10 +1220,10 @@ function resolveExportTarget(value) {
|
|
|
1217
1220
|
function cssFileCandidates(p) {
|
|
1218
1221
|
return [p, `${p}.css`, path3.join(p, "index.css")];
|
|
1219
1222
|
}
|
|
1220
|
-
function exportsTarget(exportsField, subpath) {
|
|
1223
|
+
function exportsTarget(exportsField, subpath, conditions = CSS_EXPORT_CONDITIONS) {
|
|
1221
1224
|
const map = isPlainObject(exportsField) && Object.keys(exportsField).some((k) => k.startsWith(".")) ? exportsField : { ".": exportsField };
|
|
1222
1225
|
if (Object.prototype.hasOwnProperty.call(map, subpath)) {
|
|
1223
|
-
const t = resolveExportTarget(map[subpath]);
|
|
1226
|
+
const t = resolveExportTarget(map[subpath], conditions);
|
|
1224
1227
|
if (t === void 0) return void 0;
|
|
1225
1228
|
return t.includes("*") || !t.startsWith("./") ? "?" : t;
|
|
1226
1229
|
}
|
|
@@ -1228,6 +1231,9 @@ function exportsTarget(exportsField, subpath) {
|
|
|
1228
1231
|
return void 0;
|
|
1229
1232
|
}
|
|
1230
1233
|
function resolveCssPackageImport(fromDir, spec) {
|
|
1234
|
+
return resolvePackageSubpath(fromDir, spec, CSS_EXPORT_CONDITIONS, cssFileCandidates);
|
|
1235
|
+
}
|
|
1236
|
+
function resolvePackageSubpath(fromDir, spec, conditions, candidates) {
|
|
1231
1237
|
const parsed = splitPackageSpec(spec);
|
|
1232
1238
|
if (parsed === void 0 || parsed.rest === "") return { kind: "unknown" };
|
|
1233
1239
|
const subpath = `./${parsed.rest}`;
|
|
@@ -1244,16 +1250,16 @@ function resolveCssPackageImport(fromDir, spec) {
|
|
|
1244
1250
|
}
|
|
1245
1251
|
if (manifest !== void 0 && manifest.exports) {
|
|
1246
1252
|
const version = exactVersionOf(manifest.version);
|
|
1247
|
-
const target = exportsTarget(manifest.exports, subpath);
|
|
1253
|
+
const target = exportsTarget(manifest.exports, subpath, conditions);
|
|
1248
1254
|
if (target === "?") return { kind: "unknown" };
|
|
1249
1255
|
if (target === void 0) {
|
|
1250
1256
|
return version !== void 0 ? { kind: "not-exported", pkgDir, subpath, version } : { kind: "not-exported", pkgDir, subpath };
|
|
1251
1257
|
}
|
|
1252
|
-
const file =
|
|
1258
|
+
const file = candidates(path3.join(pkgDir, target)).find(isFile);
|
|
1253
1259
|
if (file !== void 0) return { kind: "resolved", pkgDir, file };
|
|
1254
1260
|
return version !== void 0 ? { kind: "target-missing", pkgDir, subpath, target, version } : { kind: "target-missing", pkgDir, subpath, target };
|
|
1255
1261
|
}
|
|
1256
|
-
const bare =
|
|
1262
|
+
const bare = candidates(path3.join(pkgDir, parsed.rest)).find(isFile);
|
|
1257
1263
|
if (bare !== void 0) return { kind: "resolved", pkgDir, file: bare };
|
|
1258
1264
|
}
|
|
1259
1265
|
const parent = path3.dirname(dir);
|
|
@@ -1304,6 +1310,25 @@ function cssPackageLineResolution(baseDir, lineDir, spec, otherDirs = []) {
|
|
|
1304
1310
|
}
|
|
1305
1311
|
return { kind: "ok" };
|
|
1306
1312
|
}
|
|
1313
|
+
var JS_REQUIRE_CONDITIONS = /* @__PURE__ */ new Set(["require", "node", "module-sync", "default"]);
|
|
1314
|
+
var JS_IMPORT_CONDITIONS = /* @__PURE__ */ new Set(["import", "node", "module-sync", "default"]);
|
|
1315
|
+
function jsFileCandidates(p) {
|
|
1316
|
+
return [p, `${p}.js`, `${p}.json`, `${p}.node`, path3.join(p, "index.js"), path3.join(p, "index.json"), path3.join(p, "index.node")];
|
|
1317
|
+
}
|
|
1318
|
+
function tailwindConfigImportResolution(baseDir, spec, refs) {
|
|
1319
|
+
if (isPnpProject(baseDir)) return { kind: "ok" };
|
|
1320
|
+
const blocked = (conditions) => {
|
|
1321
|
+
const r = resolvePackageSubpath(baseDir, spec, conditions, jsFileCandidates);
|
|
1322
|
+
return r.kind === "not-exported" ? r : void 0;
|
|
1323
|
+
};
|
|
1324
|
+
const viaRequire = refs.require || refs.import ? blocked(JS_REQUIRE_CONDITIONS) : void 0;
|
|
1325
|
+
if (refs.require && viaRequire !== void 0) return viaRequire;
|
|
1326
|
+
if (refs.import && viaRequire !== void 0) {
|
|
1327
|
+
const viaImport = blocked(JS_IMPORT_CONDITIONS);
|
|
1328
|
+
if (viaImport !== void 0) return viaImport;
|
|
1329
|
+
}
|
|
1330
|
+
return { kind: "ok" };
|
|
1331
|
+
}
|
|
1307
1332
|
function findPnpUnpluggedPackages(baseDirInput, name, range) {
|
|
1308
1333
|
const root = pnpProjectRoot(baseDirInput);
|
|
1309
1334
|
if (root === void 0) return [];
|
|
@@ -1328,6 +1353,17 @@ function findPnpUnpluggedPackages(baseDirInput, name, range) {
|
|
|
1328
1353
|
}
|
|
1329
1354
|
return found;
|
|
1330
1355
|
}
|
|
1356
|
+
var PNP_REAL_DIR_RANGE = /^(?:workspace|portal|link):/;
|
|
1357
|
+
function pnpComponentSourceHidden(baseDirInput, name, range) {
|
|
1358
|
+
if (!isPnpProject(baseDirInput)) return false;
|
|
1359
|
+
const r = range.trim();
|
|
1360
|
+
if (PNP_REAL_DIR_RANGE.test(r)) return false;
|
|
1361
|
+
const probe = versionSatisfiesRange("0.0.0", r) === void 0 ? "*" : r;
|
|
1362
|
+
return findPnpUnpluggedPackages(baseDirInput, name, probe).length === 0;
|
|
1363
|
+
}
|
|
1364
|
+
function pnpUnplugSetupPhrase(name) {
|
|
1365
|
+
return `Plug'n'Play \uB8E8\uD2B8(.pnp.cjs \uAC00 \uC788\uB294 \uACF3) package.json \uC758 dependenciesMeta \uC5D0 "${name}": { "unplugged": true } \uB97C \uB450\uACE0 yarn install`;
|
|
1366
|
+
}
|
|
1331
1367
|
function parsePartialVersion(token) {
|
|
1332
1368
|
const m = /^v?(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(token.trim());
|
|
1333
1369
|
if (!m) return void 0;
|
|
@@ -1440,9 +1476,6 @@ import { basename, dirname as dirname2, extname, isAbsolute, join as join2, rela
|
|
|
1440
1476
|
function declaredRange(baseDir, pkg, name) {
|
|
1441
1477
|
return declaredDependency(baseDir, pkg, name)?.range;
|
|
1442
1478
|
}
|
|
1443
|
-
function declaredRangeForCheck(baseDir, pkg, name) {
|
|
1444
|
-
return declaredDependency(baseDir, pkg, name, void 0, { appOnlyInPnp: true })?.range;
|
|
1445
|
-
}
|
|
1446
1479
|
function isPlainObject2(value) {
|
|
1447
1480
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1448
1481
|
}
|
|
@@ -1765,18 +1798,19 @@ function packageNameOfSpec(spec) {
|
|
|
1765
1798
|
function displayRel(baseDir, p) {
|
|
1766
1799
|
return relative(baseDir, p).split(sep).join("/");
|
|
1767
1800
|
}
|
|
1768
|
-
function packageLineShadowIssue(baseDir, expanded, origin, spec) {
|
|
1801
|
+
function packageLineShadowIssue(baseDir, expanded, origin, spec, opts = {}) {
|
|
1769
1802
|
const name = packageNameOfSpec(spec);
|
|
1770
1803
|
const lineDir = dirname2(origin.path);
|
|
1771
1804
|
const others = () => [...new Set(expanded.files.map((f) => dirname2(f.path)))].filter((d) => d !== lineDir);
|
|
1772
1805
|
const r = cssPackageLineResolution(baseDir, lineDir, spec, others);
|
|
1773
1806
|
const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uADF8 \uC904\uC774 \uC788\uB294 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C`;
|
|
1774
1807
|
const label = (pkgDir, version) => `${displayRel(baseDir, pkgDir)}(${version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
|
|
1808
|
+
if (opts.tailwind3 === true && r.kind !== "shadow-not-exported") return void 0;
|
|
1775
1809
|
switch (r.kind) {
|
|
1776
1810
|
case "ok":
|
|
1777
1811
|
return void 0;
|
|
1778
1812
|
case "shadow-not-exported": {
|
|
1779
|
-
const current = r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
|
|
1813
|
+
const current = opts.tailwind3 === true || r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
|
|
1780
1814
|
const todo = current ? "\uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694" : `${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uB9DE\uCD94\uC138\uC694`;
|
|
1781
1815
|
return `${head} \uBA3C\uC800 \uC7A1\uD788\uB294 ${label(r.pkgDir, r.version)}\uAC00 ${r.subpath} \uB97C \uB0B4\uBCF4\uB0B4\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 \uC911\uCCA9 node_modules \uC758 ${name} \uB97C \uC9C0\uC6B0\uAC70\uB098 ${todo}`;
|
|
1782
1816
|
}
|
|
@@ -1819,13 +1853,20 @@ function judgeGlobalsCss(baseDir, selection, candidate, expanded) {
|
|
|
1819
1853
|
const origin = evidenceOrigin(expanded, (f) => findTokensCssImport(f) === imported);
|
|
1820
1854
|
via = cssImportViaNote(viaFiles([origin]));
|
|
1821
1855
|
const tailwind4 = (detectTailwind(baseDir, pkg).major ?? 0) >= 4;
|
|
1822
|
-
const
|
|
1856
|
+
const inside = origin !== void 0 && !isOutsideEntry(origin);
|
|
1857
|
+
const issue = tailwind4 && inside ? tokensCssUnresolvedIssue(
|
|
1823
1858
|
baseDir,
|
|
1824
1859
|
pkg,
|
|
1825
1860
|
imported,
|
|
1826
1861
|
void 0,
|
|
1827
1862
|
() => packageLineShadowIssue(baseDir, expanded, origin, imported)
|
|
1828
|
-
) : tokensCssUnresolvedIssue(
|
|
1863
|
+
) : tokensCssUnresolvedIssue(
|
|
1864
|
+
baseDir,
|
|
1865
|
+
pkg,
|
|
1866
|
+
imported,
|
|
1867
|
+
origin !== void 0 ? origin.cssDir : outsideCssDir(selection),
|
|
1868
|
+
inside ? () => packageLineShadowIssue(baseDir, expanded, origin, imported, { tailwind3: true }) : void 0
|
|
1869
|
+
);
|
|
1829
1870
|
if (issue !== void 0) unresolved = `${candidate}\uC5D0 ${issue}`;
|
|
1830
1871
|
else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
|
|
1831
1872
|
} else if (AXIS_VARIABLE_DEFINITION.test(stripCssComments(expanded.evidence))) {
|
|
@@ -2029,6 +2070,8 @@ function stripJsComments(src) {
|
|
|
2029
2070
|
}
|
|
2030
2071
|
var TOKENS_TAILWIND3_PRESET = "@axis-ds/tokens/tailwind";
|
|
2031
2072
|
var PRESET_REFERENCE = /(?:\brequire\s*\(\s*|\bimport\s*\(\s*|\bfrom\s*|\bimport\s+)(["'])@axis-ds\/tokens\/tailwind\1/;
|
|
2073
|
+
var PRESET_REQUIRE_REFERENCE = /\brequire\s*\(\s*(["'])@axis-ds\/tokens\/tailwind\1/;
|
|
2074
|
+
var PRESET_IMPORT_REFERENCE = /(?:\bimport\s*\(\s*|\bfrom\s*|\bimport\s+)(["'])@axis-ds\/tokens\/tailwind\1/;
|
|
2032
2075
|
function hasTokensPresetReference(source) {
|
|
2033
2076
|
return PRESET_REFERENCE.test(stripJsComments(source));
|
|
2034
2077
|
}
|
|
@@ -2056,7 +2099,7 @@ function hasBareCjsPresetRequire(code) {
|
|
|
2056
2099
|
function isCommonJsConfig(file, source) {
|
|
2057
2100
|
return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
|
|
2058
2101
|
}
|
|
2059
|
-
function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
|
|
2102
|
+
function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs, code) {
|
|
2060
2103
|
const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
|
|
2061
2104
|
const head = `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${TOKENS_PACKAGE_NAME} \uAC00`;
|
|
2062
2105
|
if (r.kind === "not-installed") {
|
|
@@ -2065,6 +2108,14 @@ function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
|
|
|
2065
2108
|
if (r.kind === "pnp-root-only" && !bareCjs) {
|
|
2066
2109
|
return `${head} ${PNP_ROOT_ONLY_NOTE}(\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 \uC120\uC5B8 ${r.range}) \u2192 \uC571 package.json \uC5D0 ${TOKENS_PACKAGE_NAME} \uB97C \uC120\uC5B8\uD558\uC138\uC694`;
|
|
2067
2110
|
}
|
|
2111
|
+
const e = tailwindConfigImportResolution(baseDir, TOKENS_TAILWIND3_PRESET, {
|
|
2112
|
+
require: PRESET_REQUIRE_REFERENCE.test(code),
|
|
2113
|
+
import: PRESET_IMPORT_REFERENCE.test(code)
|
|
2114
|
+
});
|
|
2115
|
+
if (e.kind === "not-exported") {
|
|
2116
|
+
const label = `${displayRel(baseDir, e.pkgDir)}(${e.version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
|
|
2117
|
+
return `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC \uBA3C\uC800 \uC7A1\uD788\uB294 ${label}\uAC00 ${e.subpath} \uB97C \uB0B4\uBCF4\uB0B4\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 node_modules \uC758 ${TOKENS_PACKAGE_NAME} \uB97C \uC9C0\uC6B0\uAC70\uB098 \uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694`;
|
|
2118
|
+
}
|
|
2068
2119
|
return void 0;
|
|
2069
2120
|
}
|
|
2070
2121
|
function packageVersionGate(baseDirInput, pkg, name, min, options = {}) {
|
|
@@ -2119,7 +2170,8 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
|
|
|
2119
2170
|
const r = resolutions.get(name);
|
|
2120
2171
|
if (r.kind === "undeclared" || r.kind === "app-lockfile") continue;
|
|
2121
2172
|
if (hasComponentTailwindImport(evidence, name) || hasComponentSource(evidence, name)) continue;
|
|
2122
|
-
if (
|
|
2173
|
+
if (r.kind === "app" && pnpComponentSourceHidden(baseDir, name, r.range)) unresolvedMissing.push(componentCssPnpMissingIssue(name));
|
|
2174
|
+
else if (componentCssResolvable(r)) missing.push(name);
|
|
2123
2175
|
else unresolvedMissing.push(componentCssMissingIssue(baseDir, name, r));
|
|
2124
2176
|
}
|
|
2125
2177
|
if (missing.length > 0) {
|
|
@@ -2135,12 +2187,17 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
|
|
|
2135
2187
|
}
|
|
2136
2188
|
for (const name of TAILWIND4_COMPONENT_PACKAGES) {
|
|
2137
2189
|
if (!hasComponentTailwindImport(evidence, name)) continue;
|
|
2138
|
-
const
|
|
2190
|
+
const r = resolutions.get(name);
|
|
2191
|
+
const unresolved = componentCssPresentIssue(baseDir, name, r);
|
|
2139
2192
|
const spec = `${name}/tailwind.css`;
|
|
2140
2193
|
if (unresolved !== void 0) {
|
|
2141
2194
|
issues.push(unresolved);
|
|
2142
2195
|
continue;
|
|
2143
2196
|
}
|
|
2197
|
+
if (r.kind === "app" && pnpComponentSourceHidden(baseDir, name, r.range)) {
|
|
2198
|
+
issues.push(componentCssPnpPresentIssue(name));
|
|
2199
|
+
continue;
|
|
2200
|
+
}
|
|
2144
2201
|
const shadow = input.lineIssue === void 0 ? false : input.lineIssue(spec);
|
|
2145
2202
|
let lineProblem;
|
|
2146
2203
|
if (shadow !== false) lineProblem = shadow;
|
|
@@ -2159,6 +2216,13 @@ function componentInstallPhrase(baseDir, name, range) {
|
|
|
2159
2216
|
const g = dependencyInstallGuide(baseDir, name, range);
|
|
2160
2217
|
return g.kind === "install-at-root" ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}` : g.installCommand;
|
|
2161
2218
|
}
|
|
2219
|
+
var PNP_ZIP_SOURCE_NOTE = `Plug'n'Play \uC5D0\uC11C @source "./dist" \uAC00 .yarn/cache zip \uC548\uC744 \uAC00\uB9AC\uCF1C \uCEF4\uD3EC\uB10C\uD2B8 \uD074\uB798\uC2A4\uAC00 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`;
|
|
2220
|
+
function componentCssPnpMissingIssue(name) {
|
|
2221
|
+
return `${name} \uC758 tailwind.css \uB294 ${PNP_ZIP_SOURCE_NOTE} \u2192 ${pnpUnplugSetupPhrase(name)} \uB4A4 ${componentTailwindImportLine(name)}`;
|
|
2222
|
+
}
|
|
2223
|
+
function componentCssPnpPresentIssue(name) {
|
|
2224
|
+
return `${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${PNP_ZIP_SOURCE_NOTE} \u2192 ${pnpUnplugSetupPhrase(name)} \uD558\uC138\uC694`;
|
|
2225
|
+
}
|
|
2162
2226
|
function componentCssMissingIssue(baseDir, name, r) {
|
|
2163
2227
|
const line = componentTailwindImportLine(name);
|
|
2164
2228
|
switch (r.kind) {
|
|
@@ -2254,13 +2318,13 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2254
2318
|
};
|
|
2255
2319
|
}
|
|
2256
2320
|
for (const file of TAILWIND_CONFIG_FILES) {
|
|
2257
|
-
const
|
|
2258
|
-
if (!existsSync3(
|
|
2259
|
-
const content = readFileSync4(
|
|
2321
|
+
const path12 = join2(baseDir, file);
|
|
2322
|
+
if (!existsSync3(path12)) continue;
|
|
2323
|
+
const content = readFileSync4(path12, "utf8");
|
|
2260
2324
|
if (hasTokensPresetReference(content)) {
|
|
2261
2325
|
const code = stripJsComments(content);
|
|
2262
2326
|
const bareCjs = isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code);
|
|
2263
|
-
const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs);
|
|
2327
|
+
const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs, code);
|
|
2264
2328
|
if (unresolved !== void 0) return { name: "tailwind.config", severity: "warn", message: unresolved };
|
|
2265
2329
|
if (bareCjs) {
|
|
2266
2330
|
const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION, { appOnlyInPnp: true });
|
|
@@ -2677,6 +2741,33 @@ function componentsUseAnimation(baseDir, componentsDir) {
|
|
|
2677
2741
|
}
|
|
2678
2742
|
return false;
|
|
2679
2743
|
}
|
|
2744
|
+
function animationPluginProblem(baseDir, pkg, name, pnp) {
|
|
2745
|
+
const declared = declaredDependency(baseDir, pkg, name, void 0, { appOnlyInPnp: true });
|
|
2746
|
+
if (declared === void 0) {
|
|
2747
|
+
return pnpRootOnlyDependency(baseDir, pkg, name) !== void 0 ? { name, kind: "pnpRootOnly", why: `${name} \uAC00 ${PNP_ROOT_ONLY_NOTE}` } : { name, kind: "undeclared", why: `${name} \uC120\uC5B8 \uC5C6\uC74C` };
|
|
2748
|
+
}
|
|
2749
|
+
if (!pnp && findInstalledPackage(baseDir, name) === void 0) {
|
|
2750
|
+
return { name, kind: "notInstalled", why: `${name} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`, root: declared.source === "root" };
|
|
2751
|
+
}
|
|
2752
|
+
return void 0;
|
|
2753
|
+
}
|
|
2754
|
+
function inspectTailwind4Animation(baseDirInput, pkgInput) {
|
|
2755
|
+
const baseDir = resolveBaseDir(baseDirInput);
|
|
2756
|
+
const pkg = pkgInput ?? readPackageJson(baseDir);
|
|
2757
|
+
const pnp = isPnpProject(baseDir);
|
|
2758
|
+
const selection = selectCheckGlobalCss(baseDir);
|
|
2759
|
+
const note = globalCssSelectionNote(selection);
|
|
2760
|
+
const expanded = selection.path !== void 0 && selection.rel !== void 0 ? expandGlobalCss(baseDir, selection.path, selection.rel, outsideCssDir(selection)) : void 0;
|
|
2761
|
+
const css = expanded !== void 0 ? stripCssComments(expanded.evidence) : "";
|
|
2762
|
+
const twAnimate = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`);
|
|
2763
|
+
const animatePlugin = new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`);
|
|
2764
|
+
const lines = [];
|
|
2765
|
+
if (twAnimate.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
|
|
2766
|
+
if (animatePlugin.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
|
|
2767
|
+
const via = expanded !== void 0 ? cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => twAnimate.test(f)), evidenceOrigin(expanded, (f) => animatePlugin.test(f))])) : "";
|
|
2768
|
+
const problems = lines.map((name) => animationPluginProblem(baseDir, pkg, name, pnp)).filter((p) => p !== void 0);
|
|
2769
|
+
return { selection, file: selection.rel, note, via, lines, problems };
|
|
2770
|
+
}
|
|
2680
2771
|
function checkAnimationPlugin(baseDirInput) {
|
|
2681
2772
|
const baseDir = resolveBaseDir(baseDirInput);
|
|
2682
2773
|
const pkg = readPackageJson(baseDir);
|
|
@@ -2687,25 +2778,8 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2687
2778
|
const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
|
|
2688
2779
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
2689
2780
|
const pnp = isPnpProject(baseDir);
|
|
2690
|
-
const pluginProblem = (name) => {
|
|
2691
|
-
if (declaredRangeForCheck(baseDir, pkg, name) === void 0) {
|
|
2692
|
-
return pnpRootOnlyDependency(baseDir, pkg, name) !== void 0 ? `${name} \uAC00 ${PNP_ROOT_ONLY_NOTE}` : `${name} \uC120\uC5B8 \uC5C6\uC74C`;
|
|
2693
|
-
}
|
|
2694
|
-
if (!pnp && findInstalledPackage(baseDir, name) === void 0) return `${name} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`;
|
|
2695
|
-
return void 0;
|
|
2696
|
-
};
|
|
2697
2781
|
if (tailwind.major !== void 0 && tailwind.major >= 4) {
|
|
2698
|
-
const
|
|
2699
|
-
const note = globalCssSelectionNote(selection);
|
|
2700
|
-
const file = selection.rel;
|
|
2701
|
-
const expanded = selection.path !== void 0 && selection.rel !== void 0 ? expandGlobalCss(baseDir, selection.path, selection.rel, outsideCssDir(selection)) : void 0;
|
|
2702
|
-
const css = expanded !== void 0 ? stripCssComments(expanded.evidence) : "";
|
|
2703
|
-
const twAnimate = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`);
|
|
2704
|
-
const animatePlugin = new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`);
|
|
2705
|
-
const lines = [];
|
|
2706
|
-
if (twAnimate.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
|
|
2707
|
-
if (animatePlugin.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
|
|
2708
|
-
const via = expanded !== void 0 ? cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => twAnimate.test(f)), evidenceOrigin(expanded, (f) => animatePlugin.test(f))])) : "";
|
|
2782
|
+
const { file, note, via, lines, problems } = inspectTailwind4Animation(baseDir, pkg);
|
|
2709
2783
|
if (lines.length === 0) {
|
|
2710
2784
|
return {
|
|
2711
2785
|
name: "animation",
|
|
@@ -2713,7 +2787,6 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2713
2787
|
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}";${note}`
|
|
2714
2788
|
};
|
|
2715
2789
|
}
|
|
2716
|
-
const problems = lines.map((name) => ({ name, why: pluginProblem(name) })).filter((x) => x.why !== void 0);
|
|
2717
2790
|
if (problems.length === 0) return { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4${via}${note}` };
|
|
2718
2791
|
return {
|
|
2719
2792
|
name: "animation",
|
|
@@ -2724,7 +2797,7 @@ function checkAnimationPlugin(baseDirInput) {
|
|
|
2724
2797
|
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
|
|
2725
2798
|
const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
|
|
2726
2799
|
const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
|
|
2727
|
-
const pluginReason =
|
|
2800
|
+
const pluginReason = animationPluginProblem(baseDir, pkg, ANIMATION_PLUGIN_TAILWIND3, pnp)?.why;
|
|
2728
2801
|
if (plugins === "found" && pluginReason === void 0) {
|
|
2729
2802
|
return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
2730
2803
|
}
|
|
@@ -3238,7 +3311,7 @@ function missingDependencies(root, items) {
|
|
|
3238
3311
|
for (const item of items) {
|
|
3239
3312
|
for (const dep of item.dependencies) {
|
|
3240
3313
|
const name = dependencyName(dep);
|
|
3241
|
-
if (declaredDependency(root, pkg, name, rootPkg) !== void 0) continue;
|
|
3314
|
+
if (declaredDependency(root, pkg, name, rootPkg, { appOnlyInPnp: true }) !== void 0) continue;
|
|
3242
3315
|
if (name in specs) continue;
|
|
3243
3316
|
const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
|
|
3244
3317
|
specs[name] = explicit ?? ranges[name];
|
|
@@ -3690,11 +3763,11 @@ async function handleGetComponent(params, deps = {}) {
|
|
|
3690
3763
|
return { component, source: describeOrigin(client, latest.version), notices };
|
|
3691
3764
|
}
|
|
3692
3765
|
function handleGetToken(params) {
|
|
3693
|
-
const { path:
|
|
3694
|
-
if (!
|
|
3766
|
+
const { path: path12 } = params;
|
|
3767
|
+
if (!path12 || path12.trim() === "") {
|
|
3695
3768
|
throw new Error("\uD1A0\uD070 \uACBD\uB85C(path)\uB294 \uD544\uC218\uC785\uB2C8\uB2E4.");
|
|
3696
3769
|
}
|
|
3697
|
-
const token = getToken(
|
|
3770
|
+
const token = getToken(path12);
|
|
3698
3771
|
if (!token) {
|
|
3699
3772
|
return null;
|
|
3700
3773
|
}
|
|
@@ -3775,9 +3848,9 @@ function cssUsage(token) {
|
|
|
3775
3848
|
const shadcnColor = !token.cssVariable.startsWith("--axis-") && token.value.startsWith("hsl(");
|
|
3776
3849
|
return shadcnColor ? `hsl(var(${token.cssVariable}))` : `var(${token.cssVariable})`;
|
|
3777
3850
|
}
|
|
3778
|
-
function formatTokenNotFound(
|
|
3851
|
+
function formatTokenNotFound(path12) {
|
|
3779
3852
|
return [
|
|
3780
|
-
`\uD1A0\uD070\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: \`${
|
|
3853
|
+
`\uD1A0\uD070\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: \`${path12}\``,
|
|
3781
3854
|
"",
|
|
3782
3855
|
"- \uACBD\uB85C\uB294 `axis.list_tokens` \uB85C \uD655\uC778\uD558\uC138\uC694. \uACBD\uB85C \xB7 tokens \uC774\uB984 \uAE30\uBC18 \uACBD\uB85C(\uC608: `control.h.md`) \xB7 CSS \uBCC0\uC218 \uC774\uB984(\uC608: `--axis-control-h-md`)\uC744 \uBC1B\uC2B5\uB2C8\uB2E4.",
|
|
3783
3856
|
"- \uBE0C\uB79C\uB4DC \uAC12\uC740 `axis.list_brands` \xB7 `axis.get_brand` \uB85C \uC870\uD68C\uD558\uC138\uC694."
|
|
@@ -5475,7 +5548,7 @@ function formatSaveResult(result) {
|
|
|
5475
5548
|
// src/tools/template.ts
|
|
5476
5549
|
import fetch from "node-fetch";
|
|
5477
5550
|
import fs6 from "fs-extra";
|
|
5478
|
-
import
|
|
5551
|
+
import path10 from "path";
|
|
5479
5552
|
|
|
5480
5553
|
// src/tools/brand-core.ts
|
|
5481
5554
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -6035,11 +6108,15 @@ function checkDependencies(baseDirInput) {
|
|
|
6035
6108
|
if (missingRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`);
|
|
6036
6109
|
if (pnpRootRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 ${pnpRootRecommended.join(", ")} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`);
|
|
6037
6110
|
if (pnpRootAxis.length > 0) problems.push(`${pnpRootAxis.join(", ")} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`);
|
|
6111
|
+
const installCommand = detectInstallCommand(baseDir);
|
|
6038
6112
|
if (notInstalledOther.length > 0) {
|
|
6039
|
-
|
|
6113
|
+
const phrase = installCommandPhrase(installCommand, notInstalledOther.some((d) => fromRoot(d)));
|
|
6114
|
+
problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalledOther.join(", ")} \u2192 ${phrase}`);
|
|
6040
6115
|
}
|
|
6041
6116
|
if (notInstalledRoot.length > 0) {
|
|
6042
|
-
problems.push(
|
|
6117
|
+
problems.push(
|
|
6118
|
+
`\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: ${notInstalledRoot.join(", ")} \u2192 ${installCommandPhrase(installCommand, true)}`
|
|
6119
|
+
);
|
|
6043
6120
|
}
|
|
6044
6121
|
if (problems.length > 0) {
|
|
6045
6122
|
return { name: "dependencies", severity: "warn", message: problems.join(" / ") + (rootNote ? ` (${rootNote})` : "") };
|
|
@@ -6052,6 +6129,192 @@ function checkDependencies(baseDirInput) {
|
|
|
6052
6129
|
};
|
|
6053
6130
|
}
|
|
6054
6131
|
|
|
6132
|
+
// ../axis-registry-core/src/template/apply-files.ts
|
|
6133
|
+
import { existsSync as existsSync9, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync10, readdirSync as readdirSync3, realpathSync as realpathSync4, rmdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6134
|
+
import path9 from "path";
|
|
6135
|
+
var TemplatePathError = class extends Error {
|
|
6136
|
+
constructor(relPath, reason) {
|
|
6137
|
+
super(`\uD15C\uD50C\uB9BF \uACBD\uB85C '${relPath}' \uAC00 \uB300\uC0C1 \uB514\uB809\uD130\uB9AC \uBC16\uC744 \uAC00\uB9AC\uCF1C(${reason}) \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4. \uC544\uBB34 \uD30C\uC77C\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4`);
|
|
6138
|
+
this.relPath = relPath;
|
|
6139
|
+
this.reason = reason;
|
|
6140
|
+
this.name = "TemplatePathError";
|
|
6141
|
+
}
|
|
6142
|
+
};
|
|
6143
|
+
function realpathOfExisting(p) {
|
|
6144
|
+
const rest = [];
|
|
6145
|
+
let cur = p;
|
|
6146
|
+
for (; ; ) {
|
|
6147
|
+
try {
|
|
6148
|
+
lstatSync3(cur);
|
|
6149
|
+
break;
|
|
6150
|
+
} catch {
|
|
6151
|
+
const parent = path9.dirname(cur);
|
|
6152
|
+
if (parent === cur) break;
|
|
6153
|
+
rest.unshift(path9.basename(cur));
|
|
6154
|
+
cur = parent;
|
|
6155
|
+
}
|
|
6156
|
+
}
|
|
6157
|
+
try {
|
|
6158
|
+
return path9.join(realpathSync4(cur), ...rest);
|
|
6159
|
+
} catch {
|
|
6160
|
+
return void 0;
|
|
6161
|
+
}
|
|
6162
|
+
}
|
|
6163
|
+
function isInside(root, target) {
|
|
6164
|
+
const rel2 = path9.relative(root, target);
|
|
6165
|
+
return rel2 !== "" && !rel2.startsWith("..") && !path9.isAbsolute(rel2);
|
|
6166
|
+
}
|
|
6167
|
+
function resolveTemplatePath(baseDir, relPath) {
|
|
6168
|
+
if (typeof relPath !== "string" || relPath === "" || relPath.includes("\0")) {
|
|
6169
|
+
throw new TemplatePathError(String(relPath), "\uBE48 \uACBD\uB85C \uB610\uB294 \uC798\uBABB\uB41C \uBB38\uC790");
|
|
6170
|
+
}
|
|
6171
|
+
if (path9.isAbsolute(relPath) || path9.win32.isAbsolute(relPath)) throw new TemplatePathError(relPath, "\uC808\uB300 \uACBD\uB85C");
|
|
6172
|
+
const base = path9.resolve(baseDir);
|
|
6173
|
+
const dest = path9.resolve(base, relPath);
|
|
6174
|
+
if (!isInside(base, dest)) throw new TemplatePathError(relPath, "\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uB85C \uB098\uAC10");
|
|
6175
|
+
const baseReal = realpathOfExisting(base);
|
|
6176
|
+
const destReal = realpathOfExisting(dest);
|
|
6177
|
+
if (!baseReal || !destReal || !isInside(baseReal, destReal)) {
|
|
6178
|
+
throw new TemplatePathError(relPath, "\uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uAC00 \uB300\uC0C1 \uB514\uB809\uD130\uB9AC \uBC16\uC744 \uAC00\uB9AC\uD0B4");
|
|
6179
|
+
}
|
|
6180
|
+
return dest;
|
|
6181
|
+
}
|
|
6182
|
+
function assertTemplatePaths(baseDir, relPaths) {
|
|
6183
|
+
for (const p of relPaths) resolveTemplatePath(baseDir, p);
|
|
6184
|
+
}
|
|
6185
|
+
var PACKAGE_JSON_MERGED_MAPS = [
|
|
6186
|
+
"scripts",
|
|
6187
|
+
"dependencies",
|
|
6188
|
+
"devDependencies",
|
|
6189
|
+
"peerDependencies",
|
|
6190
|
+
"optionalDependencies"
|
|
6191
|
+
];
|
|
6192
|
+
function isPlainObject3(v) {
|
|
6193
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
6194
|
+
}
|
|
6195
|
+
function parseObject(text) {
|
|
6196
|
+
try {
|
|
6197
|
+
const v = JSON.parse(text);
|
|
6198
|
+
return isPlainObject3(v) ? v : void 0;
|
|
6199
|
+
} catch {
|
|
6200
|
+
return void 0;
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
function mergePackageJson(user, template) {
|
|
6204
|
+
const maps = new Set(PACKAGE_JSON_MERGED_MAPS);
|
|
6205
|
+
const out = {};
|
|
6206
|
+
for (const [key, value] of Object.entries(user)) {
|
|
6207
|
+
const tpl = template[key];
|
|
6208
|
+
if (maps.has(key) && isPlainObject3(tpl)) {
|
|
6209
|
+
out[key] = isPlainObject3(value) ? { ...value, ...tpl } : tpl;
|
|
6210
|
+
} else {
|
|
6211
|
+
out[key] = value;
|
|
6212
|
+
}
|
|
6213
|
+
}
|
|
6214
|
+
for (const [key, value] of Object.entries(template)) {
|
|
6215
|
+
if (!(key in out)) out[key] = value;
|
|
6216
|
+
}
|
|
6217
|
+
return out;
|
|
6218
|
+
}
|
|
6219
|
+
function mergeAxisConfigJson(user, template) {
|
|
6220
|
+
return { ...user, ...template };
|
|
6221
|
+
}
|
|
6222
|
+
function detectJsonIndent(text) {
|
|
6223
|
+
const m = /^([ \t]+)\S/m.exec(text);
|
|
6224
|
+
if (!m) return 2;
|
|
6225
|
+
return m[1].startsWith(" ") ? " " : m[1].length;
|
|
6226
|
+
}
|
|
6227
|
+
function serializeLike(before, value) {
|
|
6228
|
+
const crlf = before.includes("\r\n");
|
|
6229
|
+
const trailing = /\r?\n$/.test(before);
|
|
6230
|
+
let text = JSON.stringify(value, null, detectJsonIndent(before));
|
|
6231
|
+
if (trailing) text += "\n";
|
|
6232
|
+
return crlf ? text.replace(/\n/g, "\r\n") : text;
|
|
6233
|
+
}
|
|
6234
|
+
var MERGERS = {
|
|
6235
|
+
"package.json": mergePackageJson,
|
|
6236
|
+
"axis.config.json": mergeAxisConfigJson
|
|
6237
|
+
};
|
|
6238
|
+
function planTemplateFileContent(relPath, templateContent, before) {
|
|
6239
|
+
if (before === void 0) return { action: "created", content: templateContent };
|
|
6240
|
+
const merger = MERGERS[relPath.replace(/^\.\//, "")];
|
|
6241
|
+
if (!merger) return { action: "overwritten", content: templateContent };
|
|
6242
|
+
const user = parseObject(before);
|
|
6243
|
+
const template = parseObject(templateContent);
|
|
6244
|
+
if (!user || !template) {
|
|
6245
|
+
return {
|
|
6246
|
+
action: "overwritten",
|
|
6247
|
+
content: templateContent,
|
|
6248
|
+
note: `\uAE30\uC874 ${relPath} \uC744 JSON \uAC1D\uCCB4\uB85C \uC77D\uC744 \uC218 \uC5C6\uC5B4 \uD15C\uD50C\uB9BF \uB0B4\uC6A9\uC73C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4`
|
|
6249
|
+
};
|
|
6250
|
+
}
|
|
6251
|
+
return { action: "merged", content: serializeLike(before, merger(user, template)) };
|
|
6252
|
+
}
|
|
6253
|
+
function planTemplateFiles(baseDir, files, extraPaths = []) {
|
|
6254
|
+
const dests = files.map((file) => resolveTemplatePath(baseDir, file.path));
|
|
6255
|
+
assertTemplatePaths(baseDir, extraPaths);
|
|
6256
|
+
return files.map((file, i) => {
|
|
6257
|
+
const dest = dests[i];
|
|
6258
|
+
const before = existsSync9(dest) ? readFileSync10(dest, "utf8") : void 0;
|
|
6259
|
+
return { path: file.path, dest, before, ...planTemplateFileContent(file.path, file.content, before) };
|
|
6260
|
+
});
|
|
6261
|
+
}
|
|
6262
|
+
var TemplateApplyError = class extends Error {
|
|
6263
|
+
constructor(message, restored, unrestored) {
|
|
6264
|
+
super(message);
|
|
6265
|
+
this.restored = restored;
|
|
6266
|
+
this.unrestored = unrestored;
|
|
6267
|
+
this.name = "TemplateApplyError";
|
|
6268
|
+
}
|
|
6269
|
+
};
|
|
6270
|
+
function writeTemplateFiles(plan) {
|
|
6271
|
+
const done = [];
|
|
6272
|
+
const madeDirs = [];
|
|
6273
|
+
try {
|
|
6274
|
+
for (const item of plan) {
|
|
6275
|
+
const dir = path9.dirname(item.dest);
|
|
6276
|
+
if (!existsSync9(dir)) {
|
|
6277
|
+
const fresh = [];
|
|
6278
|
+
for (let d = dir; !existsSync9(d); d = path9.dirname(d)) fresh.unshift(d);
|
|
6279
|
+
mkdirSync2(dir, { recursive: true });
|
|
6280
|
+
madeDirs.push(...fresh);
|
|
6281
|
+
}
|
|
6282
|
+
writeFileSync2(item.dest, item.content);
|
|
6283
|
+
done.push(item);
|
|
6284
|
+
}
|
|
6285
|
+
} catch (err) {
|
|
6286
|
+
const restored = [];
|
|
6287
|
+
const unrestored = [];
|
|
6288
|
+
const failed = plan[done.length];
|
|
6289
|
+
const targets = failed ? [...done, failed] : done;
|
|
6290
|
+
for (const item of targets.reverse()) {
|
|
6291
|
+
try {
|
|
6292
|
+
if (item.before === void 0) {
|
|
6293
|
+
if (existsSync9(item.dest)) unlinkSync(item.dest);
|
|
6294
|
+
} else {
|
|
6295
|
+
writeFileSync2(item.dest, item.before);
|
|
6296
|
+
}
|
|
6297
|
+
restored.push(item.path);
|
|
6298
|
+
} catch {
|
|
6299
|
+
unrestored.push(item.path);
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
for (const d of madeDirs.reverse()) {
|
|
6303
|
+
try {
|
|
6304
|
+
if (existsSync9(d) && readdirSync3(d).length === 0) rmdirSync(d);
|
|
6305
|
+
} catch {
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
6309
|
+
const tail = unrestored.length > 0 ? ` \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD55C \uD30C\uC77C: ${unrestored.join(", ")}` : "";
|
|
6310
|
+
throw new TemplateApplyError(
|
|
6311
|
+
`\uD15C\uD50C\uB9BF \uD30C\uC77C\uC744 \uC4F0\uB294 \uB3C4\uC911 \uC2E4\uD328\uD574 \uAC74\uB4DC\uB9B0 \uD30C\uC77C ${restored.length}\uAC1C\uB97C \uC6D0\uB798\uB300\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4(${reason}).${tail}`,
|
|
6312
|
+
restored.reverse(),
|
|
6313
|
+
unrestored
|
|
6314
|
+
);
|
|
6315
|
+
}
|
|
6316
|
+
}
|
|
6317
|
+
|
|
6055
6318
|
// src/site.ts
|
|
6056
6319
|
var AXIS_SITE_URL2 = "https://axis-design-system.pages.dev";
|
|
6057
6320
|
|
|
@@ -6105,24 +6368,18 @@ async function handleGetTemplate(params) {
|
|
|
6105
6368
|
}
|
|
6106
6369
|
async function handleApplyTemplate(params) {
|
|
6107
6370
|
const detail = await fetchTemplateDetail(params.name);
|
|
6108
|
-
const baseDir =
|
|
6371
|
+
const baseDir = path10.resolve(params.targetDir);
|
|
6109
6372
|
const installCommand = detectInstallCommand(baseDir);
|
|
6110
|
-
const
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
}
|
|
6118
|
-
files.push({
|
|
6119
|
-
path: file.path,
|
|
6120
|
-
action: exists ? "overwritten" : "created"
|
|
6121
|
-
});
|
|
6122
|
-
}
|
|
6373
|
+
const plan = planTemplateFiles(baseDir, detail.files, (detail.postInstall ?? []).map((p) => p.file));
|
|
6374
|
+
if (!params.dryRun) writeTemplateFiles(plan);
|
|
6375
|
+
const files = plan.map((item) => ({
|
|
6376
|
+
path: item.path,
|
|
6377
|
+
action: item.action,
|
|
6378
|
+
...item.note ? { note: item.note } : {}
|
|
6379
|
+
}));
|
|
6123
6380
|
if (!params.dryRun && detail.postInstall?.length) {
|
|
6124
6381
|
for (const patch of detail.postInstall) {
|
|
6125
|
-
const target =
|
|
6382
|
+
const target = resolveTemplatePath(baseDir, patch.file);
|
|
6126
6383
|
if (!await fs6.pathExists(target)) continue;
|
|
6127
6384
|
if (patch.type === "replace" && patch.search && patch.value) {
|
|
6128
6385
|
const content = await fs6.readFile(target, "utf-8");
|
|
@@ -6150,10 +6407,11 @@ async function handleApplyTemplate(params) {
|
|
|
6150
6407
|
}
|
|
6151
6408
|
async function handleDiffTemplate(params) {
|
|
6152
6409
|
const detail = await fetchTemplateDetail(params.name);
|
|
6153
|
-
const baseDir =
|
|
6410
|
+
const baseDir = path10.resolve(params.targetDir || ".");
|
|
6154
6411
|
const entries = [];
|
|
6155
|
-
|
|
6156
|
-
|
|
6412
|
+
const localPaths = detail.files.map((file) => resolveTemplatePath(baseDir, file.path));
|
|
6413
|
+
for (const [i, file] of detail.files.entries()) {
|
|
6414
|
+
const localPath = localPaths[i];
|
|
6157
6415
|
if (!await fs6.pathExists(localPath)) {
|
|
6158
6416
|
entries.push({ path: file.path, status: "added" });
|
|
6159
6417
|
continue;
|
|
@@ -6241,9 +6499,9 @@ function brandActivationResult(check) {
|
|
|
6241
6499
|
};
|
|
6242
6500
|
}
|
|
6243
6501
|
async function handleCheckProject(params) {
|
|
6244
|
-
const baseDir =
|
|
6502
|
+
const baseDir = path10.resolve(params.targetDir || ".");
|
|
6245
6503
|
const results = [];
|
|
6246
|
-
const configExists = await fs6.pathExists(
|
|
6504
|
+
const configExists = await fs6.pathExists(path10.join(baseDir, "axis.config.json"));
|
|
6247
6505
|
results.push({
|
|
6248
6506
|
name: "axis.config.json",
|
|
6249
6507
|
severity: configExists ? "pass" : "fail",
|
|
@@ -6260,7 +6518,7 @@ async function handleCheckProject(params) {
|
|
|
6260
6518
|
];
|
|
6261
6519
|
let utilsFound = false;
|
|
6262
6520
|
for (const candidate of utilsCandidates) {
|
|
6263
|
-
const fullPath =
|
|
6521
|
+
const fullPath = path10.join(baseDir, candidate);
|
|
6264
6522
|
if (await fs6.pathExists(fullPath)) {
|
|
6265
6523
|
const content2 = await fs6.readFile(fullPath, "utf-8");
|
|
6266
6524
|
const hasCn = content2.includes("function cn");
|
|
@@ -6351,9 +6609,15 @@ function formatApplyTemplateResult(result) {
|
|
|
6351
6609
|
`);
|
|
6352
6610
|
if (result.files.length > 0) {
|
|
6353
6611
|
lines.push("### \uD30C\uC77C", "");
|
|
6612
|
+
const label = {
|
|
6613
|
+
created: "\uC0DD\uC131",
|
|
6614
|
+
overwritten: "\uB36E\uC5B4\uC4F0\uAE30",
|
|
6615
|
+
merged: "\uD569\uCE58\uAE30: \uAE30\uC874 \uD544\uB4DC\uB97C \uB450\uACE0 \uD15C\uD50C\uB9BF \uD0A4\uB97C \uD569\uCE68"
|
|
6616
|
+
};
|
|
6354
6617
|
for (const f of result.files) {
|
|
6355
6618
|
const icon = f.action === "created" ? "+" : "~";
|
|
6356
|
-
lines.push(`- ${icon} ${f.path} (${f.action
|
|
6619
|
+
lines.push(`- ${icon} ${f.path} (${label[f.action]})`);
|
|
6620
|
+
if (f.note) lines.push(` - ! ${f.note}`);
|
|
6357
6621
|
}
|
|
6358
6622
|
}
|
|
6359
6623
|
const deps = Object.entries(result.dependencies);
|
|
@@ -6405,10 +6669,10 @@ function formatCheckProjectResult(result) {
|
|
|
6405
6669
|
}
|
|
6406
6670
|
|
|
6407
6671
|
// src/tools/brand.ts
|
|
6408
|
-
import
|
|
6672
|
+
import path11 from "path";
|
|
6409
6673
|
var TOKENS_INSTALL_COMMAND = addCommandFor("pnpm install", { [TOKENS_PACKAGE]: `^${TOKENS_DEPENDENCY_MIN_VERSION}` });
|
|
6410
6674
|
function baseDirOf(targetDir) {
|
|
6411
|
-
return
|
|
6675
|
+
return path11.resolve(targetDir || process.cwd());
|
|
6412
6676
|
}
|
|
6413
6677
|
function tokensInstallGuideFor(targetDir) {
|
|
6414
6678
|
return dependencyInstallGuide(baseDirOf(targetDir), TOKENS_PACKAGE, `^${TOKENS_DEPENDENCY_MIN_VERSION}`);
|
|
@@ -6696,10 +6960,10 @@ server.tool(
|
|
|
6696
6960
|
{
|
|
6697
6961
|
path: z.string().describe("\uD1A0\uD070 \uACBD\uB85C (\uC608: colors.primary, spacing.4, control.h.md) \uB610\uB294 CSS \uBCC0\uC218 \uC774\uB984 (\uC608: --axis-control-h-md)")
|
|
6698
6962
|
},
|
|
6699
|
-
async ({ path:
|
|
6963
|
+
async ({ path: path12 }) => {
|
|
6700
6964
|
try {
|
|
6701
|
-
const token = handleGetToken({ path:
|
|
6702
|
-
const formatted = formatTokenDetail(token,
|
|
6965
|
+
const token = handleGetToken({ path: path12 });
|
|
6966
|
+
const formatted = formatTokenDetail(token, path12);
|
|
6703
6967
|
return {
|
|
6704
6968
|
content: [
|
|
6705
6969
|
{
|