@axis-ds/cli 1.7.0 → 1.7.1

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +176 -36
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -107,7 +107,7 @@ axis theme add ontology
107
107
  - dependencies 항목(1.6.1 부터): `tailwindcss` 선언이 없으면 FAIL, `clsx` · `tailwind-merge` 선언이 없으면 WARN(종전과 같음). 여기에 선언된 `tailwindcss` · `clsx` · `tailwind-merge` · `@axis-ds/*` 가 `node_modules` 에 없으면 「선언됐지만 설치되지 않은 의존성」 WARN 과 lockfile 에 맞는 설치 명령을 냅니다. 상위 디렉터리의 `node_modules`(모노레포 호이스팅)도 찾고, Plug'n'Play(`.pnp.cjs`)는 설치본을 읽지 않고 선언 기준입니다. 1.6.0 까지는 선언만 보고 「모두 설치되어 있습니다」였습니다.
108
108
  - 해당할 때만 더하는 항목(1.6.0 부터, brand 항목 뒤 이 순서):
109
109
  - `brand.activation`: `brand` 가 있을 때 루트 레이아웃(`app/layout.tsx` · `src/app/layout.tsx` · `pages/_app` 등, 그 레이아웃이 import 하는 같은 디렉터리의 `./providers` 한 단계 포함)에 `data-brand` · `setBrand(` · `defaultBrand=` 가 없으면 WARN 입니다(휴리스틱, `ThemeProvider` 단독은 켜는 코드가 아님). 1.6.1 부터 마크업 `data-brand` 와 `ThemeProvider` 만 있고 `setBrand(` · `defaultBrand=` 가 없으면 설치본(없으면 선언) `@axis-ds/theme` 가 1.7.0 미만이거나 판정할 수 없을 때 WARN 입니다(1.6.2 이하는 마운트 때 속성을 지움).
110
- - `tailwind.content`: Tailwind 3 설정 파일이 있고 `componentsDir` 나 선언된 `@axis-ds/ui-react` · `@axis-ds/agentic-ui` 가 있을 때, `content` 의 문자열 glob 이 그 경로를 덮지 않으면 FAIL 입니다(그 경로의 클래스가 생성되지 않음). `content` 를 정적으로 다 읽지 못하면(변수 · 펼침) WARN 입니다.
110
+ - `tailwind.content`: Tailwind 3 설정 파일이 있고 `componentsDir` 나 선언된 `@axis-ds/ui-react` · `@axis-ds/agentic-ui` 가 있을 때, `content` 의 문자열 glob 이 그 경로를 덮지 않으면 FAIL 입니다(그 경로의 클래스가 생성되지 않음). `content` 를 정적으로 다 읽지 못하면(변수 · 펼침) WARN 입니다. 패키지 경로는 프로젝트 디렉터리부터 상위로 찾은 설치본 위치 기준이라, npm workspaces · pnpm hoisted 처럼 루트에만 설치된 앱은 `../../node_modules/@axis-ds/ui-react/dist/**/*.{js,mjs}` 를 안내합니다(1.7.1 부터, 설치본이 없거나 Plug'n'Play 면 `./node_modules/...`). `**` 는 `../` 를 넘지 않는 것으로, 절대경로 glob 은 실제 위치와 비교해 판정합니다. 상위 경로는 Tailwind 3 가 빌드를 실행한 디렉터리 기준으로 풀리므로 모노레포 루트에서 빌드하면 `content: { relative: true, files: [...] }` 를 쓰세요(판정은 프로젝트 디렉터리에서 빌드한다고 보고 함).
111
111
  - `animation`: `@axis-ds/ui-react` 선언이나 `componentsDir` 의 `animate-in` 류 클래스가 있을 때 애니메이션 플러그인(Tailwind 3 `tailwindcss-animate` 선언 + 설치본 + `plugins` 배열 참조, Tailwind 4 `@import "tw-animate-css"`)이 없으면 WARN 입니다. 1.6.1 부터 Tailwind 3 은 `plugins` 배열 안의 `require("tailwindcss-animate")` 나 그 패키지를 받은 식별자(`import animate from` · `const animate = require(...)`)만 인정합니다(import 만 있거나 다른 곳의 같은 문자열은 아님). 배열을 정적으로 다 읽지 못하면(펼침 · 단축 속성) 「확인하지 못함」 WARN 입니다.
