@axis-ds/mcp 1.3.3 → 1.3.5

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/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 readFileSync4, statSync as statSync3 } from "fs";
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((resolve4, reject) => {
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
- resolve4({ ok: status >= 200 && status < 300, status, text: async () => body });
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, statSync } 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";
@@ -898,10 +898,79 @@ var GLOBAL_CSS_CANDIDATES = [
898
898
  "src/styles/globals.css",
899
899
  "globals.css"
900
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
+ }
901
970
 
902
971
  // ../axis-registry-core/src/template/tailwind-core.ts
903
- import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync3 } from "fs";
904
- 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";
905
974
  function hasDependency2(pkg, name) {
906
975
  for (const field of ["dependencies", "devDependencies"]) {
907
976
  const deps = pkg[field];
@@ -988,7 +1057,7 @@ function detectTailwind(baseDirInput, pkg) {
988
1057
  const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
989
1058
  const declaredMajor = bounds?.lower;
990
1059
  try {
991
- const installed = JSON.parse(readFileSync3(installedFile, "utf8"));
1060
+ const installed = JSON.parse(readFileSync4(installedFile, "utf8"));
992
1061
  const version = isPlainObject2(installed) ? installed.version : void 0;
993
1062
  const major = majorFromVersion(version);
994
1063
  if (major !== void 0) {
@@ -1036,18 +1105,57 @@ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/s
1036
1105
  function findTokensCssImport(css) {
1037
1106
  return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
1038
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
+ }
1039
1126
  function checkGlobalsCss(baseDirInput) {
1040
1127
  const baseDir = resolve(baseDirInput);
1041
1128
  for (const candidate of TAILWIND_CSS_CANDIDATES) {
1042
1129
  const file = join2(baseDir, candidate);
1043
1130
  if (!existsSync3(file)) continue;
1044
- const content = readFileSync3(file, "utf8");
1045
- if (content.includes("--background") && content.includes("--primary")) {
1046
- return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4` };
1047
- }
1131
+ const content = readFileSync4(file, "utf8");
1132
+ const css = stripCssComments(content);
1048
1133
  const imported = findTokensCssImport(content);
1049
- if (imported !== void 0) {
1050
- return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)` };
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
+ };
1051
1159
  }
1052
1160
  return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
1053
1161
  }
@@ -1110,7 +1218,7 @@ function exactVersion(version) {
1110
1218
  }
1111
1219
  function installedVersion(baseDir, name) {
1112
1220
  try {
1113
- const parsed = JSON.parse(readFileSync3(join2(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
1221
+ const parsed = JSON.parse(readFileSync4(join2(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
1114
1222
  return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
1115
1223
  } catch {
1116
1224
  return void 0;
@@ -1179,8 +1287,10 @@ var CREATE_NEXT_APP_DEFAULTS = [
1179
1287
  },
1180
1288
  {
1181
1289
  prefix: "body",
1182
- pattern: /(?<![\w-])(background|background-color|color)\s*:\s*var\(\s*(--(?:background|foreground))\s*\)/g,
1183
- item: (m) => `${m[1]}: var(${m[2]})`
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"
1184
1294
  }
1185
1295
  ];
1186
1296
  function findCreateNextAppDefaults(css) {
@@ -1236,9 +1346,54 @@ function hasTokensPresetReference(source) {
1236
1346
  return PRESET_REFERENCE.test(stripJsComments(source));
1237
1347
  }
1238
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
+ }
1239
1394
  function readPackageJson(baseDir) {
1240
1395
  try {
1241
- const parsed = JSON.parse(readFileSync3(join2(baseDir, "package.json"), "utf8"));
1396
+ const parsed = JSON.parse(readFileSync4(join2(baseDir, "package.json"), "utf8"));
1242
1397
  return isPlainObject2(parsed) ? parsed : void 0;
1243
1398
  } catch {
1244
1399
  return void 0;
@@ -1277,7 +1432,7 @@ function checkTailwindSetup(baseDirInput) {
1277
1432
  for (const candidate of TAILWIND_CSS_CANDIDATES) {
1278
1433
  const file = join2(baseDir, candidate);
1279
1434
  if (!existsSync3(file)) continue;
1280
- const css = readFileSync3(file, "utf8");
1435
+ const css = readFileSync4(file, "utf8");
1281
1436
  if (!hasTailwindImport(css)) {
1282
1437
  return {
1283
1438
  name: "tailwind.config",
@@ -1309,8 +1464,20 @@ function checkTailwindSetup(baseDirInput) {
1309
1464
  for (const file of TAILWIND_CONFIG_FILES) {
1310
1465
  const path11 = join2(baseDir, file);
1311
1466
  if (!existsSync3(path11)) continue;
1312
- const content = readFileSync3(path11, "utf8");
1467
+ const content = readFileSync4(path11, "utf8");
1313
1468
  if (hasTokensPresetReference(content)) {
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
+ }
1314
1481
  return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
1315
1482
  }
1316
1483
  const ownMapping = content.includes("--background") || content.includes("hsl(var(");
@@ -1324,7 +1491,7 @@ function checkTailwindSetup(baseDirInput) {
1324
1491
  }
1325
1492
  function readAxisConfigLike(baseDir) {
1326
1493
  try {
1327
- const parsed = JSON.parse(readFileSync3(join2(baseDir, "axis.config.json"), "utf8"));
1494
+ const parsed = JSON.parse(readFileSync4(join2(baseDir, "axis.config.json"), "utf8"));
1328
1495
  return isPlainObject2(parsed) ? parsed : void 0;
1329
1496
  } catch {
1330
1497
  return void 0;
@@ -1426,7 +1593,7 @@ function inspectTailwindContent(baseDirInput) {
1426
1593
  }
1427
1594
  }
1428
1595
  if (targets.length === 0) return null;
1429
- const read = readTailwindContent(readFileSync3(join2(baseDir, configFile), "utf8"));
1596
+ const read = readTailwindContent(readFileSync4(join2(baseDir, configFile), "utf8"));
1430
1597
  const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
1431
1598
  return {
1432
1599
  configFile,
@@ -1491,7 +1658,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
1491
1658
  if (st.isDirectory()) {
1492
1659
  if (name !== "node_modules" && depth < ANIMATION_SCAN_DEPTH_LIMIT) stack.push([p, depth + 1]);
1493
1660
  } else if (st.isFile() && st.size <= ANIMATION_SCAN_FILE_BYTES && /\.(tsx|ts|jsx|js)$/.test(name)) {
1494
- if (/\banimate-(?:in|out)\b/.test(readFileSync3(p, "utf8"))) return true;
1661
+ if (/\banimate-(?:in|out)\b/.test(readFileSync4(p, "utf8"))) return true;
1495
1662
  }
1496
1663
  }
1497
1664
  }
@@ -1508,7 +1675,7 @@ function checkAnimationPlugin(baseDirInput) {
1508
1675
  const tailwind = detectTailwind(baseDir, pkg);
1509
1676
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
1510
1677
  const file = TAILWIND_CSS_CANDIDATES.find((c) => existsSync3(join2(baseDir, c)));
1511
- const css = file !== void 0 ? stripCssComments(readFileSync3(join2(baseDir, file), "utf8")) : "";
1678
+ const css = file !== void 0 ? stripCssComments(readFileSync4(join2(baseDir, file), "utf8")) : "";
1512
1679
  const ok = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`).test(css) || new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(css);
1513
1680
  return ok ? { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` } : {
1514
1681
  name: "animation",
@@ -1517,19 +1684,85 @@ function checkAnimationPlugin(baseDirInput) {
1517
1684
  };
1518
1685
  }
1519
1686
  const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
1520
- const source = configFile !== void 0 ? stripJsComments(readFileSync3(join2(baseDir, configFile), "utf8")) : "";
1521
- const pluginRef = new RegExp(`["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(source);
1687
+ const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
1688
+ const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
1522
1689
  const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
1523
- if (pluginRef && pluginDeclared) {
1524
- return { name: "animation", severity: "pass", message: `${configFile}\uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` };
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` };
1525
1693
  }
1526
- const why = !pluginDeclared ? `${ANIMATION_PLUGIN_TAILWIND3} \uBBF8\uC124\uCE58` : `${configFile ?? "tailwind.config"} plugins \uC5D0 \uC5C6\uC74C`;
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`);
1527
1700
  return {
1528
1701
  name: "animation",
1529
1702
  severity: "warn",
1530
- message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${why}): 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}")`
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}")`
1531
1704
  };
1532
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;
1765
+ }
1533
1766
 
1534
1767
  // ../axis-registry-core/src/utils-deps.ts
1535
1768
  var CLSX_RANGE = "^2.1.1";
@@ -1948,7 +2181,7 @@ function missingDependencies(root, items) {
1948
2181
  const installCommand = detectInstallCommand(root);
1949
2182
  let pkg;
1950
2183
  try {
1951
- const text = readFileSync4(path5.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
2184
+ const text = readFileSync5(path5.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
1952
2185
  const parsed = JSON.parse(text);
1953
2186
  pkg = isPlainObject(parsed) ? parsed : void 0;
1954
2187
  } catch {
@@ -2069,7 +2302,7 @@ async function runAdd(cwd, requested, options, ctx) {
2069
2302
  continue;
2070
2303
  }
2071
2304
  try {
2072
- existing.set(file, readFileSync4(file.target, "utf8"));
2305
+ existing.set(file, readFileSync5(file.target, "utf8"));
2073
2306
  } catch (e) {
2074
2307
  readErrors.push(
2075
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})`
@@ -4174,7 +4407,7 @@ import fs6 from "fs-extra";
4174
4407
  import path9 from "path";
4175
4408
 
4176
4409
  // src/tools/brand-core.ts
4177
- import { existsSync as existsSync8, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
4410
+ import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
4178
4411
  import { createRequire } from "module";
4179
4412
  import { dirname as dirname3, join as join4, relative, resolve as resolve3, sep } from "path";
4180
4413
  var TOKENS_PACKAGE = "@axis-ds/tokens";
@@ -4196,7 +4429,7 @@ var KEY_TOKENS = [
4196
4429
  ];
4197
4430
  var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
4198
4431
  function readJsonFile(file) {
4199
- return JSON.parse(readFileSync7(file, "utf8"));
4432
+ return JSON.parse(readFileSync8(file, "utf8"));
4200
4433
  }
4201
4434
  function errorCode(err) {
4202
4435
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
@@ -4235,7 +4468,7 @@ function resolveTokens(baseDir) {
4235
4468
  function brandImportPath(entry) {
4236
4469
  return tokensSpecifier(entry.css);
4237
4470
  }
4238
- function isFile(file) {
4471
+ function isFile2(file) {
4239
4472
  try {
4240
4473
  return statSync5(file).isFile();
4241
4474
  } catch {
@@ -4248,12 +4481,12 @@ function findGlobalCss(baseDir, config) {
4248
4481
  const configured = config?.globalCss;
4249
4482
  if (typeof configured === "string" && configured.trim() !== "") {
4250
4483
  const file = resolve3(root, configured);
4251
- if (isFile(file)) return { path: file };
4484
+ if (isFile2(file)) return { path: file };
4252
4485
  result.configuredMissing = configured;
4253
4486
  }
4254
4487
  for (const candidate of GLOBAL_CSS_CANDIDATES) {
4255
4488
  const file = join4(root, candidate);
4256
- if (isFile(file)) {
4489
+ if (isFile2(file)) {
4257
4490
  result.path = file;
4258
4491
  break;
4259
4492
  }
@@ -4272,7 +4505,7 @@ var AXIS_CONFIG_FILE_NAME = "axis.config.json";
4272
4505
  function readBrandConfig(baseDir) {
4273
4506
  let parsed;
4274
4507
  try {
4275
- parsed = JSON.parse(readFileSync7(join4(resolve3(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
4508
+ parsed = JSON.parse(readFileSync8(join4(resolve3(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
4276
4509
  } catch {
4277
4510
  return null;
4278
4511
  }
@@ -4291,7 +4524,7 @@ function inspectBrandImport(baseDir) {
4291
4524
  return { ...base, state: "css-missing", imports: [] };
4292
4525
  }
4293
4526
  const cssFile = relative(root, location.path).split(sep).join("/");
4294
- const imports = [...new Set(findBrandImports(readFileSync7(location.path, "utf8")))];
4527
+ const imports = [...new Set(findBrandImports(readFileSync8(location.path, "utf8")))];
4295
4528
  let state;
4296
4529
  if (imports.includes(brand)) state = "match";
4297
4530
  else if (imports.length === 0) state = "import-missing";
@@ -4375,34 +4608,23 @@ function pickKeyTokens(decls) {
4375
4608
  }
4376
4609
  return out;
4377
4610
  }
4611
+ var THEME_MARKUP_BRAND_MIN_VERSION = "1.7.0";
4378
4612
  function providerExample(name) {
4379
4613
  return [
4380
- "// 1) Provider \uC5C6\uC774: \uB8E8\uD2B8 \uB808\uC774\uC544\uC6C3(app/layout.tsx)\uC758 <html> \uC5D0 \uBD99\uC785\uB2C8\uB2E4(\uCCAB \uD654\uBA74\uBD80\uD130 \uC801\uC6A9)",
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)`,
4381
4616
  `<html lang="ko" data-brand="${name}">`,
4382
4617
  "",
4383
- "// 2) ThemeProvider \uB97C \uC4F0\uBA74 \uB9C8\uC6B4\uD2B8 \uB54C \uBE0C\uB79C\uB4DC\uAC00 \uC5C6\uC73C\uBA74 \uC18D\uC131\uC744 \uC9C0\uC6B0\uBBC0\uB85C setBrand \uB85C \uCF2D\uB2C8\uB2E4(\uC800\uC7A5\uB3FC \uC720\uC9C0, setBrand(undefined) \uB85C \uB054)",
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)`,
4384
4619
  'import { useTheme } from "@axis-ds/theme";',
4385
4620
  "const { setBrand } = useTheme();",
4386
4621
  `setBrand("${name}");`
4387
4622
  ].join("\n");
4388
4623
  }
4389
- var BRAND_ACTIVATION_FILES = [
4390
- "app/layout.tsx",
4391
- "app/layout.jsx",
4392
- "app/layout.js",
4393
- "src/app/layout.tsx",
4394
- "src/app/layout.jsx",
4395
- "src/app/layout.js",
4396
- "pages/_app.tsx",
4397
- "pages/_app.jsx",
4398
- "pages/_document.tsx",
4399
- "pages/_document.jsx",
4400
- "src/pages/_app.tsx",
4401
- "src/pages/_app.jsx",
4402
- "src/pages/_document.tsx",
4403
- "src/pages/_document.jsx"
4404
- ];
4624
+ var BRAND_ACTIVATION_FILES = ROOT_LAYOUT_FILES;
4405
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/;
4406
4628
  function stripJsLikeComments(src) {
4407
4629
  return src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`])\/\/[^\n]*/g, "$1");
4408
4630
  }
@@ -4411,17 +4633,25 @@ function findBrandActivation(baseDir) {
4411
4633
  const layoutFiles = [];
4412
4634
  for (const candidate of BRAND_ACTIVATION_FILES) {
4413
4635
  const file = join4(root, candidate);
4414
- if (!isFile(file)) continue;
4636
+ if (!isFile2(file)) continue;
4415
4637
  layoutFiles.push(candidate);
4416
- const text = stripJsLikeComments(readFileSync7(file, "utf8"));
4417
- if (BRAND_ACTIVATION_PATTERN.test(text)) return { found: candidate, layoutFiles };
4638
+ const text = stripJsLikeComments(readFileSync8(file, "utf8"));
4639
+ const providerTexts = [];
4418
4640
  for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
4419
4641
  for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
4420
4642
  const rel2 = `${dirname3(candidate)}/${m[1]}${ext}`;
4421
4643
  const p = join4(root, rel2);
4422
- if (isFile(p) && BRAND_ACTIVATION_PATTERN.test(stripJsLikeComments(readFileSync7(p, "utf8")))) {
4423
- return { found: rel2, layoutFiles };
4424
- }
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 };
4425
4655
  }
4426
4656
  }
4427
4657
  }
@@ -4431,7 +4661,18 @@ function inspectBrandActivation(baseDir) {
4431
4661
  const config = readBrandConfig(baseDir);
4432
4662
  const brand = config?.brand;
4433
4663
  if (typeof brand !== "string" || brand.trim() === "") return null;
4434
- return { brand, ...findBrandActivation(baseDir) };
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
+ }
4435
4676
  }
4436
4677
  function getBrand(baseDir, name) {
4437
4678
  const tokens = resolveTokens(baseDir);
@@ -4449,7 +4690,7 @@ function getBrand(baseDir, name) {
4449
4690
  try {
4450
4691
  summary = readSummary(baseDir, entry);
4451
4692
  const cssPath = projectRequire(baseDir).resolve(summary.importPath);
4452
- parsed = parseBrandCss(readFileSync7(cssPath, "utf8"), name);
4693
+ parsed = parseBrandCss(readFileSync8(cssPath, "utf8"), name);
4453
4694
  } catch (err) {
4454
4695
  if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
4455
4696
  throw err;
@@ -4467,6 +4708,57 @@ function getBrand(baseDir, name) {
4467
4708
  };
4468
4709
  }
4469
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
+
4470
4762
  // src/site.ts
4471
4763
  var AXIS_SITE_URL2 = "https://axis-design-system.pages.dev";
4472
4764
 
@@ -4622,6 +4914,15 @@ function brandCheckResult(check) {
4622
4914
  }
4623
4915
  }
4624
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
+ }
4625
4926
  if (check.found) {
4626
4927
  return {
4627
4928
  name: "brand.activation",
@@ -4676,40 +4977,7 @@ async function handleCheckProject(params) {
4676
4977
  message: "utils.ts\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC2DC \uD544\uC694)"
4677
4978
  });
4678
4979
  }
4679
- const pkgPath = path9.join(baseDir, "package.json");
4680
- if (await fs6.pathExists(pkgPath)) {
4681
- const pkg = await fs6.readJSON(pkgPath);
4682
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
4683
- const required = ["tailwindcss"];
4684
- const recommended = ["clsx", "tailwind-merge"];
4685
- const missingRequired = required.filter((d) => !allDeps[d]);
4686
- const missingRecommended = recommended.filter((d) => !allDeps[d]);
4687
- if (missingRequired.length > 0) {
4688
- results.push({
4689
- name: "dependencies",
4690
- severity: "fail",
4691
- message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}`
4692
- });
4693
- } else if (missingRecommended.length > 0) {
4694
- results.push({
4695
- name: "dependencies",
4696
- severity: "warn",
4697
- message: `\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`
4698
- });
4699
- } else {
4700
- results.push({
4701
- name: "dependencies",
4702
- severity: "pass",
4703
- message: "\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uBAA8\uB450 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4"
4704
- });
4705
- }
4706
- } else {
4707
- results.push({
4708
- name: "dependencies",
4709
- severity: "fail",
4710
- message: "package.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
4711
- });
4712
- }
4980
+ results.push(checkDependencies(baseDir));
4713
4981
  const brandCheck = inspectBrandImport(baseDir);
4714
4982
  if (brandCheck) results.push(brandCheckResult(brandCheck));
4715
4983
  const activation = inspectBrandActivation(baseDir);