@axis-ds/mcp 1.3.2 → 1.3.4
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 +1 -1
- package/dist/index.js +660 -108
- package/dist/registry/agentic-message-bubble.json +1 -1
- package/dist/registry/agentic-plan-card.json +1 -1
- package/dist/registry/agentic-run-progress.json +1 -1
- package/dist/registry/agentic-step-timeline.json +1 -1
- package/dist/registry/agentic-streaming-text.json +1 -1
- package/dist/registry/agentic-surface-renderer.json +1 -1
- package/dist/registry/agentic-thinking-indicator.json +1 -1
- package/dist/registry/agentic-tool-call-card.json +1 -1
- package/dist/registry/button.json +1 -1
- package/dist/registry/card.json +1 -1
- package/dist/registry/dialog.json +1 -1
- package/dist/registry/index.json +15 -15
- package/dist/registry/input.json +1 -1
- package/dist/registry/registry.json +15 -15
- package/dist/registry/select.json +1 -1
- package/dist/registry/toast.json +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -71,7 +71,7 @@ function getTokenStats() {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// ../axis-registry-core/src/add/add.ts
|
|
74
|
-
import { existsSync as existsSync5, readFileSync as
|
|
74
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
75
75
|
import path5 from "path";
|
|
76
76
|
import fs3 from "fs-extra";
|
|
77
77
|
|
|
@@ -597,7 +597,7 @@ function createPinnedFetch(options = {}) {
|
|
|
597
597
|
const judge = options.judge ?? blockedAddressReason;
|
|
598
598
|
const send = options.request ?? httpsRequest;
|
|
599
599
|
const maxBytes = options.maxBytes ?? PINNED_FETCH_MAX_BYTES;
|
|
600
|
-
return (input, init) => new Promise((
|
|
600
|
+
return (input, init) => new Promise((resolve5, reject) => {
|
|
601
601
|
let url;
|
|
602
602
|
try {
|
|
603
603
|
url = new URL(input);
|
|
@@ -638,7 +638,7 @@ function createPinnedFetch(options = {}) {
|
|
|
638
638
|
if (failed) return;
|
|
639
639
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
640
640
|
const status = res.statusCode ?? 0;
|
|
641
|
-
|
|
641
|
+
resolve5({ ok: status >= 200 && status < 300, status, text: async () => body });
|
|
642
642
|
});
|
|
643
643
|
}
|
|
644
644
|
);
|
|
@@ -865,7 +865,7 @@ var RegistryClient = class {
|
|
|
865
865
|
};
|
|
866
866
|
|
|
867
867
|
// ../axis-registry-core/src/project.ts
|
|
868
|
-
import { existsSync as existsSync2 } from "fs";
|
|
868
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "fs";
|
|
869
869
|
import path3 from "path";
|
|
870
870
|
function detectInstallCommand(baseDir) {
|
|
871
871
|
if (existsSync2(path3.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
@@ -885,10 +885,92 @@ function hasDependency(pkg, name) {
|
|
|
885
885
|
function isPlainObject(value) {
|
|
886
886
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
887
887
|
}
|
|
888
|
+
function addCommandFor(installCommand, deps) {
|
|
889
|
+
const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
|
|
890
|
+
if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
|
|
891
|
+
if (installCommand.startsWith("npm")) return `npm install ${specs}`;
|
|
892
|
+
return `pnpm add ${specs}`;
|
|
893
|
+
}
|
|
894
|
+
var GLOBAL_CSS_CANDIDATES = [
|
|
895
|
+
"app/globals.css",
|
|
896
|
+
"src/app/globals.css",
|
|
897
|
+
"styles/globals.css",
|
|
898
|
+
"src/styles/globals.css",
|
|
899
|
+
"globals.css"
|
|
900
|
+
];
|
|
901
|
+
function isFile(file) {
|
|
902
|
+
try {
|
|
903
|
+
return statSync(file).isFile();
|
|
904
|
+
} catch {
|
|
905
|
+
return false;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
var ROOT_LAYOUT_FILES = [
|
|
909
|
+
"app/layout.tsx",
|
|
910
|
+
"app/layout.jsx",
|
|
911
|
+
"app/layout.js",
|
|
912
|
+
"src/app/layout.tsx",
|
|
913
|
+
"src/app/layout.jsx",
|
|
914
|
+
"src/app/layout.js",
|
|
915
|
+
"pages/_app.tsx",
|
|
916
|
+
"pages/_app.jsx",
|
|
917
|
+
"pages/_document.tsx",
|
|
918
|
+
"pages/_document.jsx",
|
|
919
|
+
"src/pages/_app.tsx",
|
|
920
|
+
"src/pages/_app.jsx",
|
|
921
|
+
"src/pages/_document.tsx",
|
|
922
|
+
"src/pages/_document.jsx"
|
|
923
|
+
];
|
|
924
|
+
function exactVersionOf(version) {
|
|
925
|
+
if (typeof version !== "string") return void 0;
|
|
926
|
+
const v = version.trim();
|
|
927
|
+
if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
|
|
928
|
+
return v;
|
|
929
|
+
}
|
|
930
|
+
function findInstalledPackage(baseDirInput, name) {
|
|
931
|
+
let dir = path3.resolve(baseDirInput);
|
|
932
|
+
for (; ; ) {
|
|
933
|
+
const pkgDir = path3.join(dir, "node_modules", ...name.split("/"));
|
|
934
|
+
const file = path3.join(pkgDir, "package.json");
|
|
935
|
+
if (isFile(file)) {
|
|
936
|
+
let version;
|
|
937
|
+
try {
|
|
938
|
+
const parsed = JSON.parse(readFileSync3(file, "utf8"));
|
|
939
|
+
version = isPlainObject(parsed) ? exactVersionOf(parsed.version) : void 0;
|
|
940
|
+
} catch {
|
|
941
|
+
version = void 0;
|
|
942
|
+
}
|
|
943
|
+
return { dir: pkgDir, version };
|
|
944
|
+
}
|
|
945
|
+
const parent = path3.dirname(dir);
|
|
946
|
+
if (parent === dir) return void 0;
|
|
947
|
+
dir = parent;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
function isPnpProject(baseDirInput) {
|
|
951
|
+
let dir = path3.resolve(baseDirInput);
|
|
952
|
+
for (; ; ) {
|
|
953
|
+
if (isFile(path3.join(dir, ".pnp.cjs")) || isFile(path3.join(dir, ".pnp.js"))) return true;
|
|
954
|
+
const parent = path3.dirname(dir);
|
|
955
|
+
if (parent === dir) return false;
|
|
956
|
+
dir = parent;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
function compareExactVersions(a, b) {
|
|
960
|
+
const parse = (v) => {
|
|
961
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?/.exec(v.trim());
|
|
962
|
+
return m ? { core: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] !== void 0 } : void 0;
|
|
963
|
+
};
|
|
964
|
+
const x = parse(a);
|
|
965
|
+
const y = parse(b);
|
|
966
|
+
if (!x || !y) return void 0;
|
|
967
|
+
for (let i = 0; i < 3; i++) if (x.core[i] !== y.core[i]) return x.core[i] - y.core[i];
|
|
968
|
+
return Number(y.pre) - Number(x.pre);
|
|
969
|
+
}
|
|
888
970
|
|
|
889
971
|
// ../axis-registry-core/src/template/tailwind-core.ts
|
|
890
|
-
import { existsSync as existsSync3, readFileSync as
|
|
891
|
-
import { join as join2, resolve } from "path";
|
|
972
|
+
import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
973
|
+
import { extname, join as join2, resolve } from "path";
|
|
892
974
|
function hasDependency2(pkg, name) {
|
|
893
975
|
for (const field of ["dependencies", "devDependencies"]) {
|
|
894
976
|
const deps = pkg[field];
|
|
@@ -975,7 +1057,7 @@ function detectTailwind(baseDirInput, pkg) {
|
|
|
975
1057
|
const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
|
|
976
1058
|
const declaredMajor = bounds?.lower;
|
|
977
1059
|
try {
|
|
978
|
-
const installed = JSON.parse(
|
|
1060
|
+
const installed = JSON.parse(readFileSync4(installedFile, "utf8"));
|
|
979
1061
|
const version = isPlainObject2(installed) ? installed.version : void 0;
|
|
980
1062
|
const major = majorFromVersion(version);
|
|
981
1063
|
if (major !== void 0) {
|
|
@@ -1023,18 +1105,57 @@ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/s
|
|
|
1023
1105
|
function findTokensCssImport(css) {
|
|
1024
1106
|
return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
|
|
1025
1107
|
}
|
|
1108
|
+
var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
|
|
1109
|
+
var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
|
|
1110
|
+
function findLayoutTokensCssImport(baseDirInput) {
|
|
1111
|
+
const baseDir = resolve(baseDirInput);
|
|
1112
|
+
for (const candidate of ROOT_LAYOUT_FILES) {
|
|
1113
|
+
const file = join2(baseDir, candidate);
|
|
1114
|
+
if (!existsSync3(file)) continue;
|
|
1115
|
+
let text;
|
|
1116
|
+
try {
|
|
1117
|
+
text = readFileSync4(file, "utf8");
|
|
1118
|
+
} catch {
|
|
1119
|
+
continue;
|
|
1120
|
+
}
|
|
1121
|
+
const m = TOKENS_CSS_JS_IMPORT.exec(stripJsComments(text));
|
|
1122
|
+
if (m) return { file: candidate, spec: m[2] };
|
|
1123
|
+
}
|
|
1124
|
+
return void 0;
|
|
1125
|
+
}
|
|
1026
1126
|
function checkGlobalsCss(baseDirInput) {
|
|
1027
1127
|
const baseDir = resolve(baseDirInput);
|
|
1028
1128
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
1029
1129
|
const file = join2(baseDir, candidate);
|
|
1030
1130
|
if (!existsSync3(file)) continue;
|
|
1031
|
-
const content =
|
|
1032
|
-
|
|
1033
|
-
return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
1034
|
-
}
|
|
1131
|
+
const content = readFileSync4(file, "utf8");
|
|
1132
|
+
const css = stripCssComments(content);
|
|
1035
1133
|
const imported = findTokensCssImport(content);
|
|
1036
|
-
|
|
1037
|
-
|
|
1134
|
+
let pass;
|
|
1135
|
+
if (imported !== void 0) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
|
|
1136
|
+
else if (AXIS_VARIABLE_DEFINITION.test(css)) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218(--axis-*)\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`;
|
|
1137
|
+
else {
|
|
1138
|
+
const layout = findLayoutTokensCssImport(baseDir);
|
|
1139
|
+
if (layout) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${layout.file}\uC758 ${layout.spec} import)`;
|
|
1140
|
+
}
|
|
1141
|
+
if (pass !== void 0) {
|
|
1142
|
+
const tailwind = detectTailwind(baseDir, readPackageJson(baseDir));
|
|
1143
|
+
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
1144
|
+
if (!tailwind4 && findCreateNextAppDefaults(content).some((d) => d.includes("font-family: Arial"))) {
|
|
1145
|
+
return {
|
|
1146
|
+
name: "globals.css",
|
|
1147
|
+
severity: "warn",
|
|
1148
|
+
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)`
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
return { name: "globals.css", severity: "pass", message: pass };
|
|
1152
|
+
}
|
|
1153
|
+
if (css.includes("--background") && css.includes("--primary")) {
|
|
1154
|
+
return {
|
|
1155
|
+
name: "globals.css",
|
|
1156
|
+
severity: "warn",
|
|
1157
|
+
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`
|
|
1158
|
+
};
|
|
1038
1159
|
}
|
|
1039
1160
|
return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
|
|
1040
1161
|
}
|
|
@@ -1097,7 +1218,7 @@ function exactVersion(version) {
|
|
|
1097
1218
|
}
|
|
1098
1219
|
function installedVersion(baseDir, name) {
|
|
1099
1220
|
try {
|
|
1100
|
-
const parsed = JSON.parse(
|
|
1221
|
+
const parsed = JSON.parse(readFileSync4(join2(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
|
|
1101
1222
|
return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
|
|
1102
1223
|
} catch {
|
|
1103
1224
|
return void 0;
|
|
@@ -1166,8 +1287,10 @@ var CREATE_NEXT_APP_DEFAULTS = [
|
|
|
1166
1287
|
},
|
|
1167
1288
|
{
|
|
1168
1289
|
prefix: "body",
|
|
1169
|
-
|
|
1170
|
-
|
|
1290
|
+
// WI-0070: create-next-app 의 body `font-family: Arial, Helvetica, sans-serif` 도 같은 특징으로 봅니다. 레이어 밖 규칙이라
|
|
1291
|
+
// AXIS 글꼴(Pretendard, html 에 적용)을 이기고 Button 등이 `font-family: inherit` 로 Arial 을 물려받습니다.
|
|
1292
|
+
pattern: /(?<![\w-])(?:(background|background-color|color)\s*:\s*var\(\s*(--(?:background|foreground))\s*\)|font-family\s*:\s*Arial\b)/g,
|
|
1293
|
+
item: (m) => m[1] !== void 0 ? `${m[1]}: var(${m[2]})` : "font-family: Arial"
|
|
1171
1294
|
}
|
|
1172
1295
|
];
|
|
1173
1296
|
function findCreateNextAppDefaults(css) {
|
|
@@ -1223,9 +1346,54 @@ function hasTokensPresetReference(source) {
|
|
|
1223
1346
|
return PRESET_REFERENCE.test(stripJsComments(source));
|
|
1224
1347
|
}
|
|
1225
1348
|
var PRESET_PASS_SUFFIX = `\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${TOKENS_TAILWIND3_PRESET} preset)`;
|
|
1349
|
+
var TOKENS_CJS_PRESET_FIXED_VERSION = "1.7.0";
|
|
1350
|
+
var TOKENS_TAILWIND3_CJS_REQUIRE = `require("${TOKENS_TAILWIND3_PRESET}").default`;
|
|
1351
|
+
var PRESET_REQUIRE_CALL = /\brequire\s*\(\s*(["'])@axis-ds\/tokens\/tailwind\1\s*\)/g;
|
|
1352
|
+
var DEFAULT_ACCESS_AHEAD = /^\s*(?:\.\s*default\b|\[\s*["']default["']\s*\])/;
|
|
1353
|
+
function hasBareCjsPresetRequire(code) {
|
|
1354
|
+
for (const m of code.matchAll(PRESET_REQUIRE_CALL)) {
|
|
1355
|
+
const start = m.index ?? 0;
|
|
1356
|
+
const end = start + m[0].length;
|
|
1357
|
+
if (DEFAULT_ACCESS_AHEAD.test(code.slice(end))) continue;
|
|
1358
|
+
const before = code.slice(0, start);
|
|
1359
|
+
if (/\b(?:const|let|var)\s*\{[^{}]*\}\s*=\s*$/.test(before)) continue;
|
|
1360
|
+
const bound = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*$/.exec(before);
|
|
1361
|
+
if (!bound) return true;
|
|
1362
|
+
const ident = escapeRegExp(bound[1]);
|
|
1363
|
+
const rest = code.slice(0, bound.index) + code.slice(end);
|
|
1364
|
+
const bareUse = new RegExp(`(?<![\\w$.])${ident}(?![\\w$])(?!\\s*(?:\\.\\s*default\\b|\\[\\s*["']default["']\\s*\\]))`);
|
|
1365
|
+
if (bareUse.test(rest)) return true;
|
|
1366
|
+
}
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
function isCommonJsConfig(file, source) {
|
|
1370
|
+
return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
|
|
1371
|
+
}
|
|
1372
|
+
function packageVersionGate(baseDirInput, pkg, name, min) {
|
|
1373
|
+
const baseDir = resolve(baseDirInput);
|
|
1374
|
+
if (!isPnpProject(baseDir)) {
|
|
1375
|
+
const installed = findInstalledPackage(baseDir, name)?.version;
|
|
1376
|
+
if (installed !== void 0) {
|
|
1377
|
+
const cmp = compareExactVersions(installed, min);
|
|
1378
|
+
if (cmp !== void 0) return { status: cmp >= 0 ? "ok" : "below", source: "installed", value: installed };
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
const declared = pkg ? hasDependency2(pkg, name) : void 0;
|
|
1382
|
+
if (declared !== void 0) {
|
|
1383
|
+
const atLeast = rangeLowerAtLeast(declared, min);
|
|
1384
|
+
if (atLeast !== void 0) return { status: atLeast ? "ok" : "below", source: "declared", value: declared };
|
|
1385
|
+
return { status: "unknown", source: "declared", value: declared };
|
|
1386
|
+
}
|
|
1387
|
+
return { status: "unknown", source: "none" };
|
|
1388
|
+
}
|
|
1389
|
+
function versionGateLabel(gate) {
|
|
1390
|
+
if (gate.source === "installed") return `\uC124\uCE58\uBCF8 ${gate.value}`;
|
|
1391
|
+
if (gate.source === "declared") return `\uC120\uC5B8 ${gate.value}`;
|
|
1392
|
+
return "\uC124\uCE58\uBCF8 \xB7 \uC120\uC5B8 \uC5C6\uC74C";
|
|
1393
|
+
}
|
|
1226
1394
|
function readPackageJson(baseDir) {
|
|
1227
1395
|
try {
|
|
1228
|
-
const parsed = JSON.parse(
|
|
1396
|
+
const parsed = JSON.parse(readFileSync4(join2(baseDir, "package.json"), "utf8"));
|
|
1229
1397
|
return isPlainObject2(parsed) ? parsed : void 0;
|
|
1230
1398
|
} catch {
|
|
1231
1399
|
return void 0;
|
|
@@ -1264,7 +1432,7 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
1264
1432
|
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
1265
1433
|
const file = join2(baseDir, candidate);
|
|
1266
1434
|
if (!existsSync3(file)) continue;
|
|
1267
|
-
const css =
|
|
1435
|
+
const css = readFileSync4(file, "utf8");
|
|
1268
1436
|
if (!hasTailwindImport(css)) {
|
|
1269
1437
|
return {
|
|
1270
1438
|
name: "tailwind.config",
|
|
@@ -1293,29 +1461,307 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
1293
1461
|
message: `${label}: @import "tailwindcss" \uB97C \uD655\uC778\uD560 CSS \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4`
|
|
1294
1462
|
};
|
|
1295
1463
|
}
|
|
1296
|
-
const
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
const content =
|
|
1300
|
-
const hasTokens = content.includes("--background") || content.includes("hsl(var(");
|
|
1301
|
-
if (hasTokens) {
|
|
1302
|
-
return { name: "tailwind.config", severity: "pass", message: "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4" };
|
|
1303
|
-
}
|
|
1464
|
+
for (const file of TAILWIND_CONFIG_FILES) {
|
|
1465
|
+
const path11 = join2(baseDir, file);
|
|
1466
|
+
if (!existsSync3(path11)) continue;
|
|
1467
|
+
const content = readFileSync4(path11, "utf8");
|
|
1304
1468
|
if (hasTokensPresetReference(content)) {
|
|
1305
|
-
|
|
1469
|
+
const code = stripJsComments(content);
|
|
1470
|
+
if (isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code)) {
|
|
1471
|
+
const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION);
|
|
1472
|
+
if (gate.status !== "ok") {
|
|
1473
|
+
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`;
|
|
1474
|
+
return {
|
|
1475
|
+
name: "tailwind.config",
|
|
1476
|
+
severity: "warn",
|
|
1477
|
+
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`
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
|
|
1306
1482
|
}
|
|
1307
|
-
|
|
1483
|
+
const ownMapping = content.includes("--background") || content.includes("hsl(var(");
|
|
1484
|
+
return {
|
|
1485
|
+
name: "tailwind.config",
|
|
1486
|
+
severity: "warn",
|
|
1487
|
+
message: ownMapping ? `${file}\uC5D0 AXIS preset(${TOKENS_TAILWIND3_PRESET})\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC790\uCCB4 CSS \uBCC0\uC218 \uB9E4\uD551\uB9CC \uC788\uC74C, presets \uC5D0 \uB123\uC73C\uC138\uC694)` : `${file}\uC5D0 AXIS preset(${TOKENS_TAILWIND3_PRESET})\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (presets \uC5D0 \uB123\uC73C\uC138\uC694)`
|
|
1488
|
+
};
|
|
1308
1489
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1490
|
+
return { name: "tailwind.config", severity: "fail", message: "tailwind.config \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
|
|
1491
|
+
}
|
|
1492
|
+
function readAxisConfigLike(baseDir) {
|
|
1493
|
+
try {
|
|
1494
|
+
const parsed = JSON.parse(readFileSync4(join2(baseDir, "axis.config.json"), "utf8"));
|
|
1495
|
+
return isPlainObject2(parsed) ? parsed : void 0;
|
|
1496
|
+
} catch {
|
|
1497
|
+
return void 0;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
function contentGlobToRegExp(glob) {
|
|
1501
|
+
const g = glob.trim().replace(/^\.\//, "");
|
|
1502
|
+
let re = "";
|
|
1503
|
+
for (let i = 0; i < g.length; i++) {
|
|
1504
|
+
const c = g[i];
|
|
1505
|
+
if (c === "*") {
|
|
1506
|
+
if (g[i + 1] === "*") {
|
|
1507
|
+
const slash = g[i + 2] === "/";
|
|
1508
|
+
re += slash ? "(?:.*/)?" : ".*";
|
|
1509
|
+
i += slash ? 2 : 1;
|
|
1510
|
+
} else re += "[^/]*";
|
|
1511
|
+
} else if (c === "?") re += "[^/]";
|
|
1512
|
+
else if (c === "{") {
|
|
1513
|
+
const end = g.indexOf("}", i);
|
|
1514
|
+
if (end === -1) {
|
|
1515
|
+
re += "\\{";
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
re += `(?:${g.slice(i + 1, end).split(",").map((part) => part.replace(/[.+^$()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*")).join("|")})`;
|
|
1519
|
+
i = end;
|
|
1520
|
+
} else if (c === "[") {
|
|
1521
|
+
const end = g.indexOf("]", i);
|
|
1522
|
+
if (end === -1) re += "\\[";
|
|
1523
|
+
else {
|
|
1524
|
+
re += g.slice(i, end + 1);
|
|
1525
|
+
i = end;
|
|
1314
1526
|
}
|
|
1315
|
-
|
|
1527
|
+
} else re += c.replace(/[.+^$()|\\]/g, "\\$&");
|
|
1528
|
+
}
|
|
1529
|
+
return new RegExp(`^${re}$`);
|
|
1530
|
+
}
|
|
1531
|
+
function balancedSlice(src, start) {
|
|
1532
|
+
const open = src[start];
|
|
1533
|
+
const close = open === "[" ? "]" : "}";
|
|
1534
|
+
let depth = 0;
|
|
1535
|
+
for (let i = start; i < src.length; i++) {
|
|
1536
|
+
const c = src[i];
|
|
1537
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
1538
|
+
let j = i + 1;
|
|
1539
|
+
while (j < src.length && src[j] !== c) j += src[j] === "\\" ? 2 : 1;
|
|
1540
|
+
i = j;
|
|
1541
|
+
continue;
|
|
1316
1542
|
}
|
|
1543
|
+
if (c === open) depth++;
|
|
1544
|
+
else if (c === close && --depth === 0) return src.slice(start, i + 1);
|
|
1317
1545
|
}
|
|
1318
|
-
return
|
|
1546
|
+
return void 0;
|
|
1547
|
+
}
|
|
1548
|
+
function stringLiterals(src) {
|
|
1549
|
+
return [...src.matchAll(/(["'`])((?:\\.|(?!\1)[^\\])*)\1/g)].map((m) => m[2]).filter((s) => !s.includes("${"));
|
|
1550
|
+
}
|
|
1551
|
+
function readTailwindContent(source) {
|
|
1552
|
+
const src = stripJsComments(source);
|
|
1553
|
+
const key = /\bcontent\s*:\s*/g;
|
|
1554
|
+
for (const m of src.matchAll(key)) {
|
|
1555
|
+
let at = (m.index ?? 0) + m[0].length;
|
|
1556
|
+
let block = src[at] === "[" || src[at] === "{" ? balancedSlice(src, at) : void 0;
|
|
1557
|
+
if (block === void 0) continue;
|
|
1558
|
+
if (block.startsWith("{")) {
|
|
1559
|
+
const files = /\bfiles\s*:\s*\[/.exec(block);
|
|
1560
|
+
if (!files) return { globs: [], dynamic: true };
|
|
1561
|
+
at = files.index + files[0].length - 1;
|
|
1562
|
+
block = balancedSlice(block, at);
|
|
1563
|
+
if (block === void 0) return { globs: [], dynamic: true };
|
|
1564
|
+
}
|
|
1565
|
+
const inner = block.slice(1, -1);
|
|
1566
|
+
const globs = stringLiterals(inner);
|
|
1567
|
+
const rest = inner.replace(/(["'`])((?:\\.|(?!\1)[^\\])*)\1/g, "").replace(/[\s,]/g, "");
|
|
1568
|
+
return { globs, dynamic: rest !== "" };
|
|
1569
|
+
}
|
|
1570
|
+
return void 0;
|
|
1571
|
+
}
|
|
1572
|
+
function normalizeRel(p) {
|
|
1573
|
+
const s = p.trim().replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
1574
|
+
if (s === "" || s.startsWith("../") || s.startsWith("/") || /^[A-Za-z]:/.test(s)) return void 0;
|
|
1575
|
+
return s;
|
|
1576
|
+
}
|
|
1577
|
+
function inspectTailwindContent(baseDirInput) {
|
|
1578
|
+
const baseDir = resolve(baseDirInput);
|
|
1579
|
+
const pkg = readPackageJson(baseDir);
|
|
1580
|
+
const tailwind = detectTailwind(baseDir, pkg);
|
|
1581
|
+
if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
|
|
1582
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
|
|
1583
|
+
if (configFile === void 0) return null;
|
|
1584
|
+
const targets = [];
|
|
1585
|
+
const componentsDir = readAxisConfigLike(baseDir)?.componentsDir;
|
|
1586
|
+
const rel2 = typeof componentsDir === "string" ? normalizeRel(componentsDir) : void 0;
|
|
1587
|
+
if (rel2 !== void 0) {
|
|
1588
|
+
targets.push({ label: `componentsDir(${componentsDir})`, sample: `${rel2}/button.tsx`, suggest: `./${rel2}/**/*.{ts,tsx}` });
|
|
1589
|
+
}
|
|
1590
|
+
for (const name of TAILWIND4_COMPONENT_PACKAGES) {
|
|
1591
|
+
if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
|
|
1592
|
+
targets.push({ label: name, sample: `node_modules/${name}/dist/index.js`, suggest: `./node_modules/${name}/dist/**/*.{js,mjs}` });
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
if (targets.length === 0) return null;
|
|
1596
|
+
const read = readTailwindContent(readFileSync4(join2(baseDir, configFile), "utf8"));
|
|
1597
|
+
const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
|
|
1598
|
+
return {
|
|
1599
|
+
configFile,
|
|
1600
|
+
unreadable: read === void 0,
|
|
1601
|
+
dynamic: read?.dynamic ?? false,
|
|
1602
|
+
targets: targets.map((t) => ({ ...t, covered: patterns.some((re) => re.test(t.sample)) }))
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
function checkTailwindContent(baseDir) {
|
|
1606
|
+
const r = inspectTailwindContent(baseDir);
|
|
1607
|
+
if (r === null) return null;
|
|
1608
|
+
const missing = r.targets.filter((t) => !t.covered);
|
|
1609
|
+
if (missing.length === 0) {
|
|
1610
|
+
return {
|
|
1611
|
+
name: "tailwind.content",
|
|
1612
|
+
severity: "pass",
|
|
1613
|
+
message: `${r.configFile}\uC758 content \uAC00 ${r.targets.map((t) => t.label).join(" \xB7 ")} \uB97C \uB36E\uC2B5\uB2C8\uB2E4`
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"`).join(" \xB7 ");
|
|
1617
|
+
if (r.unreadable || r.dynamic) {
|
|
1618
|
+
return {
|
|
1619
|
+
name: "tailwind.content",
|
|
1620
|
+
severity: "warn",
|
|
1621
|
+
message: `${r.configFile}\uC758 content \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${list}`
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
return {
|
|
1625
|
+
name: "tailwind.content",
|
|
1626
|
+
severity: "fail",
|
|
1627
|
+
message: `${r.configFile}\uC758 content \uAC00 \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C\uB97C \uB36E\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uD074\uB798\uC2A4\uAC00 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC74C): ${list}`
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
var ANIMATION_PLUGIN_TAILWIND3 = "tailwindcss-animate";
|
|
1631
|
+
var ANIMATION_PLUGIN_TAILWIND4 = "tw-animate-css";
|
|
1632
|
+
var ANIMATION_SCAN_ENTRY_LIMIT = 2e3;
|
|
1633
|
+
var ANIMATION_SCAN_DEPTH_LIMIT = 8;
|
|
1634
|
+
var ANIMATION_SCAN_FILE_BYTES = 512 * 1024;
|
|
1635
|
+
function componentsUseAnimation(baseDir, componentsDir) {
|
|
1636
|
+
const rel2 = normalizeRel(componentsDir);
|
|
1637
|
+
if (rel2 === void 0) return false;
|
|
1638
|
+
const stack = [[join2(baseDir, rel2), 0]];
|
|
1639
|
+
let visited = 0;
|
|
1640
|
+
while (stack.length > 0) {
|
|
1641
|
+
const [dir, depth] = stack.pop();
|
|
1642
|
+
let names;
|
|
1643
|
+
try {
|
|
1644
|
+
names = readdirSync(dir);
|
|
1645
|
+
} catch {
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1648
|
+
for (const name of names) {
|
|
1649
|
+
if (++visited > ANIMATION_SCAN_ENTRY_LIMIT) return false;
|
|
1650
|
+
const p = join2(dir, name);
|
|
1651
|
+
let st;
|
|
1652
|
+
try {
|
|
1653
|
+
st = lstatSync(p);
|
|
1654
|
+
} catch {
|
|
1655
|
+
continue;
|
|
1656
|
+
}
|
|
1657
|
+
if (st.isSymbolicLink()) continue;
|
|
1658
|
+
if (st.isDirectory()) {
|
|
1659
|
+
if (name !== "node_modules" && depth < ANIMATION_SCAN_DEPTH_LIMIT) stack.push([p, depth + 1]);
|
|
1660
|
+
} else if (st.isFile() && st.size <= ANIMATION_SCAN_FILE_BYTES && /\.(tsx|ts|jsx|js)$/.test(name)) {
|
|
1661
|
+
if (/\banimate-(?:in|out)\b/.test(readFileSync4(p, "utf8"))) return true;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return false;
|
|
1666
|
+
}
|
|
1667
|
+
function checkAnimationPlugin(baseDirInput) {
|
|
1668
|
+
const baseDir = resolve(baseDirInput);
|
|
1669
|
+
const pkg = readPackageJson(baseDir);
|
|
1670
|
+
const config = readAxisConfigLike(baseDir);
|
|
1671
|
+
const declared = pkg !== void 0 && hasDependency2(pkg, "@axis-ds/ui-react") !== void 0;
|
|
1672
|
+
const copied = typeof config?.componentsDir === "string" && componentsUseAnimation(baseDir, config.componentsDir);
|
|
1673
|
+
if (!declared && !copied) return null;
|
|
1674
|
+
const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
|
|
1675
|
+
const tailwind = detectTailwind(baseDir, pkg);
|
|
1676
|
+
if (tailwind.major !== void 0 && tailwind.major >= 4) {
|
|
1677
|
+
const file = TAILWIND_CSS_CANDIDATES.find((c) => existsSync3(join2(baseDir, c)));
|
|
1678
|
+
const css = file !== void 0 ? stripCssComments(readFileSync4(join2(baseDir, file), "utf8")) : "";
|
|
1679
|
+
const ok = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`).test(css) || new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(css);
|
|
1680
|
+
return ok ? { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` } : {
|
|
1681
|
+
name: "animation",
|
|
1682
|
+
severity: "warn",
|
|
1683
|
+
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}";`
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
|
|
1687
|
+
const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
|
|
1688
|
+
const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
|
|
1689
|
+
const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
|
|
1690
|
+
const pluginInstalled = pluginDeclared && (isPnpProject(baseDir) || findInstalledPackage(baseDir, ANIMATION_PLUGIN_TAILWIND3) !== void 0);
|
|
1691
|
+
if (plugins === "found" && pluginDeclared && pluginInstalled) {
|
|
1692
|
+
return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
|
|
1693
|
+
}
|
|
1694
|
+
const cfg = configFile ?? "tailwind.config";
|
|
1695
|
+
const reasons = [];
|
|
1696
|
+
if (!pluginDeclared) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uC120\uC5B8 \uC5C6\uC74C`);
|
|
1697
|
+
else if (!pluginInstalled) reasons.push(`${ANIMATION_PLUGIN_TAILWIND3} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`);
|
|
1698
|
+
if (plugins === "dynamic") reasons.push(`${cfg} plugins \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD568`);
|
|
1699
|
+
else if (plugins !== "found") reasons.push(`${cfg} plugins \uC5D0 \uC5C6\uC74C`);
|
|
1700
|
+
return {
|
|
1701
|
+
name: "animation",
|
|
1702
|
+
severity: "warn",
|
|
1703
|
+
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}")`
|
|
1704
|
+
};
|
|
1705
|
+
}
|
|
1706
|
+
function readAnimationPluginUse(source) {
|
|
1707
|
+
const name = escapeRegExp(ANIMATION_PLUGIN_TAILWIND3);
|
|
1708
|
+
const idents = /* @__PURE__ */ new Set();
|
|
1709
|
+
for (const m of source.matchAll(new RegExp(`\\bimport\\s+([A-Za-z_$][\\w$]*)\\s+from\\s*(["'])${name}\\2`, "g"))) idents.add(m[1]);
|
|
1710
|
+
for (const m of source.matchAll(
|
|
1711
|
+
new RegExp(`\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*require\\s*\\(\\s*(["'])${name}\\2\\s*\\)`, "g")
|
|
1712
|
+
)) {
|
|
1713
|
+
idents.add(m[1]);
|
|
1714
|
+
}
|
|
1715
|
+
const requireCall = new RegExp(`^require\\s*\\(\\s*(["'])${name}\\1\\s*\\)(?:\\s*\\.\\s*default)?$`);
|
|
1716
|
+
let sawDynamic = false;
|
|
1717
|
+
for (const m of source.matchAll(/\bplugins\b\s*(:)?\s*/g)) {
|
|
1718
|
+
if (m[1] === void 0) {
|
|
1719
|
+
const before = source.slice(Math.max(0, (m.index ?? 0) - 1), m.index ?? 0);
|
|
1720
|
+
if (/[{,\s]/.test(before) || before === "") sawDynamic = true;
|
|
1721
|
+
continue;
|
|
1722
|
+
}
|
|
1723
|
+
const at = (m.index ?? 0) + m[0].length;
|
|
1724
|
+
if (source[at] !== "[") {
|
|
1725
|
+
sawDynamic = true;
|
|
1726
|
+
continue;
|
|
1727
|
+
}
|
|
1728
|
+
const block = balancedSlice(source, at);
|
|
1729
|
+
if (block === void 0) {
|
|
1730
|
+
sawDynamic = true;
|
|
1731
|
+
continue;
|
|
1732
|
+
}
|
|
1733
|
+
const elements = splitTopLevel(block.slice(1, -1));
|
|
1734
|
+
for (const el of elements) {
|
|
1735
|
+
const e = el.trim();
|
|
1736
|
+
if (e === "") continue;
|
|
1737
|
+
if (requireCall.test(e) || idents.has(e) || idents.has(e.replace(/\(\s*\)$/, ""))) return "found";
|
|
1738
|
+
if (/^require\s*\(\s*(["'])[^"']+\1\s*\)(?:\s*\.\s*default)?$/.test(e)) continue;
|
|
1739
|
+
sawDynamic = true;
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
return sawDynamic ? "dynamic" : "absent";
|
|
1743
|
+
}
|
|
1744
|
+
function splitTopLevel(body) {
|
|
1745
|
+
const out = [];
|
|
1746
|
+
let depth = 0;
|
|
1747
|
+
let start = 0;
|
|
1748
|
+
for (let i = 0; i < body.length; i++) {
|
|
1749
|
+
const c = body[i];
|
|
1750
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
1751
|
+
let j = i + 1;
|
|
1752
|
+
while (j < body.length && body[j] !== c) j += body[j] === "\\" ? 2 : 1;
|
|
1753
|
+
i = j;
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
1757
|
+
else if (c === ")" || c === "]" || c === "}") depth--;
|
|
1758
|
+
else if (c === "," && depth === 0) {
|
|
1759
|
+
out.push(body.slice(start, i));
|
|
1760
|
+
start = i + 1;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
out.push(body.slice(start));
|
|
1764
|
+
return out;
|
|
1319
1765
|
}
|
|
1320
1766
|
|
|
1321
1767
|
// ../axis-registry-core/src/utils-deps.ts
|
|
@@ -1332,7 +1778,7 @@ function selectUtilsDependencies(tailwind) {
|
|
|
1332
1778
|
}
|
|
1333
1779
|
|
|
1334
1780
|
// ../axis-registry-core/src/add/safe-write.ts
|
|
1335
|
-
import { constants as fsConstants, existsSync as existsSync4, lstatSync, realpathSync, statSync } from "fs";
|
|
1781
|
+
import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync, statSync as statSync2 } from "fs";
|
|
1336
1782
|
import path4 from "path";
|
|
1337
1783
|
import fs2 from "fs-extra";
|
|
1338
1784
|
var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
|
|
@@ -1370,7 +1816,7 @@ function escapeReason(root, target, options = {}) {
|
|
|
1370
1816
|
}
|
|
1371
1817
|
let st = null;
|
|
1372
1818
|
try {
|
|
1373
|
-
st =
|
|
1819
|
+
st = lstatSync2(target);
|
|
1374
1820
|
} catch {
|
|
1375
1821
|
st = null;
|
|
1376
1822
|
}
|
|
@@ -1388,7 +1834,7 @@ function escapeReason(root, target, options = {}) {
|
|
|
1388
1834
|
}
|
|
1389
1835
|
let followed;
|
|
1390
1836
|
try {
|
|
1391
|
-
followed =
|
|
1837
|
+
followed = statSync2(realTarget);
|
|
1392
1838
|
} catch {
|
|
1393
1839
|
return `\uAE30\uC874 \uD30C\uC77C \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${target})`;
|
|
1394
1840
|
}
|
|
@@ -1404,7 +1850,7 @@ function escapeReason(root, target, options = {}) {
|
|
|
1404
1850
|
}
|
|
1405
1851
|
function isSymlink(p) {
|
|
1406
1852
|
try {
|
|
1407
|
-
return
|
|
1853
|
+
return lstatSync2(p).isSymbolicLink();
|
|
1408
1854
|
} catch {
|
|
1409
1855
|
return false;
|
|
1410
1856
|
}
|
|
@@ -1420,7 +1866,7 @@ function outsideLinkTarget(root, target) {
|
|
|
1420
1866
|
}
|
|
1421
1867
|
function hardLinkCount(target) {
|
|
1422
1868
|
try {
|
|
1423
|
-
const st =
|
|
1869
|
+
const st = lstatSync2(target);
|
|
1424
1870
|
return st.isFile() && st.nlink >= 2 ? st.nlink : null;
|
|
1425
1871
|
} catch {
|
|
1426
1872
|
return null;
|
|
@@ -1660,7 +2106,7 @@ function relativeSpecifierResolves(fromFile, spec) {
|
|
|
1660
2106
|
const base = path5.resolve(path5.dirname(fromFile), spec);
|
|
1661
2107
|
return RESOLVE_EXTS.some((ext) => {
|
|
1662
2108
|
try {
|
|
1663
|
-
return
|
|
2109
|
+
return statSync3(base + ext).isFile();
|
|
1664
2110
|
} catch {
|
|
1665
2111
|
return false;
|
|
1666
2112
|
}
|
|
@@ -1735,7 +2181,7 @@ function missingDependencies(root, items) {
|
|
|
1735
2181
|
const installCommand = detectInstallCommand(root);
|
|
1736
2182
|
let pkg;
|
|
1737
2183
|
try {
|
|
1738
|
-
const text =
|
|
2184
|
+
const text = readFileSync5(path5.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
|
|
1739
2185
|
const parsed = JSON.parse(text);
|
|
1740
2186
|
pkg = isPlainObject(parsed) ? parsed : void 0;
|
|
1741
2187
|
} catch {
|
|
@@ -1856,7 +2302,7 @@ async function runAdd(cwd, requested, options, ctx) {
|
|
|
1856
2302
|
continue;
|
|
1857
2303
|
}
|
|
1858
2304
|
try {
|
|
1859
|
-
existing.set(file,
|
|
2305
|
+
existing.set(file, readFileSync5(file.target, "utf8"));
|
|
1860
2306
|
} catch (e) {
|
|
1861
2307
|
readErrors.push(
|
|
1862
2308
|
`${file.item.name}: \uAE30\uC874 \uD30C\uC77C ${rel(root, file.target)} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${e.code ?? e.message})`
|
|
@@ -2417,7 +2863,7 @@ function formatTokenList(result) {
|
|
|
2417
2863
|
}
|
|
2418
2864
|
|
|
2419
2865
|
// src/tools/install.ts
|
|
2420
|
-
import { statSync as
|
|
2866
|
+
import { statSync as statSync4 } from "fs";
|
|
2421
2867
|
import path6 from "path";
|
|
2422
2868
|
var DEFAULT_LAYOUT_CONFIG = { componentsDir: "components/ui" };
|
|
2423
2869
|
var MCP_ADD_HINTS = {
|
|
@@ -2456,7 +2902,7 @@ async function handleInstallComponent(params, deps = {}) {
|
|
|
2456
2902
|
const root = path6.resolve(params.targetDir);
|
|
2457
2903
|
let isDir = false;
|
|
2458
2904
|
try {
|
|
2459
|
-
isDir =
|
|
2905
|
+
isDir = statSync4(root).isDirectory();
|
|
2460
2906
|
} catch {
|
|
2461
2907
|
isDir = false;
|
|
2462
2908
|
}
|
|
@@ -2570,7 +3016,7 @@ var REUSABLE_PATTERNS = {
|
|
|
2570
3016
|
};
|
|
2571
3017
|
var PROJECT_SPECIFIC_PATTERNS = [
|
|
2572
3018
|
// 파일 경로
|
|
2573
|
-
/(?:src|packages|apps|lib|components)\/[\w
|
|
3019
|
+
/(?:src|packages|apps|lib|components)\/[\w\-/]+\.(?:ts|tsx|js|jsx|md)/gi,
|
|
2574
3020
|
// 컴포넌트명 (PascalCase)
|
|
2575
3021
|
/\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b/g,
|
|
2576
3022
|
// 버전
|
|
@@ -2584,7 +3030,7 @@ function segmentText(text) {
|
|
|
2584
3030
|
const sections = text.split(/(?=^#{1,3}\s)/m);
|
|
2585
3031
|
return sections.filter((s) => s.trim().length > 50);
|
|
2586
3032
|
}
|
|
2587
|
-
function calculateRepeatability(text
|
|
3033
|
+
function calculateRepeatability(text) {
|
|
2588
3034
|
let score = 0;
|
|
2589
3035
|
const structuredPatterns = [
|
|
2590
3036
|
REUSABLE_PATTERNS.goal,
|
|
@@ -2597,7 +3043,7 @@ function calculateRepeatability(text, _context) {
|
|
|
2597
3043
|
}
|
|
2598
3044
|
}
|
|
2599
3045
|
if (/^#{1,3}\s/m.test(text)) score += 5;
|
|
2600
|
-
if (/^[
|
|
3046
|
+
if (/^[-*]\s/m.test(text)) score += 3;
|
|
2601
3047
|
if (/^\d+\.\s/m.test(text)) score += 2;
|
|
2602
3048
|
return Math.min(25, score);
|
|
2603
3049
|
}
|
|
@@ -2648,8 +3094,8 @@ function calculateClarity(text) {
|
|
|
2648
3094
|
}
|
|
2649
3095
|
return Math.min(20, score);
|
|
2650
3096
|
}
|
|
2651
|
-
function calculateScores(text
|
|
2652
|
-
const repeatability = calculateRepeatability(text
|
|
3097
|
+
function calculateScores(text) {
|
|
3098
|
+
const repeatability = calculateRepeatability(text);
|
|
2653
3099
|
const generality = calculateGenerality(text);
|
|
2654
3100
|
const independence = calculateIndependence(text);
|
|
2655
3101
|
const clarity = calculateClarity(text);
|
|
@@ -2752,7 +3198,7 @@ function handleDetect(params) {
|
|
|
2752
3198
|
const candidates = [];
|
|
2753
3199
|
for (let i = 0; i < segments.length; i++) {
|
|
2754
3200
|
const segment = segments[i];
|
|
2755
|
-
const scores = calculateScores(segment
|
|
3201
|
+
const scores = calculateScores(segment);
|
|
2756
3202
|
if (scores.total >= minScore) {
|
|
2757
3203
|
candidates.push({
|
|
2758
3204
|
id: `candidate-${i + 1}`,
|
|
@@ -2882,7 +3328,7 @@ var CATEGORY_KEYWORDS = {
|
|
|
2882
3328
|
]
|
|
2883
3329
|
};
|
|
2884
3330
|
var PROJECT_PATTERNS = {
|
|
2885
|
-
path: /(?:src|packages|apps|lib|components)\/[\w
|
|
3331
|
+
path: /(?:src|packages|apps|lib|components)\/[\w\-/]+\.(?:ts|tsx|js|jsx|md)/gi,
|
|
2886
3332
|
name: /\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b/g,
|
|
2887
3333
|
version: /\b\d+\.\d+\.\d+(?:-[\w.]+)?\b/g,
|
|
2888
3334
|
date: /\b\d{4}-\d{2}-\d{2}\b/g,
|
|
@@ -2899,7 +3345,7 @@ function calculateRepeatability2(text) {
|
|
|
2899
3345
|
score += 4;
|
|
2900
3346
|
reasons.push(`${headerCount}\uAC1C \uC139\uC158 \uC874\uC7AC`);
|
|
2901
3347
|
}
|
|
2902
|
-
const listCount = (text.match(/^[
|
|
3348
|
+
const listCount = (text.match(/^[-*]\s/gm) || []).length;
|
|
2903
3349
|
const numberedCount = (text.match(/^\d+\.\s/gm) || []).length;
|
|
2904
3350
|
if (listCount + numberedCount >= 5) {
|
|
2905
3351
|
score += 8;
|
|
@@ -3229,7 +3675,7 @@ function formatAnalyzeResult(result) {
|
|
|
3229
3675
|
// src/tools/prompt/refine.ts
|
|
3230
3676
|
var VARIABLE_PATTERNS = [
|
|
3231
3677
|
{
|
|
3232
|
-
pattern: /(?:src|packages|apps|lib|components)\/[\w
|
|
3678
|
+
pattern: /(?:src|packages|apps|lib|components)\/[\w\-/]+\.(?:ts|tsx|js|jsx|md)/gi,
|
|
3233
3679
|
variable: "{{FILE_PATH}}",
|
|
3234
3680
|
description: "\uD30C\uC77C \uACBD\uB85C",
|
|
3235
3681
|
type: "path"
|
|
@@ -3554,7 +4000,7 @@ function checkRequiredSections(text) {
|
|
|
3554
4000
|
function checkHardcodedPaths(text) {
|
|
3555
4001
|
const hardcodedPatterns = [
|
|
3556
4002
|
// 절대 경로 (변수화되지 않은)
|
|
3557
|
-
/(?<!{{)(?:src|packages|apps|lib|components)\/[\w
|
|
4003
|
+
/(?<!{{)(?:src|packages|apps|lib|components)\/[\w\-/]+\.(?:ts|tsx|js|jsx|md)(?!}})/gi,
|
|
3558
4004
|
// 특정 프로젝트 경로
|
|
3559
4005
|
/D:\\|C:\\|\/Users\/|\/home\//gi
|
|
3560
4006
|
];
|
|
@@ -3586,7 +4032,7 @@ function checkVariablesDocumented(text) {
|
|
|
3586
4032
|
undocumented
|
|
3587
4033
|
};
|
|
3588
4034
|
}
|
|
3589
|
-
function checkDuplicate(text
|
|
4035
|
+
function checkDuplicate(text) {
|
|
3590
4036
|
const similar = [];
|
|
3591
4037
|
try {
|
|
3592
4038
|
const indexPath = path7.resolve(process.cwd(), INDEX_PATH);
|
|
@@ -3832,7 +4278,7 @@ function savePromptFile(basePath, category, name, content) {
|
|
|
3832
4278
|
fs5.writeFileSync(promptPath, content, "utf-8");
|
|
3833
4279
|
return `${PROMPTS_BASE_PATH}/${category}/${name}.md`;
|
|
3834
4280
|
}
|
|
3835
|
-
function updateIndex(index, entry
|
|
4281
|
+
function updateIndex(index, entry) {
|
|
3836
4282
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3837
4283
|
const existingIndex = index.prompts.findIndex((p) => p.id === entry.id);
|
|
3838
4284
|
if (existingIndex >= 0) {
|
|
@@ -3900,8 +4346,7 @@ function handleSave(params) {
|
|
|
3900
4346
|
description,
|
|
3901
4347
|
path: relativePath,
|
|
3902
4348
|
variables
|
|
3903
|
-
}
|
|
3904
|
-
!isDuplicate
|
|
4349
|
+
}
|
|
3905
4350
|
);
|
|
3906
4351
|
saveIndex(basePath, index);
|
|
3907
4352
|
return {
|
|
@@ -3962,11 +4407,12 @@ import fs6 from "fs-extra";
|
|
|
3962
4407
|
import path9 from "path";
|
|
3963
4408
|
|
|
3964
4409
|
// src/tools/brand-core.ts
|
|
3965
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4410
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
|
|
3966
4411
|
import { createRequire } from "module";
|
|
3967
4412
|
import { dirname as dirname3, join as join4, relative, resolve as resolve3, sep } from "path";
|
|
3968
4413
|
var TOKENS_PACKAGE = "@axis-ds/tokens";
|
|
3969
4414
|
var MIN_BRAND_TOKENS_VERSION = "1.3.0";
|
|
4415
|
+
var TOKENS_DEPENDENCY_MIN_VERSION = "1.6.0";
|
|
3970
4416
|
var KEY_TOKENS = [
|
|
3971
4417
|
"--primary",
|
|
3972
4418
|
"--primary-foreground",
|
|
@@ -3983,7 +4429,7 @@ var KEY_TOKENS = [
|
|
|
3983
4429
|
];
|
|
3984
4430
|
var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
|
|
3985
4431
|
function readJsonFile(file) {
|
|
3986
|
-
return JSON.parse(
|
|
4432
|
+
return JSON.parse(readFileSync8(file, "utf8"));
|
|
3987
4433
|
}
|
|
3988
4434
|
function errorCode(err) {
|
|
3989
4435
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
@@ -4022,10 +4468,9 @@ function resolveTokens(baseDir) {
|
|
|
4022
4468
|
function brandImportPath(entry) {
|
|
4023
4469
|
return tokensSpecifier(entry.css);
|
|
4024
4470
|
}
|
|
4025
|
-
|
|
4026
|
-
function isFile(file) {
|
|
4471
|
+
function isFile2(file) {
|
|
4027
4472
|
try {
|
|
4028
|
-
return
|
|
4473
|
+
return statSync5(file).isFile();
|
|
4029
4474
|
} catch {
|
|
4030
4475
|
return false;
|
|
4031
4476
|
}
|
|
@@ -4036,12 +4481,12 @@ function findGlobalCss(baseDir, config) {
|
|
|
4036
4481
|
const configured = config?.globalCss;
|
|
4037
4482
|
if (typeof configured === "string" && configured.trim() !== "") {
|
|
4038
4483
|
const file = resolve3(root, configured);
|
|
4039
|
-
if (
|
|
4484
|
+
if (isFile2(file)) return { path: file };
|
|
4040
4485
|
result.configuredMissing = configured;
|
|
4041
4486
|
}
|
|
4042
4487
|
for (const candidate of GLOBAL_CSS_CANDIDATES) {
|
|
4043
4488
|
const file = join4(root, candidate);
|
|
4044
|
-
if (
|
|
4489
|
+
if (isFile2(file)) {
|
|
4045
4490
|
result.path = file;
|
|
4046
4491
|
break;
|
|
4047
4492
|
}
|
|
@@ -4060,7 +4505,7 @@ var AXIS_CONFIG_FILE_NAME = "axis.config.json";
|
|
|
4060
4505
|
function readBrandConfig(baseDir) {
|
|
4061
4506
|
let parsed;
|
|
4062
4507
|
try {
|
|
4063
|
-
parsed = JSON.parse(
|
|
4508
|
+
parsed = JSON.parse(readFileSync8(join4(resolve3(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
|
|
4064
4509
|
} catch {
|
|
4065
4510
|
return null;
|
|
4066
4511
|
}
|
|
@@ -4079,7 +4524,7 @@ function inspectBrandImport(baseDir) {
|
|
|
4079
4524
|
return { ...base, state: "css-missing", imports: [] };
|
|
4080
4525
|
}
|
|
4081
4526
|
const cssFile = relative(root, location.path).split(sep).join("/");
|
|
4082
|
-
const imports = [...new Set(findBrandImports(
|
|
4527
|
+
const imports = [...new Set(findBrandImports(readFileSync8(location.path, "utf8")))];
|
|
4083
4528
|
let state;
|
|
4084
4529
|
if (imports.includes(brand)) state = "match";
|
|
4085
4530
|
else if (imports.length === 0) state = "import-missing";
|
|
@@ -4163,13 +4608,72 @@ function pickKeyTokens(decls) {
|
|
|
4163
4608
|
}
|
|
4164
4609
|
return out;
|
|
4165
4610
|
}
|
|
4611
|
+
var THEME_MARKUP_BRAND_MIN_VERSION = "1.7.0";
|
|
4166
4612
|
function providerExample(name) {
|
|
4167
4613
|
return [
|
|
4168
|
-
|
|
4614
|
+
"// 1) \uB8E8\uD2B8 \uB808\uC774\uC544\uC6C3(app/layout.tsx)\uC758 <html> \uC5D0 \uBD99\uC785\uB2C8\uB2E4(\uCCAB \uD654\uBA74\uBD80\uD130 \uC801\uC6A9)",
|
|
4615
|
+
`// 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)`,
|
|
4616
|
+
`<html lang="ko" data-brand="${name}">`,
|
|
4169
4617
|
"",
|
|
4170
|
-
|
|
4618
|
+
`// 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)`,
|
|
4619
|
+
'import { useTheme } from "@axis-ds/theme";',
|
|
4620
|
+
"const { setBrand } = useTheme();",
|
|
4621
|
+
`setBrand("${name}");`
|
|
4171
4622
|
].join("\n");
|
|
4172
4623
|
}
|
|
4624
|
+
var BRAND_ACTIVATION_FILES = ROOT_LAYOUT_FILES;
|
|
4625
|
+
var BRAND_ACTIVATION_PATTERN = /data-brand|setBrand\s*\(|defaultBrand\s*=/;
|
|
4626
|
+
var PROVIDER_ACTIVATION_PATTERN = /setBrand\s*\(|defaultBrand\s*=/;
|
|
4627
|
+
var THEME_PROVIDER_PATTERN = /<ThemeProvider\b/;
|
|
4628
|
+
function stripJsLikeComments(src) {
|
|
4629
|
+
return src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`])\/\/[^\n]*/g, "$1");
|
|
4630
|
+
}
|
|
4631
|
+
function findBrandActivation(baseDir) {
|
|
4632
|
+
const root = resolve3(baseDir);
|
|
4633
|
+
const layoutFiles = [];
|
|
4634
|
+
for (const candidate of BRAND_ACTIVATION_FILES) {
|
|
4635
|
+
const file = join4(root, candidate);
|
|
4636
|
+
if (!isFile2(file)) continue;
|
|
4637
|
+
layoutFiles.push(candidate);
|
|
4638
|
+
const text = stripJsLikeComments(readFileSync8(file, "utf8"));
|
|
4639
|
+
const providerTexts = [];
|
|
4640
|
+
for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
|
|
4641
|
+
for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
|
|
4642
|
+
const rel2 = `${dirname3(candidate)}/${m[1]}${ext}`;
|
|
4643
|
+
const p = join4(root, rel2);
|
|
4644
|
+
if (isFile2(p)) providerTexts.push({ rel: rel2, text: stripJsLikeComments(readFileSync8(p, "utf8")) });
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
const all = [text, ...providerTexts.map((x) => x.text)];
|
|
4648
|
+
const markupWithProvider = !all.some((t) => PROVIDER_ACTIVATION_PATTERN.test(t)) && all.some((t) => THEME_PROVIDER_PATTERN.test(t));
|
|
4649
|
+
if (BRAND_ACTIVATION_PATTERN.test(text)) {
|
|
4650
|
+
return markupWithProvider ? { found: candidate, layoutFiles, markupWithProvider } : { found: candidate, layoutFiles };
|
|
4651
|
+
}
|
|
4652
|
+
for (const x of providerTexts) {
|
|
4653
|
+
if (BRAND_ACTIVATION_PATTERN.test(x.text)) {
|
|
4654
|
+
return markupWithProvider ? { found: x.rel, layoutFiles, markupWithProvider } : { found: x.rel, layoutFiles };
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
}
|
|
4658
|
+
return { layoutFiles };
|
|
4659
|
+
}
|
|
4660
|
+
function inspectBrandActivation(baseDir) {
|
|
4661
|
+
const config = readBrandConfig(baseDir);
|
|
4662
|
+
const brand = config?.brand;
|
|
4663
|
+
if (typeof brand !== "string" || brand.trim() === "") return null;
|
|
4664
|
+
const location = findBrandActivation(baseDir);
|
|
4665
|
+
if (!location.markupWithProvider) return { brand, ...location };
|
|
4666
|
+
return { brand, ...location, theme: packageVersionGate(baseDir, readProjectPackageJson(baseDir), THEME_PACKAGE, THEME_MARKUP_BRAND_MIN_VERSION) };
|
|
4667
|
+
}
|
|
4668
|
+
var THEME_PACKAGE = "@axis-ds/theme";
|
|
4669
|
+
function readProjectPackageJson(baseDir) {
|
|
4670
|
+
try {
|
|
4671
|
+
const parsed = JSON.parse(readFileSync8(join4(resolve3(baseDir), "package.json"), "utf8"));
|
|
4672
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
|
|
4673
|
+
} catch {
|
|
4674
|
+
return void 0;
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4173
4677
|
function getBrand(baseDir, name) {
|
|
4174
4678
|
const tokens = resolveTokens(baseDir);
|
|
4175
4679
|
if (tokens.status !== "ok" || !tokens.indexPath) {
|
|
@@ -4186,7 +4690,7 @@ function getBrand(baseDir, name) {
|
|
|
4186
4690
|
try {
|
|
4187
4691
|
summary = readSummary(baseDir, entry);
|
|
4188
4692
|
const cssPath = projectRequire(baseDir).resolve(summary.importPath);
|
|
4189
|
-
parsed = parseBrandCss(
|
|
4693
|
+
parsed = parseBrandCss(readFileSync8(cssPath, "utf8"), name);
|
|
4190
4694
|
} catch (err) {
|
|
4191
4695
|
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
|
|
4192
4696
|
throw err;
|
|
@@ -4204,6 +4708,57 @@ function getBrand(baseDir, name) {
|
|
|
4204
4708
|
};
|
|
4205
4709
|
}
|
|
4206
4710
|
|
|
4711
|
+
// ../axis-registry-core/src/template/dependencies-core.ts
|
|
4712
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
4713
|
+
import { join as join5, resolve as resolve4 } from "path";
|
|
4714
|
+
var REQUIRED_DEPENDENCIES = ["tailwindcss"];
|
|
4715
|
+
var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
|
|
4716
|
+
function declaredAxisPackages(pkg) {
|
|
4717
|
+
const out = [];
|
|
4718
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
4719
|
+
const deps = pkg[field];
|
|
4720
|
+
if (!isPlainObject(deps)) continue;
|
|
4721
|
+
for (const name of Object.keys(deps)) if (name.startsWith("@axis-ds/") && !out.includes(name)) out.push(name);
|
|
4722
|
+
}
|
|
4723
|
+
return out;
|
|
4724
|
+
}
|
|
4725
|
+
function checkDependencies(baseDirInput) {
|
|
4726
|
+
const baseDir = resolve4(baseDirInput);
|
|
4727
|
+
let pkg;
|
|
4728
|
+
try {
|
|
4729
|
+
const parsed = JSON.parse(readFileSync9(join5(baseDir, "package.json"), "utf8"));
|
|
4730
|
+
if (!isPlainObject(parsed)) throw new Error("not object");
|
|
4731
|
+
pkg = parsed;
|
|
4732
|
+
} catch (err) {
|
|
4733
|
+
if (err?.code === "ENOENT") {
|
|
4734
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
|
|
4735
|
+
}
|
|
4736
|
+
return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
|
|
4737
|
+
}
|
|
4738
|
+
const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
4739
|
+
if (missingRequired.length > 0) {
|
|
4740
|
+
return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
|
|
4741
|
+
}
|
|
4742
|
+
const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
|
|
4743
|
+
const targets = [
|
|
4744
|
+
...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0),
|
|
4745
|
+
...declaredAxisPackages(pkg)
|
|
4746
|
+
];
|
|
4747
|
+
const pnp = isPnpProject(baseDir);
|
|
4748
|
+
const notInstalled = pnp ? [] : targets.filter((d) => findInstalledPackage(baseDir, d) === void 0);
|
|
4749
|
+
const problems = [];
|
|
4750
|
+
if (missingRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`);
|
|
4751
|
+
if (notInstalled.length > 0) {
|
|
4752
|
+
problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalled.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
|
|
4753
|
+
}
|
|
4754
|
+
if (problems.length > 0) return { name: "dependencies", severity: "warn", message: problems.join(" / ") };
|
|
4755
|
+
return {
|
|
4756
|
+
name: "dependencies",
|
|
4757
|
+
severity: "pass",
|
|
4758
|
+
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)`
|
|
4759
|
+
};
|
|
4760
|
+
}
|
|
4761
|
+
|
|
4207
4762
|
// src/site.ts
|
|
4208
4763
|
var AXIS_SITE_URL2 = "https://axis-design-system.pages.dev";
|
|
4209
4764
|
|
|
@@ -4358,6 +4913,30 @@ function brandCheckResult(check) {
|
|
|
4358
4913
|
};
|
|
4359
4914
|
}
|
|
4360
4915
|
}
|
|
4916
|
+
function brandActivationResult(check) {
|
|
4917
|
+
if (check.found && check.theme && check.theme.status !== "ok") {
|
|
4918
|
+
const label = versionGateLabel(check.theme);
|
|
4919
|
+
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`;
|
|
4920
|
+
return {
|
|
4921
|
+
name: "brand.activation",
|
|
4922
|
+
severity: "warn",
|
|
4923
|
+
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}")`
|
|
4924
|
+
};
|
|
4925
|
+
}
|
|
4926
|
+
if (check.found) {
|
|
4927
|
+
return {
|
|
4928
|
+
name: "brand.activation",
|
|
4929
|
+
severity: "pass",
|
|
4930
|
+
message: `${check.found}\uC5D0 \uBE0C\uB79C\uB4DC\uB97C \uCF1C\uB294 \uCF54\uB4DC(data-brand \xB7 setBrand \uB4F1)\uAC00 \uC788\uC2B5\uB2C8\uB2E4`
|
|
4931
|
+
};
|
|
4932
|
+
}
|
|
4933
|
+
const where = check.layoutFiles.length > 0 ? check.layoutFiles.join(" \xB7 ") : "\uB8E8\uD2B8 \uB808\uC774\uC544\uC6C3(app/layout.tsx \uB4F1)";
|
|
4934
|
+
return {
|
|
4935
|
+
name: "brand.activation",
|
|
4936
|
+
severity: "warn",
|
|
4937
|
+
message: `brand "${check.brand}" \uAC00 \uC124\uC815\uB410\uC9C0\uB9CC ${where}\uC5D0 \uBE0C\uB79C\uB4DC\uB97C \uCF1C\uB294 \uCF54\uB4DC(data-brand \xB7 setBrand \uB4F1)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(ThemeProvider \uB9CC\uC73C\uB85C\uB294 \uB9C8\uC6B4\uD2B8 \uB54C \uAEBC\uC9D0) \u2192 <html data-brand="${check.brand}"> \uB610\uB294 setBrand("${check.brand}")`
|
|
4938
|
+
};
|
|
4939
|
+
}
|
|
4361
4940
|
async function handleCheckProject(params) {
|
|
4362
4941
|
const baseDir = path9.resolve(params.targetDir || ".");
|
|
4363
4942
|
const results = [];
|
|
@@ -4380,8 +4959,8 @@ async function handleCheckProject(params) {
|
|
|
4380
4959
|
for (const candidate of utilsCandidates) {
|
|
4381
4960
|
const fullPath = path9.join(baseDir, candidate);
|
|
4382
4961
|
if (await fs6.pathExists(fullPath)) {
|
|
4383
|
-
const
|
|
4384
|
-
const hasCn =
|
|
4962
|
+
const content2 = await fs6.readFile(fullPath, "utf-8");
|
|
4963
|
+
const hasCn = content2.includes("function cn");
|
|
4385
4964
|
results.push({
|
|
4386
4965
|
name: "utils.ts",
|
|
4387
4966
|
severity: hasCn ? "pass" : "warn",
|
|
@@ -4398,42 +4977,15 @@ async function handleCheckProject(params) {
|
|
|
4398
4977
|
message: "utils.ts\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC2DC \uD544\uC694)"
|
|
4399
4978
|
});
|
|
4400
4979
|
}
|
|
4401
|
-
|
|
4402
|
-
if (await fs6.pathExists(pkgPath)) {
|
|
4403
|
-
const pkg = await fs6.readJSON(pkgPath);
|
|
4404
|
-
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4405
|
-
const required = ["tailwindcss"];
|
|
4406
|
-
const recommended = ["clsx", "tailwind-merge"];
|
|
4407
|
-
const missingRequired = required.filter((d) => !allDeps[d]);
|
|
4408
|
-
const missingRecommended = recommended.filter((d) => !allDeps[d]);
|
|
4409
|
-
if (missingRequired.length > 0) {
|
|
4410
|
-
results.push({
|
|
4411
|
-
name: "dependencies",
|
|
4412
|
-
severity: "fail",
|
|
4413
|
-
message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}`
|
|
4414
|
-
});
|
|
4415
|
-
} else if (missingRecommended.length > 0) {
|
|
4416
|
-
results.push({
|
|
4417
|
-
name: "dependencies",
|
|
4418
|
-
severity: "warn",
|
|
4419
|
-
message: `\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`
|
|
4420
|
-
});
|
|
4421
|
-
} else {
|
|
4422
|
-
results.push({
|
|
4423
|
-
name: "dependencies",
|
|
4424
|
-
severity: "pass",
|
|
4425
|
-
message: "\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uBAA8\uB450 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4"
|
|
4426
|
-
});
|
|
4427
|
-
}
|
|
4428
|
-
} else {
|
|
4429
|
-
results.push({
|
|
4430
|
-
name: "dependencies",
|
|
4431
|
-
severity: "fail",
|
|
4432
|
-
message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
|
|
4433
|
-
});
|
|
4434
|
-
}
|
|
4980
|
+
results.push(checkDependencies(baseDir));
|
|
4435
4981
|
const brandCheck = inspectBrandImport(baseDir);
|
|
4436
4982
|
if (brandCheck) results.push(brandCheckResult(brandCheck));
|
|
4983
|
+
const activation = inspectBrandActivation(baseDir);
|
|
4984
|
+
if (activation) results.push(brandActivationResult(activation));
|
|
4985
|
+
const content = checkTailwindContent(baseDir);
|
|
4986
|
+
if (content) results.push(content);
|
|
4987
|
+
const animation = checkAnimationPlugin(baseDir);
|
|
4988
|
+
if (animation) results.push(animation);
|
|
4437
4989
|
const summary = {
|
|
4438
4990
|
pass: results.filter((r) => r.severity === "pass").length,
|
|
4439
4991
|
warn: results.filter((r) => r.severity === "warn").length,
|
|
@@ -4550,7 +5102,7 @@ function formatCheckProjectResult(result) {
|
|
|
4550
5102
|
|
|
4551
5103
|
// src/tools/brand.ts
|
|
4552
5104
|
import path10 from "path";
|
|
4553
|
-
var TOKENS_INSTALL_COMMAND =
|
|
5105
|
+
var TOKENS_INSTALL_COMMAND = addCommandFor("pnpm install", { [TOKENS_PACKAGE]: `^${TOKENS_DEPENDENCY_MIN_VERSION}` });
|
|
4554
5106
|
function baseDirOf(targetDir) {
|
|
4555
5107
|
return path10.resolve(targetDir || process.cwd());
|
|
4556
5108
|
}
|