112
112
  - FAIL 이 하나라도 있으면 종료 코드 1 로 끝납니다. WARN 만 있으면 0 입니다(1.3.0 부터, 이전에는 결과와 관계없이 0).
113
113
  - MCP `axis.check_project` 도 같은 항목 · 문구를 냅니다.
package/dist/index.js CHANGED
@@ -1907,16 +1907,51 @@ async function readAxisConfig(baseDir) {
1907
1907
  }
1908
1908
 
1909
1909
  // ../axis-registry-core/src/template/tailwind-core.ts
1910
- import { existsSync as existsSync2, lstatSync, readdirSync, readFileSync as readFileSync2 } from "fs";
1911
- import { extname, join, resolve } from "path";
1910
+ import { existsSync as existsSync2, lstatSync, readdirSync, readFileSync as readFileSync2, realpathSync } from "fs";
1911
+ import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "path";
1912
1912
 
1913
1913
  // ../axis-registry-core/src/project.ts
1914
1914
  import { existsSync, readFileSync, statSync } from "fs";
1915
1915
  import path8 from "path";
1916
- function detectInstallCommand(baseDir) {
1917
- if (existsSync(path8.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
1918
- if (existsSync(path8.join(baseDir, "yarn.lock"))) return "yarn install";
1919
- if (existsSync(path8.join(baseDir, "package-lock.json"))) return "npm install";
1916
+ var LOCKFILE_COMMANDS = [
1917
+ ["pnpm-lock.yaml", "pnpm install"],
1918
+ ["yarn.lock", "yarn install"],
1919
+ ["package-lock.json", "npm install"]
1920
+ ];
1921
+ function lockfileCommandAt(dir) {
1922
+ return LOCKFILE_COMMANDS.find(([file]) => existsSync(path8.join(dir, file)))?.[1];
1923
+ }
1924
+ function isWorkspaceRootDir(dir) {
1925
+ if (isFile(path8.join(dir, "pnpm-workspace.yaml"))) return true;
1926
+ let parsed;
1927
+ try {
1928
+ parsed = JSON.parse(readFileSync(path8.join(dir, "package.json"), "utf8"));
1929
+ } catch {
1930
+ return false;
1931
+ }
1932
+ if (!isPlainObject(parsed)) return false;
1933
+ const ws = parsed.workspaces;
1934
+ return Array.isArray(ws) || isPlainObject(ws) && Array.isArray(ws.packages);
1935
+ }
1936
+ function findWorkspaceRoot(baseDirInput) {
1937
+ let dir = path8.resolve(baseDirInput);
1938
+ for (; ; ) {
1939
+ if (isWorkspaceRootDir(dir)) return dir;
1940
+ if (existsSync(path8.join(dir, ".git"))) return void 0;
1941
+ const parent = path8.dirname(dir);
1942
+ if (parent === dir) return void 0;
1943
+ dir = parent;
1944
+ }
1945
+ }
1946
+ function detectInstallCommand(baseDirInput) {
1947
+ const baseDir = path8.resolve(baseDirInput);
1948
+ const own = lockfileCommandAt(baseDir);
1949
+ if (own !== void 0) return own;
1950
+ const root = findWorkspaceRoot(baseDir);
1951
+ if (root !== void 0 && root !== baseDir) {
1952
+ const fromRoot = lockfileCommandAt(root);
1953
+ if (fromRoot !== void 0) return fromRoot;
1954
+ }
1920
1955
  return "pnpm install";
1921
1956
  }
1922
1957
  function hasDependency(pkg, name) {
@@ -2592,6 +2627,92 @@ function contentGlobToRegExp(glob) {
2592
2627
  }
2593
2628
  return new RegExp(`^${re}$`);
2594
2629
  }
2630
+ function leadingParentSegments(p) {
2631
+ const s = p.trim().replace(/\\/g, "/").replace(/^\.\//, "");
2632
+ return (/^(?:\.\.\/)*/.exec(s)?.[0].length ?? 0) / 3;
2633
+ }
2634
+ function isAbsoluteGlob(glob) {
2635
+ const t = glob.trim();
2636
+ return t.startsWith("/") || /^[A-Za-z]:[\\/]/.test(t);
2637
+ }
2638
+ var MAX_BRACE_EXPANSION = 256;
2639
+ function expandBraces(glob) {
2640
+ const open = glob.indexOf("{");
2641
+ if (open === -1) return [glob];
2642
+ let depth = 0;
2643
+ let close = -1;
2644
+ const commas = [];
2645
+ for (let i = open; i < glob.length; i++) {
2646
+ const c = glob[i];
2647
+ if (c === "{") depth++;
2648
+ else if (c === "}") {
2649
+ depth--;
2650
+ if (depth === 0) {
2651
+ close = i;
2652
+ break;
2653
+ }
2654
+ } else if (c === "," && depth === 1) commas.push(i);
2655
+ }
2656
+ const head = glob.slice(0, open + 1);
2657
+ if (close === -1 || commas.length === 0) {
2658
+ return expandBraces(glob.slice(open + 1))?.map((r) => head + r);
2659
+ }
2660
+ const parts = [];
2661
+ let from = open + 1;
2662
+ for (const c of [...commas, close]) {
2663
+ parts.push(glob.slice(from, c));
2664
+ from = c + 1;
2665
+ }
2666
+ const prefix = glob.slice(0, open);
2667
+ const suffix = glob.slice(close + 1);
2668
+ const out = [];
2669
+ for (const part of parts) {
2670
+ const expanded = expandBraces(prefix + part + suffix);
2671
+ if (expanded === void 0) return void 0;
2672
+ out.push(...expanded);
2673
+ if (out.length > MAX_BRACE_EXPANSION) return void 0;
2674
+ }
2675
+ return out;
2676
+ }
2677
+ function realpathPosix(p) {
2678
+ let cur = p;
2679
+ const tail = [];
2680
+ for (let i = 0; i < 64; i++) {
2681
+ try {
2682
+ return [realpathSync(cur), ...tail].join(sep).split(sep).join("/");
2683
+ } catch {
2684
+ const parent = dirname(cur);
2685
+ if (parent === cur) return void 0;
2686
+ tail.unshift(basename(cur));
2687
+ cur = parent;
2688
+ }
2689
+ }
2690
+ return void 0;
2691
+ }
2692
+ function contentGlobBranchCovers(glob, sample, baseDir) {
2693
+ if (isAbsoluteGlob(glob)) {
2694
+ const re = contentGlobToRegExp(glob.trim().replace(/\\/g, "/"));
2695
+ const absSample = resolve(baseDir, sample);
2696
+ if (re.test(absSample.split(sep).join("/"))) return true;
2697
+ const real = realpathPosix(absSample);
2698
+ return real !== void 0 && re.test(real);
2699
+ }
2700
+ return leadingParentSegments(glob) === leadingParentSegments(sample) && contentGlobToRegExp(glob).test(sample);
2701
+ }
2702
+ function contentGlobCovers(glob, sample, baseDir) {
2703
+ const branches = expandBraces(glob.trim()) ?? [glob];
2704
+ return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir));
2705
+ }
2706
+ 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";
2707
+ function packageContentTarget(baseDir, name) {
2708
+ const found = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, name);
2709
+ const rel3 = found === void 0 ? void 0 : relative(baseDir, found.dir);
2710
+ const relDir = rel3 === void 0 || rel3 === "" || isAbsolute(rel3) ? `node_modules/${name}` : rel3.split(sep).join("/");
2711
+ return {
2712
+ sample: `${relDir}/dist/index.js`,
2713
+ suggest: `${relDir.startsWith("../") ? "" : "./"}${relDir}/dist/**/*.{js,mjs}`
2714
+ };
2715
+ }
2595
2716
  function balancedSlice(src, start) {
2596
2717
  const open = src[start];
2597
2718
  const close = open === "[" ? "]" : "}";
@@ -2653,17 +2774,17 @@ function inspectTailwindContent(baseDirInput) {
2653
2774
  }
2654
2775
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
2655
2776
  if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
2656
- targets.push({ label: name, sample: `node_modules/${name}/dist/index.js`, suggest: `./node_modules/${name}/dist/**/*.{js,mjs}` });
2777
+ targets.push({ label: name, ...packageContentTarget(baseDir, name) });
2657
2778
  }
2658
2779
  }
