@animus-ui/vite-plugin 0.1.38 → 0.1.39

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
@@ -23,6 +23,8 @@ export default defineConfig({
23
23
 
24
24
  The `system` option points to the file that exports your built system instance. The plugin loads this file in a subprocess to serialize the prop config and theme data for the Rust extraction pipeline.
25
25
 
26
+ TypeScript apps get the plugin's virtual modules (`virtual:animus/styles.css`, `virtual:animus/font-preloads`) typed with `/// <reference types="@animus-ui/vite-plugin/client" />` or `"types": ["@animus-ui/vite-plugin/client"]` in `tsconfig.json`.
27
+
26
28
  ## What It Does
27
29
 
28
30
  1. **Build time**: Analyzes all files importing from `@animus-ui/system`, extracts static styles into CSS with `@layer` ordering
@@ -137,6 +139,38 @@ file can delay first paint by seconds on a slow link. A preloaded file that
137
139
  is not WOFF2 or WOFF, or an `asset()` file over 150 KB, reports
138
140
  `animus.style.font-face-preload-costly`.
139
141
 
142
+ ## Split stylesheets
143
+
144
+ `stylesheets: 'split'` builds the stylesheet as three files instead of one,
145
+ each a consecutive slice of the single sheet, in its order:
146
+
147
+ 1. foundation: theme variables and color modes, `@property` registrations,
148
+ and `anm-global` (resets, `@font-face`, keyframes), with any
149
+ `quarantine` sheets;
150
+ 2. components: `anm-base`, `anm-variants`, `anm-compounds`, `anm-states`;
151
+ 3. utilities: `anm-system`, `anm-custom`.
152
+
153
+ Each page links them in that order exactly where Vite places the single sheet
154
+ among the app's own CSS, as ordinary render-blocking stylesheets: app CSS
155
+ bundled with it keeps its place before or after the three files. They hold
156
+ the single sheet's rules in its order, so the cascade is unchanged; Vite
157
+ minifies each file on its own, which leaves its bytes the same apart from
158
+ the newline ending each file. Their URLs are the ones Vite gives its own
159
+ links, through `base` and `experimental.renderBuiltUrl`.
160
+ Each file is named by its content, so a browser keeps its cached copy of a
161
+ file an edit leaves alone: an edit to a component's styles changes only the
162
+ components file. The three files compress slightly worse than one (about
163
+ 0.1% more gzip on a large app).
164
+
165
+ ```ts
166
+ animusExtract({ system: './src/ds.ts', stylesheets: 'split' });
167
+ ```
168
+
169
+ A split build needs a page Vite builds from HTML that links the stylesheet,
170
+ which is where the links go: one with no page, or whose stylesheet only a lazy
171
+ chunk loads, fails. The dev server keeps one sheet. `'single'` (the default)
172
+ is one sheet the bundle imports.
173
+
140
174
  ## Third-party stylesheets
141
175
 
142
176
  A library's plain CSS outside any `@layer` beats every Animus layer. With
package/client.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ // The modules @animus-ui/vite-plugin serves to app code. Reference them with
2
+ // `/// <reference types="@animus-ui/vite-plugin/client" />`, or with
3
+ // `"types": ["@animus-ui/vite-plugin/client"]` in tsconfig.json. Free of the
4
+ // plugin's own (Node) types, so a browser tsconfig needs nothing more.
5
+
6
+ /** Animus's stylesheet: import it once, from the app's entry. */
7
+ declare module 'virtual:animus/styles.css' {}
8
+
9
+ /** Each font file this build preloads, at the URL index.html preloads it,
10
+ * with the faces that preload it. */
11
+ declare module 'virtual:animus/font-preloads' {
12
+ /** A face that preloads a file: its family, as `fontPreloads` matches
13
+ * it, and the descriptors it declares. */
14
+ interface PreloadedFontFace {
15
+ family: string;
16
+ weight?: string;
17
+ style?: string;
18
+ unicodeRange?: string;
19
+ }
20
+ /** A preloaded font file: the plugin's `FontPreload`. */
21
+ interface FontPreload {
22
+ href: string;
23
+ /** The file's MIME type, where its format names a known one. */
24
+ type?: string;
25
+ faces?: PreloadedFontFace[];
26
+ }
27
+ const preloads: ReadonlyArray<FontPreload>;
28
+ export default preloads;
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,cAAc,GACrB,IAAI,CA+EN"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkFN"}
@@ -1,3 +1,4 @@
1
+ import type { StylesheetSlice } from '@animus-ui/extract/pipeline';
1
2
  /**
2
3
  * The namespace every virtual module here lives under; the `transform` guard
3
4
  * matches on this same string so a rename cannot strand it.
@@ -5,6 +6,18 @@
5
6
  export declare const VIRTUAL_PREFIX = "virtual:animus/";
6
7
  export declare const VIRTUAL_CSS_ID = "virtual:animus/styles.css";
7
8
  export declare const RESOLVED_CSS_ID = "\0virtual:animus/styles.css";
9
+ /** A slice of the stylesheet, which `stylesheets: 'split'` builds emit as
10
+ * a file of its own. */
11
+ export declare const sliceStylesheetId: (slice: StylesheetSlice) => string;
12
+ export declare const RESOLVED_SLICE_IDS: ReadonlyMap<string, StylesheetSlice>;
13
+ /**
14
+ * What the stylesheet module holds in a split build: one rule that keeps
15
+ * the stylesheet's place in Vite's CSS, where the page's links to the
16
+ * slices then go. Its own property, so no minifier merges or drops it.
17
+ */
18
+ export declare const SPLIT_STYLESHEET_MARKER = ".animus-split-stylesheet{--animus-split-stylesheet:1}";
19
+ /** The marker as a built stylesheet spells it, minified or not. */
20
+ export declare const SPLIT_STYLESHEET_MARKER_RE: RegExp;
8
21
  export declare const VIRTUAL_COMPONENTS_ID = "virtual:animus/components.js";
9
22
  export declare const RESOLVED_COMPONENTS_ID = "\0virtual:animus/components.js";
10
23
  export declare const VIRTUAL_BRIDGE_ID = "virtual:animus/hmr-bridge.js";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,cAAc,8BAAgC,CAAC;AAC5D,eAAO,MAAM,eAAe,gCAAwB,CAAC;AAErD,eAAO,MAAM,qBAAqB,iCAAmC,CAAC;AACtE,eAAO,MAAM,sBAAsB,mCAA+B,CAAC;AAEnE,eAAO,MAAM,iBAAiB,iCAAmC,CAAC;AAClE,eAAO,MAAM,kBAAkB,mCAA2B,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,sCAA8B,CAAC;AAE7D,eAAO,MAAM,uBAAuB,gCAAkC,CAAC;AACvE,eAAO,MAAM,wBAAwB,kCAAiC,CAAC;AAEvE;kDACkD;AAClD,eAAO,MAAM,wBAAwB,iCAA0B,CAAC;AAChE,eAAO,MAAM,yBAAyB,mCAAkC,CAAC;AAIzE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,cAAc,8BAAgC,CAAC;AAC5D,eAAO,MAAM,eAAe,gCAAwB,CAAC;AAErD;yBACyB;AACzB,eAAO,MAAM,iBAAiB,UAAW,eAAe,KAAG,MACnB,CAAC;AACzC,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAEnE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,0DACqB,CAAC;AAC1D,mEAAmE;AACnE,eAAO,MAAM,0BAA0B,QAC4C,CAAC;AAEpF,eAAO,MAAM,qBAAqB,iCAAmC,CAAC;AACtE,eAAO,MAAM,sBAAsB,mCAA+B,CAAC;AAEnE,eAAO,MAAM,iBAAiB,iCAAmC,CAAC;AAClE,eAAO,MAAM,kBAAkB,mCAA2B,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,sCAA8B,CAAC;AAE7D,eAAO,MAAM,uBAAuB,gCAAkC,CAAC;AACvE,eAAO,MAAM,wBAAwB,kCAAiC,CAAC;AAEvE;kDACkD;AAClD,eAAO,MAAM,wBAAwB,iCAA0B,CAAC;AAChE,eAAO,MAAM,yBAAyB,mCAAkC,CAAC;AAIzE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/context.d.ts CHANGED
@@ -4,7 +4,7 @@ import type { LightningTargets } from './css';
4
4
  import type { AnimusExtractOptions } from './index';
5
5
  import type { ExcludeMatcher, ExternalPackageOutcome, FontPreload, HostAssetClassification, HostExtensionPolicy, HostLoadExpander, ProjectManifest, SystemConfig } from '@animus-ui/extract/pipeline';
6
6
  import type { SessionOutcome, SessionPublication, WatchChanges } from '@animus-ui/extract/session';
7
- import type { Logger } from 'vite';
7
+ import type { Logger, ResolvedConfig } from 'vite';
8
8
  /** A Session outcome, and whether its publication changed the served
9
9
  * system-props module. */
10
10
  export interface ObservedOutcome {
@@ -23,6 +23,9 @@ export declare class PluginContext {
23
23
  /** Emission mode (the explicit `mode` option wins over the command); feeds
24
24
  * engine devMode and the minify default. Lifecycle stays on `isProd`. */
25
25
  emissionProd: boolean;
26
+ /** A build that links the stylesheet's slices from each page, in place of
27
+ * the one sheet the CSS module carries; the dev server keeps one sheet. */
28
+ get splitsStylesheet(): boolean;
26
29
  rootDir: string;
27
30
  logger: Logger | null;
28
31
  lcssTargets: LightningTargets;
@@ -91,6 +94,7 @@ export declare class PluginContext {
91
94
  /** Coalesces a burst of invalidations into one full reload. */
92
95
  private readonly reloadWindow;
93
96
  base: string;
97
+ renderBuiltUrl: ResolvedConfig['experimental']['renderBuiltUrl'];
94
98
  /** Vite's root and `server.origin`, which a dev asset URL is served
95
99
  * under. */
96
100
  viteRoot: string;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { PluginContext } from './context';
2
- import type { HtmlTagDescriptor } from 'vite';
2
+ import type { HtmlTagDescriptor, Rolldown } from 'vite';
3
3
  /**
4
4
  * The hrefs a finished document preloads both through Animus's tag and
5
5
  * through another, which the page wrote or a hook running after Animus's
@@ -21,4 +21,15 @@ export declare function injectHeadTags(html: string, tags: HtmlTagDescriptor[]):
21
21
  * the font preloads, then the development bridge.
22
22
  */
23
23
  export declare function buildIndexHtmlTags(ctx: PluginContext, html?: string): HtmlTagDescriptor[];
24
+ /**
25
+ * Puts a split build's slices where the single stylesheet would have been.
26
+ * The stylesheet module held only a marker rule, so it kept its place in
27
+ * Vite's CSS: the file holding the marker is cut there, and each page's
28
+ * link to it becomes the file's CSS before the marker, the slices in
29
+ * order, then its CSS after the marker, in a file of its own when CSS
30
+ * precedes the marker too. A carrier left empty is kept, unlinked, for a
31
+ * lazy chunk that names it. The build fails when no page links the
32
+ * carrier: its stylesheet loads with a lazy chunk, or no page is built.
33
+ */
34
+ export declare function placeStylesheetSlices(ctx: PluginContext, bundle: Rolldown.OutputBundle, sliceIds: readonly string[], emitAsset: (name: string, source: string) => string): void;
24
35
  //# sourceMappingURL=index-html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-html.d.ts","sourceRoot":"","sources":["../src/index-html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AA0C9C;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CAeV;AAsED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,iBAAiB,EAAE,GACxB,MAAM,GAAG,iBAAiB,EAAE,CAU9B;AA0BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,IAAI,SAAK,GACR,iBAAiB,EAAE,CAuCrB"}
1
+ {"version":3,"file":"index-html.d.ts","sourceRoot":"","sources":["../src/index-html.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AA0CxD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CAeV;AAsED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,iBAAiB,EAAE,GACxB,MAAM,GAAG,iBAAiB,EAAE,CAU9B;AA0BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,IAAI,SAAK,GACR,iBAAiB,EAAE,CAuCrB;AAsCD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,QAAQ,CAAC,YAAY,EAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAClD,IAAI,CAuFN"}
package/dist/index.cjs CHANGED
@@ -204,6 +204,7 @@ function applyResolvedConfig(ctx, config) {
204
204
  ctx.log(`extension order: ${ctx.extensionPolicy.resolverVersion}`);
205
205
  ctx.logger = config.logger;
206
206
  ctx.base = config.base ?? "/";
207
+ ctx.renderBuiltUrl = config.experimental.renderBuiltUrl;
207
208
  ctx.viteRoot = config.root;
208
209
  ctx.serverOrigin = config.server.origin ?? "";
209
210
  ctx.publicDir = config.publicDir;
@@ -235,6 +236,18 @@ function applyResolvedConfig(ctx, config) {
235
236
  const VIRTUAL_PREFIX = "virtual:animus/";
236
237
  const VIRTUAL_CSS_ID = `${VIRTUAL_PREFIX}styles.css`;
237
238
  const RESOLVED_CSS_ID = `\0${VIRTUAL_CSS_ID}`;
239
+ /** A slice of the stylesheet, which `stylesheets: 'split'` builds emit as
240
+ * a file of its own. */
241
+ const sliceStylesheetId = (slice) => `${VIRTUAL_PREFIX}styles.${slice}.css`;
242
+ const RESOLVED_SLICE_IDS = new Map(_animus_ui_extract_pipeline.STYLESHEET_SLICES.map((slice) => [`\0${sliceStylesheetId(slice)}`, slice]));
243
+ /**
244
+ * What the stylesheet module holds in a split build: one rule that keeps
245
+ * the stylesheet's place in Vite's CSS, where the page's links to the
246
+ * slices then go. Its own property, so no minifier merges or drops it.
247
+ */
248
+ const SPLIT_STYLESHEET_MARKER = ".animus-split-stylesheet{--animus-split-stylesheet:1}";
249
+ /** The marker as a built stylesheet spells it, minified or not. */
250
+ const SPLIT_STYLESHEET_MARKER_RE = /\.animus-split-stylesheet\s*\{\s*--animus-split-stylesheet\s*:\s*1\s*;?\s*\}\n?/;
238
251
  const VIRTUAL_COMPONENTS_ID = `${VIRTUAL_PREFIX}components.js`;
239
252
  const RESOLVED_COMPONENTS_ID = `\0${VIRTUAL_COMPONENTS_ID}`;
240
253
  const VIRTUAL_BRIDGE_ID = `${VIRTUAL_PREFIX}hmr-bridge.js`;
@@ -349,6 +362,11 @@ var PluginContext = class {
349
362
  /** Emission mode (the explicit `mode` option wins over the command); feeds
350
363
  * engine devMode and the minify default. Lifecycle stays on `isProd`. */
351
364
  emissionProd = false;
365
+ /** A build that links the stylesheet's slices from each page, in place of
366
+ * the one sheet the CSS module carries; the dev server keeps one sheet. */
367
+ get splitsStylesheet() {
368
+ return this.isProd && this.options.stylesheets === "split";
369
+ }
352
370
  rootDir = "";
353
371
  logger = null;
354
372
  lcssTargets = {};
@@ -458,6 +476,7 @@ var PluginContext = class {
458
476
  this.devServer?.hot?.send({ type: "full-reload" });
459
477
  });
460
478
  base = "/";
479
+ renderBuiltUrl;
461
480
  /** Vite's root and `server.origin`, which a dev asset URL is served
462
481
  * under. */
463
482
  viteRoot = "";
@@ -1501,6 +1520,92 @@ function buildIndexHtmlTags(ctx, html = "") {
1501
1520
  });
1502
1521
  return tags;
1503
1522
  }
1523
+ /**
1524
+ * A built file's URL in a page, as Vite writes its own links: the host's
1525
+ * `renderBuiltUrl` first, then relative to the page under a relative base,
1526
+ * else under the base.
1527
+ */
1528
+ function builtUrl(ctx, page, fileName) {
1529
+ let relative = ctx.base === "" || ctx.base === "./";
1530
+ const rendered = ctx.renderBuiltUrl?.(fileName, {
1531
+ hostId: page,
1532
+ hostType: "html",
1533
+ type: "asset",
1534
+ ssr: false
1535
+ });
1536
+ if (rendered instanceof Object) {
1537
+ if (rendered.runtime !== void 0) throw new Error(`[animus-extract] renderBuiltUrl returned { runtime } for ${fileName}, which a page's <link> cannot load`);
1538
+ if (rendered.relative !== void 0) relative = rendered.relative;
1539
+ } else if (rendered) return rendered;
1540
+ if (relative) return `${path.posix.join(path.posix.relative(page, "").slice(0, -2), "./")}${fileName}`;
1541
+ return `${decodeURI(ctx.base).replace(/\/$/, "")}/${fileName}`;
1542
+ }
1543
+ /** `tag`, a stylesheet link, linking `href` instead, with `attributes`. */
1544
+ function linkingInstead(tag, href, attributes = "") {
1545
+ return tag.replace(HREF_RE, ` href="${escapeHtml(href)}"`).replace(/\s*\/?>$/, `${attributes}>`);
1546
+ }
1547
+ /**
1548
+ * Puts a split build's slices where the single stylesheet would have been.
1549
+ * The stylesheet module held only a marker rule, so it kept its place in
1550
+ * Vite's CSS: the file holding the marker is cut there, and each page's
1551
+ * link to it becomes the file's CSS before the marker, the slices in
1552
+ * order, then its CSS after the marker, in a file of its own when CSS
1553
+ * precedes the marker too. A carrier left empty is kept, unlinked, for a
1554
+ * lazy chunk that names it. The build fails when no page links the
1555
+ * carrier: its stylesheet loads with a lazy chunk, or no page is built.
1556
+ */
1557
+ function placeStylesheetSlices(ctx, bundle, sliceIds, emitAsset) {
1558
+ const fileOf = /* @__PURE__ */ new Map();
1559
+ const pages = [];
1560
+ const carriers = [];
1561
+ for (const file of Object.values(bundle)) {
1562
+ if (file.type !== "asset") continue;
1563
+ if (file.fileName.endsWith(".html")) pages.push(file);
1564
+ if (file.fileName.endsWith(".css") && SPLIT_STYLESHEET_MARKER_RE.test(String(file.source))) carriers.push(file);
1565
+ const id = sliceIds.find((slice) => file.originalFileNames.some((name) => name.endsWith(slice)));
1566
+ if (id !== void 0) fileOf.set(id, file.fileName);
1567
+ }
1568
+ const slices = sliceIds.map((id) => {
1569
+ const fileName = fileOf.get(id);
1570
+ if (fileName === void 0) throw new Error(`[animus-extract] stylesheets: 'split' emitted ${id}, and the bundle holds no file for it, so the stylesheet would load without it.`);
1571
+ return fileName;
1572
+ });
1573
+ if (carriers.length === 0) {
1574
+ for (const fileName of slices) delete bundle[fileName];
1575
+ return;
1576
+ }
1577
+ if (carriers.length > 1) throw new Error(`[animus-extract] stylesheets: 'split' found Animus's stylesheet in ${carriers.map((file) => file.fileName).join(" and ")}, and places it once.`);
1578
+ const carrier = carriers[0];
1579
+ const text = String(carrier.source);
1580
+ const marker = SPLIT_STYLESHEET_MARKER_RE.exec(text);
1581
+ const before = text.slice(0, marker.index);
1582
+ const after = text.slice(marker.index + marker[0].length);
1583
+ const precedes = before.trim() !== "";
1584
+ const follows = after.trim() !== "";
1585
+ carrier.source = precedes ? before : after;
1586
+ const rest = precedes && follows ? emitAsset(carrier.names[0] ?? "index.css", after) : null;
1587
+ const sequence = [
1588
+ ...precedes ? [null] : [],
1589
+ ...slices,
1590
+ ...follows ? [rest] : []
1591
+ ];
1592
+ let linked = false;
1593
+ for (const page of pages) {
1594
+ const html = Buffer.from(page.source).toString("utf8");
1595
+ const carrierUrl = builtUrl(ctx, page.fileName, carrier.fileName);
1596
+ page.source = html.replace(LINK_TAG_RE, (tag, offset) => {
1597
+ const rel = attribute(tag, REL_RE)?.toLowerCase().split(/\s+/) ?? [];
1598
+ const href = attribute(tag, HREF_RE);
1599
+ if (!rel.includes("stylesheet") || href === void 0) return tag;
1600
+ if (attributeText(href) !== carrierUrl) return tag;
1601
+ linked = true;
1602
+ const lineStart = html.lastIndexOf("\n", offset - 1) + 1;
1603
+ const indent = /^[ \t]*/.exec(html.slice(lineStart))[0];
1604
+ return sequence.map((fileName) => fileName === null ? tag : linkingInstead(tag, builtUrl(ctx, page.fileName, fileName), fileName === rest ? "" : " data-animus-stylesheet")).join(`\n${indent}`);
1605
+ });
1606
+ }
1607
+ if (!linked) throw new Error(`[animus-extract] stylesheets: 'split' links the stylesheet's files where a page links ${carrier.fileName}, which holds Animus's stylesheet, and no page links it: it loads with a lazy chunk, or the build has no HTML page. Import Animus's components from the page's entry, or leave \`stylesheets\` unset for one sheet.`);
1608
+ }
1504
1609
  //#endregion
1505
1610
  //#region src/quarantine-plugin.ts
1506
1611
  /**
@@ -1538,6 +1643,7 @@ function sheetRegistryHash(ctx) {
1538
1643
  }
1539
1644
  function resolveVirtualId(ctx, id) {
1540
1645
  if (id === VIRTUAL_CSS_ID) return RESOLVED_CSS_ID;
1646
+ if (id.startsWith("virtual:animus/") && RESOLVED_SLICE_IDS.has(`\0${id}`)) return `\0${id}`;
1541
1647
  if (id === VIRTUAL_COMPONENTS_ID) return RESOLVED_COMPONENTS_ID;
1542
1648
  if (id === VIRTUAL_BRIDGE_ID) return RESOLVED_BRIDGE_ID;
1543
1649
  if (id === VIRTUAL_SYSTEM_PROPS_ID) return RESOLVED_SYSTEM_PROPS_ID;
@@ -1552,47 +1658,46 @@ function resolveVirtualId(ctx, id) {
1552
1658
  }
1553
1659
  return null;
1554
1660
  }
1555
- function loadVirtualModule(ctx, id) {
1556
- const lcssOpts = {
1661
+ function lightningOptions(ctx) {
1662
+ return {
1557
1663
  minify: ctx.options.minify ?? ctx.emissionProd,
1558
1664
  targets: ctx.lcssTargets,
1559
1665
  warnFn: (msg) => ctx.warn(msg)
1560
1666
  };
1561
- const checked = (css) => {
1562
- (0, _animus_ui_extract_pipeline.reportSurvivingAssetPlaceholders)(css, {
1563
- strict: ctx.options.strict,
1564
- warn: (message) => ctx.warn(message),
1565
- reportErrors: ctx.reportErrors(),
1566
- prefix: "[animus-extract]"
1567
- });
1568
- return css;
1569
- };
1570
- if (id === RESOLVED_CSS_ID) {
1571
- if (!ctx.isProd && ctx.storedManifest) {
1572
- const { variables, body } = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
1573
- layers: ctx.options.layers,
1574
- variableCss: ctx.variableCss,
1575
- globalCss: ctx.globalCss,
1576
- split: true
1577
- });
1578
- return checked([variables, (0, _animus_ui_extract_pipeline.postProcessCss)(body, {
1579
- ...lcssOpts,
1580
- minify: false
1581
- })].filter(Boolean).join("\n"));
1582
- }
1583
- const { variables, body } = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
1584
- layers: ctx.options.layers,
1585
- variableCss: ctx.variableCss,
1586
- globalCss: ctx.globalCss,
1587
- componentCss: ctx.resolvedComponentCss,
1588
- split: true
1589
- });
1590
- return checked([variables, (0, _animus_ui_extract_pipeline.postProcessCss)(body, lcssOpts)].filter(Boolean).join("\n"));
1591
- }
1667
+ }
1668
+ function checked(ctx, css) {
1669
+ (0, _animus_ui_extract_pipeline.reportSurvivingAssetPlaceholders)(css, {
1670
+ strict: ctx.options.strict,
1671
+ warn: (message) => ctx.warn(message),
1672
+ reportErrors: ctx.reportErrors(),
1673
+ prefix: "[animus-extract]"
1674
+ });
1675
+ return css;
1676
+ }
1677
+ /**
1678
+ * The stylesheet `virtual:animus/styles.css` serves: the variables, then
1679
+ * the post-processed body. In development the component layers arrive
1680
+ * through the bridge's sheet instead, unminified.
1681
+ */
1682
+ function stylesheetSource(ctx) {
1683
+ const bridged = !ctx.isProd && Boolean(ctx.storedManifest);
1684
+ const { variables, body } = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
1685
+ layers: ctx.options.layers,
1686
+ variableCss: ctx.variableCss,
1687
+ globalCss: ctx.globalCss,
1688
+ componentCss: bridged ? void 0 : ctx.resolvedComponentCss,
1689
+ split: true
1690
+ });
1691
+ const lcssOpts = lightningOptions(ctx);
1692
+ if (bridged) lcssOpts.minify = false;
1693
+ return checked(ctx, [variables, (0, _animus_ui_extract_pipeline.postProcessCss)(body, lcssOpts)].filter(Boolean).join("\n"));
1694
+ }
1695
+ function loadVirtualModule(ctx, id) {
1696
+ if (id === RESOLVED_CSS_ID) return ctx.splitsStylesheet ? SPLIT_STYLESHEET_MARKER : stylesheetSource(ctx);
1592
1697
  if (id === RESOLVED_COMPONENTS_ID) {
1593
1698
  const strippedCss = (0, _animus_ui_extract_pipeline.stripLeadingLayerDeclaration)(ctx.resolvedComponentCss || "");
1594
- return `export default \`${checked((0, _animus_ui_extract_pipeline.postProcessCss)(strippedCss, {
1595
- ...lcssOpts,
1699
+ return `export default \`${checked(ctx, (0, _animus_ui_extract_pipeline.postProcessCss)(strippedCss, {
1700
+ ...lightningOptions(ctx),
1596
1701
  minify: false
1597
1702
  })).replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;`;
1598
1703
  }
@@ -1702,6 +1807,11 @@ async function sourceKitConfig(rootDir, systemPath, engine) {
1702
1807
  /** The URL a build's root is served at, for resolving a page's hrefs: an
1703
1808
  * absolute `base`, a root-relative one on a stand-in origin, or the root
1704
1809
  * for a relative one, which every page resolves from its own location. */
1810
+ /** Whether a hook runs for the browser's environment; a host without
1811
+ * environments builds only that one. */
1812
+ function isClient(context) {
1813
+ return (context.environment?.config.consumer ?? "client") === "client";
1814
+ }
1705
1815
  function servedBase(base) {
1706
1816
  const origin = "https://animus.invalid/";
1707
1817
  if (/^[a-z][a-z\d+.-]*:/i.test(base)) return new URL(base.replace(/\/?$/, "/"));
@@ -1726,6 +1836,14 @@ function animusExtract(options) {
1726
1836
  ...options,
1727
1837
  layers: vendor.order
1728
1838
  } : options);
1839
+ /** The stylesheet with the declared vendor sheets at its head, so they
1840
+ * arrive wherever it does, whatever imports it. */
1841
+ async function withVendorHead(context, sheet) {
1842
+ const layergate = await vendor?.plugin();
1843
+ return layergate ? await layergate.stylesheetHead.call(context, RESOLVED_CSS_ID) + sheet : sheet;
1844
+ }
1845
+ let slices = /* @__PURE__ */ new Map();
1846
+ let linkedSlices = [];
1729
1847
  return {
1730
1848
  name: "animus-extract",
1731
1849
  enforce: "pre",
@@ -1770,6 +1888,22 @@ function animusExtract(options) {
1770
1888
  name: fileName,
1771
1889
  source
1772
1890
  }) : void 0);
1891
+ if (ctx.splitsStylesheet && isClient(this)) {
1892
+ const sheet = await withVendorHead(this, stylesheetSource(ctx));
1893
+ const cut = (0, _animus_ui_extract_pipeline.splitStylesheet)(sheet);
1894
+ slices = new Map(cut.map(({ slice, css }) => [slice, css]));
1895
+ linkedSlices = [];
1896
+ for (const { slice, css } of cut) {
1897
+ if (css === "") continue;
1898
+ const id = sliceStylesheetId(slice);
1899
+ this.emitFile({
1900
+ type: "chunk",
1901
+ id,
1902
+ name: `animus-${slice}`
1903
+ });
1904
+ linkedSlices.push(id);
1905
+ }
1906
+ }
1773
1907
  },
1774
1908
  async resolveId(id, importer, resolveOptions) {
1775
1909
  const owned = await (await vendor?.plugin())?.resolveId.call(this, id, importer, resolveOptions);
@@ -1786,11 +1920,12 @@ function animusExtract(options) {
1786
1920
  };
1787
1921
  },
1788
1922
  async load(id) {
1789
- const layergate = await vendor?.plugin();
1790
- const loaded = await layergate?.load.call(this, id);
1923
+ const loaded = await (await vendor?.plugin())?.load.call(this, id);
1791
1924
  if (loaded) return loaded;
1925
+ const slice = RESOLVED_SLICE_IDS.get(id);
1926
+ if (slice !== void 0) return slices.get(slice) ?? "";
1792
1927
  const own = loadVirtualModule(ctx, id);
1793
- if (layergate && id === RESOLVED_CSS_ID && own !== null) return await layergate.stylesheetHead.call(this, id) + own;
1928
+ if (id === RESOLVED_CSS_ID && own !== null && !ctx.splitsStylesheet) return withVendorHead(this, own);
1794
1929
  return own;
1795
1930
  },
1796
1931
  async transform(code, id) {
@@ -1800,6 +1935,11 @@ function animusExtract(options) {
1800
1935
  generateBundle: {
1801
1936
  order: "post",
1802
1937
  handler(_output, bundle) {
1938
+ if (linkedSlices.length > 0 && isClient(this)) placeStylesheetSlices(ctx, bundle, linkedSlices, (name, source) => this.getFileName(this.emitFile({
1939
+ type: "asset",
1940
+ name,
1941
+ source
1942
+ })));
1803
1943
  if (!ctx.served?.fontPreloads.length) return;
1804
1944
  for (const file of Object.values(bundle)) {
1805
1945
  if (file.type !== "asset" || !file.fileName.endsWith(".html")) continue;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { AnimusQuarantineOptions, ClosedDynamicImport, FontPreloadEntry, DiagnosticLevels, StaticCssConfig } from '@animus-ui/extract/pipeline';
1
+ import type { AnimusQuarantineOptions, ClosedDynamicImport, FontPreloadEntry, DiagnosticLevels, StaticCssConfig, StylesheetDelivery } from '@animus-ui/extract/pipeline';
2
2
  import type { Plugin } from 'vite';
3
3
  export { discoverFiles } from '@animus-ui/extract/pipeline';
4
- export type { AnimusQuarantineOptions } from '@animus-ui/extract/pipeline';
4
+ export type { AnimusQuarantineOptions, StylesheetDelivery, } from '@animus-ui/extract/pipeline';
5
5
  /** The entries `virtual:animus/font-preloads` exports by default: each file
6
6
  * this build preloads, the URL it is preloaded at, and its faces. */
7
7
  export type { FontPreload, PreloadedFontFace, } from '@animus-ui/extract/pipeline';
@@ -34,6 +34,15 @@ export interface AnimusExtractOptions {
34
34
  * where the app renders it: family names, or `{ family, weight?, style? }`
35
35
  * (see `FontPreloadEntry`). `[]` preloads none. */
36
36
  fontPreloads?: FontPreloadEntry[];
37
+ /** `'split'` builds the stylesheet as three consecutive files, each page
38
+ * linking them in order where it would link the one sheet `'single'`
39
+ * (the default) builds: foundation (variables, `@property`,
40
+ * `anm-global`), components (base through states), then utilities
41
+ * (`anm-system`, `anm-custom`). In order they hold that sheet's rules,
42
+ * so the cascade is unchanged, and a file an edit leaves alone keeps its
43
+ * hash. Needs a page Vite builds from HTML to link the stylesheet; the
44
+ * dev server keeps one sheet. */
45
+ stylesheets?: StylesheetDelivery;
37
46
  /**
38
47
  * Substrings, or globs when `*`/`?` present. Replaces the defaults `dist`,
39
48
  * `.test.`, `.spec.`; `node_modules`, `.next`, `.animus` always apply.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAEhB,eAAe,EAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E;sEACsE;AACtE,YAAY,EACV,WAAW,EACX,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AA+CrC,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf;;;0DAGsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7C;;;wDAGoD;IACpD,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;+CAE2C;IAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC;;sDAEkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;gBAEY;IACZ,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAiBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CA4MnE;eAEc,aAAa"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAEhB,eAAe,EACf,kBAAkB,EAEnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAe,MAAM,EAAwB,MAAM,MAAM,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EACV,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC;sEACsE;AACtE,YAAY,EACV,WAAW,EACX,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AA+CrC,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf;;;0DAGsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7C;;;wDAGoD;IACpD,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC;;;;;;;sCAOkC;IAClC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;+CAE2C;IAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC;;sDAEkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;gBAEY;IACZ,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAuBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAiPnE;eAEc,aAAa"}
@@ -3,5 +3,11 @@ export declare function resolveVirtualId(ctx: PluginContext, id: string): string
3
3
  id: string;
4
4
  moduleSideEffects: boolean;
5
5
  } | null;
6
+ /**
7
+ * The stylesheet `virtual:animus/styles.css` serves: the variables, then
8
+ * the post-processed body. In development the component layers arrive
9
+ * through the bridge's sheet instead, unminified.
10
+ */
11
+ export declare function stylesheetSource(ctx: PluginContext): string;
6
12
  export declare function loadVirtualModule(ctx: PluginContext, id: string): string | null;
7
13
  //# sourceMappingURL=virtual-modules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-modules.d.ts","sourceRoot":"","sources":["../src/virtual-modules.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAa/C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAoB5D;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAkHf"}
1
+ {"version":3,"file":"virtual-modules.d.ts","sourceRoot":"","sources":["../src/virtual-modules.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAa/C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAuB5D;AAoBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAa3D;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAgFf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animus-ui/vite-plugin",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "description": "Animus static CSS extraction Vite plugin",
5
5
  "keywords": [
6
6
  "animus",
@@ -20,6 +20,7 @@
20
20
  "directory": "packages/vite-plugin"
21
21
  },
22
22
  "files": [
23
+ "client.d.ts",
23
24
  "dist"
24
25
  ],
25
26
  "main": "./dist/index.cjs",
@@ -28,6 +29,9 @@
28
29
  ".": {
29
30
  "types": "./dist/index.d.ts",
30
31
  "default": "./dist/index.cjs"
32
+ },
33
+ "./client": {
34
+ "types": "./client.d.ts"
31
35
  }
32
36
  },
33
37
  "publishConfig": {
@@ -39,16 +43,16 @@
39
43
  "compile": "bun check"
40
44
  },
41
45
  "dependencies": {
42
- "@animus-ui/extract": "0.1.38",
46
+ "@animus-ui/extract": "0.1.39",
43
47
  "browserslist": "^4.28.8",
44
48
  "lightningcss": "^1.33.0"
45
49
  },
46
50
  "devDependencies": {
47
- "@animus-ui/assertions": "0.1.38",
48
- "@animus-ui/layergate": "0.1.38"
51
+ "@animus-ui/assertions": "0.1.39",
52
+ "@animus-ui/layergate": "0.1.39"
49
53
  },
50
54
  "peerDependencies": {
51
- "@animus-ui/layergate": "0.1.38",
55
+ "@animus-ui/layergate": "0.1.39",
52
56
  "vite": ">=8 <9"
53
57
  },
54
58
  "peerDependenciesMeta": {