@axis-ds/mcp 1.4.5 → 1.4.7

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.
Files changed (2) hide show
  1. package/dist/index.js +1076 -145
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -77,7 +77,7 @@ function getTokenStats() {
77
77
  }
78
78
 
79
79
  // ../axis-registry-core/src/add/add.ts
80
- import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
80
+ import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
81
81
  import path5 from "path";
82
82
  import fs3 from "fs-extra";
83
83
 
@@ -237,8 +237,8 @@ function validateRegistryIndex(data, where = "index.json") {
237
237
  if (!isValidRegistryName(raw.name)) throw new Error(`${at}: name \uC774 slug \uADDC\uCE59\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
238
238
  if (seen.has(raw.name)) throw new Error(`${at}: name '${raw.name}' \uAC00 \uC911\uBCF5\uC785\uB2C8\uB2E4`);
239
239
  seen.add(raw.name);
240
- const sha256 = optionalString(raw, "sha256", at);
241
- if (sha256 !== void 0 && !/^[0-9a-f]{64}$/.test(sha256)) {
240
+ const sha2562 = optionalString(raw, "sha256", at);
241
+ if (sha2562 !== void 0 && !/^[0-9a-f]{64}$/.test(sha2562)) {
242
242
  throw new Error(`${at}: sha256 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
243
243
  }
244
244
  return {
@@ -246,7 +246,7 @@ function validateRegistryIndex(data, where = "index.json") {
246
246
  type: requireType(raw, at),
247
247
  title: optionalString(raw, "title", at),
248
248
  description: optionalString(raw, "description", at),
249
- ...sha256 !== void 0 ? { sha256 } : {}
249
+ ...sha2562 !== void 0 ? { sha256: sha2562 } : {}
250
250
  };
251
251
  });
252
252
  return {
@@ -871,7 +871,7 @@ var RegistryClient = class {
871
871
  };
872
872
 
873
873
  // ../axis-registry-core/src/project.ts
874
- import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, statSync } from "fs";
874
+ import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3, realpathSync, statSync } from "fs";
875
875
  import path3 from "path";
876
876
  function resolveBaseDir(baseDirInput) {
877
877
  const resolved = path3.resolve(baseDirInput);
@@ -1062,6 +1062,39 @@ function isFile(file) {
1062
1062
  return false;
1063
1063
  }
1064
1064
  }
1065
+ function isDirectory(dir) {
1066
+ try {
1067
+ return statSync(dir).isDirectory();
1068
+ } catch {
1069
+ return false;
1070
+ }
1071
+ }
1072
+ function selectGlobalCss(baseDir, configured, candidates, options = {}) {
1073
+ const result = {};
1074
+ if (typeof configured === "string" && configured.trim() !== "") {
1075
+ const file = path3.resolve(baseDir, configured);
1076
+ if (!isFile(file)) result.configuredMissing = configured;
1077
+ else if (options.requireStylesheet && path3.extname(file).toLowerCase() !== ".css") result.configuredRejected = configured;
1078
+ else return { path: file, rel: path3.relative(baseDir, file).split(path3.sep).join("/") };
1079
+ }
1080
+ for (const candidate of candidates) {
1081
+ const file = path3.join(baseDir, candidate);
1082
+ if (isFile(file)) {
1083
+ result.path = file;
1084
+ result.rel = candidate;
1085
+ break;
1086
+ }
1087
+ }
1088
+ return result;
1089
+ }
1090
+ function globalCssSelectionNote(selection) {
1091
+ if (selection.configuredMissing !== void 0) return ` (globalCss ${selection.configuredMissing} \uC5C6\uC74C)`;
1092
+ if (selection.configuredRejected !== void 0) return ` (globalCss ${selection.configuredRejected}: .css \uD30C\uC77C\uC774 \uC544\uB2D8)`;
1093
+ return "";
1094
+ }
1095
+ function cssImportViaNote(files) {
1096
+ return files !== void 0 && files.length > 0 ? ` (${files.join(" \xB7 ")} \uC758 import)` : "";
1097
+ }
1065
1098
  var ROOT_LAYOUT_FILES = [
1066
1099
  "app/layout.tsx",
1067
1100
  "app/layout.jsx",
@@ -1105,15 +1138,290 @@ function findInstalledPackage(baseDirInput, name) {
1105
1138
  }
1106
1139
  }
1107
1140
  function isPnpProject(baseDirInput) {
1141
+ return pnpProjectRoot(baseDirInput) !== void 0;
1142
+ }
1143
+ function pnpProjectRoot(baseDirInput) {
1108
1144
  let dir = resolveBaseDir(baseDirInput);
1109
1145
  for (; ; ) {
1110
- if (isFile(path3.join(dir, ".pnp.cjs")) || isFile(path3.join(dir, ".pnp.js"))) return true;
1111
- if (existsSync2(path3.join(dir, ".git"))) return false;
1146
+ if (isFile(path3.join(dir, ".pnp.cjs")) || isFile(path3.join(dir, ".pnp.js"))) return dir;
1147
+ if (existsSync2(path3.join(dir, ".git"))) return void 0;
1148
+ const parent = path3.dirname(dir);
1149
+ if (parent === dir) return void 0;
1150
+ dir = parent;
1151
+ }
1152
+ }
1153
+ var TAILWIND4_MIN_AXIS_VERSION = "1.4.0";
1154
+ var COMPONENT_TAILWIND_CSS_MIN_VERSION = TAILWIND4_MIN_AXIS_VERSION;
1155
+ function componentCssResolution(baseDir, pkg, name) {
1156
+ if (pkg === void 0) return { kind: "undeclared" };
1157
+ const own = hasDependency(pkg, name);
1158
+ if (own !== void 0) return { kind: "app", range: own };
1159
+ const pnpRoot = pnpRootOnlyDependency(baseDir, pkg, name);
1160
+ if (pnpRoot !== void 0) return { kind: "pnp-root-only", range: pnpRoot.range };
1161
+ const declared = declaredDependency(baseDir, pkg, name);
1162
+ if (declared?.source !== "root") return { kind: "undeclared" };
1163
+ if (!rootDeclarationsAllowed(baseDir, pkg)) return { kind: "app-lockfile", range: declared.range };
1164
+ const installed = findInstalledPackage(baseDir, name);
1165
+ if (installed === void 0) return { kind: "root-not-installed", range: declared.range };
1166
+ if (isFile(path3.join(installed.dir, "tailwind.css"))) {
1167
+ return installed.version !== void 0 ? { kind: "root-ok", range: declared.range, installedVersion: installed.version } : { kind: "root-ok", range: declared.range };
1168
+ }
1169
+ const installedVersion = installed.version ?? "?";
1170
+ const current = installedVersion !== "?" && (compareExactVersions(installedVersion, COMPONENT_TAILWIND_CSS_MIN_VERSION) ?? -1) >= 0;
1171
+ return current ? { kind: "root-missing-file", range: declared.range, installedVersion } : { kind: "root-old", range: declared.range, installedVersion };
1172
+ }
1173
+ function componentCssResolvable(resolution) {
1174
+ return resolution.kind === "app" || resolution.kind === "root-ok";
1175
+ }
1176
+ function tokensCssResolution(baseDir, pkg, name = "@axis-ds/tokens") {
1177
+ const own = pkg !== void 0 ? hasDependency(pkg, name) : void 0;
1178
+ if (own !== void 0) return { kind: "app", range: own };
1179
+ const pnpRoot = pnpRootOnlyDependency(baseDir, pkg, name);
1180
+ if (pnpRoot !== void 0) return { kind: "pnp-root-only", range: pnpRoot.range };
1181
+ if (!isPnpProject(baseDir) && findInstalledPackage(baseDir, name) !== void 0) return { kind: "installed" };
1182
+ const declared = rootDeclarationsAllowed(baseDir, pkg) ? declaredDependency(baseDir, pkg, name) : void 0;
1183
+ return declared?.source === "root" ? { kind: "not-installed", source: "root", range: declared.range } : { kind: "not-installed", source: "none" };
1184
+ }
1185
+ function outsideCssPackageResolution(baseDir, cssDir, name, file) {
1186
+ if (isPnpProject(baseDir)) return "unknown";
1187
+ const usable = (p) => p !== void 0 && (file === void 0 || isFile(path3.join(p.dir, file)));
1188
+ if (!usable(findInstalledPackage(baseDir, name))) return "unknown";
1189
+ return usable(findInstalledPackage(cssDir, name)) ? "resolved" : "unresolved";
1190
+ }
1191
+ var CSS_EXPORT_CONDITIONS = /* @__PURE__ */ new Set(["style", "default"]);
1192
+ function splitPackageSpec(spec) {
1193
+ const parts = spec.split("/");
1194
+ const n = spec.startsWith("@") ? 2 : 1;
1195
+ if (parts.length < n || parts.slice(0, n).some((p) => p === "" || p === "." || p === "..")) return void 0;
1196
+ return { name: parts.slice(0, n).join("/"), rest: parts.slice(n).join("/") };
1197
+ }
1198
+ function resolveExportTarget(value) {
1199
+ if (typeof value === "string") return value;
1200
+ if (Array.isArray(value)) {
1201
+ for (const v of value) {
1202
+ const r = resolveExportTarget(v);
1203
+ if (r !== void 0) return r;
1204
+ }
1205
+ return void 0;
1206
+ }
1207
+ if (isPlainObject(value)) {
1208
+ for (const [key, v] of Object.entries(value)) {
1209
+ if (!CSS_EXPORT_CONDITIONS.has(key)) continue;
1210
+ if (v === null) return void 0;
1211
+ const r = resolveExportTarget(v);
1212
+ if (r !== void 0) return r;
1213
+ }
1214
+ }
1215
+ return void 0;
1216
+ }
1217
+ function cssFileCandidates(p) {
1218
+ return [p, `${p}.css`, path3.join(p, "index.css")];
1219
+ }
1220
+ function exportsTarget(exportsField, subpath) {
1221
+ const map = isPlainObject(exportsField) && Object.keys(exportsField).some((k) => k.startsWith(".")) ? exportsField : { ".": exportsField };
1222
+ if (Object.prototype.hasOwnProperty.call(map, subpath)) {
1223
+ const t = resolveExportTarget(map[subpath]);
1224
+ if (t === void 0) return void 0;
1225
+ return t.includes("*") || !t.startsWith("./") ? "?" : t;
1226
+ }
1227
+ if (Object.keys(map).some((k) => k.includes("*") || k.endsWith("/") && subpath.startsWith(k))) return "?";
1228
+ return void 0;
1229
+ }
1230
+ function resolveCssPackageImport(fromDir, spec) {
1231
+ const parsed = splitPackageSpec(spec);
1232
+ if (parsed === void 0 || parsed.rest === "") return { kind: "unknown" };
1233
+ const subpath = `./${parsed.rest}`;
1234
+ let dir = resolveBaseDir(fromDir);
1235
+ for (; ; ) {
1236
+ const pkgDir = path3.join(dir, "node_modules", ...parsed.name.split("/"));
1237
+ if (isDirectory(pkgDir)) {
1238
+ let manifest;
1239
+ try {
1240
+ const raw = JSON.parse(readFileSync3(path3.join(pkgDir, "package.json"), "utf8"));
1241
+ manifest = isPlainObject(raw) ? raw : void 0;
1242
+ } catch {
1243
+ manifest = void 0;
1244
+ }
1245
+ if (manifest !== void 0 && manifest.exports) {
1246
+ const version = exactVersionOf(manifest.version);
1247
+ const target = exportsTarget(manifest.exports, subpath);
1248
+ if (target === "?") return { kind: "unknown" };
1249
+ if (target === void 0) {
1250
+ return version !== void 0 ? { kind: "not-exported", pkgDir, subpath, version } : { kind: "not-exported", pkgDir, subpath };
1251
+ }
1252
+ const file = cssFileCandidates(path3.join(pkgDir, target)).find(isFile);
1253
+ if (file !== void 0) return { kind: "resolved", pkgDir, file };
1254
+ return version !== void 0 ? { kind: "target-missing", pkgDir, subpath, target, version } : { kind: "target-missing", pkgDir, subpath, target };
1255
+ }
1256
+ const bare = cssFileCandidates(path3.join(pkgDir, parsed.rest)).find(isFile);
1257
+ if (bare !== void 0) return { kind: "resolved", pkgDir, file: bare };
1258
+ }
1112
1259
  const parent = path3.dirname(dir);
1113
- if (parent === dir) return false;
1260
+ if (parent === dir) return { kind: "not-found" };
1114
1261
  dir = parent;
1115
1262
  }
1116
1263
  }