2659
2780
  if (targets.length === 0) return null;
2660
2781
  const read = readTailwindContent(readFileSync2(join(baseDir, configFile), "utf8"));
2661
- const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
2782
+ const globs = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!"));
2662
2783
  return {
2663
2784
  configFile,
2664
2785
  unreadable: read === void 0,
2665
2786
  dynamic: read?.dynamic ?? false,
2666
- targets: targets.map((t) => ({ ...t, covered: patterns.some((re) => re.test(t.sample)) }))
2787
+ targets: targets.map((t) => ({ ...t, covered: globs.some((g) => contentGlobCovers(g, t.sample, baseDir)) }))
2667
2788
  };
2668
2789
  }
2669
2790
  function checkTailwindContent(baseDir) {
@@ -2678,17 +2799,18 @@ function checkTailwindContent(baseDir) {
2678
2799
  };
2679
2800
  }
2680
2801
  const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"`).join(" \xB7 ");
2802
+ const note = missing.some((t) => t.suggest.startsWith("../")) ? ` (${CONTENT_PARENT_PATH_NOTE})` : "";
2681
2803
  if (r.unreadable || r.dynamic) {
2682
2804
  return {
2683
2805
  name: "tailwind.content",
2684
2806
  severity: "warn",
2685
- 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}`
2807
+ 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}`
2686
2808
  };
