@axis-ds/mcp 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +272 -40
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2434,9 +2434,222 @@ var TAILWIND_CSS_CANDIDATES = [
2434
2434
  "styles/globals.css"
2435
2435
  ];
2436
2436
  var TAILWIND_IMPORT = /@import\s+(?:url\(\s*)?["']tailwindcss["']/;
2437
+ function stripCssComments(css) {
2438
+ return css.replace(/\/\*[\s\S]*?\*\//g, "");
2439
+ }
2437
2440
  function hasTailwindImport(css) {
2438
- return TAILWIND_IMPORT.test(css.replace(/\/\*[\s\S]*?\*\//g, ""));
2441
+ return TAILWIND_IMPORT.test(stripCssComments(css));
2442
+ }
2443
+ var TOKENS_TAILWIND4_ENTRY = "@axis-ds/tokens/css/tailwind4";
2444
+ var TOKENS_TAILWIND4_IMPORT_LINE = `@import "${TOKENS_TAILWIND4_ENTRY}";`;
2445
+ var TOKENS_TAILWIND4_IMPORT = /@import\s+(?:url\(\s*)?["']@axis-ds\/tokens\/css\/tailwind4["']/;
2446
+ function hasTokensTailwind4Import(css) {
2447
+ return TOKENS_TAILWIND4_IMPORT.test(stripCssComments(css));
2448
+ }
2449
+ var TOKENS_CSS_IMPORT = /@import\s+(?:url\(\s*)?["'](@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)["']/;
2450
+ function findTokensCssImport(css) {
2451
+ return TOKENS_CSS_IMPORT.exec(stripCssComments(css))?.[1];
2452
+ }
2453
+ function checkGlobalsCss(baseDirInput) {
2454
+ const baseDir = resolve3(baseDirInput);
2455
+ for (const candidate of TAILWIND_CSS_CANDIDATES) {
2456
+ const file = join5(baseDir, candidate);
2457
+ if (!existsSync5(file)) continue;
2458
+ const content = readFileSync6(file, "utf8");
2459
+ if (content.includes("--background") && content.includes("--primary")) {
2460
+ return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4` };
2461
+ }
2462
+ const imported = findTokensCssImport(content);
2463
+ if (imported !== void 0) {
2464
+ return { name: "globals.css", severity: "pass", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)` };
2465
+ }
2466
+ return { name: "globals.css", severity: "warn", message: `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4` };
2467
+ }
2468
+ return { name: "globals.css", severity: "fail", message: "globals.css \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4" };
2469
+ }
2470
+ var TAILWIND4_MIN_AXIS_VERSION = "1.4.0";
2471
+ var TAILWIND4_AXIS_PACKAGES = ["@axis-ds/tokens", "@axis-ds/ui-react", "@axis-ds/agentic-ui"];
2472
+ function lowerOf(token) {
2473
+ const v = versionParts(token);
2474
+ if (!v) return void 0;
2475
+ const num = (part) => isWild(part) ? 0 : Number(part);
2476
+ const pre = /^v?\d+(?:\.(?:\d+|[xX*]))?(?:\.(?:\d+|[xX*]))?-/.test(token);
2477
+ return { core: [v.major, num(v.minor), num(v.patch)], pre };
2478
+ }
2479
+ function compareLower(a, b) {
2480
+ for (let i = 0; i < 3; i++) {
2481
+ if (a.core[i] !== b.core[i]) return a.core[i] - b.core[i];
2482
+ }
2483
+ return Number(b.pre) - Number(a.pre);
2439
2484
  }
2485
+ function rangeLowerVersion(range) {
2486
+ const r = range.trim();
2487
+ if (r === "" || r.includes("||")) return void 0;
2488
+ const simple = new RegExp(`^(?:\\^|~|=)?\\s*(${VERSION})$`).exec(r);
2489
+ if (simple) return lowerOf(simple[1]);
2490
+ if (new RegExp(`^(${VERSION})\\s+-\\s+(${VERSION})$`).test(r)) {
2491
+ const [a, b] = r.split(/\s+-\s+/);
2492
+ return lowerOf(b) ? lowerOf(a) : void 0;
2493
+ }
2494
+ const tokens = r.replace(/(>=|<=|>|<|=)\s+/g, "$1").split(/\s+/);
2495
+ let lower;
2496
+ for (const t of tokens) {
2497
+ const c = /^(>=|<=|>|<|=)(.+)$/.exec(t);
2498
+ if (!c) return void 0;
2499
+ const v = versionParts(c[2]);
2500
+ const low = lowerOf(c[2]);
2501
+ if (!v || !low) return void 0;
2502
+ let candidate;
2503
+ if (c[1] === ">=" || c[1] === "=") candidate = low;
2504
+ else if (c[1] === ">") {
2505
+ if (isWild(v.minor)) candidate = { core: [v.major + 1, 0, 0], pre: false };
2506
+ else if (isWild(v.patch)) candidate = { core: [v.major, Number(v.minor) + 1, 0], pre: false };
2507
+ else candidate = { core: [v.major, Number(v.minor), Number(v.patch) + 1], pre: false };
2508
+ }
2509
+ if (candidate && (!lower || compareLower(candidate, lower) > 0)) lower = candidate;
2510
+ }
2511
+ return lower;
2512
+ }
2513
+ function rangeLowerAtLeast(range, min) {
2514
+ const lower = rangeLowerVersion(range);
2515
+ const target = lowerOf(min);
2516
+ if (!lower || !target) return void 0;
2517
+ return compareLower(lower, target) >= 0;
2518
+ }
2519
+ function exactVersion(version) {
2520
+ if (typeof version !== "string") return void 0;
2521
+ const v = version.trim();
2522
+ if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
2523
+ return v;
2524
+ }
2525
+ function installedVersion(baseDir, name) {
2526
+ try {
2527
+ const parsed = JSON.parse(readFileSync6(join5(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
2528
+ return isPlainObject(parsed) ? exactVersion(parsed.version) : void 0;
2529
+ } catch {
2530
+ return void 0;
2531
+ }
2532
+ }
2533
+ function axisPackagesBelowTailwind4(pkg, baseDirInput) {
2534
+ if (!pkg) return [];
2535
+ const baseDir = baseDirInput !== void 0 ? resolve3(baseDirInput) : void 0;
2536
+ const out = [];
2537
+ const min = lowerOf(TAILWIND4_MIN_AXIS_VERSION);
2538
+ for (const name of TAILWIND4_AXIS_PACKAGES) {
2539
+ const range = hasDependency(pkg, name);
2540
+ if (range === void 0 || range.trim().startsWith("workspace:")) continue;
2541
+ const installed = baseDir !== void 0 ? installedVersion(baseDir, name) : void 0;
2542
+ const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
2543
+ if (installed !== void 0 && installedLower !== void 0) {
2544
+ if (compareLower(installedLower, min) < 0) out.push({ name, range, status: "below", source: "installed", installed });
2545
+ continue;
2546
+ }
2547
+ const atLeast = rangeLowerAtLeast(range, TAILWIND4_MIN_AXIS_VERSION);
2548
+ if (atLeast === false) out.push({ name, range, status: "below", source: "declared" });
2549
+ else if (atLeast === void 0) out.push({ name, range, status: "unknown", source: "declared" });
2550
+ }
2551
+ return out;
2552
+ }
2553
+ function axisPackageVersionLabel(issue) {
2554
+ return issue.source === "installed" ? `${issue.name} \uC124\uCE58\uBCF8 ${issue.installed}` : `${issue.name} ${issue.range}`;
2555
+ }
2556
+ var declaredList = (issues) => issues.map(axisPackageVersionLabel).join(" \xB7 ");
2557
+ function tailwind4VersionNote(issues) {
2558
+ const below = issues.filter((i) => i.status === "below");
2559
+ const unknown = issues.filter((i) => i.status === "unknown");
2560
+ let note = "";
2561
+ if (below.length > 0) note += ` (${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1 \uD544\uC694: ${declaredList(below)})`;
2562
+ if (unknown.length > 0) note += ` (\uC124\uCE58\uB41C \uBC84\uC804\uC774 ${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC778\uC9C0 \uD655\uC778\uD558\uC138\uC694: ${declaredList(unknown)})`;
2563
+ return note;
2564
+ }
2565
+ var TAILWIND4_COMPONENT_PACKAGES = ["@axis-ds/ui-react", "@axis-ds/agentic-ui"];
2566
+ function componentTailwindImportLine(name) {
2567
+ return `@import "${name}/tailwind.css";`;
2568
+ }
2569
+ var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2570
+ function hasComponentTailwindImport(css, name) {
2571
+ const re = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${escapeRegExp(name)}/tailwind\\.css["']`);
2572
+ return re.test(stripCssComments(css));
2573
+ }
2574
+ function hasComponentSource(css, name) {
2575
+ const re = new RegExp(`@source\\s+(["'])(?!@axis-ds/)[^"'\\n]*${escapeRegExp(name)}(?:[/\\\\][^"'\\n]*)?\\1`);
2576
+ return re.test(stripCssComments(css));
2577
+ }
2578
+ var CREATE_NEXT_APP_DEFAULTS = [
2579
+ {
2580
+ prefix: ":root \uC0C9\uAC12",
2581
+ pattern: /(?<![\w-])(--(?:background|foreground))\s*:\s*(?:#[0-9a-fA-F]{3,8}\b|(?:rgba?|hsla?|hwb|oklch|oklab|lab|lch|color)\()/g,
2582
+ item: (m) => m[1]
2583
+ },
2584
+ {
2585
+ prefix: "@theme",
2586
+ pattern: /(?<![\w-])(--color-(?:background|foreground))\s*:\s*var\(\s*(--(?:background|foreground))\s*\)/g,
2587
+ item: (m) => `${m[1]}: var(${m[2]})`
2588
+ },
2589
+ {
2590
+ prefix: "@theme",
2591
+ pattern: /(?<![\w-])(--font-(?:sans|mono))\s*:\s*var\(\s*(--font-geist-(?:sans|mono))\s*\)/g,
2592
+ item: (m) => `${m[1]}: var(${m[2]})`
2593
+ },
2594
+ {
2595
+ prefix: "body",
2596
+ pattern: /(?<![\w-])(background|background-color|color)\s*:\s*var\(\s*(--(?:background|foreground))\s*\)/g,
2597
+ item: (m) => `${m[1]}: var(${m[2]})`
2598
+ }
2599
+ ];
2600
+ function findCreateNextAppDefaults(css) {
2601
+ const body = stripCssComments(css);
2602
+ const labels = [];
2603
+ for (const d of CREATE_NEXT_APP_DEFAULTS) {
2604
+ const items = [];
2605
+ for (const m of body.matchAll(d.pattern)) {
2606
+ const item = d.item(m);
2607
+ if (!items.includes(item)) items.push(item);
2608
+ }
2609
+ if (items.length > 0) labels.push(`${d.prefix} ${items.join(", ")}`);
2610
+ }
2611
+ return labels;
2612
+ }
2613
+ function stripJsComments(src) {
2614
+ let out = "";
2615
+ let i = 0;
2616
+ const n = src.length;
2617
+ while (i < n) {
2618
+ const c = src[i];
2619
+ const d = src[i + 1];
2620
+ if (c === '"' || c === "'" || c === "`") {
2621
+ let j = i + 1;
2622
+ while (j < n && src[j] !== c) {
2623
+ if (src[j] === "\\") j++;
2624
+ else if (c !== "`" && src[j] === "\n") break;
2625
+ j++;
2626
+ }
2627
+ out += src.slice(i, j + 1);
2628
+ i = j + 1;
2629
+ continue;
2630
+ }
2631
+ if (c === "/" && d === "/") {
2632
+ const end = src.indexOf("\n", i);
2633
+ i = end === -1 ? n : end;
2634
+ continue;
2635
+ }
2636
+ if (c === "/" && d === "*") {
2637
+ const end = src.indexOf("*/", i + 2);
2638
+ i = end === -1 ? n : end + 2;
2639
+ out += " ";
2640
+ continue;
2641
+ }
2642
+ out += c;
2643
+ i++;
2644
+ }
2645
+ return out;
2646
+ }
2647
+ var TOKENS_TAILWIND3_PRESET = "@axis-ds/tokens/tailwind";
2648
+ var PRESET_REFERENCE = /(?:\brequire\s*\(\s*|\bimport\s*\(\s*|\bfrom\s*|\bimport\s+)(["'])@axis-ds\/tokens\/tailwind\1/;
2649
+ function hasTokensPresetReference(source) {
2650
+ return PRESET_REFERENCE.test(stripJsComments(source));
2651
+ }
2652
+ var PRESET_PASS_SUFFIX = `\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${TOKENS_TAILWIND3_PRESET} preset)`;
2440
2653
  function readPackageJson(baseDir) {
2441
2654
  try {
2442
2655
  const parsed = JSON.parse(readFileSync6(join5(baseDir, "package.json"), "utf8"));
@@ -2445,19 +2658,60 @@ function readPackageJson(baseDir) {
2445
2658
  return void 0;
2446
2659
  }
2447
2660
  }
2661
+ function tailwind4Issues(css, pkg, versions) {
2662
+ const issues = [];
2663
+ const hasEntry = hasTokensTailwind4Import(css);
2664
+ if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
2665
+ const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
2666
+ (name) => pkg !== void 0 && hasDependency(pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
2667
+ );
2668
+ if (missing.length > 0) {
2669
+ issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
2670
+ }
2671
+ if (hasEntry) {
2672
+ const defaults = findCreateNextAppDefaults(css);
2673
+ 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`);
2674
+ if (versions.some((v) => v.name === TAILWIND4_AXIS_PACKAGES[0])) {
2675
+ 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`);
2676
+ }
2677
+ }
2678
+ for (const name of TAILWIND4_COMPONENT_PACKAGES) {
2679
+ if (hasComponentTailwindImport(css, name) && versions.some((v) => v.name === name)) {
2680
+ issues.push(`${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${name} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
2681
+ }
2682
+ }
2683
+ return issues;
2684
+ }
2448
2685
  function checkTailwindSetup(baseDirInput) {
2449
2686
  const baseDir = resolve3(baseDirInput);
2450
- const tailwind = detectTailwind(baseDir, readPackageJson(baseDir));
2687
+ const pkg = readPackageJson(baseDir);
2688
+ const tailwind = detectTailwind(baseDir, pkg);
2451
2689
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
2452
2690
  const label = `Tailwind ${tailwind.major}`;
2453
2691
  for (const candidate of TAILWIND_CSS_CANDIDATES) {
2454
2692
  const file = join5(baseDir, candidate);
2455
2693
  if (!existsSync5(file)) continue;
2456
- const found = hasTailwindImport(readFileSync6(file, "utf8"));
2694
+ const css = readFileSync6(file, "utf8");
2695
+ if (!hasTailwindImport(css)) {
2696
+ return {
2697
+ name: "tailwind.config",
2698
+ severity: "warn",
2699
+ message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4`
2700
+ };
2701
+ }
2702
+ const versions = axisPackagesBelowTailwind4(pkg, baseDir);
2703
+ const issues = tailwind4Issues(css, pkg, versions);
2704
+ if (issues.length > 0) {
2705
+ return {
2706
+ name: "tailwind.config",
2707
+ severity: "warn",
2708
+ message: `${label}: ${candidate}\uC5D0 ${issues.join(" / ")}${tailwind4VersionNote(versions)}`
2709
+ };
2710
+ }
2457
2711
  return {
2458
2712
  name: "tailwind.config",
2459
- severity: found ? "pass" : "warn",
2460
- message: found ? `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uAC00 \uC788\uC2B5\uB2C8\uB2E4` : `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4`
2713
+ severity: "pass",
2714
+ message: `${label}: ${candidate}\uC5D0 @import "tailwindcss" \uC640 AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC788\uC2B5\uB2C8\uB2E4`
2461
2715
  };
2462
2716
  }
2463
2717
  return {
@@ -2471,14 +2725,20 @@ function checkTailwindSetup(baseDirInput) {
2471
2725
  if (existsSync5(tsPath)) {
2472
2726
  const content = readFileSync6(tsPath, "utf8");
2473
2727
  const hasTokens = content.includes("--background") || content.includes("hsl(var(");
2474
- return {
2475
- name: "tailwind.config",
2476
- severity: hasTokens ? "pass" : "warn",
2477
- message: hasTokens ? "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4" : "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
2478
- };
2728
+ if (hasTokens) {
2729
+ return { name: "tailwind.config", severity: "pass", message: "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070\uC774 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4" };
2730
+ }
2731
+ if (hasTokensPresetReference(content)) {
2732
+ return { name: "tailwind.config", severity: "pass", message: `tailwind.config.ts${PRESET_PASS_SUFFIX}` };
2733
+ }
2734
+ return { name: "tailwind.config", severity: "warn", message: "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
2479
2735
  }
2480
2736
  for (const file of otherFiles) {
2481
- if (existsSync5(join5(baseDir, file))) {
2737
+ const path5 = join5(baseDir, file);
2738
+ if (existsSync5(path5)) {
2739
+ if (hasTokensPresetReference(readFileSync6(path5, "utf8"))) {
2740
+ return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
2741
+ }
2482
2742
  return { name: "tailwind.config", severity: "warn", message: `${file} \uC874\uC7AC (TypeScript \uAD8C\uC7A5)` };
2483
2743
  }
2484
2744
  }
@@ -2646,35 +2906,7 @@ async function handleCheckProject(params) {
2646
2906
  message: configExists ? "axis.config.json \uD30C\uC77C\uC774 \uC874\uC7AC\uD569\uB2C8\uB2E4" : "axis.config.json \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 'axis init'\uC744 \uC2E4\uD589\uD558\uC138\uC694"
2647
2907
  });
2648
2908
  results.push(checkTailwindSetup(baseDir));
2649
- const cssCandidates = [
2650
- "globals.css",
2651
- "app/globals.css",
2652
- "src/app/globals.css",
2653
- "src/globals.css",
2654
- "styles/globals.css"
2655
- ];
2656
- let cssFound = false;
2657
- for (const candidate of cssCandidates) {
2658
- const fullPath = path3.join(baseDir, candidate);
2659
- if (await fs3.pathExists(fullPath)) {
2660
- const content = await fs3.readFile(fullPath, "utf-8");
2661
- const hasTokens = content.includes("--background") && content.includes("--primary");
2662
- results.push({
2663
- name: "globals.css",
2664
- severity: hasTokens ? "pass" : "warn",
2665
- message: hasTokens ? `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC815\uC758\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4` : `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4`
2666
- });
2667
- cssFound = true;
2668
- break;
2669
- }
2670
- }
2671
- if (!cssFound) {
2672
- results.push({
2673
- name: "globals.css",
2674
- severity: "fail",
2675
- message: "globals.css \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4"
2676
- });
2677
- }
2909
+ results.push(checkGlobalsCss(baseDir));
2678
2910
  const utilsCandidates = [
2679
2911
  "lib/utils.ts",
2680
2912
  "src/lib/utils.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/mcp",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - MCP Server for AI-assisted component discovery",
6
6
  "bin": {