1264
+ function installBase(pkgDir, name) {
1265
+ let base = pkgDir;
1266
+ for (let i = 0; i < name.split("/").length + 1; i++) base = path3.dirname(base);
1267
+ try {
1268
+ return realpathSync(base);
1269
+ } catch {
1270
+ return path3.resolve(base);
1271
+ }
1272
+ }
1273
+ function isAncestorInstall(hit, app, name) {
1274
+ const h = installBase(hit, name);
1275
+ const a = installBase(app, name);
1276
+ return a !== h && a.startsWith(h.endsWith(path3.sep) ? h : h + path3.sep);
1277
+ }
1278
+ function sameRealDir(a, b) {
1279
+ const real = (p) => {
1280
+ try {
1281
+ return realpathSync(p);
1282
+ } catch {
1283
+ return path3.resolve(p);
1284
+ }
1285
+ };
1286
+ return real(a) === real(b);
1287
+ }
1288
+ function cssPackageLineResolution(baseDir, lineDir, spec, otherDirs = []) {
1289
+ if (isPnpProject(baseDir)) return { kind: "ok" };
1290
+ const parsed = splitPackageSpec(spec);
1291
+ if (parsed === void 0) return { kind: "ok" };
1292
+ const r = resolveCssPackageImport(lineDir, spec);
1293
+ if (r.kind === "resolved" || r.kind === "unknown") return { kind: "ok" };
1294
+ const app = findInstalledPackage(baseDir, parsed.name);
1295
+ if (r.kind === "not-exported" || r.kind === "target-missing") {
1296
+ if (app !== void 0 && sameRealDir(app.dir, r.pkgDir)) return { kind: "ok" };
1297
+ if (app !== void 0 && isAncestorInstall(r.pkgDir, app.dir, parsed.name)) return { kind: "ok" };
1298
+ return r.kind === "not-exported" ? { ...r, kind: "shadow-not-exported" } : { ...r, kind: "shadow-target-missing" };
1299
+ }
1300
+ if (app !== void 0) return { kind: "ok" };
1301
+ for (const other of typeof otherDirs === "function" ? otherDirs() : otherDirs) {
1302
+ const o = resolveCssPackageImport(other, spec);
1303
+ if (o.kind === "resolved") return { kind: "not-visible", pkgDir: o.pkgDir, fromDir: resolveBaseDir(other) };
1304
+ }
1305
+ return { kind: "ok" };
1306
+ }
1307
+ function findPnpUnpluggedPackages(baseDirInput, name, range) {
1308
+ const root = pnpProjectRoot(baseDirInput);
1309
+ if (root === void 0) return [];
1310
+ const unplugged = path3.join(root, ".yarn", "unplugged");
1311
+ let entries;
1312
+ try {
1313
+ entries = readdirSync(unplugged).sort();
1314
+ } catch {
1315
+ return [];
1316
+ }
1317
+ const found = [];
1318
+ for (const entry of entries) {
1319
+ const pkgDir = path3.join(unplugged, entry, "node_modules", ...name.split("/"));
1320
+ let version;
1321
+ try {
1322
+ const parsed = JSON.parse(readFileSync3(path3.join(pkgDir, "package.json"), "utf8"));
1323
+ version = isPlainObject(parsed) && parsed.name === name ? exactVersionOf(parsed.version) : void 0;
1324
+ } catch {
1325
+ version = void 0;
1326
+ }
1327
+ if (version !== void 0 && versionSatisfiesRange(version, range) === true) found.push(pkgDir);
1328
+ }
1329
+ return found;
1330
+ }
1331
+ function parsePartialVersion(token) {
1332
+ const m = /^v?(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(token.trim());
1333
+ if (!m) return void 0;
1334
+ const num = (s) => s === void 0 || /^[xX*]$/.test(s) ? void 0 : Number(s);
1335
+ const major = num(m[1]);
1336
+ const minor = major === void 0 ? void 0 : num(m[2]);
1337
+ const patch = minor === void 0 ? void 0 : num(m[3]);
1338
+ return { major, minor, patch, pre: patch === void 0 ? void 0 : m[4] };
1339
+ }
1340
+ function coreOf(v) {
1341
+ return v.replace(/^v/, "").replace(/[-+].*$/, "");
1342
+ }
1343
+ function intervalsOfToken(token) {
1344
+ const t = token.trim();
1345
+ if (t === "" || t === "*" || /^[xX]$/.test(t)) return [{ preCores: [] }];
1346
+ const op = /^(\^|~>?|>=|<=|>|<|=)?\s*(.+)$/.exec(t);
1347
+ if (!op) return void 0;
1348
+ const p = parsePartialVersion(op[2]);
1349
+ if (!p) return void 0;
1350
+ const full = (maj, min, pat, pre) => `${maj}.${min}.${pat}${pre ? `-${pre}` : ""}`;
1351
+ const preCores = p.pre !== void 0 ? [full(p.major ?? 0, p.minor ?? 0, p.patch ?? 0)] : [];
1352
+ const lower = full(p.major ?? 0, p.minor ?? 0, p.patch ?? 0, p.pre);
1353
+ const kind = op[1] ?? "";
1354
+ if (p.major === void 0) return kind === "" || kind === "=" || kind === ">=" ? [{ preCores }] : void 0;
1355
+ const next = p.minor === void 0 ? full(p.major + 1, 0, 0) : p.patch === void 0 ? full(p.major, p.minor + 1, 0) : void 0;
1356
+ switch (kind) {
1357
+ case "":
1358
+ case "=":
1359
+ return [next === void 0 ? { min: { v: lower, inclusive: true }, max: { v: lower, inclusive: true }, preCores } : { min: { v: lower, inclusive: true }, max: { v: next, inclusive: false, coreOnly: true }, preCores }];
1360
+ case ">=":
1361
+ return [{ min: { v: lower, inclusive: true }, preCores }];
1362
+ case ">":
1363
+ return [next === void 0 ? { min: { v: lower, inclusive: false }, preCores } : { min: { v: next, inclusive: true }, preCores }];
1364
+ case "<":
1365
+ return [{ max: { v: lower, inclusive: false, coreOnly: p.pre === void 0 }, preCores }];
1366
+ case "<=":
1367
+ return [next === void 0 ? { max: { v: lower, inclusive: true }, preCores } : { max: { v: next, inclusive: false, coreOnly: true }, preCores }];
1368
+ case "~":
1369
+ case "~>": {
1370
+ const upper = p.minor === void 0 ? full(p.major + 1, 0, 0) : full(p.major, p.minor + 1, 0);
1371
+ return [{ min: { v: lower, inclusive: true }, max: { v: upper, inclusive: false, coreOnly: true }, preCores }];
1372
+ }
1373
+ case "^": {
1374
+ const upper = p.major > 0 || p.minor === void 0 ? full(p.major + 1, 0, 0) : p.minor > 0 || p.patch === void 0 ? full(0, p.minor + 1, 0) : full(0, 0, p.patch + 1);
1375
+ return [{ min: { v: lower, inclusive: true }, max: { v: upper, inclusive: false, coreOnly: true }, preCores }];
1376
+ }
1377
+ }
1378
+ return void 0;
1379
+ }
1380
+ function satisfiesInterval(version, iv) {
1381
+ if (iv.min !== void 0) {
1382
+ const c = compareExactVersions(version, iv.min.v);
1383
+ if (c === void 0) return void 0;
1384
+ if (c < 0 || c === 0 && !iv.min.inclusive) return false;
1385
+ }
1386
+ if (iv.max !== void 0) {
1387
+ const c = iv.max.coreOnly ? compareExactVersions(coreOf(version), coreOf(iv.max.v)) : compareExactVersions(version, iv.max.v);
1388
+ if (c === void 0) return void 0;
1389
+ if (c > 0 || c === 0 && !iv.max.inclusive) return false;
1390
+ }
1391
+ return true;
1392
+ }
1393
+ function versionSatisfiesRange(version, range) {
1394
+ if (exactVersionOf(version) === void 0) return void 0;
1395
+ const alternatives = range.trim().split("||");
1396
+ let unknown = false;
1397
+ for (const alt of alternatives) {
1398
+ const a = alt.trim();
1399
+ let intervals;
1400
+ const hyphen = /^(\S+)\s+-\s+(\S+)$/.exec(a);
1401
+ if (hyphen) {
1402
+ const lo = intervalsOfToken(`>=${hyphen[1]}`);
1403
+ const hi = intervalsOfToken(`<=${hyphen[2]}`);
1404
+ intervals = lo && hi ? [...lo, ...hi] : void 0;
1405
+ } else {
1406
+ const tokens = a === "" ? [""] : a.replace(/(>=|<=|>|<|=|\^|~>?)\s+/g, "$1").split(/\s+/);
1407
+ const parts = tokens.map(intervalsOfToken);
1408
+ intervals = parts.every((x) => x !== void 0) ? parts.flat() : void 0;
1409
+ }
1410
+ if (intervals === void 0) {
1411
+ unknown = true;
1412
+ continue;
1413
+ }
1414
+ const pre = /-/.test(version.replace(/\+.*$/, ""));
1415
+ if (pre && !intervals.some((iv) => iv.preCores.includes(coreOf(version)))) continue;
1416
+ const results = intervals.map((iv) => satisfiesInterval(version, iv));
1417
+ if (results.some((x) => x === void 0)) {
1418
+ unknown = true;
1419
+ continue;
1420
+ }
1421
+ if (results.every((x) => x === true)) return true;
1422
+ }
1423
+ return unknown ? void 0 : false;
1424
+ }
1117
1425
  function compareExactVersions(a, b) {
1118
1426
  const parse = (v) => {
1119
1427
  const m = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?/.exec(v.trim());
@@ -1127,7 +1435,7 @@ function compareExactVersions(a, b) {
1127
1435
  }
1128
1436
 
1129
1437
  // ../axis-registry-core/src/template/tailwind-core.ts
1130
- import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4, realpathSync as realpathSync2 } from "fs";
1438
+ import { existsSync as existsSync3, lstatSync, readdirSync as readdirSync2, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
1131
1439
  import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "path";
1132
1440
  function declaredRange(baseDir, pkg, name) {
1133
1441
  return declaredDependency(baseDir, pkg, name)?.range;
@@ -1255,6 +1563,157 @@ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/s
1255
1563
  function findTokensCssImport(css) {
1256
1564
  return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
1257
1565
  }
1566
+ var CSS_IMPORT_DEPTH_LIMIT = 32;
1567
+ var CSS_IMPORT_CYCLE_DEPTH_LIMIT = 100;
1568
+ var RELATIVE_CSS_IMPORT = /@import\s*(?:"(\.{1,2}\/[^"\n]*)"|'(\.{1,2}\/[^'\n]*)')(?=([^;{}]*))/g;
1569
+ function isConditionalCssImport(tail) {
1570
+ return tail !== void 0 && tail.trim() !== "";
1571
+ }
1572
+ function resolveRelativeCssImport(fromDir, spec) {
1573
+ if (spec.endsWith("/")) return void 0;
1574
+ const target = resolve(fromDir, spec);
1575
+ if (regularFile(target)) return target;
1576
+ if (regularFile(`${target}.css`)) return `${target}.css`;
1577
+ return void 0;
1578
+ }
1579
+ var CSS_IMPORT_SPEC = /@import\s+(?:url\(\s*)?(["'])([^"'\n]+)\1/g;
1580
+ function isPackageCssSpec(spec) {
1581
+ return !spec.startsWith("./") && !spec.startsWith("../") && !spec.startsWith("/") && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(spec);
1582
+ }
1583
+ function cssImportCycleIssue(files) {
1584
+ if (files.length === 1) return `${files[0]} \uC774 \uC790\uAE30 \uC790\uC2E0\uC744 @import \uD574 \uBE4C\uB4DC\uAC00 \uC21C\uD658\uC73C\uB85C \uC2E4\uD328\uD569\uB2C8\uB2E4 \u2192 \uC21C\uD658\uD558\uB294 @import \uB97C \uC5C6\uC560\uC138\uC694`;
1585
+ return `${files.join(" \xB7 ")} \uC774 \uC11C\uB85C @import \uD574 \uBE4C\uB4DC\uAC00 \uC21C\uD658\uC73C\uB85C \uC2E4\uD328\uD569\uB2C8\uB2E4 \u2192 \uC21C\uD658\uD558\uB294 @import \uB97C \uC5C6\uC560\uC138\uC694`;
1586
+ }
1587
+ function findImportCycle(start, edges) {
1588
+ const state = /* @__PURE__ */ new Map();
1589
+ const trail = [start];
1590
+ const stack = [{ node: start, next: 0 }];
1591
+ state.set(start, "open");
1592
+ while (stack.length > 0) {
1593
+ const top = stack[stack.length - 1];
1594
+ const out = edges.get(top.node) ?? [];
1595
+ if (top.next >= out.length) {
1596
+ state.set(top.node, "done");
1597
+ stack.pop();
1598
+ trail.pop();
1599
+ continue;
1600
+ }
1601
+ const to = out[top.next++];
1602
+ const s = state.get(to);
1603
+ if (s === "open") return trail.slice(trail.indexOf(to));
1604
+ if (s === "done") continue;
1605
+ state.set(to, "open");
1606
+ trail.push(to);
1607
+ stack.push({ node: to, next: 0 });
1608
+ }
1609
+ return void 0;
1610
+ }
1611
+ function regularFile(file) {
1612
+ try {
1613
+ return statSync2(file).isFile();
1614
+ } catch {
1615
+ return false;
1616
+ }
1617
+ }
1618
+ function expandGlobalCss(baseDirInput, entryPath, entryRel, entryCssDir) {
1619
+ const baseDir = resolveBaseDir(baseDirInput);
1620
+ const entry = readFileSync4(entryPath, "utf8");
1621
+ let entryReal = entryPath;
1622
+ try {
1623
+ entryReal = realpathSync2(entryPath);
1624
+ } catch {
1625
+ }
1626
+ const raws = /* @__PURE__ */ new Map([[entryReal, entry]]);
1627
+ const files = [];
1628
+ const packageLines = [];
1629
+ const evidenceWalk = walkRelativeCssImports(baseDir, entryReal, raws, CSS_IMPORT_DEPTH_LIMIT, false);
1630
+ const relOfReal = /* @__PURE__ */ new Map([[entryReal, entryRel]]);
1631
+ for (const node of evidenceWalk.order) {
1632
+ const isEntry = node.real === entryReal;
1633
+ const rel2 = isEntry ? entryRel : node.rel;
1634
+ const css = stripCssComments(raws.get(node.real) ?? "");
1635
+ const file = { rel: rel2, path: node.real, css, depth: node.depth };
1636
+ const cssDir = isEntry ? entryCssDir : dirname2(node.real);
1637
+ if (cssDir !== void 0) file.cssDir = cssDir;
1638
+ files.push(file);
1639
+ relOfReal.set(node.real, rel2);
1640
+ for (const m of css.matchAll(CSS_IMPORT_SPEC)) {
1641
+ if (!isPackageCssSpec(m[2])) continue;
1642
+ const line = { spec: m[2], file: rel2 };
1643
+ if (cssDir !== void 0) line.cssDir = cssDir;
1644
+ packageLines.push(line);
1645
+ }
1646
+ }
1647
+ const cycleWalk = walkRelativeCssImports(baseDir, entryReal, raws, CSS_IMPORT_CYCLE_DEPTH_LIMIT, true);
1648
+ const cycle = findImportCycle(entryReal, cycleWalk.edges);
1649
+ if (cycle !== void 0) {
1650
+ for (const node of cycleWalk.order) if (!relOfReal.has(node.real)) relOfReal.set(node.real, node.rel);
1651
+ const head = files[0];
1652
+ return {
1653
+ entry,
1654
+ evidence: entry,
1655
+ files: [head],
1656
+ packageLines: packageLines.filter((l) => l.file === head.rel),
1657
+ cycle: cycle.map((p) => relOfReal.get(p) ?? p)
1658
+ };
1659
+ }
1660
+ const evidence = files.length === 1 ? entry : files.map((f) => f.css).join("\n");
1661
+ return { entry, evidence, files, packageLines };
1662
+ }
1663
+ function walkRelativeCssImports(baseDir, entryReal, raws, limit, includeConditional) {
1664
+ const order = [];
1665
+ const edges = /* @__PURE__ */ new Map();
1666
+ const visited = /* @__PURE__ */ new Set([entryReal]);
1667
+ const queue = [{ real: entryReal, rel: "", depth: 0 }];
1668
+ while (queue.length > 0) {
1669
+ const cur = queue.shift();
1670
+ order.push(cur);
1671
+ const css = stripCssComments(raws.get(cur.real) ?? "");
1672
+ const out = [];
1673
+ edges.set(cur.real, out);
1674
+ for (const m of css.matchAll(RELATIVE_CSS_IMPORT)) {
1675
+ if (!includeConditional && isConditionalCssImport(m[3])) continue;
1676
+ const target = resolveRelativeCssImport(dirname2(cur.real), m[1] ?? m[2]);
1677
+ if (target === void 0) continue;
1678
+ let real;
1679
+ try {
1680
+ real = realpathSync2(target);
1681
+ } catch {
1682
+ continue;
1683
+ }
1684
+ if (visited.has(real)) {
1685
+ out.push(real);
1686
+ continue;
1687
+ }
1688
+ if (cur.depth >= limit) continue;
1689
+ const rel2 = relative(baseDir, real);
1690
+ if (rel2 === "" || rel2 === ".." || rel2.startsWith(`..${sep}`) || isAbsolute(rel2)) continue;
1691
+ if (!raws.has(real)) {
1692
+ try {
1693
+ raws.set(real, readFileSync4(real, "utf8"));
1694
+ } catch {
1695
+ continue;
1696
+ }
1697
+ }
1698
+ visited.add(real);
1699
+ out.push(real);
1700
+ queue.push({ real, rel: rel2.split(sep).join("/"), depth: cur.depth + 1 });
1701
+ }
1702
+ }
1703
+ return { order, edges };
1704
+ }
1705
+ function evidenceOrigin(expanded, test) {
1706
+ return expanded.files.find((f) => test(f.css));
1707
+ }
1708
+ function packageLineCssDir(expanded, spec) {
1709
+ const line = expanded.packageLines.find((l) => l.spec === spec);
1710
+ return line !== void 0 ? line.cssDir : expanded.files[0]?.cssDir;
1711
+ }
1712
+ function viaFiles(origins) {
1713
+ const out = [];
1714
+ for (const o of origins) if (o !== void 0 && o.depth > 0 && !out.includes(o.rel)) out.push(o.rel);
1715
+ return out;
1716
+ }
1258
1717
  var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
1259
1718
  var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
1260
1719
  function findLayoutTokensCssImport(baseDirInput) {
@@ -1273,45 +1732,133 @@ function findLayoutTokensCssImport(baseDirInput) {
1273
1732
  }
1274
1733
  return void 0;
1275
1734
  }
1735
+ var TOKENS_PACKAGE_NAME = "@axis-ds/tokens";
1736
+ function outsideCssDir(selection) {
1737
+ if (selection.path === void 0 || selection.rel === void 0) return void 0;
1738
+ const outside = selection.rel === ".." || selection.rel.startsWith("../") || isAbsolute(selection.rel);
1739
+ return outside ? dirname2(selection.path) : void 0;
1740
+ }
1741
+ function outsideCssUnresolvedIssue(spec, name) {
1742
+ return `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uC774 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C ${name} \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC124\uCE58\uBCF8\uC774 \uC571 \uCABD node_modules \uC5D0\uB9CC \uC788\uC74C) \u2192 \uC774 \uD30C\uC77C\uC758 \uC0C1\uC704 node_modules(\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 \uB4F1)\uC5D0 \uC124\uCE58\uD558\uAC70\uB098 globalCss \uB97C \uC571 \uC548 \uD30C\uC77C\uB85C \uBC14\uAFB8\uC138\uC694`;
1743
+ }
1744
+ function tokensInstallPhrase(baseDir, range = `^${TAILWIND4_MIN_AXIS_VERSION}`) {
1745
+ const g = dependencyInstallGuide(baseDir, TOKENS_PACKAGE_NAME, range);
1746
+ if (g.kind === "install-at-root") return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}`;
1747
+ return g.kind === "install" ? g.installCommand : g.addCommand;
1748
+ }
1749
+ function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir, lineIssue) {
1750
+ const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
1751
+ const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC`;
1752
+ if (r.kind === "pnp-root-only") return `${head} ${TOKENS_PACKAGE_NAME} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`;
1753
+ if (r.kind === "not-installed") {
1754
+ return `${head} ${TOKENS_PACKAGE_NAME} \uAC00 \uC124\uCE58\uB418\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uC124\uCE58(${tokensInstallPhrase(baseDir)})`;
1755
+ }
1756
+ if (cssDir !== void 0 && outsideCssPackageResolution(baseDir, cssDir, TOKENS_PACKAGE_NAME) === "unresolved") {
1757
+ return outsideCssUnresolvedIssue(spec, TOKENS_PACKAGE_NAME);
1758
+ }
1759
+ return lineIssue?.();
1760
+ }
1761
+ function packageNameOfSpec(spec) {
1762
+ const parts = spec.split("/");
1763
+ return parts.slice(0, spec.startsWith("@") ? 2 : 1).join("/");
1764
+ }
1765
+ function displayRel(baseDir, p) {
1766
+ return relative(baseDir, p).split(sep).join("/");
1767
+ }
1768
+ function packageLineShadowIssue(baseDir, expanded, origin, spec) {
1769
+ const name = packageNameOfSpec(spec);
1770
+ const lineDir = dirname2(origin.path);
1771
+ const others = () => [...new Set(expanded.files.map((f) => dirname2(f.path)))].filter((d) => d !== lineDir);
1772
+ const r = cssPackageLineResolution(baseDir, lineDir, spec, others);
1773
+ const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uADF8 \uC904\uC774 \uC788\uB294 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C`;
1774
+ const label = (pkgDir, version) => `${displayRel(baseDir, pkgDir)}(${version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
1775
+ switch (r.kind) {
1776
+ case "ok":
1777
+ return void 0;
1778
+ case "shadow-not-exported": {
1779
+ const current = r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
1780
+ const todo = current ? "\uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694" : `${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uB9DE\uCD94\uC138\uC694`;
1781
+ return `${head} \uBA3C\uC800 \uC7A1\uD788\uB294 ${label(r.pkgDir, r.version)}\uAC00 ${r.subpath} \uB97C \uB0B4\uBCF4\uB0B4\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 \uC911\uCCA9 node_modules \uC758 ${name} \uB97C \uC9C0\uC6B0\uAC70\uB098 ${todo}`;
1782
+ }
1783
+ case "shadow-target-missing":
1784
+ return `${head} \uBA3C\uC800 \uC7A1\uD788\uB294 ${label(r.pkgDir, r.version)}\uC5D0 \uB0B4\uBCF4\uB0B8 \uD30C\uC77C(${r.target})\uC774 \uC5C6\uC5B4 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 \uC911\uCCA9 node_modules \uC758 ${name} \uB97C \uC9C0\uC6B0\uAC70\uB098 \uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694`;
1785
+ case "not-visible": {
1786
+ const there = expanded.files.find((f) => dirname2(f.path) === r.fromDir);
1787
+ const move = there !== void 0 ? `\uC774 \uC904(${origin.rel})\uC744 ${there.rel} \uB85C \uC62E\uAE30\uC138\uC694` : `\uC774 \uC904(${origin.rel})\uC744 \uADF8 \uC704\uCE58\uC758 CSS \uD30C\uC77C\uB85C \uC62E\uAE30\uC138\uC694`;
1788
+ return `${head} ${name} \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC124\uCE58\uBCF8\uC774 ${displayRel(baseDir, r.pkgDir)} \uC5D0\uB9CC \uC788\uC74C) \u2192 \uC571 \uB610\uB294 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC124\uCE58\uD558\uAC70\uB098 ${move}`;
1789
+ }
1790
+ }
1791
+ }
1792
+ function isOutsideEntry(origin) {
1793
+ return origin.depth === 0 && origin.cssDir !== void 0;
1794
+ }
1276
1795
  function checkGlobalsCss(baseDirInput) {
1277
1796
  const baseDir = resolveBaseDir(baseDirInput);
1278
- for (const candidate of TAILWIND_CSS_CANDIDATES) {
1279
- const file = join2(baseDir, candidate);
1280
- if (!existsSync3(file)) continue;
1281
- const content = readFileSync4(file, "utf8");
1282
- const css = stripCssComments(content);
1283
- const imported = findTokensCssImport(content);
1284
- let pass;
1285
- if (imported !== void 0) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
1286
- else if (AXIS_VARIABLE_DEFINITION.test(css)) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218(--axis-*)\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`;
1287
- else {
1288
- const layout = findLayoutTokensCssImport(baseDir);
1289
- if (layout) pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${layout.file}\uC758 ${layout.spec} import)`;
1290
- }
1291
- if (pass !== void 0) {
1292
- const tailwind = detectTailwind(baseDir, readPackageJson(baseDir));
1293
- const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
1294
- if (!tailwind4 && findCreateNextAppDefaults(content).some((d) => d.includes("font-family: Arial"))) {
1295
- return {
1296
- name: "globals.css",
1297
- severity: "warn",
1298
- 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)`
1299
- };
1300
- }
1301
- return { name: "globals.css", severity: "pass", message: pass };
1302
- }
1303
- if (css.includes("--background") && css.includes("--primary")) {
1797
+ const selection = selectCheckGlobalCss(baseDir);
1798
+ const note = globalCssSelectionNote(selection);
1799
+ if (selection.path !== void 0 && selection.rel !== void 0) {
1800
+ const candidate = selection.rel;
1801
+ const expanded = expandGlobalCss(baseDir, selection.path, candidate, outsideCssDir(selection));
1802
+ const judged = judgeGlobalsCss(baseDir, selection, candidate, expanded);
1803
+ if (expanded.cycle !== void 0) {
1804
+ return { name: "globals.css", severity: "warn", message: `${judged.message} / ${cssImportCycleIssue(expanded.cycle)}${note}` };
1805
+ }
1806
+ return { name: "globals.css", severity: judged.severity, message: `${judged.message}${note}` };
1807
+ }
1808
+ return { name: "globals.css", severity: "fail", message: `globals.css \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4${note}` };
1809
+ }
1810
+ function judgeGlobalsCss(baseDir, selection, candidate, expanded) {
1811
+ const content = expanded.entry;
1812
+ const css = stripCssComments(content);
1813
+ const imported = findTokensCssImport(expanded.evidence);
1814
+ const pkg = readPackageJson(baseDir);
1815
+ let pass;
1816
+ let unresolved;
1817
+ let via = "";
1818
+ if (imported !== void 0) {
1819
+ const origin = evidenceOrigin(expanded, (f) => findTokensCssImport(f) === imported);
1820
+ via = cssImportViaNote(viaFiles([origin]));
1821
+ const tailwind4 = (detectTailwind(baseDir, pkg).major ?? 0) >= 4;
1822
+ const issue = tailwind4 && origin !== void 0 && !isOutsideEntry(origin) ? tokensCssUnresolvedIssue(
1823
+ baseDir,
1824
+ pkg,
1825
+ imported,
1826
+ void 0,
1827
+ () => packageLineShadowIssue(baseDir, expanded, origin, imported)
1828
+ ) : tokensCssUnresolvedIssue(baseDir, pkg, imported, origin !== void 0 ? origin.cssDir : outsideCssDir(selection));
1829
+ if (issue !== void 0) unresolved = `${candidate}\uC5D0 ${issue}`;
1830
+ else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
1831
+ } else if (AXIS_VARIABLE_DEFINITION.test(stripCssComments(expanded.evidence))) {
1832
+ via = cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => AXIS_VARIABLE_DEFINITION.test(f))]));
1833
+ pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218(--axis-*)\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`;
1834
+ } else {
1835
+ const layout = findLayoutTokensCssImport(baseDir);
1836
+ if (layout) {
1837
+ const issue = tokensCssUnresolvedIssue(baseDir, pkg, layout.spec);
1838
+ if (issue !== void 0) unresolved = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uACE0 ${layout.file}\uC758 ${issue}`;
1839
+ else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${layout.file}\uC758 ${layout.spec} import)`;
1840
+ }
1841
+ }
1842
+ const head = pass ?? unresolved;
1843
+ if (head !== void 0) {
1844
+ const tailwind = detectTailwind(baseDir, pkg);
1845
+ const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
1846
+ if (!tailwind4 && findCreateNextAppDefaults(content).some((d) => d.includes("font-family: Arial"))) {
1304
1847
  return {
1305
- name: "globals.css",
1306
1848
  severity: "warn",
1307
- 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`
1849
+ message: `${head}. \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)${via}`
1308
1850
  };
1309
1851
  }
1310
- return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
1852
+ return { severity: pass !== void 0 ? "pass" : "warn", message: `${head}${via}` };
1311
1853
  }
1312
- return { name: "globals.css", severity: "fail", message: "globals.css \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4" };
1854
+ if (css.includes("--background") && css.includes("--primary")) {
1855
+ return {
1856
+ severity: "warn",
1857
+ 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`
1858
+ };
1859
+ }
1860
+ return { severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
1313
1861
  }
1314
- var TAILWIND4_MIN_AXIS_VERSION = "1.4.0";
1315
1862
  var TAILWIND4_AXIS_PACKAGES = ["@axis-ds/tokens", "@axis-ds/ui-react", "@axis-ds/agentic-ui"];
1316
1863
  function lowerOf(token) {
1317
1864
  const v = versionParts(token);
@@ -1509,6 +2056,17 @@ function hasBareCjsPresetRequire(code) {
1509
2056
  function isCommonJsConfig(file, source) {
1510
2057
  return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
1511
2058
  }
2059
+ function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
2060
+ const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
2061
+ const head = `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${TOKENS_PACKAGE_NAME} \uAC00`;
2062
+ if (r.kind === "not-installed") {
2063
+ return `${head} \uC124\uCE58\uB418\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uC124\uCE58(${tokensInstallPhrase(baseDir, `^${TOKENS_CJS_PRESET_FIXED_VERSION}`)})`;
2064
+ }
2065
+ if (r.kind === "pnp-root-only" && !bareCjs) {
2066
+ return `${head} ${PNP_ROOT_ONLY_NOTE}(\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 \uC120\uC5B8 ${r.range}) \u2192 \uC571 package.json \uC5D0 ${TOKENS_PACKAGE_NAME} \uB97C \uC120\uC5B8\uD558\uC138\uC694`;
2067
+ }
2068
+ return void 0;
2069
+ }
1512
2070
  function packageVersionGate(baseDirInput, pkg, name, min, options = {}) {
1513
2071
  const baseDir = resolveBaseDir(baseDirInput);
1514
2072
  if (!isPnpProject(baseDir)) {
@@ -1544,66 +2102,155 @@ function readPackageJson(baseDir) {
1544
2102
  return void 0;
1545
2103
  }
1546
2104
  }
1547
- function tailwind4Issues(css, pkg, versions, baseDir) {
2105
+ function tailwind4Issues(input, pkg, versions, baseDir) {
2106
+ const { entry, evidence } = input;
2107
+ const cssDirOf = input.cssDirOf ?? (() => void 0);
1548
2108
  const issues = [];
1549
- const hasEntry = hasTokensTailwind4Import(css);
2109
+ const tailwindDir = cssDirOf("tailwindcss");
2110
+ if (tailwindDir !== void 0 && outsideCssPackageResolution(baseDir, tailwindDir, "tailwindcss") === "unresolved") {
2111
+ issues.push(outsideCssUnresolvedIssue("tailwindcss", "tailwindcss"));
2112
+ }
2113
+ const hasEntry = hasTokensTailwind4Import(evidence);
1550
2114
  if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
1551
- const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
1552
- (name) => declaredRange(baseDir, pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
1553
- );
2115
+ const resolutions = new Map(TAILWIND4_COMPONENT_PACKAGES.map((name) => [name, componentCssResolution(baseDir, pkg, name)]));
2116
+ const missing = [];
2117
+ const unresolvedMissing = [];
2118
+ for (const name of TAILWIND4_COMPONENT_PACKAGES) {
2119
+ const r = resolutions.get(name);
2120
+ if (r.kind === "undeclared" || r.kind === "app-lockfile") continue;
2121
+ if (hasComponentTailwindImport(evidence, name) || hasComponentSource(evidence, name)) continue;
2122
+ if (componentCssResolvable(r)) missing.push(name);
2123
+ else unresolvedMissing.push(componentCssMissingIssue(baseDir, name, r));
2124
+ }
1554
2125
  if (missing.length > 0) {
1555
2126
  issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
1556
2127
  }
2128
+ issues.push(...unresolvedMissing);
1557
2129
  if (hasEntry) {
1558
- const defaults = findCreateNextAppDefaults(css);
2130
+ const defaults = findCreateNextAppDefaults(entry);
1559
2131
  if (defaults.length > 0) issues.push(`create-next-app \uAE30\uBCF8 \uC815\uC758\uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4(${defaults.join(" \xB7 ")}) \u2192 \uC9C0\uC6B0\uC138\uC694`);
1560
2132
  if (versions.some((v) => v.name === TAILWIND4_AXIS_PACKAGES[0])) {
1561
2133
  issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC788\uC9C0\uB9CC ${TAILWIND4_AXIS_PACKAGES[0]} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
1562
2134
  }
1563
2135
  }
1564
2136
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
1565
- if (hasComponentTailwindImport(css, name) && versions.some((v) => v.name === name)) {
1566
- issues.push(`${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${name} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
2137
+ if (!hasComponentTailwindImport(evidence, name)) continue;
2138
+ const unresolved = componentCssPresentIssue(baseDir, name, resolutions.get(name));
2139
+ const spec = `${name}/tailwind.css`;
2140
+ if (unresolved !== void 0) {
2141
+ issues.push(unresolved);
2142
+ continue;
1567
2143
  }
2144
+ const shadow = input.lineIssue === void 0 ? false : input.lineIssue(spec);
2145
+ let lineProblem;
2146
+ if (shadow !== false) lineProblem = shadow;
2147
+ else {
2148
+ const componentDir = cssDirOf(spec);
2149
+ if (componentDir !== void 0 && outsideCssPackageResolution(baseDir, componentDir, name, "tailwind.css") === "unresolved") {
2150
+ lineProblem = outsideCssUnresolvedIssue(spec, name);
2151
+ }
2152
+ }
2153
+ if (lineProblem !== void 0) issues.push(lineProblem);
2154
+ else if (versions.some((v) => v.name === name)) issues.push(`${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${name} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
1568
2155
  }
1569
2156
  return issues;
1570
2157
  }
2158
+ function componentInstallPhrase(baseDir, name, range) {
2159
+ const g = dependencyInstallGuide(baseDir, name, range);
2160
+ return g.kind === "install-at-root" ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}` : g.installCommand;
2161
+ }
2162
+ function componentCssMissingIssue(baseDir, name, r) {
2163
+ const line = componentTailwindImportLine(name);
2164
+ switch (r.kind) {
2165
+ case "pnp-root-only":
2166
+ return `${name} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD55C \uB4A4 ${line}`;
2167
+ case "root-not-installed":
2168
+ return `${name} \uAC00 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2192 \uC124\uCE58(${componentInstallPhrase(baseDir, name, r.range)}) \uB4A4 ${line}`;
2169
+ case "root-old":
2170
+ return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB41C ${name} \uC758 \uC124\uCE58\uBCF8(${r.installedVersion === "?" ? "\uBC84\uC804 \uBAA8\uB984" : r.installedVersion})\uC5D0 tailwind.css \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(${TAILWIND4_MIN_AXIS_VERSION} \uBD80\uD130 \uC81C\uACF5) \u2192 ${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uC62C\uB9B0 \uB4A4 ${line}`;
2171
+ case "root-missing-file":
2172
+ return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB41C ${name} \uC758 \uC124\uCE58\uBCF8(${r.installedVersion})\uC5D0 tailwind.css \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(\uC124\uCE58\uAC00 \uC190\uC0C1\uB410\uC744 \uC218 \uC788\uC74C) \u2192 \uB2E4\uC2DC \uC124\uCE58(${componentInstallPhrase(baseDir, name, r.range)}) \uB4A4 ${line}`;
2173
+ default:
2174
+ return line;
2175
+ }
2176
+ }
2177
+ function componentCssPresentIssue(baseDir, name, r) {
2178
+ const head = `${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC`;
2179
+ switch (r.kind) {
2180
+ case "pnp-root-only":
2181
+ return `${head} ${name} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`;
2182
+ case "root-not-installed":
2183
+ return `${head} ${name} \uAC00 \uC124\uCE58\uB418\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uC124\uCE58(${componentInstallPhrase(baseDir, name, r.range)})`;
2184
+ case "root-missing-file":
2185
+ return `${head} ${name} \uC124\uCE58\uBCF8(${r.installedVersion})\uC5D0 tailwind.css \uAC00 \uC5C6\uC5B4 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uB2E4\uC2DC \uC124\uCE58(${componentInstallPhrase(baseDir, name, r.range)})`;
2186
+ case "root-old":
2187
+ return r.installedVersion === "?" ? `${head} ${name} \uC124\uCE58\uBCF8(\uBC84\uC804 \uBAA8\uB984)\uC5D0 tailwind.css \uAC00 \uC5C6\uC5B4 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 ${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uC62C\uB9AC\uC138\uC694` : void 0;
2188
+ default:
2189
+ return void 0;
2190
+ }
2191
+ }
1571
2192
  function checkTailwindSetup(baseDirInput) {
1572
2193
  const baseDir = resolveBaseDir(baseDirInput);
1573
2194
  const pkg = readPackageJson(baseDir);
1574
2195
  const tailwind = detectTailwind(baseDir, pkg);
1575
2196
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
1576
2197
  const label = `Tailwind ${tailwind.major}`;
1577
- for (const candidate of TAILWIND_CSS_CANDIDATES) {
1578
- const file = join2(baseDir, candidate);
1579
- if (!existsSync3(file)) continue;
1580
- const css = readFileSync4(file, "utf8");
1581
- if (!hasTailwindImport(css)) {
2198
+ const selection = selectCheckGlobalCss(baseDir);
2199
+ const note = globalCssSelectionNote(selection);
2200
+ if (selection.path !== void 0 && selection.rel !== void 0) {
2201
+ const candidate = selection.rel;
2202
+ const expanded = expandGlobalCss(baseDir, selection.path, candidate, outsideCssDir(selection));
2203
+ if (!hasTailwindImport(expanded.evidence)) {
1582
2204
  return {
1583
2205
  name: "tailwind.config",
1584
2206
  severity: "warn",
1585
- message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4`
2207
+ message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4${note}`
1586
2208
  };
1587
2209
  }
2210
+ const via = cssImportViaNote(
2211
+ viaFiles([
2212
+ evidenceOrigin(expanded, hasTailwindImport),
2213
+ evidenceOrigin(expanded, hasTokensTailwind4Import),
2214
+ ...TAILWIND4_COMPONENT_PACKAGES.flatMap((name) => [
2215
+ evidenceOrigin(expanded, (f) => hasComponentTailwindImport(f, name)),
2216
+ evidenceOrigin(expanded, (f) => hasComponentSource(f, name))
2217
+ ])
2218
+ ])
2219
+ );
1588
2220
  const versions = axisPackagesBelowTailwind4(pkg, baseDir);
1589
- const issues = tailwind4Issues(css, pkg, versions, baseDir);
2221
+ const issues = tailwind4Issues(
2222
+ {
2223
+ entry: expanded.entry,
2224
+ evidence: expanded.evidence,
2225
+ cssDirOf: (spec) => packageLineCssDir(expanded, spec),
2226
+ lineIssue: (spec) => {
2227
+ const line = expanded.packageLines.find((l) => l.spec === spec);
2228
+ const origin = line !== void 0 ? expanded.files.find((f) => f.rel === line.file) : void 0;
2229
+ if (origin === void 0 || isOutsideEntry(origin)) return false;
2230
+ return packageLineShadowIssue(baseDir, expanded, origin, spec);
2231
+ }
2232
+ },
2233
+ pkg,
2234
+ versions,
2235
+ baseDir
2236
+ );
1590
2237
  if (issues.length > 0) {
1591
2238
  return {
1592
2239
  name: "tailwind.config",
1593
2240
  severity: "warn",
1594
- message: `${label}: ${candidate}\uC5D0 ${issues.join(" / ")}${tailwind4VersionNote(versions)}`
2241
+ message: `${label}: ${candidate}\uC5D0 ${issues.join(" / ")}${tailwind4VersionNote(versions)}${via}${note}`
1595
2242
  };
1596
2243
  }
1597
2244
  return {
1598
2245
  name: "tailwind.config",
1599
2246
  severity: "pass",
1600
- message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uC640 AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC788\uC2B5\uB2C8\uB2E4`
2247
+ message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uC640 AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC788\uC2B5\uB2C8\uB2E4${via}${note}`
1601
2248
  };
1602
2249
  }
1603
2250
  return {
1604
2251
  name: "tailwind.config",
1605
2252
  severity: "warn",
1606
- message: `${label}: @import "tailwindcss" \uB97C \uD655\uC778\uD560 CSS \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4`
2253
+ message: `${label}: @import "tailwindcss" \uB97C \uD655\uC778\uD560 CSS \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4${note}`
1607
2254
  };
1608
2255
  }
1609
2256
  for (const file of TAILWIND_CONFIG_FILES) {
@@ -1612,7 +2259,10 @@ function checkTailwindSetup(baseDirInput) {
1612
2259
  const content = readFileSync4(path11, "utf8");
1613
2260
  if (hasTokensPresetReference(content)) {
1614
2261
  const code = stripJsComments(content);
1615
- if (isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code)) {
2262
+ const bareCjs = isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code);
2263
+ const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs);
2264
+ if (unresolved !== void 0) return { name: "tailwind.config", severity: "warn", message: unresolved };
2265
+ if (bareCjs) {
1616
2266
  const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION, { appOnlyInPnp: true });
1617
2267
  if (gate.status === "unresolved") {
1618
2268
  return {
@@ -1649,31 +2299,45 @@ function readAxisConfigLike(baseDir) {
1649
2299
  return void 0;
1650
2300
  }
1651
2301
  }
1652
- function contentGlobToRegExp(glob) {
2302
+ function selectCheckGlobalCss(baseDir) {
2303
+ return selectGlobalCss(baseDir, readAxisConfigLike(baseDir)?.globalCss, TAILWIND_CSS_CANDIDATES, { requireStylesheet: true });
2304
+ }
2305
+ function contentGlobToRegExp(glob, opts = {}) {
2306
+ const noDot = opts.noDot === true;
1653
2307
  const g = glob.trim().replace(/^\.\//, "");
2308
+ const lead = (i) => noDot && (i === 0 || g[i - 1] === "/") ? "(?!\\.)" : "";
1654
2309
  let re = "";
1655
2310
  for (let i = 0; i < g.length; i++) {
1656
2311
  const c = g[i];
1657
2312
  if (c === "*") {
1658
2313
  if (g[i + 1] === "*") {
1659
2314
  const slash = g[i + 2] === "/";
1660
- re += slash ? "(?:.*/)?" : ".*";
2315
+ if (noDot) re += slash ? `(?:${lead(i)}[^/]*/(?:(?!\\.)[^/]*/)*)?` : `${lead(i)}[^/]*(?:/(?!\\.)[^/]*)*`;
2316
+ else re += slash ? "(?:.*/)?" : ".*";
1661
2317
  i += slash ? 2 : 1;
1662
- } else re += "[^/]*";
1663
- } else if (c === "?") re += "[^/]";
2318
+ } else re += `${lead(i)}[^/]*`;
2319
+ } else if (c === "?") re += `${lead(i)}[^/]`;
1664
2320
  else if (c === "{") {
1665
2321
  const end = g.indexOf("}", i);
1666
2322
  if (end === -1) {
1667
2323
  re += "\\{";
1668
2324
  continue;
1669
2325
  }
1670
- re += `(?:${g.slice(i + 1, end).split(",").map((part) => part.replace(/[.+^$()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*")).join("|")})`;
2326
+ const atStart = lead(i) !== "";
2327
+ re += `(?:${g.slice(i + 1, end).split(",").map((part) => {
2328
+ const body = part.replace(/[.+^$()|[\]\\]/g, "\\$&");
2329
+ if (!noDot) return body.replace(/\*/g, "[^/]*");
2330
+ return body.replace(
2331
+ /(\/)?\*/g,
2332
+ (_m, slash, off) => slash !== void 0 || off === 0 && atStart ? `${slash ?? ""}(?!\\.)[^/]*` : "[^/]*"
2333
+ );
2334
+ }).join("|")})`;
1671
2335
  i = end;
1672
2336
  } else if (c === "[") {
1673
2337
  const end = g.indexOf("]", i);
1674
2338
  if (end === -1) re += "\\[";
1675
2339
  else {
1676
- re += g.slice(i, end + 1);
2340
+ re += lead(i) + g.slice(i, end + 1);
1677
2341
  i = end;
1678
2342
  }
1679
2343
  } else re += c.replace(/[.+^$()|\\]/g, "\\$&");
@@ -1742,22 +2406,46 @@ function realpathPosix(p) {
1742
2406
  }
1743
2407
  return void 0;
1744
2408
  }
1745
- function contentGlobBranchCovers(glob, sample, baseDir) {
2409
+ function contentGlobBranchCovers(glob, sample, baseDir, noDot) {
1746
2410
  if (isAbsoluteGlob(glob)) {
1747
- const re = contentGlobToRegExp(glob.trim().replace(/\\/g, "/"));
2411
+ const re = contentGlobToRegExp(glob.trim().replace(/\\/g, "/"), { noDot });
1748
2412
  const absSample = resolve(baseDir, sample);
1749
2413
  if (re.test(absSample.split(sep).join("/"))) return true;
1750
2414
  const real = realpathPosix(absSample);
1751
2415
  return real !== void 0 && re.test(real);
1752
2416
  }
1753
- return leadingParentSegments(glob) === leadingParentSegments(sample) && contentGlobToRegExp(glob).test(sample);
2417
+ return leadingParentSegments(glob) === leadingParentSegments(sample) && contentGlobToRegExp(glob, { noDot }).test(sample);
1754
2418
  }
1755
- function contentGlobCovers(glob, sample, baseDirInput) {
2419
+ function contentGlobCovers(glob, sample, baseDirInput, opts = {}) {
1756
2420
  const baseDir = resolveBaseDir(baseDirInput);
1757
2421
  const branches = expandBraces(glob.trim()) ?? [glob];
1758
- return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir));
2422
+ return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir, opts.noDot === true));
2423
+ }
2424
+ var CONTENT_PARENT_PATH_NOTE = "\uC0C1\uC704 \uACBD\uB85C\uB294 Tailwind 3 \uAC00 \uBE4C\uB4DC\uB97C \uC2E4\uD589\uD55C \uB514\uB809\uD130\uB9AC \uAE30\uC900\uC73C\uB85C \uD480\uB9BD\uB2C8\uB2E4. \uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8 \uB4F1 \uC571 \uB514\uB809\uD130\uB9AC \uBC16\uC5D0\uC11C \uBE4C\uB4DC\uD558\uBA74 content: { relative: true, files: [...] } \uB85C \uC124\uC815 \uD30C\uC77C \uAE30\uC900\uC73C\uB85C \uBC14\uAFB8\uC138\uC694";
2425
+ function contentPnpNote(names, unplugged = []) {
2426
+ const list = [...new Set(typeof names === "string" ? [names] : names)];
2427
+ const dyn = list.map((n) => `path.join(path.dirname(require.resolve("${n}")), "..", "dist/**/*.{js,mjs}")`).join(", ");
2428
+ const needsSetup = list.filter((n) => !unplugged.includes(n));
2429
+ const meta = needsSetup.map((n) => `"${n}": { "unplugged": true }`).join(", ");
2430
+ const setup = needsSetup.length > 0 ? ` \uC815\uC801 \uACBD\uB85C\uB97C \uC4F0\uB824\uBA74 package.json \uC758 dependenciesMeta \uC5D0 ${meta} \uB97C \uB450\uACE0 yarn install \uB4A4 .yarn/unplugged \uACBD\uB85C\uB97C \uB123\uC73C\uC138\uC694` : "";
2431
+ return `Plug'n'Play \uC5D0\uB294 node_modules \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. content \uC5D0 ${dyn} \uCC98\uB7FC \uC2E4\uC81C \uC704\uCE58\uB97C \uB123\uC73C\uC138\uC694(\uC815\uC801\uC73C\uB85C \uD655\uC778\uD560 \uC218 \uC5C6\uC5B4 WARN \uC73C\uB85C \uB0A8\uC2B5\uB2C8\uB2E4).${setup}`;
2432
+ }
2433
+ function contentPnpNoteTargets(targets) {
2434
+ return targets.filter((t) => t.pnp !== void 0 && t.pnp.state !== "rootOnly").map((t) => t.label);
2435
+ }
2436
+ function contentPnpNoteFor(targets) {
2437
+ const names = contentPnpNoteTargets(targets);
2438
+ if (names.length === 0) return void 0;
2439
+ const unplugged = targets.filter((t) => t.pnp?.state === "unplugged").map((t) => t.label);
2440
+ return contentPnpNote(names, unplugged);
2441
+ }
2442
+ var CONTENT_PNP_ROOT_ONLY_ACTION = "\uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694";
2443
+ var CONTENT_PNP_NO_NODE_MODULES = "Plug'n'Play \uB77C node_modules \uACBD\uB85C\uAC00 \uC5C6\uC74C";
2444
+ function contentTargetText(t) {
2445
+ if (t.pnp?.state === "noNodeModules") return `${t.label}(${CONTENT_PNP_NO_NODE_MODULES})`;
2446
+ if (t.pnp?.state === "rootOnly") return `${t.label} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 ${CONTENT_PNP_ROOT_ONLY_ACTION}`;
2447
+ return `${t.label} \u2192 "${t.suggest}"${t.note === void 0 ? "" : ` (${t.note})`}`;
1759
2448
  }
1760
- var CONTENT_PARENT_PATH_NOTE = "\uC0C1\uC704 \uACBD\uB85C\uB294 Tailwind 3 \uAC00 \uBE4C\uB4DC\uB97C \uC2E4\uD589\uD55C \uB514\uB809\uD130\uB9AC \uAE30\uC900\uC73C\uB85C \uD480\uB824\uC694. \uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8 \uB4F1 \uC571 \uB514\uB809\uD130\uB9AC \uBC16\uC5D0\uC11C \uBE4C\uB4DC\uD558\uBA74 content: { relative: true, files: [...] } \uB85C \uC124\uC815 \uD30C\uC77C \uAE30\uC900\uC73C\uB85C \uBC14\uAFB8\uC138\uC694";
1761
2449
  function relDirOf(baseDir, dir) {
1762
2450
  const rel2 = relative(baseDir, dir);
1763
2451
  return rel2 === "" || isAbsolute(rel2) ? void 0 : rel2.split(sep).join("/");
@@ -1777,8 +2465,26 @@ function packageVersion(dir) {
1777
2465
  return void 0;
1778
2466
  }
1779
2467
  }
1780
- function packageContentTarget(baseDir, name) {
1781
- const found = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, name);
2468
+ function pnpPackageContentTarget(baseDir, name, pkg) {
2469
+ const legacySample = `node_modules/${name}/dist/index.js`;
2470
+ const none = { sample: "", suggest: "", alternates: [], others: [] };
2471
+ if (pnpRootOnlyDependency(baseDir, pkg, name) !== void 0) return { ...none, pnp: { state: "rootOnly", legacySample } };
2472
+ const range = pkg === void 0 ? void 0 : hasDependency(pkg, name);
2473
+ const rels = (range === void 0 ? [] : findPnpUnpluggedPackages(baseDir, name, range)).map((d) => relDirOf(baseDir, d)).filter((r) => r !== void 0);
2474
+ const root = pnpProjectRoot(baseDir);
2475
+ if (rels.length === 0 || root === void 0) return { ...none, pnp: { state: "noNodeModules", legacySample } };
2476
+ const rootRel = relDirOf(baseDir, root);
2477
+ return {
2478
+ sample: `${rels[0]}/dist/index.js`,
2479
+ suggest: `${rootRel === void 0 ? "." : rootRel}/.yarn/unplugged/*/node_modules/${name}/dist/**/*.{js,mjs}`,
2480
+ alternates: rels.slice(1).map((r) => `${r}/dist/index.js`),
2481
+ others: [],
2482
+ pnp: { state: "unplugged", legacySample }
2483
+ };
2484
+ }
2485
+ function packageContentTarget(baseDir, name, pkg) {
2486
+ if (isPnpProject(baseDir)) return pnpPackageContentTarget(baseDir, name, pkg);
2487
+ const found = findInstalledPackage(baseDir, name);
1782
2488
  const relDir = (found === void 0 ? void 0 : relDirOf(baseDir, found.dir)) ?? `node_modules/${name}`;
1783
2489
  const alternates = [];
1784
2490
  const others = [];
@@ -1799,7 +2505,7 @@ function packageContentTarget(baseDir, name) {
1799
2505
  const versions = theirs === void 0 || ours === void 0 ? "" : theirs === ours ? `(\uBC84\uC804\uC740 ${ours} \uB85C \uAC19\uC74C)` : `(${theirs}, \uC571 ${ours})`;
1800
2506
  others.push({
1801
2507
  sample: `${rel2}/dist/index.js`,
1802
- note: `\uC0C1\uC704 \uACBD\uB85C ${rel2} \uB294 \uC571\uC774 \uC4F0\uB294 \uC124\uCE58\uBCF8\uACFC \uB2E4\uB978 \uC124\uCE58\uBCF8${versions}\uC774\uB77C \uB36E\uC74C\uC73C\uB85C \uBCF4\uC9C0 \uC54A\uC544\uC694`
2508
+ note: `\uC0C1\uC704 \uACBD\uB85C ${rel2} \uB294 \uC571\uC774 \uC4F0\uB294 \uC124\uCE58\uBCF8\uACFC \uB2E4\uB978 \uC124\uCE58\uBCF8${versions}\uC774\uB77C \uB36E\uC74C\uC73C\uB85C \uBCF4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`
1803
2509
  });
1804
2510
  }
1805
2511
  }
@@ -1876,7 +2582,7 @@ function inspectTailwindContent(baseDirInput) {
1876
2582
  }
1877
2583
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
1878
2584
  if (declaredRange(baseDir, pkg, name) !== void 0) {
1879
- targets.push({ label: name, ...packageContentTarget(baseDir, name) });
2585
+ targets.push({ label: name, ...packageContentTarget(baseDir, name, pkg) });
1880
2586
  }
1881
2587
  }
1882
2588
  if (targets.length === 0) return null;
@@ -1886,11 +2592,14 @@ function inspectTailwindContent(baseDirInput) {
1886
2592
  configFile,
1887
2593
  unreadable: read === void 0,
1888
2594
  dynamic: read?.dynamic ?? false,
1889
- targets: targets.map(({ alternates = [], others = [], ...t }) => {
2595
+ targets: targets.map(({ alternates = [], others = [], pnp, ...t }) => {
1890
2596
  const covers = (sample) => globs.some((g) => contentGlobCovers(g, sample, baseDir));
1891
- const covered = [t.sample, ...alternates].some(covers);
2597
+ const samples = pnp !== void 0 && pnp.state !== "unplugged" ? [] : [t.sample, ...alternates];
2598
+ const coversSample = pnp?.state === "unplugged" ? (sample) => globs.some((g) => contentGlobCovers(g, sample, baseDir, { noDot: true })) : covers;
2599
+ const covered = samples.some(coversSample);
1892
2600
  const note = covered ? void 0 : others.find((o) => covers(o.sample))?.note;
1893
- return note === void 0 ? { ...t, covered } : { ...t, covered, note };
2601
+ const base = note === void 0 ? { ...t, covered } : { ...t, covered, note };
2602
+ return pnp === void 0 ? base : { ...base, pnp: { state: pnp.state, legacyCovered: covers(pnp.legacySample) } };
1894
2603
  })
1895
2604
  };
1896
2605
  }
@@ -1905,19 +2614,30 @@ function checkTailwindContent(baseDir) {
1905
2614
  message: `${r.configFile}\uC758 content \uAC00 ${r.targets.map((t) => t.label).join(" \xB7 ")} \uB97C \uB36E\uC2B5\uB2C8\uB2E4`
1906
2615
  };
1907
2616
  }
1908
- const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"${t.note === void 0 ? "" : ` (${t.note})`}`).join(" \xB7 ");
2617
+ const list = missing.map(contentTargetText).join(" \xB7 ");
1909
2618
  const note = missing.some((t) => t.suggest.startsWith("../")) ? ` (${CONTENT_PARENT_PATH_NOTE})` : "";
2619
+ const pnpText = contentPnpNoteFor(missing);
2620
+ const pnpNote = pnpText === void 0 ? "" : ` (${pnpText})`;
1910
2621
  if (r.unreadable || r.dynamic) {
1911
2622
  return {
1912
2623
  name: "tailwind.content",
1913
2624
  severity: "warn",
1914
- 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}${note}`
2625
+ 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}${note}${pnpNote}`
2626
+ };
2627
+ }
2628
+ if (missing.every((t) => t.pnp?.legacyCovered === true)) {
2629
+ const labels = missing.map((t) => t.label).join(" \xB7 ");
2630
+ const details = missing.filter((t) => t.pnp?.state !== "noNodeModules").map(contentTargetText);
2631
+ return {
2632
+ name: "tailwind.content",
2633
+ severity: "warn",
2634
+ message: `${r.configFile}\uC758 content \uAC00 Plug'n'Play \uC5D0\uC11C \uC2A4\uCE94\uB418\uC9C0 \uC54A\uB294 \uACBD\uB85C\uB85C ${labels} \uB97C \uB36E\uC2B5\uB2C8\uB2E4(node_modules \uACBD\uB85C \xB7 ./** \uB294 \uC2A4\uCE94\uB418\uC9C0 \uC54A\uC74C)${details.length > 0 ? `: ${details.join(" \xB7 ")}` : ""}${note}${pnpNote}`
1915
2635
  };
1916
2636
  }
1917
2637
  return {
1918
2638
  name: "tailwind.content",
1919
2639
  severity: "fail",
1920
- 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}${note}`
2640
+ 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}${note}${pnpNote}`
1921
2641
  };
1922
2642
  }
1923
2643
  var ANIMATION_PLUGIN_TAILWIND3 = "tailwindcss-animate";
@@ -1934,7 +2654,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
1934
2654
  const [dir, depth] = stack.pop();
1935
2655
  let names;
1936
2656
  try {
1937
- names = readdirSync(dir);
2657
+ names = readdirSync2(dir);
1938
2658
  } catch {
1939
2659
  continue;
1940
2660
  }
@@ -1975,24 +2695,30 @@ function checkAnimationPlugin(baseDirInput) {
1975
2695
  return void 0;
1976
2696
  };
1977
2697
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
1978
- const file = TAILWIND_CSS_CANDIDATES.find((c) => existsSync3(join2(baseDir, c)));
1979
- const css = file !== void 0 ? stripCssComments(readFileSync4(join2(baseDir, file), "utf8")) : "";
2698
+ const selection = selectCheckGlobalCss(baseDir);
2699
+ const note = globalCssSelectionNote(selection);
2700
+ const file = selection.rel;
2701
+ const expanded = selection.path !== void 0 && selection.rel !== void 0 ? expandGlobalCss(baseDir, selection.path, selection.rel, outsideCssDir(selection)) : void 0;
2702
+ const css = expanded !== void 0 ? stripCssComments(expanded.evidence) : "";
2703
+ const twAnimate = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`);
2704
+ const animatePlugin = new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`);
1980
2705
  const lines = [];
1981
- if (new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`).test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
1982
- if (new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`).test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
2706
+ if (twAnimate.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
2707
+ if (animatePlugin.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
2708
+ const via = expanded !== void 0 ? cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => twAnimate.test(f)), evidenceOrigin(expanded, (f) => animatePlugin.test(f))])) : "";
1983
2709
  if (lines.length === 0) {
1984
2710
  return {
1985
2711
  name: "animation",
1986
2712
  severity: "warn",
1987
- 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}";`
2713
+ message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 ${ANIMATION_PLUGIN_TAILWIND4} \uC124\uCE58 \uB4A4 @import "${ANIMATION_PLUGIN_TAILWIND4}";${note}`
1988
2714
  };
1989
2715
  }
1990
2716
  const problems = lines.map((name) => ({ name, why: pluginProblem(name) })).filter((x) => x.why !== void 0);
1991
- if (problems.length === 0) return { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4` };
2717
+ if (problems.length === 0) return { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4${via}${note}` };
1992
2718
  return {
1993
2719
  name: "animation",
1994
2720
  severity: "warn",
1995
- message: `${file}\uC758 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${problems.map((x) => x.why).join(" \xB7 ")}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uACE0 \uBE4C\uB4DC\uAC00 \uC2E4\uD328\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2192 ${problems.map((x) => x.name).join(" \xB7 ")} \uB97C package.json \uC5D0 \uC120\uC5B8 \xB7 \uC124\uCE58\uD558\uC138\uC694`
2721
+ message: `${file}\uC758 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${problems.map((x) => x.why).join(" \xB7 ")}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uACE0 \uBE4C\uB4DC\uAC00 \uC2E4\uD328\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2192 ${problems.map((x) => x.name).join(" \xB7 ")} \uB97C package.json \uC5D0 \uC120\uC5B8 \xB7 \uC124\uCE58\uD558\uC138\uC694${via}${note}`
1996
2722
  };
1997
2723
  }
1998
2724
  const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
@@ -2097,7 +2823,7 @@ function selectUtilsDependencies(tailwind) {
2097
2823
  }
2098
2824
 
2099
2825
  // ../axis-registry-core/src/add/safe-write.ts
2100
- import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
2826
+ import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
2101
2827
  import path4 from "path";
2102
2828
  import fs2 from "fs-extra";
2103
2829
  var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
@@ -2153,7 +2879,7 @@ function escapeReason(root, target, options = {}) {
2153
2879
  }
2154
2880
  let followed;
2155
2881
  try {
2156
- followed = statSync2(realTarget);
2882
+ followed = statSync3(realTarget);
2157
2883
  } catch {
2158
2884
  return `\uAE30\uC874 \uD30C\uC77C \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${target})`;
2159
2885
  }
@@ -2425,7 +3151,7 @@ function relativeSpecifierResolves(fromFile, spec) {
2425
3151
  const base = path5.resolve(path5.dirname(fromFile), spec);
2426
3152
  return RESOLVE_EXTS.some((ext) => {
2427
3153
  try {
2428
- return statSync3(base + ext).isFile();
3154
+ return statSync4(base + ext).isFile();
2429
3155
  } catch {
2430
3156
  return false;
2431
3157
  }
@@ -3208,7 +3934,7 @@ function formatTokenList(result) {
3208
3934
  }
3209
3935
 
3210
3936
  // src/tools/install.ts
3211
- import { statSync as statSync4 } from "fs";
3937
+ import { statSync as statSync5 } from "fs";
3212
3938
  import path6 from "path";
3213
3939
  var DEFAULT_LAYOUT_CONFIG = { componentsDir: "components/ui" };
3214
3940
  var MCP_ADD_HINTS = {
@@ -3247,7 +3973,7 @@ async function handleInstallComponent(params, deps = {}) {
3247
3973
  const root = path6.resolve(params.targetDir);
3248
3974
  let isDir = false;
3249
3975
  try {
3250
- isDir = statSync4(root).isDirectory();
3976
+ isDir = statSync5(root).isDirectory();
3251
3977
  } catch {
3252
3978
  isDir = false;
3253
3979
  }
@@ -4752,9 +5478,11 @@ import fs6 from "fs-extra";
4752
5478
  import path9 from "path";
4753
5479
 
4754
5480
  // src/tools/brand-core.ts
4755
- import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
5481
+ import { createHash as createHash2 } from "crypto";
5482
+ import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
4756
5483
  import { createRequire } from "module";
4757
5484
  import { dirname as dirname4, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
5485
+ import { MessageChannel, Worker, receiveMessageOnPort } from "worker_threads";
4758
5486
  var TOKENS_PACKAGE = "@axis-ds/tokens";
4759
5487
  var MIN_BRAND_TOKENS_VERSION = "1.3.0";
4760
5488
  var TOKENS_DEPENDENCY_MIN_VERSION = "1.6.0";
@@ -4779,13 +5507,15 @@ function readJsonFile(file) {
4779
5507
  function errorCode(err) {
4780
5508
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
4781
5509
  }
4782
- function findTokensPackageJson(baseDir) {
5510
+ function tokensPackageJsonCandidates(baseDir) {
5511
+ const candidates = [];
4783
5512
  let dir = resolve3(baseDir);
4784
5513
  for (; ; ) {
4785
5514
  const candidate = join4(dir, "node_modules", TOKENS_PACKAGE, "package.json");
4786
- if (existsSync8(candidate)) return candidate;
5515
+ candidates.push(candidate);
5516
+ if (existsSync8(candidate)) return { found: candidate, candidates };
4787
5517
  const parent = dirname4(dir);
4788
- if (parent === dir) return void 0;
5518
+ if (parent === dir) return { candidates };
4789
5519
  dir = parent;
4790
5520
  }
4791
5521
  }
@@ -4795,18 +5525,195 @@ function projectRequire(baseDir) {
4795
5525
  function tokensSpecifier(subpath) {
4796
5526
  return `${TOKENS_PACKAGE}/${subpath.replace(/^\.\//, "")}`;
4797
5527
  }
4798
- function resolveTokens(baseDir) {
4799
- const pkgJson = findTokensPackageJson(baseDir);
4800
- if (!pkgJson) return { status: "not-installed" };
4801
- const pkg = readJsonFile(pkgJson);
4802
- const version = typeof pkg.version === "string" ? pkg.version : void 0;
5528
+ var nodeSeenStates = /* @__PURE__ */ new Map();
5529
+ var ABSENT = "absent";
5530
+ var UNKNOWN = "unknown";
5531
+ var isolationDisabled = false;
5532
+ var isolatedStats = { workers: 0, resolves: 0, fallbacks: 0 };
5533
+ var ISOLATED_RESOLVE_TIMEOUT_MS = 5e3;
5534
+ var ISOLATED_RESOLVE_SOURCE = `
5535
+ const { workerData } = require("node:worker_threads");
5536
+ const { createRequire } = require("node:module");
5537
+ const { port, signal, from } = workerData;
5538
+ const req = createRequire(from);
5539
+ port.on("message", (spec) => {
5540
+ let reply;
5541
+ try {
5542
+ reply = { path: req.resolve(spec) };
5543
+ } catch (err) {
5544
+ const code = err && typeof err === "object" && "code" in err ? String(err.code) : undefined;
5545
+ reply = { code, message: err && err.message ? String(err.message) : String(err) };
5546
+ }
5547
+ port.postMessage(reply);
5548
+ Atomics.store(signal, 0, 1);
5549
+ Atomics.notify(signal, 0);
5550
+ });
5551
+ `;
5552
+ var IsolationFailure = class extends Error {
5553
+ };
5554
+ function createWorkerResolveSession(from, source, timeoutMs) {
5555
+ const { port1, port2 } = new MessageChannel();
5556
+ const signal = new Int32Array(new SharedArrayBuffer(4));
5557
+ const worker = new Worker(source, {
5558
+ eval: true,
5559
+ workerData: { port: port2, signal, from },
5560
+ transferList: [port2]
5561
+ });
5562
+ worker.on("error", () => {
5563
+ });
5564
+ worker.unref();
5565
+ return {
5566
+ resolve(spec) {
5567
+ Atomics.store(signal, 0, 0);
5568
+ port1.postMessage(spec);
5569
+ const waited = Atomics.wait(signal, 0, 0, timeoutMs);
5570
+ const received = receiveMessageOnPort(port1);
5571
+ if (waited === "timed-out" || !received) throw new IsolationFailure("\uACA9\uB9AC \uD574\uC11D\uC774 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
5572
+ const reply = received.message;
5573
+ if (typeof reply.path === "string") return reply.path;
5574
+ throw Object.assign(new Error(reply.message ?? spec), reply.code === void 0 ? {} : { code: reply.code });
5575
+ },
5576
+ close() {
5577
+ port1.close();
5578
+ void worker.terminate();
5579
+ }
5580
+ };
5581
+ }
5582
+ function workerResolveSession(from) {
5583
+ return createWorkerResolveSession(from, ISOLATED_RESOLVE_SOURCE, ISOLATED_RESOLVE_TIMEOUT_MS);
5584
+ }
5585
+ var isolatedFactory = workerResolveSession;
5586
+ function sha256(text) {
5587
+ return createHash2("sha256").update(text).digest("hex");
5588
+ }
5589
+ function openTokensResolver(baseDir, candidates, pkgJson, pkgText) {
5590
+ const nodeRequire = projectRequire(baseDir);
5591
+ const key = sha256(pkgText);
5592
+ const current = candidates.map((c) => c === pkgJson ? key : ABSENT);
5593
+ const changed = candidates.some((c, i) => {
5594
+ const seen = nodeSeenStates.get(c);
5595
+ return seen !== void 0 && seen !== current[i];
5596
+ });
5597
+ let mode = changed ? "isolated" : "node";
5598
+ if (mode === "node") {
5599
+ candidates.forEach((c, i) => {
5600
+ if (!nodeSeenStates.has(c)) nodeSeenStates.set(c, current[i]);
5601
+ });
5602
+ }
5603
+ let session = null;
5604
+ let stale = false;
5605
+ let raced = false;
5606
+ let postChecked = false;
5607
+ const markStale = () => {
5608
+ if (!stale) isolatedStats.fallbacks += 1;
5609
+ stale = true;
5610
+ };
5611
+ const fallBack = () => {
5612
+ markStale();
5613
+ isolationDisabled = true;
5614
+ session?.close();
5615
+ session = null;
5616
+ };
5617
+ const startIsolation = () => {
5618
+ if (isolationDisabled) {
5619
+ markStale();
5620
+ return;
5621
+ }
5622
+ try {
5623
+ session = isolatedFactory(join4(resolve3(baseDir), "package.json"));
5624
+ isolatedStats.workers += 1;
5625
+ } catch {
5626
+ fallBack();
5627
+ }
5628
+ };
5629
+ if (mode === "isolated") startIsolation();
5630
+ const isolatedResolve = (spec) => {
5631
+ if (session) {
5632
+ try {
5633
+ const resolved = session.resolve(spec);
5634
+ isolatedStats.resolves += 1;
5635
+ return resolved;
5636
+ } catch (err) {
5637
+ if (!(err instanceof IsolationFailure)) {
5638
+ isolatedStats.resolves += 1;
5639
+ throw err;
5640
+ }
5641
+ fallBack();
5642
+ }
5643
+ }
5644
+ return nodeRequire.resolve(spec);
5645
+ };
5646
+ return {
5647
+ resolve(spec) {
5648
+ if (mode === "isolated") return isolatedResolve(spec);
5649
+ let resolved;
5650
+ let failure;
5651
+ let failed = false;
5652
+ try {
5653
+ resolved = nodeRequire.resolve(spec);
5654
+ } catch (err) {
5655
+ failed = true;
5656
+ failure = err;
5657
+ }
5658
+ if (!postChecked) {
5659
+ postChecked = true;
5660
+ let after;
5661
+ try {
5662
+ after = sha256(readFileSync8(pkgJson, "utf8"));
5663
+ } catch {
5664
+ after = UNKNOWN;
5665
+ }
5666
+ if (after !== key) {
5667
+ nodeSeenStates.set(pkgJson, UNKNOWN);
5668
+ raced = true;
5669
+ mode = "isolated";
5670
+ startIsolation();
5671
+ return isolatedResolve(spec);
5672
+ }
5673
+ }
5674
+ if (failed) throw failure;
5675
+ return resolved;
5676
+ },
5677
+ get stale() {
5678
+ return stale;
5679
+ },
5680
+ get raced() {
5681
+ return raced;
5682
+ },
5683
+ close() {
5684
+ session?.close();
5685
+ session = null;
5686
+ }
5687
+ };
5688
+ }
5689
+ function readVersion(pkgText) {
5690
+ const pkg = JSON.parse(pkgText);
5691
+ return typeof pkg.version === "string" ? pkg.version : void 0;
5692
+ }
5693
+ function openTokens(baseDir) {
5694
+ const { found: pkgJson, candidates } = tokensPackageJsonCandidates(baseDir);
5695
+ if (!pkgJson) return { resolution: { status: "not-installed" } };
5696
+ const pkgText = readFileSync8(pkgJson, "utf8");
5697
+ let version = readVersion(pkgText);
5698
+ const resolver = openTokensResolver(baseDir, candidates, pkgJson, pkgText);
5699
+ const finish = (status, indexPath) => {
5700
+ if (resolver.raced) {
5701
+ try {
5702
+ version = readVersion(readFileSync8(pkgJson, "utf8"));
5703
+ } catch {
5704
+ }
5705
+ }
5706
+ const resolution = indexPath === void 0 ? { status, version } : { status, version, indexPath };
5707
+ return { resolution: resolver.stale ? { ...resolution, stale: true } : resolution, resolver };
5708
+ };
4803
5709
  try {
4804
- const indexPath = projectRequire(baseDir).resolve(tokensSpecifier("./brands"));
4805
- return { status: "ok", version, indexPath };
5710
+ const indexPath = resolver.resolve(tokensSpecifier("./brands"));
5711
+ return finish("ok", indexPath);
4806
5712
  } catch (err) {
4807
5713
  const code = errorCode(err);
4808
- if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return { status: "unsupported", version };
4809
- if (code === "MODULE_NOT_FOUND") return { status: "not-built", version };
5714
+ if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return finish("unsupported");
5715
+ if (code === "MODULE_NOT_FOUND") return finish("not-built");
5716
+ resolver.close();
4810
5717
  throw err;
4811
5718
  }
4812
5719
  }
@@ -4815,29 +5722,11 @@ function brandImportPath(entry) {
4815
5722
  }
4816
5723
  function isFile2(file) {
4817
5724
  try {
4818
- return statSync5(file).isFile();
5725
+ return statSync6(file).isFile();
4819
5726
  } catch {
4820
5727
  return false;
4821
5728
  }
4822
5729
  }
4823
- function findGlobalCss(baseDir, config) {
4824
- const root = resolve3(baseDir);
4825
- const result = {};
4826
- const configured = config?.globalCss;
4827
- if (typeof configured === "string" && configured.trim() !== "") {
4828
- const file = resolve3(root, configured);
4829
- if (isFile2(file)) return { path: file };
4830
- result.configuredMissing = configured;
4831
- }
4832
- for (const candidate of GLOBAL_CSS_CANDIDATES) {
4833
- const file = join4(root, candidate);
4834
- if (isFile2(file)) {
4835
- result.path = file;
4836
- break;
4837
- }
4838
- }
4839
- return result;
4840
- }
4841
5730
  function findBrandImports(css) {
4842
5731
  const names = [];
4843
5732
  const pattern = /@import\s+(?:url\(\s*)?["']?@axis-ds\/tokens\/css\/brands\/([a-z][a-z0-9-]*)(?:\.css)?["']?\s*\)?\s*(?=[;\s]|$)/g;
@@ -4862,18 +5751,24 @@ function inspectBrandImport(baseDir) {
4862
5751
  const brand = config?.brand;
4863
5752
  if (typeof brand !== "string" || brand.trim() === "") return null;
4864
5753
  const root = resolve3(baseDir);
4865
- const location = findGlobalCss(root, config);
5754
+ const location = selectGlobalCss(root, config?.globalCss, GLOBAL_CSS_CANDIDATES, { requireStylesheet: true });
4866
5755
  const base = { brand };
4867
5756
  if (location.configuredMissing !== void 0) base.configuredMissing = location.configuredMissing;
5757
+ if (location.configuredRejected !== void 0) base.configuredRejected = location.configuredRejected;
4868
5758
  if (!location.path) {
4869
5759
  return { ...base, state: "css-missing", imports: [] };
4870
5760
  }
4871
5761
  const cssFile = relative2(root, location.path).split(sep2).join("/");
4872
- const imports = [...new Set(findBrandImports(readFileSync8(location.path, "utf8")))];
5762
+ const expanded = expandGlobalCss(root, location.path, cssFile);
5763
+ const imports = [...new Set(findBrandImports(expanded.evidence))];
4873
5764
  let state;
4874
5765
  if (imports.includes(brand)) state = "match";
4875
5766
  else if (imports.length === 0) state = "import-missing";
4876
5767
  else state = "other-brand";
5768
+ const sub = expanded.files.filter((f) => f.depth > 0);
5769
+ const via = state === "match" ? sub.filter((f) => findBrandImports(f.css).includes(brand)).slice(0, 1) : state === "other-brand" ? sub.filter((f) => findBrandImports(f.css).length > 0) : [];
5770
+ const entryHas = state === "match" && findBrandImports(expanded.files[0].css).includes(brand);
5771
+ if (via.length > 0 && !entryHas) return { ...base, state, cssFile, imports, importVia: via.map((f) => f.rel) };
4877
5772
  return { ...base, state, cssFile, imports };
4878
5773
  }
4879
5774
  function isMissingBuildFile(err) {
@@ -4887,8 +5782,8 @@ function readBrandIndex(indexPath) {
4887
5782
  }
4888
5783
  return data.brands;
4889
5784
  }
4890
- function readSummary(baseDir, entry) {
4891
- const metaPath = projectRequire(baseDir).resolve(tokensSpecifier(entry.meta));
5785
+ function readSummary(resolver, entry) {
5786
+ const metaPath = resolver.resolve(tokensSpecifier(entry.meta));
4892
5787
  const meta = readJsonFile(metaPath);
4893
5788
  return {
4894
5789
  name: entry.name,
@@ -4899,20 +5794,33 @@ function readSummary(baseDir, entry) {
4899
5794
  };
4900
5795
  }
4901
5796
  function listBrands(baseDir) {
4902
- const tokens = resolveTokens(baseDir);
4903
- if (tokens.status !== "ok" || !tokens.indexPath) {
5797
+ const { resolution: tokens, resolver } = openTokens(baseDir);
5798
+ try {
5799
+ return withStaleOf(resolver, listBrandsWith(tokens, resolver));
5800
+ } finally {
5801
+ resolver?.close();
5802
+ }
5803
+ }
5804
+ function listBrandsWith(tokens, resolver) {
5805
+ if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
4904
5806
  return { status: tokens.status, version: tokens.version, brands: [] };
4905
5807
  }
4906
5808
  const entries = readBrandIndex(tokens.indexPath);
4907
- let brands;
4908
- try {
4909
- brands = entries.map((entry) => readSummary(baseDir, entry));
4910
- } catch (err) {
4911
- if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
4912
- throw err;
5809
+ const brands = [];
5810
+ for (const entry of entries) {
5811
+ try {
5812
+ brands.push(readSummary(resolver, entry));
5813
+ } catch (err) {
5814
+ if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
5815
+ if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") continue;
5816
+ throw err;
5817
+ }
4913
5818
  }
4914
5819
  return { status: "ok", version: tokens.version, brands };
4915
5820
  }
5821
+ function withStaleOf(resolver, result) {
5822
+ return resolver?.stale ? { ...result, stale: true } : result;
5823
+ }
4916
5824
  function stripComments(css) {
4917
5825
  return css.replace(/\/\*[\s\S]*?\*\//g, "");
4918
5826
  }
@@ -5024,8 +5932,15 @@ function readProjectPackageJson(baseDir) {
5024
5932
  }
5025
5933
  }
5026
5934
  function getBrand(baseDir, name) {
5027
- const tokens = resolveTokens(baseDir);
5028
- if (tokens.status !== "ok" || !tokens.indexPath) {
5935
+ const { resolution: tokens, resolver } = openTokens(baseDir);
5936
+ try {
5937
+ return withStaleOf(resolver, getBrandWith(tokens, resolver, name));
5938
+ } finally {
5939
+ resolver?.close();
5940
+ }
5941
+ }
5942
+ function getBrandWith(tokens, resolver, name) {
5943
+ if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
5029
5944
  return { status: tokens.status, version: tokens.version, brand: null, available: [] };
5030
5945
  }
5031
5946
  const entries = readBrandIndex(tokens.indexPath);
@@ -5037,11 +5952,14 @@ function getBrand(baseDir, name) {
5037
5952
  let summary;
5038
5953
  let parsed;
5039
5954
  try {
5040
- summary = readSummary(baseDir, entry);
5041
- const cssPath = projectRequire(baseDir).resolve(summary.importPath);
5955
+ summary = readSummary(resolver, entry);
5956
+ const cssPath = resolver.resolve(summary.importPath);
5042
5957
  parsed = parseBrandCss(readFileSync8(cssPath, "utf8"), name);
5043
5958
  } catch (err) {
5044
5959
  if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
5960
+ if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
5961
+ return { status: "ok", version: tokens.version, brand: null, available: available.filter((n) => n !== name) };
5962
+ }
5045
5963
  throw err;
5046
5964
  }
5047
5965
  return {
@@ -5262,13 +6180,14 @@ async function handleDiffTemplate(params) {
5262
6180
  }
5263
6181
  function brandCheckResult(check) {
5264
6182
  const { brand } = check;
5265
- const suffix = check.configuredMissing !== void 0 ? ` (globalCss ${check.configuredMissing} \uC5C6\uC74C)` : "";
6183
+ const suffix = globalCssSelectionNote(check);
6184
+ const via = cssImportViaNote(check.importVia);
5266
6185
  switch (check.state) {
5267
6186
  case "match":
5268
6187
  return {
5269
6188
  name: "brand",
5270
6189
  severity: "pass",
5271
- message: `brand "${brand}" import \uAC00 ${check.cssFile}\uC5D0 \uC788\uC2B5\uB2C8\uB2E4${suffix}`
6190
+ message: `brand "${brand}" import \uAC00 ${check.cssFile}\uC5D0 \uC788\uC2B5\uB2C8\uB2E4${via}${suffix}`
5272
6191
  };
5273
6192
  case "css-missing":
5274
6193
  return {
@@ -5286,7 +6205,7 @@ function brandCheckResult(check) {
5286
6205
  return {
5287
6206
  name: "brand",
5288
6207
  severity: "warn",
5289
- message: `brand "${brand}" \uC640 import(${check.imports.join(", ")})\uAC00 \uB2E4\uB985\uB2C8\uB2E4${suffix}`
6208
+ message: `brand "${brand}" \uC640 import(${check.imports.join(", ")})\uAC00 \uB2E4\uB985\uB2C8\uB2E4${via}${suffix}`
5290
6209
  };
5291
6210
  }
5292
6211
  }
@@ -5527,7 +6446,16 @@ function formatTokensStatusGuide(status, version, installCommand = TOKENS_INSTAL
5527
6446
  ].join("\n");
5528
6447
  }
5529
6448
  }
6449
+ var STALE_TOKENS_NOTE = `- \uC8FC\uC758: \uC774 MCP \uC11C\uBC84\uAC00 ${TOKENS_PACKAGE} \uB97C \uCC98\uC74C \uC77D\uC740 \uB4A4 \uB0B4\uC6A9\uC774 \uBC14\uB00C\uC5C8\uB294\uB370 \uC0C8 \uC0C1\uD0DC\uB97C \uB2E4\uC2DC \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uACB0\uACFC\uB294 \uC774\uC804 \uC124\uCE58 \uAE30\uC900\uC77C \uC218 \uC788\uC73C\uB2C8 MCP \uC11C\uBC84\uB97C \uB2E4\uC2DC \uC2DC\uC791\uD558\uC138\uC694.`;
6450
+ function withStaleNote(text, result) {
6451
+ return result.stale ? `${text}
6452
+
6453
+ ${STALE_TOKENS_NOTE}` : text;
6454
+ }
5530
6455
  function formatListBrandsResult(result, installCommand) {
6456
+ return withStaleNote(listBrandsText(result, installCommand), result);
6457
+ }
6458
+ function listBrandsText(result, installCommand) {
5531
6459
  const lines = ["## AXIS \uBE0C\uB79C\uB4DC\n"];
5532
6460
  if (result.status !== "ok") {
5533
6461
  lines.push(formatTokensStatusGuide(result.status, result.version, installCommand));
@@ -5565,6 +6493,9 @@ function tokenTable(brand) {
5565
6493
  return lines;
5566
6494
  }
5567
6495
  function formatGetBrandResult(result, name, installCommand) {
6496
+ return withStaleNote(getBrandText(result, name, installCommand), result);
6497
+ }
6498
+ function getBrandText(result, name, installCommand) {
5568
6499
  if (result.status !== "ok") {
5569
6500
  return [`## \uBE0C\uB79C\uB4DC: ${name}
5570
6501
  `, formatTokensStatusGuide(result.status, result.version, installCommand)].join("\n");