2687
2809
  }
2688
2810
  return {
2689
2811
  name: "tailwind.content",
2690
2812
  severity: "fail",
2691
- 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}`
2813
+ 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}`
2692
2814
  };
2693
2815
  }
2694
2816
  var ANIMATION_PLUGIN_TAILWIND3 = "tailwindcss-animate";
@@ -3165,7 +3287,7 @@ import chalk7 from "chalk";
3165
3287
  // src/theme/brand-core.ts
3166
3288
  import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
3167
3289
  import { createRequire } from "module";
3168
- import { dirname, join as join2, relative, resolve as resolve2, sep } from "path";
3290
+ import { dirname as dirname2, join as join2, relative as relative2, resolve as resolve2, sep as sep2 } from "path";
3169
3291
  var TOKENS_PACKAGE = "@axis-ds/tokens";
3170
3292
  var BRAND_NAME_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
3171
3293
  var MIN_BRAND_TOKENS_VERSION = "1.3.0";
@@ -3196,7 +3318,7 @@ function findTokensPackageJson(baseDir) {
3196
3318
  for (; ; ) {
3197
3319
  const candidate = join2(dir, "node_modules", TOKENS_PACKAGE, "package.json");
3198
3320
  if (existsSync3(candidate)) return candidate;
3199
- const parent = dirname(dir);
3321
+ const parent = dirname2(dir);
3200
3322
  if (parent === dir) return void 0;
3201
3323
  dir = parent;
3202
3324
  }
@@ -3280,7 +3402,7 @@ function inspectBrandImport(baseDir) {
3280
3402
  if (!location.path) {
3281
3403
  return { ...base, state: "css-missing", imports: [] };
3282
3404
  }
3283
- const cssFile = relative(root, location.path).split(sep).join("/");
3405
+ const cssFile = relative2(root, location.path).split(sep2).join("/");
3284
3406
  const imports = [...new Set(findBrandImports(readFileSync3(location.path, "utf8")))];
3285
3407
  let state;
3286
3408
  if (imports.includes(brand)) state = "match";
@@ -3396,7 +3518,7 @@ function findBrandActivation(baseDir) {
3396
3518
  const providerTexts = [];
3397
3519
  for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
3398
3520
  for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
3399
- const rel3 = `${dirname(candidate)}/${m[1]}${ext}`;
3521
+ const rel3 = `${dirname2(candidate)}/${m[1]}${ext}`;
3400
3522
  const p = join2(root, rel3);
3401
3523
  if (isFile2(p)) providerTexts.push({ rel: rel3, text: stripJsLikeComments(readFileSync3(p, "utf8")) });
3402
3524
  }
@@ -3479,6 +3601,16 @@ function declaredAxisPackages(pkg) {
3479
3601
  }
3480
3602
  return out;
3481
3603
  }
3604
+ function workspaceRootPackage(baseDir) {
3605
+ const root = findWorkspaceRoot(baseDir);
3606
+ if (root === void 0 || root === baseDir) return void 0;
3607
+ try {
3608
+ const parsed = JSON.parse(readFileSync4(join3(root, "package.json"), "utf8"));
3609
+ return isPlainObject(parsed) ? parsed : void 0;
3610
+ } catch {
3611
+ return void 0;
3612
+ }
3613
+ }
3482
3614
  function checkDependencies(baseDirInput) {
3483
3615
  const baseDir = resolve3(baseDirInput);
3484
3616
  let pkg;
@@ -3492,13 +3624,17 @@ function checkDependencies(baseDirInput) {
3492
3624
  }
3493
3625
  return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
3494
3626
  }
3495
- const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
3627
+ const rootPkg = workspaceRootPackage(baseDir);
3628
+ const fromRoot = (d) => !hasDependency(pkg, d) && rootPkg !== void 0 && Boolean(hasDependency(rootPkg, d));
3629
+ const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d) && !fromRoot(d));
3496
3630
  if (missingRequired.length > 0) {
3497
3631
  return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
3498
3632
  }
