@axis-ds/cli 1.7.3 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/index.js +150 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ axis list
|
|
|
48
48
|
- `utils.ts` 가 이미 있으면 같은 내용이면 「유지(이미 같은 내용)」(다시 쓰지 않음), 다르면 init 의 utils 로 덮어쓰고 「덮어씀」으로 알립니다(터미널이 아닌 곳에서 `-y` 없이 실행하면 덮어쓰지 않고 rc 1, 아래 「터미널이 아닌 곳에서 실행」). `utils.ts` 쓰기는 `axis add` 와 같은 규칙입니다: 심볼릭 링크면 같은 내용일 때 「유지(이미 같은 내용, 링크)」로 두고, 내용이 다른 링크(프로젝트 안 · 밖) · 깨진 링크 · 디렉터리 · 읽을 수 없는 파일 · 다른 경로와 하드링크로 이어진 파일은 쓰지 않고 그 사실을 알린 뒤 rc 1 입니다. 이 판정은 쓰기 전에 하므로 이때는 `axis.config.json` · `package.json` 도 쓰지 않습니다. 다른 경로와 하드링크로 이어진 `axis.config.json` 을 다시 써야 할 때도 같습니다.
|
|
49
49
|
- 경로 기본값(`-y` 값 · 대화형 초기값)은 실제 프로젝트를 보고 정합니다(1.6.0 부터). `componentsDir` 는 `src/` 가 있으면 `./src/components/ui`, 없으면 `./components/ui` 이고 `src/` 를 새로 만들지 않습니다. `globalCss` 는 `app/globals.css` · `src/app/globals.css` · `styles/globals.css` · `src/styles/globals.css` · `globals.css` 가운데 실제로 있는 첫 파일, `tailwindConfig` 는 있는 `tailwind.config.{ts,js,mjs,cjs}` 가운데 첫 파일입니다. 찾지 못하면 기본값을 기록하고 그 사실을 한 줄 알립니다. Tailwind 4 안내 제목도 이 경로를 씁니다.
|
|
50
50
|
- config 가 이미 있으면 출력이 「생성 완료」가 아니라 사실대로 「유지(이미 같은 내용)」 또는 「갱신」입니다. 갱신은 init 이 다루는 키(`$schema` · `componentsDir` · `tailwindConfig` · `globalCss` · `registry`)만 바꾸고, 그 밖의 키(`brand` · `monetDir` · `template` · `agenticDir` 등)는 값과 순서를 그대로 둡니다(1.6.0 부터, 이전에는 빠졌음). 들여쓰기도 기존 파일을 따릅니다. 기존 `componentsDir` 는 그대로 두고, `globalCss` · `tailwindConfig` 는 가리키는 파일이 있으면 그대로, 없으면 찾은 파일로 바꾸고 알립니다(찾지 못하면 그대로 두고 알림). Tailwind 4 이상이면 `tailwindConfig` 를 지우고 알립니다. `registry` 가 종전 기본값이면 위처럼 새 기본값으로 바꿉니다. `AXIS_REGISTRY_URL` 은 config 에 기록하지 않고 add · list 를 실행할 때만 우선합니다.
|
|
51
|
-
- 애니메이션 플러그인(`tailwindcss-animate` · `tw-animate-css`)이 `package.json` 에 없으면, Dialog · Select 등의 열고 닫는 애니메이션에 필요하다는 안내 한 줄을 냅니다(Tailwind 3 은 plugins, Tailwind 4 는 `@import "tw-animate-css";`).
|
|
51
|
+
- 애니메이션 플러그인(`tailwindcss-animate` · `tw-animate-css`)이 `package.json` 에 없으면, Dialog · Select 등의 열고 닫는 애니메이션에 필요하다는 안내 한 줄을 냅니다(Tailwind 3 은 plugins, Tailwind 4 는 `@import "tw-animate-css";`). 1.7.5 부터 선언은 앱 다음 워크스페이스 루트 `package.json` 까지 보고, 이름은 `axis check` 와 같습니다(Tailwind 3 은 `tailwindcss-animate` 만, Tailwind 4 는 `tw-animate-css` · `tailwindcss-animate` 둘 다). 선언과 설치본이 모두 있으면 안내하지 않고, 선언만 있고 설치본이 없으면 「선언돼 있지만 설치되지 않았습니다」와 설치 명령 · 설정 줄을 냅니다. Yarn PnP 는 루트 선언을 인정하지 않고 앱 선언이 있으면 안내하지 않습니다.
|
|
52
52
|
- `tailwind-merge` 범위와 아래 안내는 프로젝트의 Tailwind 버전(설치본, 없으면 `package.json` 선언)으로 정합니다. 판정하지 못하면 Tailwind 3 으로 봅니다.
|
|
53
53
|
- Tailwind 4 이상이면 전역 CSS 에 넣을 줄을 안내합니다. CSS 파일은 고치지 않습니다.
|
|
54
54
|
|
|
@@ -83,8 +83,9 @@ axis theme info ontology
|
|
|
83
83
|
axis theme add ontology
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
- `axis theme add` 는 `axis.config.json` 의 `globalCss` → `app/globals.css` → `src/app/globals.css` → `styles/globals.css` → `src/styles/globals.css` → 루트 `globals.css` 순으로 찾은 파일의 앞쪽 import 구간 끝(`@tailwind` 등 규칙보다 앞)에 줄을 넣습니다. 1.6.0 부터 브랜드 import 앞에 기본 토큰 CSS 도 넣습니다: Tailwind 3 은 `@axis-ds/tokens/css` · `@axis-ds/tokens/css/shadcn`, Tailwind 4 는 `@axis-ds/tokens/css/tailwind4` 와 `package.json` 에 선언된 `@axis-ds/ui-react` · `@axis-ds/agentic-ui` 의 `tailwind.css` 입니다. 이미 있는 줄은 다시 넣지 않으므로 여러 번 실행해도 같습니다. 규칙 뒤에 있는 기존 `@import` 는 CSS 규칙상 무시될 수 있어 맨 앞으로 옮기라고 알립니다(Next.js 15 는 위치와 관계없이 앞으로 끌어올려 적용함을 측정).
|
|
86
|
+
- `axis theme add` 는 `axis.config.json` 의 `globalCss` → `app/globals.css` → `src/app/globals.css` → `styles/globals.css` → `src/styles/globals.css` → 루트 `globals.css` 순으로 찾은 파일의 앞쪽 import 구간 끝(`@tailwind` 등 규칙보다 앞)에 줄을 넣습니다. 1.6.0 부터 브랜드 import 앞에 기본 토큰 CSS 도 넣습니다: Tailwind 3 은 `@axis-ds/tokens/css` · `@axis-ds/tokens/css/shadcn`, Tailwind 4 는 `@axis-ds/tokens/css/tailwind4` 와 `package.json` 에 선언된 `@axis-ds/ui-react` · `@axis-ds/agentic-ui` 의 `tailwind.css` 입니다. 1.7.5 부터 워크스페이스 루트에만 선언한 패키지는 설치본에 `tailwind.css` 가 실제로 있을 때만 넣고, 없으면(미설치 · 1.4.0 미만) 넣지 않은 이유를 한 줄로 알립니다. 이미 있는 줄은 다시 넣지 않으므로 여러 번 실행해도 같습니다. 규칙 뒤에 있는 기존 `@import` 는 CSS 규칙상 무시될 수 있어 맨 앞으로 옮기라고 알립니다(Next.js 15 는 위치와 관계없이 앞으로 끌어올려 적용함을 측정).
|
|
87
87
|
- `package.json` 에 `@axis-ds/tokens` 가 없으면 `dependencies` 에 `^1.6.0`(1.6.0 부터, 이전에는 `^1.3.0`)을 더하고 설치 명령만 안내합니다. 설치는 실행하지 않습니다. 설치 · 업그레이드 안내 명령은 lockfile 로 고릅니다(`npm install` · `yarn add` · `pnpm add`). lockfile 이 없으면 `package.json` 의 `packageManager`(`npm@…` · `yarn@…` · `pnpm@…`)를 보고, 둘 다 없으면 `pnpm` 입니다(1.7.2 부터 `packageManager` 를 봄).
|
|
88
|
+
- 1.7.5 부터 `@axis-ds/tokens` 가 워크스페이스 루트 `package.json`(`dependencies` · `devDependencies`)에 선언돼 있으면 앱 `package.json` 에 쓰지 않고 「워크스페이스 루트에 선언돼 있어 앱 package.json 은 바꾸지 않음」으로 알립니다. 설치본이 없으면 설치 명령을, 업그레이드 안내 때는 루트 선언을 올리라는 줄을 더합니다. 루트에 `@axis-ds/theme` 가 있으면 ThemeProvider 설치 안내를 내지 않습니다. 앱만 따로 운영 설치 · 배포하면 루트 선언이 따라가지 않으니 앱에 직접 선언합니다. Yarn PnP 와 앱 디렉터리에 자체 lockfile 이 있는 앱은 루트 선언을 보지 않습니다(종전).
|
|
88
89
|
- 브랜드 CSS 는 `[data-brand="<brand>"]` 선택자로 적용되므로 루트 레이아웃의 `<html data-brand>` 나 `ThemeProvider` 의 `setBrand` 가 있어야 화면이 바뀝니다. 코드는 고치지 않고, 레이아웃에서 찾지 못하면 두 방법의 예시를 냅니다(`defaultBrand` 는 `@axis-ds/theme` 1.6.2 이하에서 `setBrand(undefined)` 로 끈 상태가 새로고침 뒤 유지되지 않아 예시에 쓰지 않습니다). 마크업 `data-brand` 와 `ThemeProvider` 를 함께 쓰는 레이아웃이면 theme 1.7.0 이상이 필요하다고 한 줄 더 알립니다(1.6.1 부터). Tailwind 3 이면 preset · content 가 빠졌을 때 넣을 줄도 안내합니다(설정 파일은 고치지 않음). preset 안내는 1.6.1 부터 CommonJS 에서 모든 tokens 버전에 되는 `require("@axis-ds/tokens/tailwind").default` 입니다(1.6.0 의 `.default` 없는 형태는 tokens 1.6.2 이하에서 preset 이 빠짐).
|
|
89
90
|
- 넣은 import 줄의 출력은 1.6.1 부터 실제 위치 · 분류를 따릅니다. 컴포넌트 `tailwind.css` 는 「컴포넌트 스캔 경로, 위치 무관」, 기본 토큰 CSS 는 브랜드 줄보다 앞에 들어갔을 때만 「브랜드 앞」이고 뒤에 들어가면 옮기라고 경고합니다.
|
|
90
91
|
- `@axis-ds/tokens` 가 없거나 1.3.0 미만이면 목록 대신 설치 · 업그레이드 안내를 내고 종료 코드 1 로 끝납니다.
|
|
@@ -107,7 +108,7 @@ axis theme add ontology
|
|
|
107
108
|
- 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
109
|
- 해당할 때만 더하는 항목(1.6.0 부터, brand 항목 뒤 이 순서):
|
|
109
110
|
- `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 입니다. 패키지 경로는 프로젝트 디렉터리부터 상위로 찾은 설치본 위치 기준이라, 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
|
+
- `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 은 실제 위치와 비교해 판정합니다. 1.7.4 부터 pnpm 기본 레이아웃처럼 앱 설치본이 링크이면 실경로가 같은 상위 설치본(`../../node_modules/...`)과 `.pnpm` 스토어 실경로를 상대 경로로 쓴 glob 도 인정하고, 실경로가 다른 상위 설치본을 가리키면 FAIL 문구에 그 이유를 붙입니다. 상위 경로는 Tailwind 3 가 빌드를 실행한 디렉터리 기준으로 풀리므로 모노레포 루트에서 빌드하면 `content: { relative: true, files: [...] }` 를 쓰세요(판정은 프로젝트 디렉터리에서 빌드한다고 보고 함).
|
|
111
112
|
- `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
113
|
- FAIL 이 하나라도 있으면 종료 코드 1 로 끝납니다. WARN 만 있으면 0 입니다(1.3.0 부터, 이전에는 결과와 관계없이 0).
|
|
113
114
|
- MCP `axis.check_project` 도 같은 항목 · 문구를 냅니다.
|
package/dist/index.js
CHANGED
|
@@ -2543,13 +2543,61 @@ function contentGlobCovers(glob, sample, baseDirInput) {
|
|
|
2543
2543
|
return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir));
|
|
2544
2544
|
}
|
|
2545
2545
|
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";
|
|
2546
|
+
function relDirOf(baseDir, dir) {
|
|
2547
|
+
const rel3 = relative(baseDir, dir);
|
|
2548
|
+
return rel3 === "" || isAbsolute(rel3) ? void 0 : rel3.split(sep).join("/");
|
|
2549
|
+
}
|
|
2550
|
+
function realDir(dir) {
|
|
2551
|
+
try {
|
|
2552
|
+
return realpathSync(dir);
|
|
2553
|
+
} catch {
|
|
2554
|
+
return void 0;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
function packageVersion(dir) {
|
|
2558
|
+
try {
|
|
2559
|
+
const parsed = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
2560
|
+
return isPlainObject2(parsed) && typeof parsed.version === "string" ? parsed.version : void 0;
|
|
2561
|
+
} catch {
|
|
2562
|
+
return void 0;
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2546
2565
|
function packageContentTarget(baseDir, name) {
|
|
2547
2566
|
const found = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, name);
|
|
2548
|
-
const
|
|
2549
|
-
const
|
|
2567
|
+
const relDir = (found === void 0 ? void 0 : relDirOf(baseDir, found.dir)) ?? `node_modules/${name}`;
|
|
2568
|
+
const alternates = [];
|
|
2569
|
+
const others = [];
|
|
2570
|
+
const real = found === void 0 ? void 0 : realDir(found.dir);
|
|
2571
|
+
if (found !== void 0 && real !== void 0) {
|
|
2572
|
+
const relReal = relDirOf(baseDir, real);
|
|
2573
|
+
if (relReal !== void 0 && relReal !== relDir) alternates.push(`${relReal}/dist/index.js`);
|
|
2574
|
+
let dir = dirname(resolve(found.dir, ...name.split("/").map(() => ".."), ".."));
|
|
2575
|
+
for (; ; ) {
|
|
2576
|
+
const candidate = join(dir, "node_modules", ...name.split("/"));
|
|
2577
|
+
const rel3 = existsSync(join(candidate, "package.json")) ? relDirOf(baseDir, candidate) : void 0;
|
|
2578
|
+
if (rel3 !== void 0) {
|
|
2579
|
+
const candidateReal = realDir(candidate);
|
|
2580
|
+
if (candidateReal === real) alternates.push(`${rel3}/dist/index.js`);
|
|
2581
|
+
else {
|
|
2582
|
+
const theirs = packageVersion(candidate);
|
|
2583
|
+
const ours = found.version ?? packageVersion(found.dir);
|
|
2584
|
+
const versions = theirs === void 0 || ours === void 0 ? "" : theirs === ours ? `(\uBC84\uC804\uC740 ${ours} \uB85C \uAC19\uC74C)` : `(${theirs}, \uC571 ${ours})`;
|
|
2585
|
+
others.push({
|
|
2586
|
+
sample: `${rel3}/dist/index.js`,
|
|
2587
|
+
note: `\uC0C1\uC704 \uACBD\uB85C ${rel3} \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`
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
const parent = dirname(dir);
|
|
2592
|
+
if (parent === dir) break;
|
|
2593
|
+
dir = parent;
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2550
2596
|
return {
|
|
2551
2597
|
sample: `${relDir}/dist/index.js`,
|
|
2552
|
-
suggest: `${relDir.startsWith("../") ? "" : "./"}${relDir}/dist/**/*.{js,mjs}
|
|
2598
|
+
suggest: `${relDir.startsWith("../") ? "" : "./"}${relDir}/dist/**/*.{js,mjs}`,
|
|
2599
|
+
alternates,
|
|
2600
|
+
others
|
|
2553
2601
|
};
|
|
2554
2602
|
}
|
|
2555
2603
|
function balancedSlice(src, start) {
|
|
@@ -2623,7 +2671,12 @@ function inspectTailwindContent(baseDirInput) {
|
|
|
2623
2671
|
configFile,
|
|
2624
2672
|
unreadable: read === void 0,
|
|
2625
2673
|
dynamic: read?.dynamic ?? false,
|
|
2626
|
-
targets: targets.map((
|
|
2674
|
+
targets: targets.map(({ alternates = [], others = [], ...t }) => {
|
|
2675
|
+
const covers = (sample) => globs.some((g) => contentGlobCovers(g, sample, baseDir));
|
|
2676
|
+
const covered = [t.sample, ...alternates].some(covers);
|
|
2677
|
+
const note = covered ? void 0 : others.find((o) => covers(o.sample))?.note;
|
|
2678
|
+
return note === void 0 ? { ...t, covered } : { ...t, covered, note };
|
|
2679
|
+
})
|
|
2627
2680
|
};
|
|
2628
2681
|
}
|
|
2629
2682
|
function checkTailwindContent(baseDir) {
|
|
@@ -2637,7 +2690,7 @@ function checkTailwindContent(baseDir) {
|
|
|
2637
2690
|
message: `${r.configFile}\uC758 content \uAC00 ${r.targets.map((t) => t.label).join(" \xB7 ")} \uB97C \uB36E\uC2B5\uB2C8\uB2E4`
|
|
2638
2691
|
};
|
|
2639
2692
|
}
|
|
2640
|
-
const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"`).join(" \xB7 ");
|
|
2693
|
+
const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"${t.note === void 0 ? "" : ` (${t.note})`}`).join(" \xB7 ");
|
|
2641
2694
|
const note = missing.some((t) => t.suggest.startsWith("../")) ? ` (${CONTENT_PARENT_PATH_NOTE})` : "";
|
|
2642
2695
|
if (r.unreadable || r.dynamic) {
|
|
2643
2696
|
return {
|
|
@@ -3749,11 +3802,13 @@ import chalk9 from "chalk";
|
|
|
3749
3802
|
import path12 from "path";
|
|
3750
3803
|
|
|
3751
3804
|
// src/theme/theme-add.ts
|
|
3752
|
-
import { accessSync, constants, existsSync as existsSync3, readFileSync as readFileSync4, realpathSync as realpathSync2, unlinkSync, writeFileSync } from "fs";
|
|
3805
|
+
import { accessSync, constants, existsSync as existsSync3, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync2, unlinkSync, writeFileSync } from "fs";
|
|
3753
3806
|
import path11 from "path";
|
|
3754
3807
|
var TOKENS_DEPENDENCY_RANGE = `^${TOKENS_DEPENDENCY_MIN_VERSION}`;
|
|
3755
3808
|
var TAILWIND3_BASE_IMPORTS = [`${TOKENS_PACKAGE}/css`, `${TOKENS_PACKAGE}/css/shadcn`];
|
|
3756
3809
|
var THEME_MIN_VERSION = "1.3.0";
|
|
3810
|
+
var COMPONENT_TAILWIND_CSS_MIN_VERSION = "1.4.0";
|
|
3811
|
+
var APP_LOCKFILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"];
|
|
3757
3812
|
function readText(file) {
|
|
3758
3813
|
return existsSync3(file) ? readFileSync4(file, "utf8") : null;
|
|
3759
3814
|
}
|
|
@@ -3852,6 +3907,13 @@ function realPathInside(baseDir, file) {
|
|
|
3852
3907
|
const inside = relPath !== "" && !relPath.startsWith("..") && !path11.isAbsolute(relPath);
|
|
3853
3908
|
return { inside, realPath };
|
|
3854
3909
|
}
|
|
3910
|
+
function isFile2(file) {
|
|
3911
|
+
try {
|
|
3912
|
+
return statSync2(file).isFile();
|
|
3913
|
+
} catch {
|
|
3914
|
+
return false;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3855
3917
|
function isStylesheet(realPath) {
|
|
3856
3918
|
return path11.extname(realPath).toLowerCase() === ".css";
|
|
3857
3919
|
}
|
|
@@ -3919,14 +3981,28 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3919
3981
|
return plan;
|
|
3920
3982
|
}
|
|
3921
3983
|
}
|
|
3984
|
+
const rootDeclarationsAllowed = pkg !== void 0 && !isPnpProject(baseDir) && !APP_LOCKFILES.some((f) => existsSync3(path11.join(baseDir, f)));
|
|
3985
|
+
const rootPkg = rootDeclarationsAllowed ? workspaceRootPackage(baseDir) ?? null : null;
|
|
3922
3986
|
const tailwind = detectTailwind(baseDir, pkg);
|
|
3923
3987
|
const tailwind4 = tailwind.major !== void 0 && tailwind.major >= 4;
|
|
3924
|
-
const
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3988
|
+
const componentImports = [];
|
|
3989
|
+
const deferredComponentImports = [];
|
|
3990
|
+
if (tailwind4 && pkg !== void 0) {
|
|
3991
|
+
for (const n of TAILWIND4_COMPONENT_PACKAGES) {
|
|
3992
|
+
if (hasDependency(pkg, n) !== void 0) {
|
|
3993
|
+
componentImports.push(n);
|
|
3994
|
+
continue;
|
|
3995
|
+
}
|
|
3996
|
+
if (declaredDependency(baseDir, pkg, n, rootPkg)?.source !== "root") continue;
|
|
3997
|
+
const installed2 = findInstalledPackage(baseDir, n);
|
|
3998
|
+
if (installed2 !== void 0 && isFile2(path11.join(installed2.dir, "tailwind.css"))) {
|
|
3999
|
+
componentImports.push(n);
|
|
4000
|
+
} else {
|
|
4001
|
+
deferredComponentImports.push(installed2 === void 0 ? { name: n } : { name: n, installedVersion: installed2.version ?? "?" });
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
const requiredBaseImports = tailwind4 ? [TOKENS_TAILWIND4_ENTRY, ...componentImports.map((n) => `${n}/tailwind.css`)] : [...TAILWIND3_BASE_IMPORTS];
|
|
3930
4006
|
const location = findGlobalCss(baseDir, config);
|
|
3931
4007
|
if (location.path) {
|
|
3932
4008
|
const where = realPathInside(baseDir, location.path);
|
|
@@ -3945,6 +4021,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3945
4021
|
const otherBrands = [...new Set(imported.filter((n) => n !== brand))];
|
|
3946
4022
|
const brandAdded = !imported.includes(brand);
|
|
3947
4023
|
const baseImports = requiredBaseImports.filter((spec) => !hasCssImport(before, spec));
|
|
4024
|
+
const deferredHere = deferredComponentImports.filter((d) => !hasCssImport(before, `${d.name}/tailwind.css`));
|
|
3948
4025
|
const lines = [...baseImports.map((spec) => `@import "${spec}";`), ...brandAdded ? [`@import "${plan.importPath}";`] : []];
|
|
3949
4026
|
plan.css = {
|
|
3950
4027
|
file: location.path,
|
|
@@ -3955,7 +4032,8 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3955
4032
|
baseImports,
|
|
3956
4033
|
requiredBaseImports,
|
|
3957
4034
|
lateImports: findLateImports(before),
|
|
3958
|
-
tailwind4
|
|
4035
|
+
tailwind4,
|
|
4036
|
+
...deferredHere.length > 0 ? { deferredComponentImports: deferredHere } : {}
|
|
3959
4037
|
};
|
|
3960
4038
|
if (lines.length > 0) {
|
|
3961
4039
|
plan.writes.push({ file: location.path, before, after: insertImportLines(before, lines) });
|
|
@@ -3969,7 +4047,8 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3969
4047
|
baseImports: requiredBaseImports,
|
|
3970
4048
|
requiredBaseImports,
|
|
3971
4049
|
lateImports: [],
|
|
3972
|
-
tailwind4
|
|
4050
|
+
tailwind4,
|
|
4051
|
+
...deferredComponentImports.length > 0 ? { deferredComponentImports } : {}
|
|
3973
4052
|
};
|
|
3974
4053
|
}
|
|
3975
4054
|
if (!tailwind4) {
|
|
@@ -3990,10 +4069,18 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
3990
4069
|
if (pkgText === null || pkg === void 0) {
|
|
3991
4070
|
plan.dependency = { action: "no-package-json", upgrade, themeMissing: false, tokensAddCommand, themeAddCommand };
|
|
3992
4071
|
} else {
|
|
3993
|
-
const themeMissing =
|
|
3994
|
-
const declared =
|
|
4072
|
+
const themeMissing = declaredDependency(baseDir, pkg, THEME_PACKAGE, rootPkg) === void 0;
|
|
4073
|
+
const declared = declaredDependency(baseDir, pkg, TOKENS_PACKAGE, rootPkg);
|
|
3995
4074
|
if (declared !== void 0) {
|
|
3996
|
-
plan.dependency = {
|
|
4075
|
+
plan.dependency = {
|
|
4076
|
+
action: "present",
|
|
4077
|
+
declaredRange: declared.range,
|
|
4078
|
+
declaredSource: declared.source,
|
|
4079
|
+
upgrade,
|
|
4080
|
+
themeMissing,
|
|
4081
|
+
tokensAddCommand,
|
|
4082
|
+
themeAddCommand
|
|
4083
|
+
};
|
|
3997
4084
|
} else {
|
|
3998
4085
|
const deps = isPlainObject(pkg.dependencies) ? { ...pkg.dependencies } : {};
|
|
3999
4086
|
deps[TOKENS_PACKAGE] = TOKENS_DEPENDENCY_RANGE;
|
|
@@ -4312,6 +4399,15 @@ function renderThemeAdd(plan, written) {
|
|
|
4312
4399
|
)
|
|
4313
4400
|
);
|
|
4314
4401
|
}
|
|
4402
|
+
for (const d of css?.deferredComponentImports ?? []) {
|
|
4403
|
+
const line = `@import "${d.name}/tailwind.css";`;
|
|
4404
|
+
const current = d.installedVersion !== void 0 && d.installedVersion !== "?" && (compareExactVersions(d.installedVersion, COMPONENT_TAILWIND_CSS_MIN_VERSION) ?? -1) >= 0;
|
|
4405
|
+
lines.push(
|
|
4406
|
+
chalk9.yellow(
|
|
4407
|
+
d.installedVersion === void 0 ? ` ! ${d.name} \uAC00 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC544 ${line} \uB97C \uB123\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58(${plan.installCommand}) \uB4A4 theme add \uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uC9C1\uC811 \uB123\uC73C\uC138\uC694.` : current ? ` ! \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB41C ${d.name} \uC758 \uC124\uCE58\uBCF8(${d.installedVersion})\uC5D0 tailwind.css \uAC00 \uC5C6\uC5B4 ${line} \uB97C \uB123\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uAC00 \uC190\uC0C1\uB410\uC744 \uC218 \uC788\uC73C\uB2C8 \uB2E4\uC2DC \uC124\uCE58(${plan.installCommand}) \uB4A4 theme add \uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uC9C1\uC811 \uB123\uC73C\uC138\uC694.` : ` ! \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB41C ${d.name} \uC758 \uC124\uCE58\uBCF8(${d.installedVersion === "?" ? "\uBC84\uC804 \uBAA8\uB984" : d.installedVersion})\uC5D0 tailwind.css \uAC00 \uC5C6\uC5B4(${COMPONENT_TAILWIND_CSS_MIN_VERSION} \uBD80\uD130 \uC81C\uACF5) ${line} \uB97C \uB123\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ${COMPONENT_TAILWIND_CSS_MIN_VERSION} \uC774\uC0C1\uC73C\uB85C \uC62C\uB9B0 \uB4A4 theme add \uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uC9C1\uC811 \uB123\uC73C\uC138\uC694.`
|
|
4408
|
+
)
|
|
4409
|
+
);
|
|
4410
|
+
}
|
|
4315
4411
|
if (css && css.otherBrands.length > 0) {
|
|
4316
4412
|
lines.push(
|
|
4317
4413
|
chalk9.yellow(
|
|
@@ -4325,6 +4421,11 @@ function renderThemeAdd(plan, written) {
|
|
|
4325
4421
|
` ${chalk9.green("\u2713")} package.json: dependencies \uC5D0 "${TOKENS_PACKAGE}": "${TOKENS_DEPENDENCY_RANGE}" \uCD94\uAC00`,
|
|
4326
4422
|
` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk9.cyan(plan.installCommand)}`
|
|
4327
4423
|
);
|
|
4424
|
+
} else if (dep?.action === "present" && dep.declaredSource === "root") {
|
|
4425
|
+
lines.push(
|
|
4426
|
+
` ${chalk9.gray("-")} package.json: ${TOKENS_PACKAGE} ${dep.declaredRange} \uAC00 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB3FC \uC788\uC5B4 \uC571 package.json \uC740 \uBC14\uAFB8\uC9C0 \uC54A\uC74C`
|
|
4427
|
+
);
|
|
4428
|
+
if (plan.tokens.status === "not-installed") lines.push(` \uC124\uCE58: ${chalk9.cyan(plan.installCommand)}`);
|
|
4328
4429
|
} else if (dep?.action === "present") {
|
|
4329
4430
|
lines.push(` ${chalk9.gray("-")} package.json: ${TOKENS_PACKAGE} ${dep.declaredRange} \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uBC94\uC704\uB97C \uBC14\uAFB8\uC9C0 \uC54A\uC74C`);
|
|
4330
4431
|
} else if (dep?.action === "no-package-json") {
|
|
@@ -4334,9 +4435,13 @@ function renderThemeAdd(plan, written) {
|
|
|
4334
4435
|
lines.push(
|
|
4335
4436
|
chalk9.yellow(
|
|
4336
4437
|
` ! \uC124\uCE58\uB41C ${TOKENS_PACKAGE} ${plan.tokens.version} \uC740 \uBE0C\uB79C\uB4DC\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1 \uD544\uC694).`
|
|
4337
|
-
)
|
|
4338
|
-
` \uC5C5\uADF8\uB808\uC774\uB4DC: ${chalk9.cyan(dep.tokensAddCommand)}`
|
|
4438
|
+
)
|
|
4339
4439
|
);
|
|
4440
|
+
if (dep.action === "present" && dep.declaredSource === "root") {
|
|
4441
|
+
lines.push(` \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 package.json \uC758 ${TOKENS_PACKAGE} \uC120\uC5B8\uC744 ^${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1\uC73C\uB85C \uC62C\uB9AC\uACE0 \uC124\uCE58\uD558\uC138\uC694.`);
|
|
4442
|
+
} else {
|
|
4443
|
+
lines.push(` \uC5C5\uADF8\uB808\uC774\uB4DC: ${chalk9.cyan(dep.tokensAddCommand)}`);
|
|
4444
|
+
}
|
|
4340
4445
|
}
|
|
4341
4446
|
if (plan.configChanged) {
|
|
4342
4447
|
lines.push(` ${chalk9.green("\u2713")} axis.config.json: "brand": "${plan.brand}" \uAE30\uB85D`);
|
|
@@ -4741,13 +4846,13 @@ async function fetchRegistryJson(url, options = {}) {
|
|
|
4741
4846
|
}
|
|
4742
4847
|
|
|
4743
4848
|
// src/init/init.ts
|
|
4744
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync5, lstatSync as lstatSync3, readFileSync as readFileSync5, realpathSync as realpathSync4, statSync as
|
|
4849
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync5, lstatSync as lstatSync3, readFileSync as readFileSync5, realpathSync as realpathSync4, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
4745
4850
|
import path14 from "path";
|
|
4746
4851
|
import chalk10 from "chalk";
|
|
4747
4852
|
import fs12 from "fs-extra";
|
|
4748
4853
|
|
|
4749
4854
|
// ../axis-registry-core/src/add/safe-write.ts
|
|
4750
|
-
import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as
|
|
4855
|
+
import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
4751
4856
|
import path13 from "path";
|
|
4752
4857
|
import fs11 from "fs-extra";
|
|
4753
4858
|
var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
|
|
@@ -4803,7 +4908,7 @@ function escapeReason(root, target, options = {}) {
|
|
|
4803
4908
|
}
|
|
4804
4909
|
let followed;
|
|
4805
4910
|
try {
|
|
4806
|
-
followed =
|
|
4911
|
+
followed = statSync3(realTarget);
|
|
4807
4912
|
} catch {
|
|
4808
4913
|
return `\uAE30\uC874 \uD30C\uC77C \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${target})`;
|
|
4809
4914
|
}
|
|
@@ -4996,9 +5101,25 @@ async function resolveInitAnswers(baseDirInput, tailwind4) {
|
|
|
4996
5101
|
}
|
|
4997
5102
|
return { answers, notes };
|
|
4998
5103
|
}
|
|
4999
|
-
function animationGuideLine(pkg, tailwind4, installCommand) {
|
|
5104
|
+
function animationGuideLine(pkg, tailwind4, installCommand, baseDir) {
|
|
5000
5105
|
const name = tailwind4 ? ANIMATION_PLUGIN_TAILWIND4 : ANIMATION_PLUGIN_TAILWIND3;
|
|
5001
|
-
if (
|
|
5106
|
+
if (baseDir !== void 0) {
|
|
5107
|
+
const pnp = isPnpProject(baseDir);
|
|
5108
|
+
const candidates = tailwind4 ? [ANIMATION_PLUGIN_TAILWIND4, ANIMATION_PLUGIN_TAILWIND3] : [ANIMATION_PLUGIN_TAILWIND3];
|
|
5109
|
+
const declaredOf = (n) => {
|
|
5110
|
+
if (pkg === void 0) return void 0;
|
|
5111
|
+
if (pnp) return hasDependency(pkg, n) !== void 0 ? { source: "app" } : void 0;
|
|
5112
|
+
return declaredDependency(baseDir, pkg, n);
|
|
5113
|
+
};
|
|
5114
|
+
for (const candidate of candidates) {
|
|
5115
|
+
const declared = declaredOf(candidate);
|
|
5116
|
+
if (declared === void 0) continue;
|
|
5117
|
+
if (pnp || findInstalledPackage(baseDir, candidate) !== void 0) return void 0;
|
|
5118
|
+
const declaredWhere = declared.source === "root" ? "\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 " : "";
|
|
5119
|
+
const setup = !tailwind4 ? `tailwind.config \uC758 plugins \uC5D0 require("${candidate}") \uB97C \uB123\uC73C\uC138\uC694` : candidate === ANIMATION_PLUGIN_TAILWIND4 ? `\uC804\uC5ED CSS \uC5D0 @import "${candidate}"; \uB97C \uB123\uC73C\uC138\uC694` : `\uC804\uC5ED CSS \uC5D0 @plugin "${candidate}"; \uB97C \uB123\uC73C\uC138\uC694`;
|
|
5120
|
+
return `\uC560\uB2C8\uBA54\uC774\uC158: ${candidate} \uB294 ${declaredWhere}\uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ${installCommand} \uB4A4 ${setup}.`;
|
|
5121
|
+
}
|
|
5122
|
+
} else if (pkg !== void 0 && (hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0 || hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND4) !== void 0)) {
|
|
5002
5123
|
return void 0;
|
|
5003
5124
|
}
|
|
5004
5125
|
const add = `${addCommandFor(installCommand, {}).trimEnd()} ${name}`;
|
|
@@ -5262,7 +5383,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
5262
5383
|
}
|
|
5263
5384
|
let target;
|
|
5264
5385
|
try {
|
|
5265
|
-
target =
|
|
5386
|
+
target = statSync4(real);
|
|
5266
5387
|
} catch (e) {
|
|
5267
5388
|
return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC758 \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
5268
5389
|
}
|
|
@@ -5338,7 +5459,7 @@ async function runInit(baseDirInput, answers, registryUrl, log = console.log, op
|
|
|
5338
5459
|
}
|
|
5339
5460
|
if (previousText !== null && previousText !== nextText) {
|
|
5340
5461
|
try {
|
|
5341
|
-
const st =
|
|
5462
|
+
const st = statSync4(configPath);
|
|
5342
5463
|
if (st.isFile() && st.nlink >= 2) rejects.push(hardLinkMessage("axis.config.json", st.nlink));
|
|
5343
5464
|
} catch {
|
|
5344
5465
|
}
|
|
@@ -5437,7 +5558,7 @@ async function runInit(baseDirInput, answers, registryUrl, log = console.log, op
|
|
|
5437
5558
|
return;
|
|
5438
5559
|
}
|
|
5439
5560
|
reportDependencies(plan, log);
|
|
5440
|
-
const animation = animationGuideLine(readPackageJsonSafe(baseDir), tailwind4, plan.installCommand);
|
|
5561
|
+
const animation = animationGuideLine(readPackageJsonSafe(baseDir), tailwind4, plan.installCommand, baseDir);
|
|
5441
5562
|
if (animation !== void 0) log(chalk10.yellow(` ${animation}`));
|
|
5442
5563
|
if (tailwind4) {
|
|
5443
5564
|
const [head, ...rest] = tailwind4GuideLines(
|
|
@@ -5497,7 +5618,7 @@ function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL, deps
|
|
|
5497
5618
|
import chalk12 from "chalk";
|
|
5498
5619
|
|
|
5499
5620
|
// ../axis-registry-core/src/add/add.ts
|
|
5500
|
-
import { existsSync as existsSync7, readFileSync as readFileSync7, statSync as
|
|
5621
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
5501
5622
|
import path16 from "path";
|
|
5502
5623
|
import fs13 from "fs-extra";
|
|
5503
5624
|
|
|
@@ -6156,7 +6277,7 @@ function relativeSpecifierResolves(fromFile, spec) {
|
|
|
6156
6277
|
const base = path16.resolve(path16.dirname(fromFile), spec);
|
|
6157
6278
|
return RESOLVE_EXTS.some((ext) => {
|
|
6158
6279
|
try {
|
|
6159
|
-
return
|
|
6280
|
+
return statSync5(base + ext).isFile();
|
|
6160
6281
|
} catch {
|
|
6161
6282
|
return false;
|
|
6162
6283
|
}
|