@aihu/css-engine 0.2.4 → 0.2.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 CHANGED
@@ -34,38 +34,138 @@ as a per-platform `optionalDependencies` package
34
34
  resolved automatically at build time — no Rust toolchain required. In a monorepo
35
35
  dev clone the engine falls back to the workspace `target/release` binary.
36
36
 
37
- ### Usage with `viteAihuPlugin`
37
+ ### Enabling utility-class CSS in a user project
38
38
 
39
- When `@aihu/css-engine` is installed alongside `@aihu/app`, the compiler hook
40
- inside `viteAihuPlugin` automatically scans every `.aihu` SFC and folds the
41
- generated utility CSS into the build. **No additional plugin wiring is needed.**
42
-
43
- There is one configuration knob you almost certainly want: **`shadowMode: 'none'`**.
44
- Utility classes rely on the global cascade, so they must escape the per-component
45
- shadow root. Forward this through `viteAihuPlugin`'s `css` option:
39
+ Utility-class CSS is **auto-wired by presence** — install `@aihu/css-engine`
40
+ alongside `@aihu/app`, set one config knob, and every `.aihu` file in your
41
+ project is scanned and the matched rules land in your bundle's CSS asset.
42
+ There is no separate `viteCssEnginePlugin`, no `aihu.config.ts` file, no
43
+ preset selection step. The entire user surface is the `css` option on
44
+ `viteAihuPlugin()` in `vite.config.ts`:
46
45
 
47
46
  ```ts
48
- // vite.config.ts
47
+ // vite.config.ts — the entire surface
49
48
  import { viteAihuPlugin } from '@aihu/app'
50
49
  import { defineConfig } from 'vite'
51
50
 
52
51
  export default defineConfig({
53
52
  plugins: [
54
53
  viteAihuPlugin({
55
- css: { shadowMode: 'none' },
54
+ css: { shadowMode: 'none' }, // ← REQUIRED for utility classes
56
55
  }),
57
56
  ],
58
57
  })
59
58
  ```
60
59
 