3499
- const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
3633
+ const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d) && !fromRoot(d));
3634
+ const rootDeclared = [...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => fromRoot(d));
3635
+ const rootNote = rootDeclared.length > 0 ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8: ${rootDeclared.join(", ")}` : void 0;
3500
3636
  const targets = [
3501
- ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0),
3637
+ ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0 || fromRoot(d)),
3502
3638
  ...declaredAxisPackages(pkg)
3503
3639
  ];
3504
3640
  const pnp = isPnpProject(baseDir);
@@ -3508,11 +3644,14 @@ function checkDependencies(baseDirInput) {
3508
3644
  if (notInstalled.length > 0) {
3509
3645
  problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalled.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
3510
3646
  }
3511
- if (problems.length > 0) return { name: "dependencies", severity: "warn", message: problems.join(" / ") };
3647
+ if (problems.length > 0) {
3648
+ return { name: "dependencies", severity: "warn", message: problems.join(" / ") + (rootNote ? ` (${rootNote})` : "") };
3649
+ }
3650
+ const note = rootNote ? `, ${rootNote}` : "";
3512
3651
  return {
3513
3652
  name: "dependencies",
3514
3653
  severity: "pass",
3515
- message: pnp ? `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (Plug'n'Play \uB77C \uC124\uCE58\uBCF8\uC740 \uD655\uC778\uD558\uC9C0 \uC54A\uC74C, ${targets.length}\uAC1C)` : `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8 \xB7 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${targets.length}\uAC1C \uD655\uC778)`
3654
+ message: pnp ? `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (Plug'n'Play \uB77C \uC124\uCE58\uBCF8\uC740 \uD655\uC778\uD558\uC9C0 \uC54A\uC74C, ${targets.length}\uAC1C${note})` : `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8 \xB7 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${targets.length}\uAC1C \uD655\uC778${note})`
3516
3655
  };
3517
3656
  }
3518
3657
 
@@ -3775,7 +3914,7 @@ import chalk9 from "chalk";
3775
3914
  import path13 from "path";
3776
3915
 
3777
3916
  // src/theme/theme-add.ts
3778
- import { accessSync, constants, existsSync as existsSync4, readFileSync as readFileSync5, realpathSync, unlinkSync, writeFileSync } from "fs";
3917
+ import { accessSync, constants, existsSync as existsSync4, readFileSync as readFileSync5, realpathSync as realpathSync2, unlinkSync, writeFileSync } from "fs";
3779
3918
  import path12 from "path";
3780
3919
  var TOKENS_DEPENDENCY_RANGE = `^${TOKENS_DEPENDENCY_MIN_VERSION}`;
3781
3920
  var TAILWIND3_BASE_IMPORTS = [`${TOKENS_PACKAGE}/css`, `${TOKENS_PACKAGE}/css/shadcn`];
@@ -3872,8 +4011,8 @@ function compareVersions(a, b) {
3872
4011
  return 0;
3873
4012
  }
3874
4013
  function realPathInside(baseDir, file) {
3875
- const realBase = realpathSync(baseDir);
3876
- const realPath = realpathSync(file);
4014
+ const realBase = realpathSync2(baseDir);
4015
+ const realPath = realpathSync2(file);
3877
4016
  const relPath = path12.relative(realBase, realPath);
3878
4017
  const inside = relPath !== "" && !relPath.startsWith("..") && !path12.isAbsolute(relPath);
3879
4018
  return { inside, realPath };
@@ -4385,6 +4524,7 @@ function renderThemeAdd(plan, written) {
4385
4524
  )
4386
4525
  );
4387
4526
  }
4527
+ if (tw.contentMissing.some((t) => t.suggest.startsWith("../"))) lines.push(chalk9.gray(` ${CONTENT_PARENT_PATH_NOTE}`));
4388
4528
  }
4389
4529
  const act = plan.activation;
4390
4530
  lines.push("", chalk9.bold(`\uBE0C\uB79C\uB4DC \uCF1C\uAE30 (ThemeProvider \uB294 ${THEME_PACKAGE} ${THEME_MIN_VERSION} \uC774\uC0C1)`));
@@ -4766,13 +4906,13 @@ async function fetchRegistryJson(url, options = {}) {
4766
4906
  }
4767
4907
 
4768
4908
  // src/init/init.ts
4769
- import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
4909
+ import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync6, realpathSync as realpathSync4, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
4770
4910
  import path15 from "path";
4771
4911
  import chalk10 from "chalk";
4772
4912
  import fs12 from "fs-extra";
4773
4913
 
4774
4914
  // ../axis-registry-core/src/add/safe-write.ts
4775
- import { constants as fsConstants, existsSync as existsSync5, lstatSync as lstatSync2, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
4915
+ import { constants as fsConstants, existsSync as existsSync5, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
4776
4916
  import path14 from "path";
4777
4917
  import fs11 from "fs-extra";
4778
4918
  var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
@@ -4799,12 +4939,12 @@ function nearestExisting(p) {
4799
4939
  return cur;
4800
4940
  }
4801
4941
  function escapeReason(root, target, options = {}) {
4802
- const realRoot = realpathSync2(root);
4942
+ const realRoot = realpathSync3(root);
4803
4943
  if (!isSameOrInside(path14.resolve(root), path14.resolve(target)) || path14.resolve(target) === path14.resolve(root)) {
4804
4944
  return `\uACBD\uB85C\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(${target})`;
4805
4945
  }
4806
4946
  const anchor = nearestExisting(path14.dirname(target));
4807
- const realAnchor = realpathSync2(anchor);
4947
+ const realAnchor = realpathSync3(anchor);
4808
4948
  if (!isSameOrInside(realRoot, realAnchor)) {
4809
4949
  return `\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realAnchor})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
