@axis-ds/cli 1.7.7 → 1.7.8
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 +6 -4
- package/dist/{chunk-EBFXCLSV.js → chunk-C2T7NVDG.js} +117 -0
- package/dist/index.js +330 -44
- package/dist/monet.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,19 +96,21 @@ axis theme add ontology
|
|
|
96
96
|
## 프로젝트 검증 (`axis check`)
|
|
97
97
|
|
|
98
98
|
- 전역 CSS 선택(1.7.7 부터): 전역 CSS 를 읽는 세 항목(Tailwind 4 의 Tailwind 구성 항목 · globals.css 항목 · Tailwind 4 의 animation 항목)은 같은 파일 하나를 봅니다. `axis.config.json` 의 `globalCss` 가 가리키는 파일이 있고 `.css` 이면 그 파일입니다. 모노레포의 `../shared/globals.css` 처럼 프로젝트 밖 경로도 읽기만 합니다(`axis theme add` 는 종전대로 밖 파일에 쓰지 않습니다). `globalCss` 키가 없거나 그 파일을 쓸 수 없으면 `globals.css` · `app/globals.css` · `src/app/globals.css` · `src/globals.css` · `styles/globals.css` 순으로 처음 찾은 파일이고, 쓸 수 없었던 이유를 항목 문구 끝에 붙입니다. 없는 파일 · 디렉터리면 `(globalCss ./nope.css 없음)`, `.css` 가 아닌 파일이면 `(globalCss ./package.json: .css 파일이 아님)` 입니다. brand 항목도 같은 `globalCss` 규칙과 표기를 쓰지만 후보 목록이 다릅니다(`app/globals.css` → `src/app/globals.css` → `styles/globals.css` → `src/styles/globals.css` → 루트 `globals.css`). 세 항목도 후보 이름과 같은 디렉터리(예: 루트 `globals.css/`)는 건너뜁니다(1.7.6 까지는 check 가 `EISDIR` 로 멈췄습니다). 1.7.6 까지는 세 항목이 `globalCss` 를 보지 않아, CSS 를 후보 밖(`src/styles/globals.css` 등)에 두고 `globalCss` 로 가리킨 프로젝트도 globals.css FAIL(종료 코드 1)이었고, 루트에 다른 `globals.css` 가 있으면 brand 와 다른 파일을 판정했습니다.
|
|
99
|
-
- 상대 `@import` 펼침(1.7.7 부터): 고른 파일이 `@import "./axis.css";` · `@import '../styles/axis.css';` 처럼 따옴표 안 상대 경로(`./` · `../`, 공백 없는 `@import"./axis.css"` · 확장자 없는 `"./axis"` 포함)로 들여온 프로젝트 안 CSS 도 근거 줄(`@import "tailwindcss"` · 토큰 진입점 · tokens CSS import · `--axis-*` 정의 · 컴포넌트 `tailwind.css` · `@source` · `tw-animate-css` · `@plugin "tailwindcss-animate"` · 브랜드 import)을 찾을 때 함께 봅니다. 근거를 하위 파일에서 찾으면 문구 끝(`globalCss` 표기 앞)에 `(app/axis.css 의 import)` 처럼 출처를 붙이고, 하위 파일이 없으면 종전 문구 그대로입니다. 확장자 없는 이름은 적힌 이름의 파일이 먼저이고 없으면 끝에 `.css` 를 붙인 파일을 봅니다(Tailwind 4 와 같음). 하위 파일이 다시 import 한 파일도 진입 파일에서 32단계까지 따라가고, 같은 파일은 한 번만 읽습니다. 프로젝트 밖으로 나가는 경로(`../` · 밖을 가리키는 심볼릭 링크), 없는 파일 · 디렉터리, `url(...)` 형태, `layer()` · `supports()` · media 조건이 붙은 import(조건 안의 토큰 진입점은 Tailwind 4 빌드가 실패함. Tailwind 3 은 조건이 붙은 import 도 펼쳐 빌드하지만 check 는 따라가지 않아 그 파일의 줄을 근거로 보지 않습니다), `./` 없는 이름(`"axis.css"`, 패키지 경로로 풀림)은 따라가지 않습니다. 프로젝트 밖 전역 CSS 가 다시 밖 파일을 import 해도 읽지 않습니다. 상대 import 가 순환하면(a → b → a · 자기 import) 빌드가 실패하므로 globals.css 항목은 진입 파일만으로 판정한 문구 뒤에 ` / ` 로 순환 문구를 붙여 WARN 을 냅니다(예: `app/globals.css에 AXIS CSS 변수가 없습니다 / app/globals.css · app/b.css 이 서로 @import 해 빌드가 순환으로 실패합니다 → 순환하는 @import 를 없애세요`, 자기 자신을 import 하면 `app/globals.css 이 자기 자신을 @import 해 빌드가 순환으로 실패합니다 → 순환하는 @import 를 없애세요`). 진입 파일이 PASS 여도 WARN 이고, 이때는 모든 항목이 진입 파일만 보며 순환 문구는 globals.css 항목에만 붙습니다. 순환은 조건이 붙은 import 까지 넣어 Tailwind 4 의 재귀 한도와 같은 100단계까지 찾습니다(근거는 위와 같이 조건 없는 import · 32단계까지만 봄). 하위 파일의 패키지 경로 줄은 진입 파일에 같은 줄이 있을 때와 같은 해석 판정(아래 Tailwind 구성 항목 2 · 5번 · globals.css 항목)을 그 하위 파일의 디렉터리 기준(그 디렉터리의 중첩 `node_modules` 포함)으로
|
|
99
|
+
- 상대 `@import` 펼침(1.7.7 부터): 고른 파일이 `@import "./axis.css";` · `@import '../styles/axis.css';` 처럼 따옴표 안 상대 경로(`./` · `../`, 공백 없는 `@import"./axis.css"` · 확장자 없는 `"./axis"` 포함)로 들여온 프로젝트 안 CSS 도 근거 줄(`@import "tailwindcss"` · 토큰 진입점 · tokens CSS import · `--axis-*` 정의 · 컴포넌트 `tailwind.css` · `@source` · `tw-animate-css` · `@plugin "tailwindcss-animate"` · 브랜드 import)을 찾을 때 함께 봅니다. 근거를 하위 파일에서 찾으면 문구 끝(`globalCss` 표기 앞)에 `(app/axis.css 의 import)` 처럼 출처를 붙이고, 하위 파일이 없으면 종전 문구 그대로입니다. 확장자 없는 이름은 적힌 이름의 파일이 먼저이고 없으면 끝에 `.css` 를 붙인 파일을 봅니다(Tailwind 4 와 같음). 하위 파일이 다시 import 한 파일도 진입 파일에서 32단계까지 따라가고, 같은 파일은 한 번만 읽습니다. 프로젝트 밖으로 나가는 경로(`../` · 밖을 가리키는 심볼릭 링크), 없는 파일 · 디렉터리, `url(...)` 형태, `layer()` · `supports()` · media 조건이 붙은 import(조건 안의 토큰 진입점은 Tailwind 4 빌드가 실패함. Tailwind 3 은 조건이 붙은 import 도 펼쳐 빌드하지만 check 는 따라가지 않아 그 파일의 줄을 근거로 보지 않습니다), `./` 없는 이름(`"axis.css"`, 패키지 경로로 풀림)은 따라가지 않습니다. 프로젝트 밖 전역 CSS 가 다시 밖 파일을 import 해도 읽지 않습니다. 상대 import 가 순환하면(a → b → a · 자기 import) 빌드가 실패하므로 globals.css 항목은 진입 파일만으로 판정한 문구 뒤에 ` / ` 로 순환 문구를 붙여 WARN 을 냅니다(예: `app/globals.css에 AXIS CSS 변수가 없습니다 / app/globals.css · app/b.css 이 서로 @import 해 빌드가 순환으로 실패합니다 → 순환하는 @import 를 없애세요`, 자기 자신을 import 하면 `app/globals.css 이 자기 자신을 @import 해 빌드가 순환으로 실패합니다 → 순환하는 @import 를 없애세요`). 진입 파일이 PASS 여도 WARN 이고, 이때는 모든 항목이 진입 파일만 보며 순환 문구는 globals.css 항목에만 붙습니다. 순환은 조건이 붙은 import 까지 넣어 Tailwind 4 의 재귀 한도와 같은 100단계까지 찾습니다(근거는 위와 같이 조건 없는 import · 32단계까지만 봄). 하위 파일의 패키지 경로 줄은 진입 파일에 같은 줄이 있을 때와 같은 해석 판정(아래 Tailwind 구성 항목 2 · 5번 · globals.css 항목)을 그 하위 파일의 디렉터리 기준(그 디렉터리의 중첩 `node_modules` 포함)으로 거치고(1.7.8 부터 Tailwind 4 의 tokens CSS import · 컴포넌트 `tailwind.css` 줄은 아래 「중첩 설치본」 규칙, `@import "tailwindcss"` 줄과 Tailwind 3 은 이 규칙 그대로), 브랜드 import 는 종전대로 그 판정 없이 위치만 봅니다. create-next-app 기본 정의 · `font-family: Arial` 같은 결함은 진입 파일에서만 봅니다. 1.7.6 까지는 하위 파일을 보지 않아, 근거를 하위 파일에 둔 프로젝트도 「없습니다」 WARN 이었습니다(종료 코드는 그대로).
|
|
100
100
|
- Tailwind 구성 항목: Tailwind 4 이상(설치본, 없으면 `package.json` 선언으로 판정)은 설정 파일 대신 위 전역 CSS 선택이 고른 파일 하나(상대 `@import` 로 들여온 하위 파일 포함)를 봅니다. Tailwind 3 이하는 `tailwind.config.ts` · `.js` · `.mjs` · `.cjs` 를 찾습니다.
|
|
101
101
|
- Tailwind 4: `@import "tailwindcss"` 가 있는 CSS 에서 아래 문제가 하나도 없으면 PASS 이고, 하나라도 있으면 WARN 입니다(블록 주석 안은 없는 것으로 봅니다). `@import "tailwindcss"` 가 없으면 그 WARN 하나만 냅니다.
|
|
102
102
|
1. 토큰 진입점 `@import "@axis-ds/tokens/css/tailwind4";` 이 없음 → 문구에 넣을 import 줄. 진입점이 없으면 `bg-primary` · `rounded-md` 같은 AXIS 매핑이 만들어지지 않습니다. `@axis-ds/tokens/css` · `css/shadcn` · `tailwind`(Tailwind 3 preset)는 진입점으로 치지 않습니다.
|
|
103
103
|
2. `package.json` 에 선언된 `@axis-ds/ui-react` · `@axis-ds/agentic-ui` 의 `tailwind.css` import 가 없음 → 빠진 import 줄. 선언이 없으면(복사 설치) 요구하지 않습니다. 1.7.7 부터는 그 줄이 이 앱에서 해석될 때만 줄을 바로 안내합니다. 앱 `package.json` 선언과, 설치본에 `tailwind.css` 가 있는 워크스페이스 루트 선언은 종전대로 줄을 안내합니다. 해석되지 않는 루트 선언은 먼저 할 일을 안내합니다: Plug'n'Play 에서 루트에만 선언(→ 앱 `package.json` 에 선언한 뒤 줄), 설치본 없음(→ 설치 뒤 줄), 설치본이 1.4.0 미만이거나 버전을 읽지 못함(→ 1.4.0 이상으로 올린 뒤 줄), 1.4.0 이상인데 `tailwind.css` 가 없음(→ 다시 설치 뒤 줄). 앱 디렉터리에 lockfile 이 있으면 루트 선언을 선언으로 보지 않습니다(`axis theme add` 와 같은 판정). 1.7.6 까지는 선언만 보고 줄을 안내해, 그대로 넣으면 빌드가 `Can't resolve` 로 깨질 수 있었습니다. `tailwind.css` 대신 그 패키지를 가리키는 `@source` 를 같은 CSS 에 직접 썼으면(예: `@source "../node_modules/@axis-ds/ui-react/dist";`, 작은따옴표 · 다른 상대 경로 포함) 스캔 경로가 있는 것으로 봅니다. 경로 문자열에 `@axis-ds/<패키지>` 가 들어 있고 그 바로 뒤가 경로 끝 · `/` · `\` 이면(`@axis-ds/ui-react-extra` 같은 다른 이름은 아님) 그 패키지를 가리킨다고 판정합니다(경로가 실제로 있는지는 보지 않음). 주석 안 · `@source not` · `@source inline()` 은 인정하지 않고, brace 확장(`@source "{…/@axis-ds/ui-react,…}/dist"`) · `@import "…" source("…")` 형태도 인정하지 않습니다(WARN 쪽으로 판정).
|
|
104
104
|
3. 진입점이 있는데 create-next-app 기본 정의가 남음 → 실제로 남은 정의 이름(예: `--font-sans` 만 남았으면 `@theme --font-sans: var(--font-geist-sans)` 만 표시). `--background` · `--foreground` 를 색값(`#ffffff` · `rgb()` · `oklch()` 등)으로 정의, `--color-background: var(--background)` 류, `--font-sans` · `--font-mono: var(--font-geist-*)`, `background` · `color: var(--background)` 류 직접 사용을 봅니다(create-next-app 15.5.28 기본 `globals.css` 실물 기준). AXIS 의 HSL 삼중값(`0 0% 100%`) 재정의나 `hsl(var(--background))` 는 걸리지 않습니다. 표시 앞머리(`:root 색값` · `@theme` · `body`)는 create-next-app 기본 블록 이름이라, 같은 선언이 다른 선택자에 있어도 그 이름으로 표시됩니다.
|
|
105
105
|
4. 진입점이 있는데 `@axis-ds/tokens` 가 아래 버전 조건에 걸림.
|
|
106
|
-
5. `@axis-ds/ui-react/tailwind.css` · `@axis-ds/agentic-ui/tailwind.css` 를 import 하는데 그 패키지가 아래 버전 조건에 걸림(`tailwind.css` 는 1.4.0 부터 있음). 직접 `@source` 로 스캔하는 패키지는 `tailwind.css` 가 필요 없으므로 이 문제를 만들지 않습니다. 1.7.7 부터는 줄이 이미 있어도 2번의 해석되지 않는 루트 선언(Plug'n'Play 루트 전용 · 설치본 없음 · 설치본에 `tailwind.css` 없음 · 버전을 읽지 못함)이면 버전 조건 대신 「`<패키지>/tailwind.css` import 가 있지만 … 해석되지 않습니다」 WARN 입니다(1.4.0 미만 설치본은 종전 버전 조건 문구, 1.7.6 까지는 버전 조건만 봐서 PASS 일 수 있었음).
|
|
106
|
+
5. `@axis-ds/ui-react/tailwind.css` · `@axis-ds/agentic-ui/tailwind.css` 를 import 하는데 그 패키지가 아래 버전 조건에 걸림(`tailwind.css` 는 1.4.0 부터 있음). 직접 `@source` 로 스캔하는 패키지는 `tailwind.css` 가 필요 없으므로 이 문제를 만들지 않습니다. 1.7.7 부터는 줄이 이미 있어도 2번의 해석되지 않는 루트 선언(Plug'n'Play 루트 전용 · 설치본 없음 · 설치본에 `tailwind.css` 없음 · 버전을 읽지 못함)이면 버전 조건 대신 「`<패키지>/tailwind.css` import 가 있지만 … 해석되지 않습니다」 WARN 입니다(1.4.0 미만 설치본은 종전 버전 조건 문구, 1.7.6 까지는 버전 조건만 봐서 PASS 일 수 있었음). 1.7.8 부터는 아래 중첩 설치본 판정도 이 자리에 나옵니다.
|
|
107
107
|
- 프로젝트 밖 전역 CSS(1.7.7 부터): 고른 파일이 앱 밖(`globalCss` 가 `../shared/globals.css` 등)이면 그 파일의 `@import "tailwindcss"` 와 컴포넌트 `tailwind.css` 줄을 그 파일 위치 기준으로도 봅니다. 빌드 도구가 패키지 경로를 그 CSS 파일 위치부터 상위 `node_modules` 로 풀기 때문입니다(설치본이 앱 아래에만 있으면 빌드가 `Can't resolve` 로 실패, 공통 상위로 호이스팅하면 성공). 앱에서는 설치본을 찾는데 그 파일 위치에서는 찾지 못하면 「import 가 있지만 이 파일 위치에서 <패키지> 를 찾지 못해 해석되지 않습니다」 WARN 입니다(`tailwindcss` 줄은 문제 목록 맨 앞, 컴포넌트 줄은 5번 자리). 토큰 진입점 줄은 globals.css 항목이 같은 기준으로 알립니다. Plug'n'Play 이거나 앱 위치에서 설치본을 찾지 못하면 이 판정을 하지 않습니다.
|
|
108
|
+
- 중첩 설치본(그림자, 1.7.8 부터): 앱 안 CSS(진입 파일 · 상대 `@import` 로 들여온 하위 파일)의 tokens CSS import 줄(`@axis-ds/tokens/css` · `css/shadcn` · `css/tailwind4`, globals.css 항목)과 컴포넌트 `tailwind.css` 줄(위 5번 자리)은 그 줄이 있는 파일 위치부터 Tailwind 4 빌드 도구와 같은 순서로 풉니다. 위로 올라가며 `node_modules/<패키지>` 를 찾고, 먼저 잡힌 설치본에 `exports` 가 있으면 그 `exports`(조건 `style` · `default`)로만 풉니다. 그 설치본이 앱 기준 설치본과 실경로가 다르고(예: `app/node_modules` 에 남은 1.3.0) subpath 를 내보내지 않거나 내보낸 파일이 없으면 빌드가 실패하므로 「import 가 있지만 그 줄이 있는 파일 위치에서 먼저 잡히는 app/node_modules/@axis-ds/ui-react(1.3.0)가 ./tailwind.css 를 내보내지 않아 해석되지 않습니다 → 그 중첩 node_modules 의 @axis-ds/ui-react 를 지우거나 1.4.0 이상으로 맞추세요」 같은 WARN 입니다(이미 1.4.0 이상이면 「다시 설치하세요」). `exports` 도 그 파일도 없는 중첩 디렉터리는 빌드 도구처럼 건너뛰고 상위 설치본으로 봅니다. 앱과 워크스페이스 루트에 설치본이 없고, 그 줄이 있는 파일 위치에서는 풀리지 않는데 같은 전역 CSS 의 다른 파일 위치에서만 풀리면 「설치본이 <경로> 에만 있음」 WARN 입니다. 그림자 파일의 내용은 보지 않고, 프로젝트 밖 전역 CSS · `@import "tailwindcss"` 줄 · Tailwind 3 은 종전대로입니다. 1.7.7 까지는 앱 안 진입 파일의 줄은 앱 기준으로만, 하위 파일의 줄은 처음 만난 설치본(tokens 는 디렉터리, 컴포넌트는 `tailwind.css` 파일)만 봐서 빌드가 실패하는 그림자도 PASS 일 수 있었습니다.
|
|
108
109
|
- 문제가 여럿이면 위 순서대로 ` / ` 로 이어 한 항목에 냅니다. 끝에는 `package.json` 에 선언된 세 AXIS 패키지 가운데 1.4.0 미만인 것을 `(1.4.0 이상 필요: @axis-ds/tokens ^1.3.0)`, 판정할 수 없는 것을 `(설치된 버전이 1.4.0 이상인지 확인하세요: @axis-ds/agentic-ui catalog:)` 로 한 번 덧붙입니다. 버전은 `axis init` 과 같은 함수로 판정합니다: 설치본(`node_modules/<패키지>/package.json` 의 정확한 `version`)이 있으면 그것으로 보고(`(1.4.0 이상 필요: @axis-ds/ui-react 설치본 1.3.0)`, 1.4.0 이상이면 선언과 관계없이 넣지 않음), 없으면 선언 범위의 하한, 하한도 읽을 수 없으면(`catalog:` · `latest` · `||` 등) 판정 불가입니다. `workspace:` 는 넣지 않습니다.
|
|
109
110
|
- 문구 예: `Tailwind 4: globals.css에 AXIS 토큰 진입점이 없습니다 → @import "@axis-ds/tokens/css/tailwind4"; / 컴포넌트 스캔 경로(tailwind.css)가 없습니다 → @import "@axis-ds/ui-react/tailwind.css"; (1.4.0 이상 필요: @axis-ds/tokens ^1.3.0 · @axis-ds/ui-react ^1.3.0)`
|
|
110
|
-
- Tailwind 3: 설정 파일(`.ts` · `.js` · `.mjs` · `.cjs`)이 `@axis-ds/tokens/tailwind` preset 을 `require` · `import` 하면(주석 밖) `tailwind.config.ts에 AXIS 토큰이 설정되어 있습니다 (@axis-ds/tokens/tailwind preset)` 처럼 PASS
|
|
111
|
-
- Tailwind 3 CommonJS(1.6.1 부터): 설정이 `.cjs` 이거나 `module.exports` 를 쓰고 `.default` 없는 `require("@axis-ds/tokens/tailwind")` 가 있으면, 설치본(없으면 선언
|
|
111
|
+
- Tailwind 3: 설정 파일(`.ts` · `.js` · `.mjs` · `.cjs`)이 `@axis-ds/tokens/tailwind` preset 을 `require` · `import` 하면(주석 밖) `tailwind.config.ts에 AXIS 토큰이 설정되어 있습니다 (@axis-ds/tokens/tailwind preset)` 처럼 PASS 이고(1.7.8 부터는 아래 tokens 해석 조건도 맞아야 함), 없으면 WARN 입니다(1.6.0 부터. 이전에는 `--background` · `hsl(var(` 문자열만 있어도 PASS 여서 AXIS 참조가 없는 자체 매핑도 통과했습니다).
|
|
112
|
+
- Tailwind 3 CommonJS(1.6.1 부터): 설정이 `.cjs` 이거나 `module.exports` 를 쓰고 `.default` 없는 `require("@axis-ds/tokens/tailwind")` 가 있으면, 설치본(없으면 선언 하한. 1.7.8 부터 선언 하한으로 가는 것은 아래 tokens 해석 조건을 통과한 경우뿐) `@axis-ds/tokens` 가 1.7.0 미만일 때 WARN 입니다. 1.6.2 이하의 이 형태는 preset 이 아니라 `{ default }` 를 받아 색 · keyframes 가 빠집니다(1.1.0 부터). `.ts` · `.mjs` 의 `export default` 안 `require` 와 `import` 형태는 Tailwind 가 `.default` 를 꺼내 줘서 이 버전 판정을 하지 않습니다.
|
|
113
|
+
- Tailwind 3 preset 의 tokens 해석(1.7.8 부터): 위 두 판정 앞에서, preset 을 어떤 모양(`require` · `.default` · `import` · `.ts`)으로 받든 `@axis-ds/tokens` 가 이 앱에서 해석되는지 봅니다. globals.css 항목과 같은 기준이라, 앱 `package.json` 에 선언했으면 설치 여부와 상관없이 종전 판정(미설치는 dependencies 항목이 알림)이고, 선언이 없거나 워크스페이스 루트에만 선언했으면 설치본 디렉터리가 있을 때만 종전 판정입니다. 설치본이 없으면 「tailwind.config.mjs에 AXIS preset 참조가 있지만 @axis-ds/tokens 가 설치되지 않아 해석되지 않습니다 → 설치(…)」, Plug'n'Play 에서 루트에만 선언했으면 「… 워크스페이스 루트에만 선언돼 Plug'n'Play 에서 앱이 해석하지 못합니다(워크스페이스 루트 선언 …) → 앱 package.json 에 @axis-ds/tokens 를 선언하세요」 WARN 입니다(CommonJS bare require 는 바로 위 단락의 종전 문구 「… 1.7.0 이상을 선언하세요」). 1.7.7 까지는 PASS 였고, CommonJS bare require 는 이미 WARN 이었던 경우(미선언 · 미설치, 루트 1.7.0 미만 선언 · 미설치)에 문구만 바뀝니다. 종료 코드는 그대로입니다. 이 레이아웃은 Tailwind 빌드가 `Cannot find module '@axis-ds/tokens/tailwind'` 로 실패합니다. 1.7.0 버전 판정은 종전대로 CommonJS bare require 만 봅니다.
|
|
112
114
|
- globals.css 항목: 위 전역 CSS 선택이 고른 CSS 하나(상대 `@import` 로 들여온 하위 파일 포함, Arial 은 진입 파일만)를 봅니다(Tailwind 3 이하도 같음). 고를 파일이 하나도 없으면 FAIL 입니다. 1.6.1 부터 AXIS 근거가 있을 때만 PASS 입니다: `@axis-ds/tokens/css` · `@axis-ds/tokens/css/shadcn` · `@axis-ds/tokens/css/tailwind4` import(블록 주석 밖, 작은따옴표 · `url()` · `layer()` 표기 포함, 문구 끝에 `(@axis-ds/tokens/css/tailwind4 import)` 처럼 경로), `--axis-*` 변수 정의, 또는 루트 레이아웃(`app/layout.tsx` 등)의 `import "@axis-ds/tokens/css"`. 1.7.7 부터 tokens import(CSS · 루트 레이아웃 JS)는 이 앱에서 해석될 때만 근거로 칩니다. 앱 `package.json` 에 `@axis-ds/tokens` 를 선언했으면 설치 여부와 상관없이 종전대로 PASS 이고(미설치는 dependencies 항목이 알림), 선언이 없거나 워크스페이스 루트에만 선언했으면 설치본 디렉터리(`node_modules/@axis-ds/tokens`, 상위 디렉터리 포함)가 있을 때 PASS 입니다. 설치본이 없으면 「<경로> import 가 있지만 @axis-ds/tokens 가 설치되지 않아 해석되지 않습니다 → 설치(…)」, Plug'n'Play 에서 루트에만 선언했으면 「… 워크스페이스 루트에만 선언돼 Plug'n'Play 에서 앱이 해석하지 못합니다 → 앱 package.json 에 선언하세요」 WARN 입니다(1.7.6 까지는 PASS, 종료 코드는 그대로). 고른 파일이 프로젝트 밖이면 Tailwind 구성 항목과 같이 그 파일 위치에서 설치본이 보이는지도 봅니다. `--axis-*` 변수 정의는 이 판정을 거치지 않습니다. 단, 해석되지 않는 tokens import 가 함께 있으면 import 판정을 따라 WARN 입니다. 자체 `--background` · `--primary` 만 있으면 「자체 CSS 변수만 있고 AXIS 토큰이 없습니다」 WARN 입니다(1.6.0 까지는 PASS). Tailwind 3 에서 create-next-app 기본 `body` 의 `font-family: Arial` 이 남아 있으면 PASS 조건을 채워도 WARN 입니다(Tailwind 4 는 tailwind.config 항목의 create-next-app 기본 정의로 냅니다).
|
|
113
115
|
- 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 까지는 선언만 보고 「모두 설치되어 있습니다」였습니다.
|
|
114
116
|
- 1.7.6 부터 워크스페이스 루트 `package.json` 에 선언한 `@axis-ds/*`(앱에 없는 것)도 설치 확인 대상이고, 설치되지 않았으면 「워크스페이스 루트에 선언돼 있지만 설치되지 않았습니다」 WARN 입니다(종료 코드는 그대로, 1.7.5 까지는 앱 선언만 봐서 PASS).
|
|
@@ -362,6 +362,122 @@ function outsideCssPackageResolution(baseDir, cssDir, name, file) {
|
|
|
362
362
|
if (!usable(findInstalledPackage(baseDir, name))) return "unknown";
|
|
363
363
|
return usable(findInstalledPackage(cssDir, name)) ? "resolved" : "unresolved";
|
|
364
364
|
}
|
|
365
|
+
var CSS_EXPORT_CONDITIONS = /* @__PURE__ */ new Set(["style", "default"]);
|
|
366
|
+
function splitPackageSpec(spec) {
|
|
367
|
+
const parts = spec.split("/");
|
|
368
|
+
const n = spec.startsWith("@") ? 2 : 1;
|
|
369
|
+
if (parts.length < n || parts.slice(0, n).some((p) => p === "" || p === "." || p === "..")) return void 0;
|
|
370
|
+
return { name: parts.slice(0, n).join("/"), rest: parts.slice(n).join("/") };
|
|
371
|
+
}
|
|
372
|
+
function resolveExportTarget(value) {
|
|
373
|
+
if (typeof value === "string") return value;
|
|
374
|
+
if (Array.isArray(value)) {
|
|
375
|
+
for (const v of value) {
|
|
376
|
+
const r = resolveExportTarget(v);
|
|
377
|
+
if (r !== void 0) return r;
|
|
378
|
+
}
|
|
379
|
+
return void 0;
|
|
380
|
+
}
|
|
381
|
+
if (isPlainObject(value)) {
|
|
382
|
+
for (const [key, v] of Object.entries(value)) {
|
|
383
|
+
if (!CSS_EXPORT_CONDITIONS.has(key)) continue;
|
|
384
|
+
if (v === null) return void 0;
|
|
385
|
+
const r = resolveExportTarget(v);
|
|
386
|
+
if (r !== void 0) return r;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return void 0;
|
|
390
|
+
}
|
|
391
|
+
function cssFileCandidates(p) {
|
|
392
|
+
return [p, `${p}.css`, path.join(p, "index.css")];
|
|
393
|
+
}
|
|
394
|
+
function exportsTarget(exportsField, subpath) {
|
|
395
|
+
const map = isPlainObject(exportsField) && Object.keys(exportsField).some((k) => k.startsWith(".")) ? exportsField : { ".": exportsField };
|
|
396
|
+
if (Object.prototype.hasOwnProperty.call(map, subpath)) {
|
|
397
|
+
const t = resolveExportTarget(map[subpath]);
|
|
398
|
+
if (t === void 0) return void 0;
|
|
399
|
+
return t.includes("*") || !t.startsWith("./") ? "?" : t;
|
|
400
|
+
}
|
|
401
|
+
if (Object.keys(map).some((k) => k.includes("*") || k.endsWith("/") && subpath.startsWith(k))) return "?";
|
|
402
|
+
return void 0;
|
|
403
|
+
}
|
|
404
|
+
function resolveCssPackageImport(fromDir, spec) {
|
|
405
|
+
const parsed = splitPackageSpec(spec);
|
|
406
|
+
if (parsed === void 0 || parsed.rest === "") return { kind: "unknown" };
|
|
407
|
+
const subpath = `./${parsed.rest}`;
|
|
408
|
+
let dir = resolveBaseDir(fromDir);
|
|
409
|
+
for (; ; ) {
|
|
410
|
+
const pkgDir = path.join(dir, "node_modules", ...parsed.name.split("/"));
|
|
411
|
+
if (isDirectory(pkgDir)) {
|
|
412
|
+
let manifest;
|
|
413
|
+
try {
|
|
414
|
+
const raw = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf8"));
|
|
415
|
+
manifest = isPlainObject(raw) ? raw : void 0;
|
|
416
|
+
} catch {
|
|
417
|
+
manifest = void 0;
|
|
418
|
+
}
|
|
419
|
+
if (manifest !== void 0 && manifest.exports) {
|
|
420
|
+
const version = exactVersionOf(manifest.version);
|
|
421
|
+
const target = exportsTarget(manifest.exports, subpath);
|
|
422
|
+
if (target === "?") return { kind: "unknown" };
|
|
423
|
+
if (target === void 0) {
|
|
424
|
+
return version !== void 0 ? { kind: "not-exported", pkgDir, subpath, version } : { kind: "not-exported", pkgDir, subpath };
|
|
425
|
+
}
|
|
426
|
+
const file = cssFileCandidates(path.join(pkgDir, target)).find(isFile);
|
|
427
|
+
if (file !== void 0) return { kind: "resolved", pkgDir, file };
|
|
428
|
+
return version !== void 0 ? { kind: "target-missing", pkgDir, subpath, target, version } : { kind: "target-missing", pkgDir, subpath, target };
|
|
429
|
+
}
|
|
430
|
+
const bare = cssFileCandidates(path.join(pkgDir, parsed.rest)).find(isFile);
|
|
431
|
+
if (bare !== void 0) return { kind: "resolved", pkgDir, file: bare };
|
|
432
|
+
}
|
|
433
|
+
const parent = path.dirname(dir);
|
|
434
|
+
if (parent === dir) return { kind: "not-found" };
|
|
435
|
+
dir = parent;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function installBase(pkgDir, name) {
|
|
439
|
+
let base = pkgDir;
|
|
440
|
+
for (let i = 0; i < name.split("/").length + 1; i++) base = path.dirname(base);
|
|
441
|
+
try {
|
|
442
|
+
return realpathSync(base);
|
|
443
|
+
} catch {
|
|
444
|
+
return path.resolve(base);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function isAncestorInstall(hit, app, name) {
|
|
448
|
+
const h = installBase(hit, name);
|
|
449
|
+
const a = installBase(app, name);
|
|
450
|
+
return a !== h && a.startsWith(h.endsWith(path.sep) ? h : h + path.sep);
|
|
451
|
+
}
|
|
452
|
+
function sameRealDir(a, b) {
|
|
453
|
+
const real = (p) => {
|
|
454
|
+
try {
|
|
455
|
+
return realpathSync(p);
|
|
456
|
+
} catch {
|
|
457
|
+
return path.resolve(p);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
return real(a) === real(b);
|
|
461
|
+
}
|
|
462
|
+
function cssPackageLineResolution(baseDir, lineDir, spec, otherDirs = []) {
|
|
463
|
+
if (isPnpProject(baseDir)) return { kind: "ok" };
|
|
464
|
+
const parsed = splitPackageSpec(spec);
|
|
465
|
+
if (parsed === void 0) return { kind: "ok" };
|
|
466
|
+
const r = resolveCssPackageImport(lineDir, spec);
|
|
467
|
+
if (r.kind === "resolved" || r.kind === "unknown") return { kind: "ok" };
|
|
468
|
+
const app = findInstalledPackage(baseDir, parsed.name);
|
|
469
|
+
if (r.kind === "not-exported" || r.kind === "target-missing") {
|
|
470
|
+
if (app !== void 0 && sameRealDir(app.dir, r.pkgDir)) return { kind: "ok" };
|
|
471
|
+
if (app !== void 0 && isAncestorInstall(r.pkgDir, app.dir, parsed.name)) return { kind: "ok" };
|
|
472
|
+
return r.kind === "not-exported" ? { ...r, kind: "shadow-not-exported" } : { ...r, kind: "shadow-target-missing" };
|
|
473
|
+
}
|
|
474
|
+
if (app !== void 0) return { kind: "ok" };
|
|
475
|
+
for (const other of typeof otherDirs === "function" ? otherDirs() : otherDirs) {
|
|
476
|
+
const o = resolveCssPackageImport(other, spec);
|
|
477
|
+
if (o.kind === "resolved") return { kind: "not-visible", pkgDir: o.pkgDir, fromDir: resolveBaseDir(other) };
|
|
478
|
+
}
|
|
479
|
+
return { kind: "ok" };
|
|
480
|
+
}
|
|
365
481
|
function deferredComponentImportReason(d, installCommand) {
|
|
366
482
|
const line = `@import "${d.name}/tailwind.css";`;
|
|
367
483
|
const current = d.installedVersion !== void 0 && d.installedVersion !== "?" && (compareExactVersions(d.installedVersion, COMPONENT_TAILWIND_CSS_MIN_VERSION) ?? -1) >= 0;
|
|
@@ -710,6 +826,7 @@ export {
|
|
|
710
826
|
componentCssResolvable,
|
|
711
827
|
tokensCssResolution,
|
|
712
828
|
outsideCssPackageResolution,
|
|
829
|
+
cssPackageLineResolution,
|
|
713
830
|
deferredComponentImportReason,
|
|
714
831
|
findPnpUnpluggedPackages,
|
|
715
832
|
compareExactVersions,
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
componentCssResolution,
|
|
12
12
|
componentCssResolvable,
|
|
13
13
|
cssImportViaNote,
|
|
14
|
+
cssPackageLineResolution,
|
|
14
15
|
declaredDependency,
|
|
15
16
|
deferredComponentImportReason,
|
|
16
17
|
dependencyInstallGuide,
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
tokensCssResolution,
|
|
34
35
|
workspaceRootPackage,
|
|
35
36
|
workspaceRunCommand
|
|
36
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-C2T7NVDG.js";
|
|
37
38
|
import {
|
|
38
39
|
V0Client
|
|
39
40
|
} from "./chunk-2PNCUPCG.js";
|
|
@@ -2248,12 +2249,12 @@ function outsideCssDir(selection) {
|
|
|
2248
2249
|
function outsideCssUnresolvedIssue(spec, name) {
|
|
2249
2250
|
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`;
|
|
2250
2251
|
}
|
|
2251
|
-
function tokensInstallPhrase(baseDir) {
|
|
2252
|
-
const g = dependencyInstallGuide(baseDir, TOKENS_PACKAGE_NAME,
|
|
2252
|
+
function tokensInstallPhrase(baseDir, range = `^${TAILWIND4_MIN_AXIS_VERSION}`) {
|
|
2253
|
+
const g = dependencyInstallGuide(baseDir, TOKENS_PACKAGE_NAME, range);
|
|
2253
2254
|
if (g.kind === "install-at-root") return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}`;
|
|
2254
2255
|
return g.kind === "install" ? g.installCommand : g.addCommand;
|
|
2255
2256
|
}
|
|
2256
|
-
function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir) {
|
|
2257
|
+
function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir, lineIssue) {
|
|
2257
2258
|
const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
|
|
2258
2259
|
const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC`;
|
|
2259
2260
|
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`;
|
|
@@ -2263,7 +2264,41 @@ function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir) {
|
|
|
2263
2264
|
if (cssDir !== void 0 && outsideCssPackageResolution(baseDir, cssDir, TOKENS_PACKAGE_NAME) === "unresolved") {
|
|
2264
2265
|
return outsideCssUnresolvedIssue(spec, TOKENS_PACKAGE_NAME);
|
|
2265
2266
|
}
|
|
2266
|
-
return
|
|
2267
|
+
return lineIssue?.();
|
|
2268
|
+
}
|
|
2269
|
+
function packageNameOfSpec(spec) {
|
|
2270
|
+
const parts = spec.split("/");
|
|
2271
|
+
return parts.slice(0, spec.startsWith("@") ? 2 : 1).join("/");
|
|
2272
|
+
}
|
|
2273
|
+
function displayRel(baseDir, p) {
|
|
2274
|
+
return relative(baseDir, p).split(sep).join("/");
|
|
2275
|
+
}
|
|
2276
|
+
function packageLineShadowIssue(baseDir, expanded, origin, spec) {
|
|
2277
|
+
const name = packageNameOfSpec(spec);
|
|
2278
|
+
const lineDir = dirname(origin.path);
|
|
2279
|
+
const others = () => [...new Set(expanded.files.map((f) => dirname(f.path)))].filter((d) => d !== lineDir);
|
|
2280
|
+
const r = cssPackageLineResolution(baseDir, lineDir, spec, others);
|
|
2281
|
+
const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uADF8 \uC904\uC774 \uC788\uB294 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C`;
|
|
2282
|
+
const label = (pkgDir, version) => `${displayRel(baseDir, pkgDir)}(${version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
|
|
2283
|
+
switch (r.kind) {
|
|
2284
|
+
case "ok":
|
|
2285
|
+
return void 0;
|
|
2286
|
+
case "shadow-not-exported": {
|
|
2287
|
+
const current = r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
|
|
2288
|
+
const todo = current ? "\uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694" : `${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uB9DE\uCD94\uC138\uC694`;
|
|
2289
|
+
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}`;
|
|
2290
|
+
}
|
|
2291
|
+
case "shadow-target-missing":
|
|
2292
|
+
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`;
|
|
2293
|
+
case "not-visible": {
|
|
2294
|
+
const there = expanded.files.find((f) => dirname(f.path) === r.fromDir);
|
|
2295
|
+
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`;
|
|
2296
|
+
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}`;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
function isOutsideEntry(origin) {
|
|
2301
|
+
return origin.depth === 0 && origin.cssDir !== void 0;
|
|
2267
2302
|
}
|
|
2268
2303
|
function checkGlobalsCss(baseDirInput) {
|
|
2269
2304
|
const baseDir = resolveBaseDir(baseDirInput);
|
|
@@ -2291,7 +2326,14 @@ function judgeGlobalsCss(baseDir, selection, candidate, expanded) {
|
|
|
2291
2326
|
if (imported !== void 0) {
|
|
2292
2327
|
const origin = evidenceOrigin(expanded, (f) => findTokensCssImport(f) === imported);
|
|
2293
2328
|
via = cssImportViaNote(viaFiles([origin]));
|
|
2294
|
-
const
|
|
2329
|
+
const tailwind4 = (detectTailwind(baseDir, pkg).major ?? 0) >= 4;
|
|
2330
|
+
const issue = tailwind4 && origin !== void 0 && !isOutsideEntry(origin) ? tokensCssUnresolvedIssue(
|
|
2331
|
+
baseDir,
|
|
2332
|
+
pkg,
|
|
2333
|
+
imported,
|
|
2334
|
+
void 0,
|
|
2335
|
+
() => packageLineShadowIssue(baseDir, expanded, origin, imported)
|
|
2336
|
+
) : tokensCssUnresolvedIssue(baseDir, pkg, imported, origin !== void 0 ? origin.cssDir : outsideCssDir(selection));
|
|
2295
2337
|
if (issue !== void 0) unresolved = `${candidate}\uC5D0 ${issue}`;
|
|
2296
2338
|
else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
|
|
2297
2339
|
} else if (AXIS_VARIABLE_DEFINITION.test(stripCssComments(expanded.evidence))) {
|
|
@@ -2522,6 +2564,17 @@ function hasBareCjsPresetRequire(code) {
|
|
|
2522
2564
|
function isCommonJsConfig(file, source) {
|
|
2523
2565
|
return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
|
|
2524
2566
|
}
|
|
2567
|
+
function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
|
|
2568
|
+
const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
|
|
2569
|
+
const head = `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${TOKENS_PACKAGE_NAME} \uAC00`;
|
|
2570
|
+
if (r.kind === "not-installed") {
|
|
2571
|
+
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}`)})`;
|
|
2572
|
+
}
|
|
2573
|
+
if (r.kind === "pnp-root-only" && !bareCjs) {
|
|
2574
|
+
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`;
|
|
2575
|
+
}
|
|
2576
|
+
return void 0;
|
|
2577
|
+
}
|
|
2525
2578
|
function packageVersionGate(baseDirInput, pkg, name, min, options = {}) {
|
|
2526
2579
|
const baseDir = resolveBaseDir(baseDirInput);
|
|
2527
2580
|
if (!isPnpProject(baseDir)) {
|
|
@@ -2591,11 +2644,22 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
|
|
|
2591
2644
|
for (const name of TAILWIND4_COMPONENT_PACKAGES) {
|
|
2592
2645
|
if (!hasComponentTailwindImport(evidence, name)) continue;
|
|
2593
2646
|
const unresolved = componentCssPresentIssue(baseDir, name, resolutions.get(name));
|
|
2594
|
-
const
|
|
2595
|
-
if (unresolved !== void 0)
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
}
|
|
2647
|
+
const spec = `${name}/tailwind.css`;
|
|
2648
|
+
if (unresolved !== void 0) {
|
|
2649
|
+
issues.push(unresolved);
|
|
2650
|
+
continue;
|
|
2651
|
+
}
|
|
2652
|
+
const shadow = input.lineIssue === void 0 ? false : input.lineIssue(spec);
|
|
2653
|
+
let lineProblem;
|
|
2654
|
+
if (shadow !== false) lineProblem = shadow;
|
|
2655
|
+
else {
|
|
2656
|
+
const componentDir = cssDirOf(spec);
|
|
2657
|
+
if (componentDir !== void 0 && outsideCssPackageResolution(baseDir, componentDir, name, "tailwind.css") === "unresolved") {
|
|
2658
|
+
lineProblem = outsideCssUnresolvedIssue(spec, name);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
if (lineProblem !== void 0) issues.push(lineProblem);
|
|
2662
|
+
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`);
|
|
2599
2663
|
}
|
|
2600
2664
|
return issues;
|
|
2601
2665
|
}
|
|
@@ -2663,7 +2727,17 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2663
2727
|
);
|
|
2664
2728
|
const versions = axisPackagesBelowTailwind4(pkg, baseDir);
|
|
2665
2729
|
const issues = tailwind4Issues(
|
|
2666
|
-
{
|
|
2730
|
+
{
|
|
2731
|
+
entry: expanded.entry,
|
|
2732
|
+
evidence: expanded.evidence,
|
|
2733
|
+
cssDirOf: (spec) => packageLineCssDir(expanded, spec),
|
|
2734
|
+
lineIssue: (spec) => {
|
|
2735
|
+
const line = expanded.packageLines.find((l) => l.spec === spec);
|
|
2736
|
+
const origin = line !== void 0 ? expanded.files.find((f) => f.rel === line.file) : void 0;
|
|
2737
|
+
if (origin === void 0 || isOutsideEntry(origin)) return false;
|
|
2738
|
+
return packageLineShadowIssue(baseDir, expanded, origin, spec);
|
|
2739
|
+
}
|
|
2740
|
+
},
|
|
2667
2741
|
pkg,
|
|
2668
2742
|
versions,
|
|
2669
2743
|
baseDir
|
|
@@ -2693,7 +2767,10 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2693
2767
|
const content = readFileSync(path17, "utf8");
|
|
2694
2768
|
if (hasTokensPresetReference(content)) {
|
|
2695
2769
|
const code = stripJsComments(content);
|
|
2696
|
-
|
|
2770
|
+
const bareCjs = isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code);
|
|
2771
|
+
const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs);
|
|
2772
|
+
if (unresolved !== void 0) return { name: "tailwind.config", severity: "warn", message: unresolved };
|
|
2773
|
+
if (bareCjs) {
|
|
2697
2774
|
const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION, { appOnlyInPnp: true });
|
|
2698
2775
|
if (gate.status === "unresolved") {
|
|
2699
2776
|
return {
|
|
@@ -3580,9 +3657,11 @@ import path10 from "path";
|
|
|
3580
3657
|
import chalk7 from "chalk";
|
|
3581
3658
|
|
|
3582
3659
|
// src/theme/brand-core.ts
|
|
3660
|
+
import { createHash } from "crypto";
|
|
3583
3661
|
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
3584
3662
|
import { createRequire } from "module";
|
|
3585
3663
|
import { dirname as dirname2, join as join2, relative as relative2, resolve as resolve2, sep as sep2 } from "path";
|
|
3664
|
+
import { MessageChannel, Worker, receiveMessageOnPort } from "worker_threads";
|
|
3586
3665
|
var TOKENS_PACKAGE = "@axis-ds/tokens";
|
|
3587
3666
|
var BRAND_NAME_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
3588
3667
|
var MIN_BRAND_TOKENS_VERSION = "1.3.0";
|
|
@@ -3608,13 +3687,15 @@ function readJsonFile(file) {
|
|
|
3608
3687
|
function errorCode(err) {
|
|
3609
3688
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
3610
3689
|
}
|
|
3611
|
-
function
|
|
3690
|
+
function tokensPackageJsonCandidates(baseDir) {
|
|
3691
|
+
const candidates = [];
|
|
3612
3692
|
let dir = resolve2(baseDir);
|
|
3613
3693
|
for (; ; ) {
|
|
3614
3694
|
const candidate = join2(dir, "node_modules", TOKENS_PACKAGE, "package.json");
|
|
3615
|
-
|
|
3695
|
+
candidates.push(candidate);
|
|
3696
|
+
if (existsSync2(candidate)) return { found: candidate, candidates };
|
|
3616
3697
|
const parent = dirname2(dir);
|
|
3617
|
-
if (parent === dir) return
|
|
3698
|
+
if (parent === dir) return { candidates };
|
|
3618
3699
|
dir = parent;
|
|
3619
3700
|
}
|
|
3620
3701
|
}
|
|
@@ -3624,21 +3705,203 @@ function projectRequire(baseDir) {
|
|
|
3624
3705
|
function tokensSpecifier(subpath) {
|
|
3625
3706
|
return `${TOKENS_PACKAGE}/${subpath.replace(/^\.\//, "")}`;
|
|
3626
3707
|
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3708
|
+
var nodeSeenStates = /* @__PURE__ */ new Map();
|
|
3709
|
+
var ABSENT = "absent";
|
|
3710
|
+
var UNKNOWN = "unknown";
|
|
3711
|
+
var isolationDisabled = false;
|
|
3712
|
+
var isolatedStats = { workers: 0, resolves: 0, fallbacks: 0 };
|
|
3713
|
+
var ISOLATED_RESOLVE_TIMEOUT_MS = 5e3;
|
|
3714
|
+
var ISOLATED_RESOLVE_SOURCE = `
|
|
3715
|
+
const { workerData } = require("node:worker_threads");
|
|
3716
|
+
const { createRequire } = require("node:module");
|
|
3717
|
+
const { port, signal, from } = workerData;
|
|
3718
|
+
const req = createRequire(from);
|
|
3719
|
+
port.on("message", (spec) => {
|
|
3720
|
+
let reply;
|
|
3632
3721
|
try {
|
|
3633
|
-
|
|
3634
|
-
|
|
3722
|
+
reply = { path: req.resolve(spec) };
|
|
3723
|
+
} catch (err) {
|
|
3724
|
+
const code = err && typeof err === "object" && "code" in err ? String(err.code) : undefined;
|
|
3725
|
+
reply = { code, message: err && err.message ? String(err.message) : String(err) };
|
|
3726
|
+
}
|
|
3727
|
+
port.postMessage(reply);
|
|
3728
|
+
Atomics.store(signal, 0, 1);
|
|
3729
|
+
Atomics.notify(signal, 0);
|
|
3730
|
+
});
|
|
3731
|
+
`;
|
|
3732
|
+
var IsolationFailure = class extends Error {
|
|
3733
|
+
};
|
|
3734
|
+
function createWorkerResolveSession(from, source, timeoutMs) {
|
|
3735
|
+
const { port1, port2 } = new MessageChannel();
|
|
3736
|
+
const signal = new Int32Array(new SharedArrayBuffer(4));
|
|
3737
|
+
const worker = new Worker(source, {
|
|
3738
|
+
eval: true,
|
|
3739
|
+
workerData: { port: port2, signal, from },
|
|
3740
|
+
transferList: [port2]
|
|
3741
|
+
});
|
|
3742
|
+
worker.on("error", () => {
|
|
3743
|
+
});
|
|
3744
|
+
worker.unref();
|
|
3745
|
+
return {
|
|
3746
|
+
resolve(spec) {
|
|
3747
|
+
Atomics.store(signal, 0, 0);
|
|
3748
|
+
port1.postMessage(spec);
|
|
3749
|
+
const waited = Atomics.wait(signal, 0, 0, timeoutMs);
|
|
3750
|
+
const received = receiveMessageOnPort(port1);
|
|
3751
|
+
if (waited === "timed-out" || !received) throw new IsolationFailure("\uACA9\uB9AC \uD574\uC11D\uC774 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
|
|
3752
|
+
const reply = received.message;
|
|
3753
|
+
if (typeof reply.path === "string") return reply.path;
|
|
3754
|
+
throw Object.assign(new Error(reply.message ?? spec), reply.code === void 0 ? {} : { code: reply.code });
|
|
3755
|
+
},
|
|
3756
|
+
close() {
|
|
3757
|
+
port1.close();
|
|
3758
|
+
void worker.terminate();
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
}
|
|
3762
|
+
function workerResolveSession(from) {
|
|
3763
|
+
return createWorkerResolveSession(from, ISOLATED_RESOLVE_SOURCE, ISOLATED_RESOLVE_TIMEOUT_MS);
|
|
3764
|
+
}
|
|
3765
|
+
var isolatedFactory = workerResolveSession;
|
|
3766
|
+
function sha256(text) {
|
|
3767
|
+
return createHash("sha256").update(text).digest("hex");
|
|
3768
|
+
}
|
|
3769
|
+
function openTokensResolver(baseDir, candidates, pkgJson, pkgText) {
|
|
3770
|
+
const nodeRequire = projectRequire(baseDir);
|
|
3771
|
+
const key = sha256(pkgText);
|
|
3772
|
+
const current = candidates.map((c) => c === pkgJson ? key : ABSENT);
|
|
3773
|
+
const changed = candidates.some((c, i) => {
|
|
3774
|
+
const seen = nodeSeenStates.get(c);
|
|
3775
|
+
return seen !== void 0 && seen !== current[i];
|
|
3776
|
+
});
|
|
3777
|
+
let mode = changed ? "isolated" : "node";
|
|
3778
|
+
if (mode === "node") {
|
|
3779
|
+
candidates.forEach((c, i) => {
|
|
3780
|
+
if (!nodeSeenStates.has(c)) nodeSeenStates.set(c, current[i]);
|
|
3781
|
+
});
|
|
3782
|
+
}
|
|
3783
|
+
let session = null;
|
|
3784
|
+
let stale = false;
|
|
3785
|
+
let raced = false;
|
|
3786
|
+
let postChecked = false;
|
|
3787
|
+
const markStale = () => {
|
|
3788
|
+
if (!stale) isolatedStats.fallbacks += 1;
|
|
3789
|
+
stale = true;
|
|
3790
|
+
};
|
|
3791
|
+
const fallBack = () => {
|
|
3792
|
+
markStale();
|
|
3793
|
+
isolationDisabled = true;
|
|
3794
|
+
session?.close();
|
|
3795
|
+
session = null;
|
|
3796
|
+
};
|
|
3797
|
+
const startIsolation = () => {
|
|
3798
|
+
if (isolationDisabled) {
|
|
3799
|
+
markStale();
|
|
3800
|
+
return;
|
|
3801
|
+
}
|
|
3802
|
+
try {
|
|
3803
|
+
session = isolatedFactory(join2(resolve2(baseDir), "package.json"));
|
|
3804
|
+
isolatedStats.workers += 1;
|
|
3805
|
+
} catch {
|
|
3806
|
+
fallBack();
|
|
3807
|
+
}
|
|
3808
|
+
};
|
|
3809
|
+
if (mode === "isolated") startIsolation();
|
|
3810
|
+
const isolatedResolve = (spec) => {
|
|
3811
|
+
if (session) {
|
|
3812
|
+
try {
|
|
3813
|
+
const resolved = session.resolve(spec);
|
|
3814
|
+
isolatedStats.resolves += 1;
|
|
3815
|
+
return resolved;
|
|
3816
|
+
} catch (err) {
|
|
3817
|
+
if (!(err instanceof IsolationFailure)) {
|
|
3818
|
+
isolatedStats.resolves += 1;
|
|
3819
|
+
throw err;
|
|
3820
|
+
}
|
|
3821
|
+
fallBack();
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
return nodeRequire.resolve(spec);
|
|
3825
|
+
};
|
|
3826
|
+
return {
|
|
3827
|
+
resolve(spec) {
|
|
3828
|
+
if (mode === "isolated") return isolatedResolve(spec);
|
|
3829
|
+
let resolved;
|
|
3830
|
+
let failure;
|
|
3831
|
+
let failed = false;
|
|
3832
|
+
try {
|
|
3833
|
+
resolved = nodeRequire.resolve(spec);
|
|
3834
|
+
} catch (err) {
|
|
3835
|
+
failed = true;
|
|
3836
|
+
failure = err;
|
|
3837
|
+
}
|
|
3838
|
+
if (!postChecked) {
|
|
3839
|
+
postChecked = true;
|
|
3840
|
+
let after;
|
|
3841
|
+
try {
|
|
3842
|
+
after = sha256(readFileSync2(pkgJson, "utf8"));
|
|
3843
|
+
} catch {
|
|
3844
|
+
after = UNKNOWN;
|
|
3845
|
+
}
|
|
3846
|
+
if (after !== key) {
|
|
3847
|
+
nodeSeenStates.set(pkgJson, UNKNOWN);
|
|
3848
|
+
raced = true;
|
|
3849
|
+
mode = "isolated";
|
|
3850
|
+
startIsolation();
|
|
3851
|
+
return isolatedResolve(spec);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
if (failed) throw failure;
|
|
3855
|
+
return resolved;
|
|
3856
|
+
},
|
|
3857
|
+
get stale() {
|
|
3858
|
+
return stale;
|
|
3859
|
+
},
|
|
3860
|
+
get raced() {
|
|
3861
|
+
return raced;
|
|
3862
|
+
},
|
|
3863
|
+
close() {
|
|
3864
|
+
session?.close();
|
|
3865
|
+
session = null;
|
|
3866
|
+
}
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
function readVersion(pkgText) {
|
|
3870
|
+
const pkg = JSON.parse(pkgText);
|
|
3871
|
+
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
3872
|
+
}
|
|
3873
|
+
function openTokens(baseDir) {
|
|
3874
|
+
const { found: pkgJson, candidates } = tokensPackageJsonCandidates(baseDir);
|
|
3875
|
+
if (!pkgJson) return { resolution: { status: "not-installed" } };
|
|
3876
|
+
const pkgText = readFileSync2(pkgJson, "utf8");
|
|
3877
|
+
let version = readVersion(pkgText);
|
|
3878
|
+
const resolver = openTokensResolver(baseDir, candidates, pkgJson, pkgText);
|
|
3879
|
+
const finish = (status, indexPath) => {
|
|
3880
|
+
if (resolver.raced) {
|
|
3881
|
+
try {
|
|
3882
|
+
version = readVersion(readFileSync2(pkgJson, "utf8"));
|
|
3883
|
+
} catch {
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
const resolution = indexPath === void 0 ? { status, version } : { status, version, indexPath };
|
|
3887
|
+
return { resolution: resolver.stale ? { ...resolution, stale: true } : resolution, resolver };
|
|
3888
|
+
};
|
|
3889
|
+
try {
|
|
3890
|
+
const indexPath = resolver.resolve(tokensSpecifier("./brands"));
|
|
3891
|
+
return finish("ok", indexPath);
|
|
3635
3892
|
} catch (err) {
|
|
3636
3893
|
const code = errorCode(err);
|
|
3637
|
-
if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return
|
|
3638
|
-
if (code === "MODULE_NOT_FOUND") return
|
|
3894
|
+
if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return finish("unsupported");
|
|
3895
|
+
if (code === "MODULE_NOT_FOUND") return finish("not-built");
|
|
3896
|
+
resolver.close();
|
|
3639
3897
|
throw err;
|
|
3640
3898
|
}
|
|
3641
3899
|
}
|
|
3900
|
+
function resolveTokens(baseDir) {
|
|
3901
|
+
const { resolution, resolver } = openTokens(baseDir);
|
|
3902
|
+
resolver?.close();
|
|
3903
|
+
return resolution;
|
|
3904
|
+
}
|
|
3642
3905
|
function brandImportPath(entry) {
|
|
3643
3906
|
return tokensSpecifier(entry.css);
|
|
3644
3907
|
}
|
|
@@ -3711,8 +3974,8 @@ function readBrandIndex(indexPath) {
|
|
|
3711
3974
|
}
|
|
3712
3975
|
return data.brands;
|
|
3713
3976
|
}
|
|
3714
|
-
function readSummary(
|
|
3715
|
-
const metaPath =
|
|
3977
|
+
function readSummary(resolver, entry) {
|
|
3978
|
+
const metaPath = resolver.resolve(tokensSpecifier(entry.meta));
|
|
3716
3979
|
const meta = readJsonFile(metaPath);
|
|
3717
3980
|
return {
|
|
3718
3981
|
name: entry.name,
|
|
@@ -3723,20 +3986,33 @@ function readSummary(baseDir, entry) {
|
|
|
3723
3986
|
};
|
|
3724
3987
|
}
|
|
3725
3988
|
function listBrands(baseDir) {
|
|
3726
|
-
const tokens =
|
|
3727
|
-
|
|
3989
|
+
const { resolution: tokens, resolver } = openTokens(baseDir);
|
|
3990
|
+
try {
|
|
3991
|
+
return withStaleOf(resolver, listBrandsWith(tokens, resolver));
|
|
3992
|
+
} finally {
|
|
3993
|
+
resolver?.close();
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
function listBrandsWith(tokens, resolver) {
|
|
3997
|
+
if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
|
|
3728
3998
|
return { status: tokens.status, version: tokens.version, brands: [] };
|
|
3729
3999
|
}
|
|
3730
4000
|
const entries = readBrandIndex(tokens.indexPath);
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
4001
|
+
const brands = [];
|
|
4002
|
+
for (const entry of entries) {
|
|
4003
|
+
try {
|
|
4004
|
+
brands.push(readSummary(resolver, entry));
|
|
4005
|
+
} catch (err) {
|
|
4006
|
+
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
|
|
4007
|
+
if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") continue;
|
|
4008
|
+
throw err;
|
|
4009
|
+
}
|
|
3737
4010
|
}
|
|
3738
4011
|
return { status: "ok", version: tokens.version, brands };
|
|
3739
4012
|
}
|
|
4013
|
+
function withStaleOf(resolver, result) {
|
|
4014
|
+
return resolver?.stale ? { ...result, stale: true } : result;
|
|
4015
|
+
}
|
|
3740
4016
|
function stripComments(css) {
|
|
3741
4017
|
return css.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
3742
4018
|
}
|
|
@@ -3848,8 +4124,15 @@ function readProjectPackageJson(baseDir) {
|
|
|
3848
4124
|
}
|
|
3849
4125
|
}
|
|
3850
4126
|
function getBrand(baseDir, name) {
|
|
3851
|
-
const tokens =
|
|
3852
|
-
|
|
4127
|
+
const { resolution: tokens, resolver } = openTokens(baseDir);
|
|
4128
|
+
try {
|
|
4129
|
+
return withStaleOf(resolver, getBrandWith(tokens, resolver, name));
|
|
4130
|
+
} finally {
|
|
4131
|
+
resolver?.close();
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
function getBrandWith(tokens, resolver, name) {
|
|
4135
|
+
if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
|
|
3853
4136
|
return { status: tokens.status, version: tokens.version, brand: null, available: [] };
|
|
3854
4137
|
}
|
|
3855
4138
|
const entries = readBrandIndex(tokens.indexPath);
|
|
@@ -3861,11 +4144,14 @@ function getBrand(baseDir, name) {
|
|
|
3861
4144
|
let summary;
|
|
3862
4145
|
let parsed;
|
|
3863
4146
|
try {
|
|
3864
|
-
summary = readSummary(
|
|
3865
|
-
const cssPath =
|
|
4147
|
+
summary = readSummary(resolver, entry);
|
|
4148
|
+
const cssPath = resolver.resolve(summary.importPath);
|
|
3866
4149
|
parsed = parseBrandCss(readFileSync2(cssPath, "utf8"), name);
|
|
3867
4150
|
} catch (err) {
|
|
3868
4151
|
if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
|
|
4152
|
+
if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
4153
|
+
return { status: "ok", version: tokens.version, brand: null, available: available.filter((n) => n !== name) };
|
|
4154
|
+
}
|
|
3869
4155
|
throw err;
|
|
3870
4156
|
}
|
|
3871
4157
|
return {
|
|
@@ -4970,7 +5256,7 @@ function registerThemeCommand(program2) {
|
|
|
4970
5256
|
import chalk11 from "chalk";
|
|
4971
5257
|
|
|
4972
5258
|
// ../axis-registry-core/src/registry/schema.ts
|
|
4973
|
-
import { createHash } from "crypto";
|
|
5259
|
+
import { createHash as createHash2 } from "crypto";
|
|
4974
5260
|
var REGISTRY_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
4975
5261
|
var REGISTRY_NAME_MAX_LENGTH = 64;
|
|
4976
5262
|
function isValidRegistryName(name) {
|
|
@@ -5103,8 +5389,8 @@ function validateRegistryIndex(data, where = "index.json") {
|
|
|
5103
5389
|
if (!isValidRegistryName(raw.name)) throw new Error(`${at}: name \uC774 slug \uADDC\uCE59\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
|
|
5104
5390
|
if (seen.has(raw.name)) throw new Error(`${at}: name '${raw.name}' \uAC00 \uC911\uBCF5\uC785\uB2C8\uB2E4`);
|
|
5105
5391
|
seen.add(raw.name);
|
|
5106
|
-
const
|
|
5107
|
-
if (
|
|
5392
|
+
const sha2562 = optionalString(raw, "sha256", at);
|
|
5393
|
+
if (sha2562 !== void 0 && !/^[0-9a-f]{64}$/.test(sha2562)) {
|
|
5108
5394
|
throw new Error(`${at}: sha256 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
5109
5395
|
}
|
|
5110
5396
|
return {
|
|
@@ -5112,7 +5398,7 @@ function validateRegistryIndex(data, where = "index.json") {
|
|
|
5112
5398
|
type: requireType(raw, at),
|
|
5113
5399
|
title: optionalString(raw, "title", at),
|
|
5114
5400
|
description: optionalString(raw, "description", at),
|
|
5115
|
-
...
|
|
5401
|
+
...sha2562 !== void 0 ? { sha256: sha2562 } : {}
|
|
5116
5402
|
};
|
|
5117
5403
|
});
|
|
5118
5404
|
return {
|
|
@@ -5160,7 +5446,7 @@ function validateRegistryItem(data, expectedName, where = `${expectedName}.json`
|
|
|
5160
5446
|
};
|
|
5161
5447
|
}
|
|
5162
5448
|
function sha256Hex(text) {
|
|
5163
|
-
return
|
|
5449
|
+
return createHash2("sha256").update(text, "utf8").digest("hex");
|
|
5164
5450
|
}
|
|
5165
5451
|
function checkItemSha256(item, entry, where = `${item.name}.json`) {
|
|
5166
5452
|
if (entry.sha256 === void 0) return;
|
package/dist/monet.js
CHANGED