61
- If `compileSfc()` fails at build time (e.g. the native `aihu-css-core` binary
62
- is unresolvable in your install), the compiler emits a one-shot warning to the
63
- console — utility classes will not appear in the output until the binary is
64
- restored. The build itself still succeeds.
60
+ ```bash
61
+ bun add @aihu/css-engine
62
+ ```
63
+
64
+ ```jsx
65
+ // any .aihu file — classes are scanned automatically
66
+ @template {
67
+ <section class="flex gap-6 px-4 py-6">
68
+ <span class="text-lg font-semibold">hi</span>
69
+ </section>
70
+ }
71
+ ```
72
+
73
+ That's it. After `bun run build`, `dist/assets/index-*.css` contains the
74
+ emitted rules (`.flex{display:flex}`, `.gap-6{gap:1.5rem}`, etc.).
75
+
76
+ #### Why `shadowMode: 'none'`?
77
+
78
+ Utility classes rely on the global cascade. With the default `shadowMode: 'open'`
79
+ each component lives behind its own shadow root, so global rules can't reach
80
+ template elements. Switching to `'none'` mounts components without a shadow
81
+ root and lets the bundled CSS reach them. Pick `'open'` or `'closed'` only if
82
+ you're authoring components with hand-written `@style { ... }` blocks instead
83
+ of utility classes.
84
+
85
+ #### Style packs vs the utility scanner — they are separate
86
+
87
+ Two distinct things ship in `@aihu/css-engine`:
88
+
89
+ | Concern | What you do | Output |
90
+ |---|---|---|
91
+ | **Utility scanner** (this section) | Install package + set `css.shadowMode: 'none'` | Per-class rules folded into the Vite CSS bundle |
92
+ | **Theme packs** (color tokens, fonts) | `import "@aihu/css-engine/styles/aihu-graphite.css"` in your entry | `--color-*` / `--font-*` CSS custom properties at `:root` |
93
+
94
+ Theme packs are plain CSS imports — they emit token variables, not utility
95
+ rules. Importing a pack alone does **not** enable the scanner; setting
96
+ `css.shadowMode: 'none'` alone does **not** import a pack. Use both for a
97
+ complete look; either independently is fine.
98
+
99
+ ### Utility vocabulary
100
+
101
+ The engine is **inspired by Tailwind v4, not a fork** — the supported set is
102
+ hand-curated in [`crates/aihu-css-core/src/tokens.rs`](crates/aihu-css-core/src/tokens.rs).
103
+
104
+ **Fixed long-tail utilities** (literal class names):
105
+
106
+ - **Display** — `block`, `inline-block`, `inline`, `flex`, `inline-flex`, `grid`, `inline-grid`, `hidden`, `contents`
107
+ - **Flexbox** — `flex-row`, `flex-col`, `flex-wrap`, `flex-nowrap`, `flex-1`, `flex-auto`, `flex-none`
108
+ - **Alignment** — `items-{start,center,end,stretch,baseline}`, `justify-{start,center,end,between,around,evenly}`
109
+ - **Position** — `static`, `relative`, `absolute`, `fixed`, `sticky`
110
+ - **Overflow** — `overflow-{hidden,auto,scroll,visible}`
111
+ - **Typography** — `text-{left,center,right,justify}`, `italic`, `not-italic`, `underline`, `line-through`, `no-underline`, `uppercase`, `lowercase`, `capitalize`, `truncate`
112
+ - **Font weight** — `font-{thin,normal,medium,semibold,bold,black}`
113
+ - **Borders / radius** — `border`, `rounded`, `rounded-{none,sm,md,lg,xl,2xl,full}`
114
+ - **Shadows** — `shadow`, `shadow-{sm,md,lg,none}`
115
+ - **Sizing keywords** — `w-{full,screen,auto}`, `h-{full,screen,auto}`
116
+
117
+ **Parameterized utilities** (`<prefix>-<value>`):
118
+
119
+ | Prefix family | Examples | Notes |
120
+ |---|---|---|
121
+ | Spacing — `p`, `px`, `py`, `pt`, `pr`, `pb`, `pl`, `m`, `mx`, `my`, `mt`, `mr`, `mb`, `ml`, `gap`, `gap-x`, `gap-y` | `p-4`, `mx-auto`, `gap-6` | value × `0.25rem` |
122
+ | Sizing — `w`, `h`, `min-w`, `max-w`, `min-h`, `max-h` | `w-64`, `max-w-7xl` | spacing scale or fractions |
123
+ | Font size — `text-{xs,sm,base,lg,xl,2xl,3xl,…}` | `text-lg` | includes paired line-height |
124
+ | z-index — `z-{N}` | `z-10`, `z-50` | numeric only |
125
+ | Opacity — `opacity-{N}` | `opacity-75` | 0–100 |
126
+ | Palette colors — `bg`, `text`, `border`, `fill`, `stroke`, `ring`, `outline` followed by a named keyword | `bg-red-500`, `text-slate-700` | |
127
+
128
+ **Arbitrary values** (`<prefix>-[<value>]` — emitted verbatim into the mapped
129
+ property): `bg-[#1a1d24]`, `w-[34ch]`, `text-[14px]`, `px-[2rem]`, etc.
130
+ Supported prefixes: `bg`, `text`, `w`, `h`, `min-w`, `max-w`, `min-h`, `max-h`,
131
+ `p`, `px`, `py`, `m`, `mx`, `my`, `gap`, `rounded`, `border`, `leading`,
132
+ `tracking`, `z`, `top`/`right`/`bottom`/`left`/`inset`, `fill`, `stroke`,
133
+ `shadow`. Underscores in the bracket become spaces (Tailwind convention).
134
+
135
+ **Brand color utilities** — `bg-primary`, `text-accent`, `border-muted`, etc.
136
+ resolve to `var(--color-*)` registered by a `@theme` block or a theme pack.
137
+
138
+ #### Not supported (common misses — call out to avoid surprises)
139
+
140
+ The vocabulary is intentionally narrower than full Tailwind. The following are
141
+ **not** in the table; use them and you'll get the class string in your HTML
142
+ with **no matching CSS rule** (the scanner returns `None` and emits nothing):
143
+
144
+ - `grid-cols-N` / `grid-rows-N` / `col-span-N` / `row-span-N` — **no grid template utilities**. Use `display: grid` via the `grid` class, then write a hand-authored `@style` block or an arbitrary `style="grid-template-columns:…"` attribute.
145
+ - `mx-auto` / `my-auto` — the spacing scale is `value × 0.25rem` and doesn't include the `auto` keyword. Use `style="margin-inline: auto"` or an arbitrary value (`mx-[auto]`) instead.
146
+ - `max-w-Nxl` / `max-w-screen` / etc. — `max-w` parameterized values follow the spacing/sizing scale, not Tailwind's named breakpoint scale. `max-w-[1280px]` (arbitrary value) works; `max-w-7xl` does not.
147
+ - Tailwind v4 colors *outside* the named keyword set (e.g. `text-zinc-200` — depends on whether `zinc` is in `named_keyword_color`)
148
+ - Responsive prefixes (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`) — **not yet handled** by the scanner
149
+ - State variants outside the WC-native set (`host:`, `slotted:`, `part-*:` are supported per the variants section above; arbitrary `hover:`, `focus:`, `dark:` etc. depend on what the current `parse_variant` accepts)
150
+ - Container queries, `@layer` ordering, JIT-style arbitrary properties (`[mask-image:url(...)]`)
151
+
152
+ **The authoritative source is [`crates/aihu-css-core/src/tokens.rs`](crates/aihu-css-core/src/tokens.rs)** — the lists above are a summary of that file's match arms and may drift; when in doubt, grep that file or write a one-liner test against `utility_to_css(class_name)`.
153
+
154
+ #### Production caveat — native binary must resolve
155
+
156
+ The scanner runs through the prebuilt `aihu-css-compile` Rust binary. For npm
157
+ consumers the binary ships as a per-platform `optionalDependencies` package
158
+ (e.g. `@aihu/css-engine-darwin-arm64`) and is auto-resolved by your package
159
+ manager. If resolution fails (offline install, unsupported platform), the
160
+ compiler emits a one-shot console warning, the build succeeds, and utility
161
+ rules are silently omitted from the bundle CSS. In monorepo dev clones the
162
+ fallback is `target/release/aihu-css-compile` (run `cargo build --release -p
163
+ aihu-css-core`).
65
164
 
66
165
  See [`examples/css-engine-utility/`](../../examples/css-engine-utility) for a
67
- minimal end-to-end demonstration, including an acceptance script that greps
68
- the built CSS for the expected `.flex { display: flex }` rule.
166
+ minimal end-to-end demonstration, including `scripts/check-utility-css.ts`
167
+ which greps the built CSS asset for the expected `.flex{display:flex}` rule
168
+ a useful pattern to copy into your own project's CI.
69
169
 
70
170
  ### Local development
71
171
 
@@ -93,7 +193,7 @@ npm install @aihu/css-engine
93
193
  bun add @aihu/css-engine
94
194
  ```
95
195
 
96
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
196
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
97
197
 
98
198
  <!-- END_AUTOGEN: install -->
99
199
 
@@ -104,12 +204,12 @@ bun add @aihu/css-engine
104
204
 
105
205
  | | |
106
206
  |---|---|
107
- | **Version** | `0.2.4` |
207
+ | **Version** | `0.2.5` |
108
208
  | **Tier** | D — Compiler — CSS engine (Tailwind v4 hard fork, WC-native scoped output) |
109
209
  | **Published files** | 5 entries |
110
210
  | **License** | MIT |
111
211
 
112
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
212
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
113
213
 
114
214
  <!-- END_AUTOGEN: stats -->
115
215
 
@@ -128,7 +228,7 @@ bun add @aihu/css-engine
128
228
  | `./runtime/cn` | `./dist/runtime/cn.js` | `—` |
129
229
  | `./runtime/progressive` | `./dist/runtime/progressive.js` | `—` |
130
230
 
131
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
231
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
132
232
 
133
233
  <!-- END_AUTOGEN: exports -->
134
234
 
@@ -139,7 +239,7 @@ bun add @aihu/css-engine
139
239
 
140
240
  **Dependencies:**
141
241
 
142
- - `@aihu/compiler` — `workspace:*`
242
+ - `@aihu/compiler` — `workspace:^`
143
243
 
144
244
  **Optional dependencies (platform-specific):**
145
245
 
@@ -148,7 +248,7 @@ bun add @aihu/css-engine
148
248
  - `@aihu/css-engine-linux-x64-gnu` — `0.1.2`
149
249
  - `@aihu/css-engine-win32-x64-msvc` — `0.1.2`
150
250
 
151
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
251
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
152
252
 
153
253
  <!-- END_AUTOGEN: deps -->
154
254
 
@@ -161,7 +261,7 @@ bun add @aihu/css-engine
161
261
  - [@aihu/compiler](../compiler)
162
262
  - [Aihu framework root](../../README.md)
163
263
 
164
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
264
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
165
265
 
166
266
  <!-- END_AUTOGEN: see-also -->
167
267
 
@@ -172,6 +272,6 @@ bun add @aihu/css-engine
172
272
 
173
273
  MIT — see [LICENSE](../../LICENSE).
174
274
 
175
- <sub><i>Auto-generated against `@aihu/css-engine@0.2.4`.</i></sub>
275
+ <sub><i>Auto-generated against `@aihu/css-engine@0.2.5`.</i></sub>
176
276
 
177
277
  <!-- END_AUTOGEN: license -->
package/dist/index.js CHANGED
@@ -2,25 +2,9 @@ import { t as defineStylePack } from "./define-style-pack--6pevgrd.js";
2
2
  import { execFileSync } from "node:child_process";
3
3
  import { accessSync, constants, existsSync, statSync } from "node:fs";
4
4
  import { createRequire } from "node:module";
5
- import { basename, dirname, join, resolve } from "node:path";
5
+ import { dirname, join, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- //#region ../compiler/dist/index.js
8
- const a = process.platform === `win32` ? `.exe` : ``, o = process.env.SCRIBE_COMPILE_BIN ?? resolve(dirname(fileURLToPath(import.meta.url)), `../bin/aihu-compile${a}`);
9
- function g(n, r) {
10
- let i = [
11
- `--stdin`,
12
- `--tag`,
13
- r ? basename(r, `.aihu`) : `Component`,
14
- `--ast-json`
15
- ];
16
- r && i.push(`--path`, r);
17
- let a = execFileSync(o, i, {
18
- input: n,
19
- encoding: `utf8`
20
- });
21
- return JSON.parse(a);
22
- }
23
- //#endregion
7
+ import { compileToAst } from "@aihu/compiler";
24
8
  //#region src/index.ts
25
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
26
10
  function detectPlatform() {
@@ -156,7 +140,7 @@ function compile(classes) {
156
140
  * @returns the scoped CSS string for the SFC
157
141
  */
158
142
  function compileSfc(source, id) {
159
- const ast = g(source, id);
143
+ const ast = compileToAst(source, id);
160
144
  return execFileSync(resolveBinary(), ["--ast-json"], {
161
145
  input: JSON.stringify(ast),
162
146
  encoding: "utf-8",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["r","n","i","t","e","compileToAst"],"sources":["../../compiler/dist/index.js","../src/index.ts"],"sourcesContent":["import{execFileSync as e}from\"node:child_process\";import{basename as t,dirname as n,resolve as r}from\"node:path\";import{fileURLToPath as i}from\"node:url\";const a=process.platform===`win32`?`.exe`:``,o=process.env.SCRIBE_COMPILE_BIN??r(n(i(import.meta.url)),`../bin/aihu-compile${a}`);function s(e,t){return e.replace(/(defineElement\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*defineComponent\\([^]*\\))\\s*\\)/,(e,n)=>`${n}, { shadowMode: '${t}' })`)}function c(e){return/\\b(?:signal|computed|effect|setSignal|onMount|onCleanup)\\s*\\(/.test(e)?`interactive`:`static`}function l(e){let t=/defineElement\\(\\s*['\"]([^'\"]+)['\"]/m.exec(e);return t?t[1]??null:null}function u(e,t){let n=e.replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/runtime'/,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`_hmrReplace`)||n.push(`_hmrReplace`),`import { ${n.join(`, `)} } from '@aihu/runtime'`}).replace(/\\bdefineComponent\\(/,`defineComponent(__aihu_setup__ = `),r=`\nexport { __aihu_setup__ as default }\n\nif (typeof __DEV__ !== 'undefined' && __DEV__ && import.meta.hot) {\n import.meta.hot.accept((newModule) => {\n if (!newModule) return\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const newSetup = (newModule as any)['default']\n if (typeof newSetup !== 'function') return\n document.querySelectorAll(${JSON.stringify(t)}).forEach((el) => {\n _hmrReplace(el as HTMLElement, newSetup)\n })\n })\n}\n`;return`let __aihu_setup__: ((ctx: any) => any) | undefined\n`+n+r}function d(e,t){let n=e.replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/runtime'/,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`_hydrateOnVisible`)||n.push(`_hydrateOnVisible`),`import { ${n.join(`, `)} } from '@aihu/runtime'`}),r=n.replace(/defineElement\\(\\s*('[^']+'|\"[^\"]+\")\\s*,\\s*defineComponent\\(/,(e,t)=>`defineElement(${t}, __aihu_wrap_defer__(defineComponent(`);if(r===n)return e;let i=r.replace(/\\)\\s*\\)\\s*\\nexport\\s/,`)))\nexport `);return i===r&&(i=r.replace(/\\)\\s*\\)\\s*$/,`)))\n`)),i===r?e:`\n// Plan 3.3 (Islands) — defer attribute support. Wraps the constructor\n// returned by defineComponent so instances bearing the \\`defer\\` attribute\n// hydrate lazily via IntersectionObserver. Bare instances retain the\n// eager Plan 3.2 hydration path.\nfunction __aihu_wrap_defer__<T extends typeof HTMLElement>(Ctor: T): T {\n const orig = (Ctor.prototype as unknown as { connectedCallback?: () => void }).connectedCallback\n if (typeof orig !== 'function') return Ctor\n ;(Ctor.prototype as unknown as { connectedCallback: () => void }).connectedCallback = function (this: HTMLElement) {\n if (this.hasAttribute('defer')) {\n _hydrateOnVisible(this, () => orig.call(this))\n } else {\n orig.call(this)\n }\n }\n return Ctor\n}\n`+i}function f(e,t){if(!/defineElement\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*defineComponent\\(/.test(e))return e;let n=e.replace(/^\\s*import\\s*\\{[^}]*\\}\\s*from\\s*'@aihu\\/runtime'\\s*;?\\s*$/m,``).replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/arbor'/,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`mount`)||n.push(`mount`),`import { ${n.join(`, `)} } from '@aihu/arbor'`}),r=JSON.stringify(t);return`// SCRIBE_STATIC_ISLAND — zero @aihu/runtime references\\n${n.replace(/defineElement\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*defineComponent\\(/,`customElements.define(${r}, class extends HTMLElement {\\n connectedCallback() {\\n const root = this.attachShadow({ mode: 'open' })\\n const __aihu_setup__ = (`).replace(/\\)\\s*\\)\\s*$/,`)\n mount(__aihu_setup__({ host: root, element: this }), root)\n }\n})\n`)}`}function p(n,r,i){let a=[`--stdin`,`--tag`,t(r,`.aihu`),`--path`,r];return i?.sidecarOut&&a.push(`--sidecar-out`,i.sidecarOut),{code:e(o,a,{input:n,encoding:`utf8`}),map:null}}function m(e){return e.replace(/\\\\/g,`\\\\\\\\`).replace(/`/g,\"\\\\`\").replace(/\\$\\{/g,\"\\\\${\")}function h(e,t){if(!t.trim())return e;let n=m(t),r=/(__style__\\.replaceSync\\(`)[^]*?(`\\);)/;if(r.test(e))return e.replace(r,(e,t,r)=>`${t}${n}${r}`);if(/defineComponent\\(\\s*\\((_ctx|ctx)\\)\\s*=>\\s*\\{/.exec(e)==null)return e;let i=e.split(`\n`),a=-1;for(let e=i.length-1;e>=0;e--){let t=(i[e]??``).trim();if(t.startsWith(`import `)||t.startsWith(`import{`)){a=e;break}}let o=`const __style__ = new CSSStyleSheet();\\n__style__.replaceSync(\\`${n}\\`);`;a===-1?i.unshift(o):i.splice(a+1,0,o);let s=i.join(`\n`);return s=s.replace(/defineComponent\\(\\s*\\((?:_ctx|ctx)\\)\\s*=>\\s*\\{/,`defineComponent((ctx) => {\n (ctx.host as ShadowRoot).adoptedStyleSheets = [__style__];`),s}function g(n,r){let i=[`--stdin`,`--tag`,r?t(r,`.aihu`):`Component`,`--ast-json`];r&&i.push(`--path`,r);let a=e(o,i,{input:n,encoding:`utf8`});return JSON.parse(a)}function _(e){let t;t=e.includes(`from '@aihu/arbor'`)?e.replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/arbor'/,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`mount`)||n.push(`mount`),`import { ${n.join(`, `)} } from '@aihu/arbor'`}):`import { mount } from '@aihu/arbor'\\n${e}`,/import\\s+\\{[^}]*\\}\\s+from\\s+'@aihu\\/signals'/.test(t)?t=t.replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/signals'/,(e,t)=>{if(e.startsWith(`import type`))return e;let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`signal`)||n.push(`signal`),`import { ${n.join(`, `)} } from '@aihu/signals'`}):/import.*from\\s*'@aihu\\/signals'/.test(t)?/import\\s+type\\s+\\{[^}]*\\}\\s+from\\s+'@aihu\\/signals'/.test(t)&&!t.match(/import\\s+\\{[^}]*\\}\\s+from\\s+'@aihu\\/signals'/)&&(t=t.replace(/(import\\s+type\\s+\\{[^}]*\\}\\s+from\\s+'@aihu\\/signals')/,(e,t)=>`${t}\\nimport { signal } from '@aihu/signals'`)):t=t.replace(/import\\s*\\{[^}]*\\}\\s*from\\s*'@aihu\\/arbor'/,e=>`${e}\\nimport { signal } from '@aihu/signals'`),t=t.replace(/import\\s*\\{([^}]*)\\}\\s*from\\s*'@aihu\\/runtime'/,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.includes(`_setMount`)||n.push(`_setMount`),n.includes(`_setSignal`)||n.push(`_setSignal`),`import { ${n.join(`, `)} } from '@aihu/runtime'`});let n=t.split(`\n`),r=-1;for(let e=n.length-1;e>=0;e--){let t=(n[e]??``).trim();if(t.startsWith(`import `)||t.startsWith(`import{`)){r=e;break}}return r!==-1&&(n.splice(r+1,0,`_setMount(mount)`,`_setSignal(signal)`,``),t=n.join(`\n`)),t}let v,y=!1;async function b(e,t){if(v===null)return``;if(v===void 0)try{v=await import(`@aihu/css-engine`)}catch{return v=null,``}try{return process.env.SCRIBE_COMPILE_BIN??(process.env.SCRIBE_COMPILE_BIN=o),v.compileSfc(e,t)}catch(e){if(!y){y=!0;let t=e instanceof Error?e.message:String(e);console.warn(`[@aihu/compiler] @aihu/css-engine is installed but compileSfc() failed; utility classes will not emit. Original error: ${t}\\nHint: ensure the native css-core binary is installed (install/upgrade @aihu/css-engine + its per-platform optional dep, or run \\`cargo build --release -p aihu-css-core\\` in a dev clone).`)}return``}}function x(e){let t=e?.islands!==!1,n=e?.shadowMode;return{name:`aihu-compiler`,enforce:`pre`,transform(e,r){let i=r.split(`?`)[0];if(i.endsWith(`.aihu`))return(async()=>{let r=p(e,i,{sidecarOut:`${i}.ts`}),a=n==null?r.code:s(r.code,n),o=await b(e,i);o&&(a=h(a,o));let m=l(a),g;t&&m!==null&&c(a)===`static`?g=f(a,m):m===null?(g=a,g=_(g)):(g=u(a,m),g=d(g,m),g=_(g));try{let e=await import(`vite`);return`transformWithEsbuild`in e&&typeof e.transformWithEsbuild==`function`?{code:(await e.transformWithEsbuild(g,`component.ts`,{target:`esnext`,sourcemap:!1})).code,map:null}:{code:g,moduleType:`ts`,map:null}}catch{return{code:g,map:null}}})()}}}export{d as _buildDeferredHydration,f as _buildStaticIsland,c as _classifyIsland,h as _foldCssEngineStyles,_ as _injectAutoWiring,s as _injectShadowMode,x as aihuCompilerPlugin,g as compileToAst,p as transform};\n//# sourceMappingURL=index.js.map","import { execFileSync } from 'node:child_process'\nimport { accessSync, constants, existsSync, statSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { compileToAst } from '@aihu/compiler'\n\nexport {\n defineStylePack,\n type StylePack,\n type StylePackInput,\n type TokenMap,\n} from './define-style-pack.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n// ---------------------------------------------------------------------------\n// Platform support matrix\n// ---------------------------------------------------------------------------\n//\n// Maps process.platform + process.arch to the per-platform npm package that\n// ships the prebuilt `aihu-css-compile` executable, plus the binary's filename\n// inside that package. Mirrors @aihu/server/src/native.ts detectPlatform() and\n// the package directory names under packages/css-engine/npm/<platform>/.\n//\n// Unlike @aihu/server (a napi `.node` addon loaded via require), the css engine\n// invokes `aihu-css-compile` as a CLI SUBPROCESS (execFileSync against the\n// executable on disk). So the platform package exposes a raw executable file,\n// and we resolve its absolute PATH — we never `require()` the binary itself.\n\ninterface PlatformDescriptor {\n readonly platformId: string\n readonly packageName: string\n /** Executable filename inside the platform package. */\n readonly binFile: string\n}\n\nfunction detectPlatform(): PlatformDescriptor | null {\n if (typeof process === 'undefined' || !process.platform || !process.arch) {\n return null\n }\n const key = `${process.platform}-${process.arch}`\n switch (key) {\n case 'darwin-arm64':\n return {\n platformId: 'darwin-arm64',\n packageName: '@aihu/css-engine-darwin-arm64',\n binFile: 'aihu-css-compile',\n }\n case 'darwin-x64':\n return {\n platformId: 'darwin-x64',\n packageName: '@aihu/css-engine-darwin-x64',\n binFile: 'aihu-css-compile',\n }\n case 'linux-x64':\n // We only ship glibc; musl users fall through to the dev/source path.\n return {\n platformId: 'linux-x64-gnu',\n packageName: '@aihu/css-engine-linux-x64-gnu',\n binFile: 'aihu-css-compile',\n }\n case 'win32-x64':\n return {\n platformId: 'win32-x64-msvc',\n packageName: '@aihu/css-engine-win32-x64-msvc',\n binFile: 'aihu-css-compile.exe',\n }\n default:\n return null\n }\n}\n\nlet _binPath: string | null = null\n\n/**\n * Whether `candidate` is a usable `aihu-css-compile` executable — NOT merely a\n * present file.\n *\n * The per-platform packages (`@aihu/css-engine-<platform>`) carry a placeholder\n * `aihu-css-compile` in source; the real prebuilt binary is only injected by\n * the release CI. Once those packages become resolvable in the workspace (e.g.\n * after a `bun.lock` refresh that pins them as optionalDependencies), a bare\n * `existsSync` would happily return the non-executable placeholder, which then\n * blows up with EACCES inside `spawnSync`/`execFileSync`. So we must verify the\n * candidate is actually runnable before accepting it.\n *\n * POSIX: require the execute bit (X_OK). A zero-byte/text placeholder without\n * +x fails here and we fall through to the dev `target/` fallback.\n *\n * Windows: there is no execute bit — `accessSync(_, X_OK)` is effectively\n * always true — so we additionally require a non-empty regular file, which\n * still rejects a zero-byte placeholder.\n */\nexport function isUsableExecutable(candidate: string): boolean {\n try {\n const st = statSync(candidate)\n if (!st.isFile() || st.size === 0) return false\n accessSync(candidate, constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Resolve the absolute path to the `aihu-css-compile` executable.\n *\n * Resolution order:\n * 1. The per-platform optionalDependency package\n * (`@aihu/css-engine-<platform>`) shipped to npm consumers — resolved via\n * `createRequire(...).resolve('<pkg>/package.json')` so it works in both\n * ESM and CJS and respects the consumer's node_modules layout.\n * 2. Dev fallback: the monorepo workspace `target/release|debug/` — only\n * present in a dev clone with a Rust toolchain (`cargo build --release -p\n * aihu-css-core`). Kept so in-repo builds + tests work without publishing.\n *\n * If the current platform is SUPPORTED but neither path yields a binary, throws\n * a structured error pointing at the missing optionalDependency (mirrors\n * @aihu/server's failure-loud contract). If the platform is UNSUPPORTED, the\n * error lists the dev fallback so source builds still have a clear remedy.\n */\nfunction resolveBinary(): string {\n if (_binPath !== null) return _binPath\n\n const descriptor = detectPlatform()\n\n // 1. Per-platform optionalDependency package (the published-consumer path).\n //\n // Accept the candidate ONLY if it is a usable executable. A present-but-\n // non-executable placeholder (the in-source stub that becomes resolvable once\n // the per-platform packages are pinned in the lockfile) must NOT be returned —\n // doing so spawns a non-executable file and fails with EACCES. In that case we\n // deliberately fall THROUGH to the dev `target/` fallback below.\n if (descriptor) {\n const requireFn = createRequire(import.meta.url)\n try {\n const pkgJson = requireFn.resolve(`${descriptor.packageName}/package.json`)\n const candidate = join(dirname(pkgJson), descriptor.binFile)\n if (isUsableExecutable(candidate)) {\n _binPath = candidate\n return _binPath\n }\n } catch {\n // Package not installed (optionalDependency skipped for this platform, or\n // a partial install). Fall through to the dev/source path, then error.\n }\n }\n\n // 2. Dev fallback: monorepo workspace target/. Only exists in a dev clone.\n const ext = process.platform === 'win32' ? '.exe' : ''\n const devCandidates = [\n resolve(__dirname, '../../../target/release', `aihu-css-compile${ext}`),\n resolve(__dirname, '../../../target/debug', `aihu-css-compile${ext}`),\n ]\n for (const c of devCandidates) {\n if (existsSync(c)) {\n _binPath = c\n return _binPath\n }\n }\n\n throw buildMissingBinaryError(descriptor, devCandidates)\n}\n\nfunction buildMissingBinaryError(\n descriptor: PlatformDescriptor | null,\n devCandidates: string[],\n): Error {\n if (descriptor === null) {\n return new Error(\n `[@aihu/css-engine] No prebuilt aihu-css-compile binary for this platform.\\n\\n` +\n ` Platform: ${typeof process !== 'undefined' ? `${process.platform}-${process.arch}` : 'unknown'}\\n\\n` +\n ` @aihu/css-engine ships prebuilt binaries for darwin-arm64, darwin-x64,\\n` +\n ` linux-x64-gnu (glibc) and win32-x64-msvc. Your platform is not in that set.\\n\\n` +\n ` To build from source you need a Rust toolchain, then run from the repo root:\\n` +\n ` cargo build --release -p aihu-css-core\\n\\n` +\n ` Checked dev fallback paths: ${devCandidates.join(', ')}`,\n )\n }\n return new Error(\n `[@aihu/css-engine] Native CSS compiler binary not found for this platform.\\n\\n` +\n ` Platform: ${descriptor.platformId}\\n` +\n ` Expected package: ${descriptor.packageName}\\n` +\n ` Expected file: ${descriptor.packageName}/${descriptor.binFile}\\n\\n` +\n ` This binary is distributed as an optionalDependency of @aihu/css-engine.\\n` +\n ` Your package manager may have skipped it (optionalDependencies are\\n` +\n ` silently dropped on install failure).\\n\\n` +\n ` To reinstall:\\n` +\n ` npm install @aihu/css-engine\\n` +\n ` # or: pnpm install or: bun install\\n\\n` +\n ` If you are working in the aihu monorepo, build from source instead:\\n` +\n ` cargo build --release -p aihu-css-core\\n` +\n ` Checked dev fallback paths: ${devCandidates.join(', ')}`,\n )\n}\n\n/**\n * Compile a list of utility class names to CSS.\n *\n * Plan 1 bootstrap — supports a hardcoded subset; see crates/aihu-css-core/src/tokens.rs.\n * Plan 2 wires the AST scanner so callers pass `.aihu` SFC ASTs instead of raw class lists.\n *\n * @param classes - utility class names like `['bg-primary', 'p-4']`\n * @returns CSS string with one rule per known class\n */\nexport function compile(classes: string[]): string {\n if (classes.length === 0) return ''\n\n const bin = resolveBinary()\n const input = classes.join('\\n')\n const result = execFileSync(bin, [], {\n input,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'inherit'],\n })\n return result\n}\n\n/**\n * Compile a `.aihu` SFC source string to scoped, shadow-DOM-embedded CSS.\n *\n * Pipeline (Plan 2 Task 9): `compileToAst(source)` (from `@aihu/compiler`)\n * → AST JSON → `aihu-css-compile --ast-json` → scoped CSS. The output is the\n * per-SFC stylesheet the compiler folds into the component's shadow `<style>`:\n * `:host`-level theme tokens, variant-resolved utility rules, and the folded\n * authored `@style` block. There is NO global utility stylesheet.\n *\n * @param source - the `.aihu` SFC source text\n * @param id - optional file path/id (used to derive the tag stem + `@route` checks)\n * @returns the scoped CSS string for the SFC\n */\nexport function compileSfc(source: string, id?: string): string {\n const ast = compileToAst(source, id)\n const bin = resolveBinary()\n return execFileSync(bin, ['--ast-json'], {\n input: JSON.stringify(ast),\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'inherit'],\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process'\nimport { accessSync, constants, existsSync, statSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { compileToAst } from '@aihu/compiler'\n\nexport {\n defineStylePack,\n type StylePack,\n type StylePackInput,\n type TokenMap,\n} from './define-style-pack.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n// ---------------------------------------------------------------------------\n// Platform support matrix\n// ---------------------------------------------------------------------------\n//\n// Maps process.platform + process.arch to the per-platform npm package that\n// ships the prebuilt `aihu-css-compile` executable, plus the binary's filename\n// inside that package. Mirrors @aihu/server/src/native.ts detectPlatform() and\n// the package directory names under packages/css-engine/npm/<platform>/.\n//\n// Unlike @aihu/server (a napi `.node` addon loaded via require), the css engine\n// invokes `aihu-css-compile` as a CLI SUBPROCESS (execFileSync against the\n// executable on disk). So the platform package exposes a raw executable file,\n// and we resolve its absolute PATH — we never `require()` the binary itself.\n\ninterface PlatformDescriptor {\n readonly platformId: string\n readonly packageName: string\n /** Executable filename inside the platform package. */\n readonly binFile: string\n}\n\nfunction detectPlatform(): PlatformDescriptor | null {\n if (typeof process === 'undefined' || !process.platform || !process.arch) {\n return null\n }\n const key = `${process.platform}-${process.arch}`\n switch (key) {\n case 'darwin-arm64':\n return {\n platformId: 'darwin-arm64',\n packageName: '@aihu/css-engine-darwin-arm64',\n binFile: 'aihu-css-compile',\n }\n case 'darwin-x64':\n return {\n platformId: 'darwin-x64',\n packageName: '@aihu/css-engine-darwin-x64',\n binFile: 'aihu-css-compile',\n }\n case 'linux-x64':\n // We only ship glibc; musl users fall through to the dev/source path.\n return {\n platformId: 'linux-x64-gnu',\n packageName: '@aihu/css-engine-linux-x64-gnu',\n binFile: 'aihu-css-compile',\n }\n case 'win32-x64':\n return {\n platformId: 'win32-x64-msvc',\n packageName: '@aihu/css-engine-win32-x64-msvc',\n binFile: 'aihu-css-compile.exe',\n }\n default:\n return null\n }\n}\n\nlet _binPath: string | null = null\n\n/**\n * Whether `candidate` is a usable `aihu-css-compile` executable — NOT merely a\n * present file.\n *\n * The per-platform packages (`@aihu/css-engine-<platform>`) carry a placeholder\n * `aihu-css-compile` in source; the real prebuilt binary is only injected by\n * the release CI. Once those packages become resolvable in the workspace (e.g.\n * after a `bun.lock` refresh that pins them as optionalDependencies), a bare\n * `existsSync` would happily return the non-executable placeholder, which then\n * blows up with EACCES inside `spawnSync`/`execFileSync`. So we must verify the\n * candidate is actually runnable before accepting it.\n *\n * POSIX: require the execute bit (X_OK). A zero-byte/text placeholder without\n * +x fails here and we fall through to the dev `target/` fallback.\n *\n * Windows: there is no execute bit — `accessSync(_, X_OK)` is effectively\n * always true — so we additionally require a non-empty regular file, which\n * still rejects a zero-byte placeholder.\n */\nexport function isUsableExecutable(candidate: string): boolean {\n try {\n const st = statSync(candidate)\n if (!st.isFile() || st.size === 0) return false\n accessSync(candidate, constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Resolve the absolute path to the `aihu-css-compile` executable.\n *\n * Resolution order:\n * 1. The per-platform optionalDependency package\n * (`@aihu/css-engine-<platform>`) shipped to npm consumers — resolved via\n * `createRequire(...).resolve('<pkg>/package.json')` so it works in both\n * ESM and CJS and respects the consumer's node_modules layout.\n * 2. Dev fallback: the monorepo workspace `target/release|debug/` — only\n * present in a dev clone with a Rust toolchain (`cargo build --release -p\n * aihu-css-core`). Kept so in-repo builds + tests work without publishing.\n *\n * If the current platform is SUPPORTED but neither path yields a binary, throws\n * a structured error pointing at the missing optionalDependency (mirrors\n * @aihu/server's failure-loud contract). If the platform is UNSUPPORTED, the\n * error lists the dev fallback so source builds still have a clear remedy.\n */\nfunction resolveBinary(): string {\n if (_binPath !== null) return _binPath\n\n const descriptor = detectPlatform()\n\n // 1. Per-platform optionalDependency package (the published-consumer path).\n //\n // Accept the candidate ONLY if it is a usable executable. A present-but-\n // non-executable placeholder (the in-source stub that becomes resolvable once\n // the per-platform packages are pinned in the lockfile) must NOT be returned —\n // doing so spawns a non-executable file and fails with EACCES. In that case we\n // deliberately fall THROUGH to the dev `target/` fallback below.\n if (descriptor) {\n const requireFn = createRequire(import.meta.url)\n try {\n const pkgJson = requireFn.resolve(`${descriptor.packageName}/package.json`)\n const candidate = join(dirname(pkgJson), descriptor.binFile)\n if (isUsableExecutable(candidate)) {\n _binPath = candidate\n return _binPath\n }\n } catch {\n // Package not installed (optionalDependency skipped for this platform, or\n // a partial install). Fall through to the dev/source path, then error.\n }\n }\n\n // 2. Dev fallback: monorepo workspace target/. Only exists in a dev clone.\n const ext = process.platform === 'win32' ? '.exe' : ''\n const devCandidates = [\n resolve(__dirname, '../../../target/release', `aihu-css-compile${ext}`),\n resolve(__dirname, '../../../target/debug', `aihu-css-compile${ext}`),\n ]\n for (const c of devCandidates) {\n if (existsSync(c)) {\n _binPath = c\n return _binPath\n }\n }\n\n throw buildMissingBinaryError(descriptor, devCandidates)\n}\n\nfunction buildMissingBinaryError(\n descriptor: PlatformDescriptor | null,\n devCandidates: string[],\n): Error {\n if (descriptor === null) {\n return new Error(\n `[@aihu/css-engine] No prebuilt aihu-css-compile binary for this platform.\\n\\n` +\n ` Platform: ${typeof process !== 'undefined' ? `${process.platform}-${process.arch}` : 'unknown'}\\n\\n` +\n ` @aihu/css-engine ships prebuilt binaries for darwin-arm64, darwin-x64,\\n` +\n ` linux-x64-gnu (glibc) and win32-x64-msvc. Your platform is not in that set.\\n\\n` +\n ` To build from source you need a Rust toolchain, then run from the repo root:\\n` +\n ` cargo build --release -p aihu-css-core\\n\\n` +\n ` Checked dev fallback paths: ${devCandidates.join(', ')}`,\n )\n }\n return new Error(\n `[@aihu/css-engine] Native CSS compiler binary not found for this platform.\\n\\n` +\n ` Platform: ${descriptor.platformId}\\n` +\n ` Expected package: ${descriptor.packageName}\\n` +\n ` Expected file: ${descriptor.packageName}/${descriptor.binFile}\\n\\n` +\n ` This binary is distributed as an optionalDependency of @aihu/css-engine.\\n` +\n ` Your package manager may have skipped it (optionalDependencies are\\n` +\n ` silently dropped on install failure).\\n\\n` +\n ` To reinstall:\\n` +\n ` npm install @aihu/css-engine\\n` +\n ` # or: pnpm install or: bun install\\n\\n` +\n ` If you are working in the aihu monorepo, build from source instead:\\n` +\n ` cargo build --release -p aihu-css-core\\n` +\n ` Checked dev fallback paths: ${devCandidates.join(', ')}`,\n )\n}\n\n/**\n * Compile a list of utility class names to CSS.\n *\n * Plan 1 bootstrap — supports a hardcoded subset; see crates/aihu-css-core/src/tokens.rs.\n * Plan 2 wires the AST scanner so callers pass `.aihu` SFC ASTs instead of raw class lists.\n *\n * @param classes - utility class names like `['bg-primary', 'p-4']`\n * @returns CSS string with one rule per known class\n */\nexport function compile(classes: string[]): string {\n if (classes.length === 0) return ''\n\n const bin = resolveBinary()\n const input = classes.join('\\n')\n const result = execFileSync(bin, [], {\n input,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'inherit'],\n })\n return result\n}\n\n/**\n * Compile a `.aihu` SFC source string to scoped, shadow-DOM-embedded CSS.\n *\n * Pipeline (Plan 2 Task 9): `compileToAst(source)` (from `@aihu/compiler`)\n * → AST JSON → `aihu-css-compile --ast-json` → scoped CSS. The output is the\n * per-SFC stylesheet the compiler folds into the component's shadow `<style>`:\n * `:host`-level theme tokens, variant-resolved utility rules, and the folded\n * authored `@style` block. There is NO global utility stylesheet.\n *\n * @param source - the `.aihu` SFC source text\n * @param id - optional file path/id (used to derive the tag stem + `@route` checks)\n * @returns the scoped CSS string for the SFC\n */\nexport function compileSfc(source: string, id?: string): string {\n const ast = compileToAst(source, id)\n const bin = resolveBinary()\n return execFileSync(bin, ['--ast-json'], {\n input: JSON.stringify(ast),\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'inherit'],\n })\n}\n"],"mappings":";;;;;;;;AAcA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAuBzD,SAAS,iBAA4C;CACnD,IAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,YAAY,CAAC,QAAQ,MAClE,OAAO;CAGT,QAAQ,GADO,QAAQ,SAAS,GAAG,QAAQ,QAC3C;EACE,KAAK,gBACH,OAAO;GACL,YAAY;GACZ,aAAa;GACb,SAAS;GACV;EACH,KAAK,cACH,OAAO;GACL,YAAY;GACZ,aAAa;GACb,SAAS;GACV;EACH,KAAK,aAEH,OAAO;GACL,YAAY;GACZ,aAAa;GACb,SAAS;GACV;EACH,KAAK,aACH,OAAO;GACL,YAAY;GACZ,aAAa;GACb,SAAS;GACV;EACH,SACE,OAAO;;;AAIb,IAAI,WAA0B;;;;;;;;;;;;;;;;;;;;AAqB9B,SAAgB,mBAAmB,WAA4B;CAC7D,IAAI;EACF,MAAM,KAAK,SAAS,UAAU;EAC9B,IAAI,CAAC,GAAG,QAAQ,IAAI,GAAG,SAAS,GAAG,OAAO;EAC1C,WAAW,WAAW,UAAU,KAAK;EACrC,OAAO;SACD;EACN,OAAO;;;;;;;;;;;;;;;;;;;;AAqBX,SAAS,gBAAwB;CAC/B,IAAI,aAAa,MAAM,OAAO;CAE9B,MAAM,aAAa,gBAAgB;CASnC,IAAI,YAAY;EACd,MAAM,YAAY,cAAc,OAAO,KAAK,IAAI;EAChD,IAAI;GAEF,MAAM,YAAY,KAAK,QADP,UAAU,QAAQ,GAAG,WAAW,YAAY,eACtB,CAAC,EAAE,WAAW,QAAQ;GAC5D,IAAI,mBAAmB,UAAU,EAAE;IACjC,WAAW;IACX,OAAO;;UAEH;;CAOV,MAAM,MAAM,QAAQ,aAAa,UAAU,SAAS;CACpD,MAAM,gBAAgB,CACpB,QAAQ,WAAW,2BAA2B,mBAAmB,MAAM,EACvE,QAAQ,WAAW,yBAAyB,mBAAmB,MAAM,CACtE;CACD,KAAK,MAAM,KAAK,eACd,IAAI,WAAW,EAAE,EAAE;EACjB,WAAW;EACX,OAAO;;CAIX,MAAM,wBAAwB,YAAY,cAAc;;AAG1D,SAAS,wBACP,YACA,eACO;CACP,IAAI,eAAe,MACjB,uBAAO,IAAI,MACT,mGACwB,OAAO,YAAY,cAAc,GAAG,QAAQ,SAAS,GAAG,QAAQ,SAAS,UAAU,6TAKxE,cAAc,KAAK,KAAK,GAC5D;CAEH,uBAAO,IAAI,MACT,qGACyB,WAAW,WAAW,wBACtB,WAAW,YAAY,wBACvB,WAAW,YAAY,GAAG,WAAW,QAAQ,mbASnC,cAAc,KAAK,KAAK,GAC5D;;;;;;;;;;;AAYH,SAAgB,QAAQ,SAA2B;CACjD,IAAI,QAAQ,WAAW,GAAG,OAAO;CASjC,OALe,aAFH,eAEmB,EAAE,EAAE,EAAE;EACnC,OAFY,QAAQ,KAAK,KAEpB;EACL,UAAU;EACV,OAAO;GAAC;GAAQ;GAAQ;GAAU;EACnC,CACY;;;;;;;;;;;;;;;AAgBf,SAAgB,WAAW,QAAgB,IAAqB;CAC9D,MAAM,MAAM,aAAa,QAAQ,GAAG;CAEpC,OAAO,aADK,eACW,EAAE,CAAC,aAAa,EAAE;EACvC,OAAO,KAAK,UAAU,IAAI;EAC1B,UAAU;EACV,OAAO;GAAC;GAAQ;GAAQ;GAAU;EACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aihu/css-engine",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  ],
38
38
  "sideEffects": false,
39
39
  "dependencies": {
40
- "@aihu/compiler": "0.5.3"
40
+ "@aihu/compiler": "^0.5.4"
41
41
  },
42
42
  "optionalDependencies": {
43
43
  "@aihu/css-engine-darwin-arm64": "0.1.2",