4810
4950
  }
@@ -4819,7 +4959,7 @@ function escapeReason(root, target, options = {}) {
4819
4959
  const shown = path14.relative(path14.resolve(root), path14.resolve(target)).split(path14.sep).join("/");
4820
4960
  let realTarget;
4821
4961
  try {
4822
- realTarget = realpathSync2(target);
4962
+ realTarget = realpathSync3(target);
4823
4963
  } catch {
4824
4964
  return `\uAE30\uC874 \uD30C\uC77C ${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uB530\uB77C\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694)`;
4825
4965
  }
@@ -4852,8 +4992,8 @@ function isSymlink(p) {
4852
4992
  function outsideLinkTarget(root, target) {
4853
4993
  if (!isSymlink(target)) return null;
4854
4994
  try {
4855
- const realTarget = realpathSync2(target);
4856
- return isSameOrInside(realpathSync2(root), realTarget) ? null : realTarget;
4995
+ const realTarget = realpathSync3(target);
4996
+ return isSameOrInside(realpathSync3(root), realTarget) ? null : realTarget;
4857
4997
  } catch {
4858
4998
  return null;
4859
4999
  }
@@ -4870,10 +5010,10 @@ function hardLinkMessage(shownPath, nlink) {
4870
5010
  return `\uAE30\uC874 \uD30C\uC77C ${shownPath} \uC774 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC9C4 \uD30C\uC77C\uC774\uB77C(\uB9C1\uD06C \uC218 ${nlink}) \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uBA74 \uC774\uC5B4\uC9C4 \uB2E4\uB978 \uACBD\uB85C\uC758 \uB0B4\uC6A9\uB3C4 \uBC14\uB01D\uB2C8\uB2E4. \uD558\uB4DC\uB9C1\uD06C\uB97C \uB04A\uC740(\uD30C\uC77C\uC744 \uBCF5\uC0AC\uD574 \uBC14\uAFBC) \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`;
4871
5011
  }
4872
5012
  function writtenOutside(root, target) {
4873
- const realRoot = realpathSync2(root);
5013
+ const realRoot = realpathSync3(root);
4874
5014
  let realTarget;
4875
5015
  try {
4876
- realTarget = realpathSync2(target);
5016
+ realTarget = realpathSync3(target);
4877
5017
  } catch {
4878
5018
  return target;
4879
5019
  }
@@ -4919,8 +5059,8 @@ async function overwriteFollowingLinks(target, content) {
4919
5059
  }
4920
5060
  }
4921
5061
  function checkParentInside(root, target) {
4922
- const realRoot = realpathSync2(root);
4923
- const realParent = realpathSync2(path14.dirname(target));
5062
+ const realRoot = realpathSync3(root);
5063
+ const realParent = realpathSync3(path14.dirname(target));
4924
5064
  if (!isSameOrInside(realRoot, realParent)) {
4925
5065
  return `\uBD80\uBAA8 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realParent})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
4926
5066
  }
@@ -5272,13 +5412,13 @@ function planUtilsWrite(baseDirInput, utilsPath) {
5272
5412
  if (st.isSymbolicLink()) {
5273
5413
  let real;
5274
5414
  try {
5275
- real = realpathSync3(utilsPath);
5415
+ real = realpathSync4(utilsPath);
5276
5416
  } catch {
5277
5417
  return { action: "reject", reason: `${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694` };
5278
5418
  }
5279
5419
  let outside = null;
5280
5420
  try {
5281
- outside = isSameOrInside(realpathSync3(baseDir), real) ? null : real;
5421
+ outside = isSameOrInside(realpathSync4(baseDir), real) ? null : real;
5282
5422
  } catch {
5283
5423
  outside = null;
5284
5424
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/cli",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - CLI for adding components (shadcn compatible)",
6
6
  "publishConfig": {