@animus-ui/vite-plugin 0.1.49 → 0.1.51
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/dist/build-start.d.ts.map +1 -1
- package/dist/bundle-removal.d.ts +27 -0
- package/dist/bundle-removal.d.ts.map +1 -0
- package/dist/index-html.d.ts +6 -1
- package/dist/index-html.d.ts.map +1 -1
- package/dist/index.cjs +454 -298
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAa/D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAY/D;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,WAAW,EAC7B,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,MAAM,GAC3D,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAa/D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAY/D;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,WAAW,EAC7B,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,MAAM,GAC3D,OAAO,CAAC,IAAI,CAAC,CAgJf"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PluginContext } from './context';
|
|
2
|
+
import type { Rolldown } from 'vite';
|
|
3
|
+
/** What a build that removes unbundled components does to its slices. */
|
|
4
|
+
export interface BundleRemoval {
|
|
5
|
+
/** Emits `file` without the removed components' rules, beside it under a
|
|
6
|
+
* name its new content hashes, and returns that name; `null` keeps it. */
|
|
7
|
+
replace(file: Rolldown.OutputAsset): string | null;
|
|
8
|
+
/** Points Vite's manifests and chunk metadata at each replacement where
|
|
9
|
+
* they named the file replaced, then reports. */
|
|
10
|
+
finish(): void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The removal of every component no output file of this client build
|
|
14
|
+
* includes, or `null` where the build keeps every component: it bundles
|
|
15
|
+
* another environment beside the client (`otherEnvironments`), whose output
|
|
16
|
+
* may render what the client's does not; it leaves a module external; it
|
|
17
|
+
* carries data the scan cannot read as text; or an output file other than
|
|
18
|
+
* Vite's `manifests` names a stylesheet slice, which a replacement would
|
|
19
|
+
* leave naming a deleted file. Every output file but the slices
|
|
20
|
+
* (`sliceIds`) and media is evidence, data URLs decoded.
|
|
21
|
+
*/
|
|
22
|
+
export declare function bundleRemoval(ctx: PluginContext, bundle: Rolldown.OutputBundle, sliceIds: readonly string[], context: {
|
|
23
|
+
otherEnvironments: readonly string[];
|
|
24
|
+
manifests: ReadonlySet<string>;
|
|
25
|
+
emit: (asset: Rolldown.EmittedAsset) => void;
|
|
26
|
+
}): BundleRemoval | null;
|
|
27
|
+
//# sourceMappingURL=bundle-removal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-removal.d.ts","sourceRoot":"","sources":["../src/bundle-removal.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAErC,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B;+EAC2E;IAC3E,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;IACnD;sDACkD;IAClD,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,QAAQ,CAAC,YAAY,EAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE;IACP,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,KAAK,IAAI,CAAC;CAC9C,GACA,aAAa,GAAG,IAAI,CAiJtB"}
|
package/dist/index-html.d.ts
CHANGED
|
@@ -21,6 +21,9 @@ 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
|
+
/** The slice `file` holds, by its id, or a path to it from the root, as
|
|
25
|
+
* Vite versions spell it. */
|
|
26
|
+
export declare function sliceIdOf(file: Rolldown.OutputAsset | Rolldown.OutputChunk, sliceIds: readonly string[]): string | undefined;
|
|
24
27
|
/**
|
|
25
28
|
* Puts a split build's slices where the single stylesheet would have been.
|
|
26
29
|
* The stylesheet module held only a marker rule, so it kept its place in
|
|
@@ -31,5 +34,7 @@ export declare function buildIndexHtmlTags(ctx: PluginContext, html?: string): H
|
|
|
31
34
|
* lazy chunk that names it. The build fails when no page links the
|
|
32
35
|
* carrier: its stylesheet loads with a lazy chunk, or no page is built.
|
|
33
36
|
*/
|
|
34
|
-
export declare function placeStylesheetSlices(ctx: PluginContext, bundle: Rolldown.OutputBundle, sliceIds: readonly string[], emitAsset: (name: string, source: string) => string
|
|
37
|
+
export declare function placeStylesheetSlices(ctx: PluginContext, bundle: Rolldown.OutputBundle, sliceIds: readonly string[], emitAsset: (name: string, source: string) => string,
|
|
38
|
+
/** The file emitted in a slice's place, or `null` to ship Vite's own. */
|
|
39
|
+
replace?: (file: Rolldown.OutputAsset) => string | null): void;
|
|
35
40
|
//# sourceMappingURL=index-html.d.ts.map
|
package/dist/index-html.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;AA2BD;;;;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,
|
|
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;AA2BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,IAAI,SAAK,GACR,iBAAiB,EAAE,CAuCrB;AAsCD;8BAC8B;AAC9B,wBAAgB,SAAS,CACvB,IAAI,EAAE,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,EACjD,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;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;AACnD,yEAAyE;AACzE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,KAAK,MAAM,GAAG,IAAI,GACtD,IAAI,CA2FN"}
|
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ let vite = require("vite");
|
|
|
8
8
|
let fs = require("fs");
|
|
9
9
|
let _animus_ui_extract_session = require("@animus-ui/extract/session");
|
|
10
10
|
let child_process = require("child_process");
|
|
11
|
+
let node_path = require("node:path");
|
|
11
12
|
let crypto = require("crypto");
|
|
12
13
|
//#region src/asset-copy-dirs.ts
|
|
13
14
|
/**
|
|
@@ -170,7 +171,8 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
|
|
|
170
171
|
}).length;
|
|
171
172
|
const componentSize = ctx.resolvedComponentCss.length;
|
|
172
173
|
ctx.log(`Delivery: split mode — static ${staticSize} bytes, components ${componentSize} bytes (adopted stylesheet)`);
|
|
173
|
-
} else ctx.log("Delivery:
|
|
174
|
+
} else if (ctx.splitsStylesheet) ctx.log("Delivery: split mode (production), linking each slice from the page");
|
|
175
|
+
else ctx.log("Delivery: single file mode (production)");
|
|
174
176
|
}
|
|
175
177
|
const { declaration } = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
|
|
176
178
|
layers: ctx.options.layers,
|
|
@@ -182,6 +184,428 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
|
|
|
182
184
|
if (ctx.options.verify) ctx.runSelfVerify();
|
|
183
185
|
}
|
|
184
186
|
//#endregion
|
|
187
|
+
//#region src/constants.ts
|
|
188
|
+
/**
|
|
189
|
+
* The namespace every virtual module here lives under; the `transform` guard
|
|
190
|
+
* matches on this same string so a rename cannot strand it.
|
|
191
|
+
*/
|
|
192
|
+
const VIRTUAL_PREFIX = "virtual:animus/";
|
|
193
|
+
const VIRTUAL_CSS_ID = `${VIRTUAL_PREFIX}styles.css`;
|
|
194
|
+
const RESOLVED_CSS_ID = `\0${VIRTUAL_CSS_ID}`;
|
|
195
|
+
/** A slice of the stylesheet, which `stylesheets: 'split'` builds emit as
|
|
196
|
+
* a file of its own. */
|
|
197
|
+
const sliceStylesheetId = (slice) => `${VIRTUAL_PREFIX}styles.${slice}.css`;
|
|
198
|
+
const RESOLVED_SLICE_IDS = new Map(_animus_ui_extract_pipeline.STYLESHEET_SLICES.map((slice) => [`\0${sliceStylesheetId(slice)}`, slice]));
|
|
199
|
+
/**
|
|
200
|
+
* What the stylesheet module holds in a split build: one rule that keeps
|
|
201
|
+
* the stylesheet's place in Vite's CSS, where the page's links to the
|
|
202
|
+
* slices then go. Its own property, so no minifier merges or drops it.
|
|
203
|
+
*/
|
|
204
|
+
const SPLIT_STYLESHEET_MARKER = ".animus-split-stylesheet{--animus-split-stylesheet:1}";
|
|
205
|
+
/** The marker as a built stylesheet spells it, minified or not. */
|
|
206
|
+
const SPLIT_STYLESHEET_MARKER_RE = /\.animus-split-stylesheet\s*\{\s*--animus-split-stylesheet\s*:\s*1\s*;?\s*\}\n?/;
|
|
207
|
+
const VIRTUAL_COMPONENTS_ID = `${VIRTUAL_PREFIX}components.js`;
|
|
208
|
+
const RESOLVED_COMPONENTS_ID = `\0${VIRTUAL_COMPONENTS_ID}`;
|
|
209
|
+
const VIRTUAL_BRIDGE_ID = `${VIRTUAL_PREFIX}hmr-bridge.js`;
|
|
210
|
+
const RESOLVED_BRIDGE_ID = `\0${VIRTUAL_BRIDGE_ID}`;
|
|
211
|
+
/**
|
|
212
|
+
* Vite reserves `/@id/` for module ids that are not file paths and strips the
|
|
213
|
+
* prefix before `resolveId`, so the unprefixed specifier travels here.
|
|
214
|
+
*/
|
|
215
|
+
const BRIDGE_SCRIPT_SRC = `/@id/${VIRTUAL_BRIDGE_ID}`;
|
|
216
|
+
const VIRTUAL_SYSTEM_PROPS_ID = `${VIRTUAL_PREFIX}system-props`;
|
|
217
|
+
const RESOLVED_SYSTEM_PROPS_ID = `\0${VIRTUAL_SYSTEM_PROPS_ID}`;
|
|
218
|
+
/** The faces this build preloads, with the URL each file is preloaded at:
|
|
219
|
+
* the module every host serves under this id. */
|
|
220
|
+
const VIRTUAL_FONT_PRELOADS_ID = _animus_ui_extract_session.FONT_PRELOADS_MODULE_ID;
|
|
221
|
+
const RESOLVED_FONT_PRELOADS_ID = `\0${VIRTUAL_FONT_PRELOADS_ID}`;
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/index-html.ts
|
|
224
|
+
const LINK_TAG_RE = /<link\b[^>]*>/gi;
|
|
225
|
+
/** Marks the preloads Animus writes, so another preload of the same file
|
|
226
|
+
* can be told from Animus's own. */
|
|
227
|
+
const ANIMUS_PRELOAD_MARKER = "data-animus-preload";
|
|
228
|
+
const MARKER_RE = /\sdata-animus-preload(?=[\s=/>])/i;
|
|
229
|
+
const REL_RE = /\srel\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
|
|
230
|
+
const HREF_RE = /\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
|
|
231
|
+
function attribute(tag, re) {
|
|
232
|
+
const match = re.exec(tag);
|
|
233
|
+
return match ? match[1] ?? match[2] ?? match[3] : void 0;
|
|
234
|
+
}
|
|
235
|
+
/** Each `<link rel="preload">` in `html`, with its href. */
|
|
236
|
+
function* preloadLinks(html) {
|
|
237
|
+
for (const [tag] of html.matchAll(LINK_TAG_RE)) {
|
|
238
|
+
const rel = attribute(tag, REL_RE)?.toLowerCase().split(/\s+/) ?? [];
|
|
239
|
+
const href = attribute(tag, HREF_RE);
|
|
240
|
+
if (rel.includes("preload") && href !== void 0) yield [tag, href];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const ENTITY_RE = /&(?:#x([0-9a-f]+)|#(\d+)|(amp|lt|gt|quot|apos));/gi;
|
|
244
|
+
const NAMED_ENTITIES = /* @__PURE__ */ new Map([
|
|
245
|
+
["amp", "&"],
|
|
246
|
+
["lt", "<"],
|
|
247
|
+
["gt", ">"],
|
|
248
|
+
["quot", "\""],
|
|
249
|
+
["apos", "'"]
|
|
250
|
+
]);
|
|
251
|
+
/** An attribute value as the browser reads it: character references decoded. */
|
|
252
|
+
function attributeText(value) {
|
|
253
|
+
return value.replace(ENTITY_RE, (_, hex, decimal, named) => named === void 0 ? String.fromCodePoint(Number.parseInt(hex ?? decimal, hex ? 16 : 10)) : NAMED_ENTITIES.get(named.toLowerCase()));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The hrefs a finished document preloads both through Animus's tag and
|
|
257
|
+
* through another, which the page wrote or a hook running after Animus's
|
|
258
|
+
* added: the browser may then fetch the file twice. Each href is compared
|
|
259
|
+
* as the browser resolves it against `pageUrl`, the URL the page is served
|
|
260
|
+
* at, and reported as Animus wrote it.
|
|
261
|
+
*/
|
|
262
|
+
function duplicatedFontPreloads(html, pageUrl) {
|
|
263
|
+
const resolved = (href) => {
|
|
264
|
+
try {
|
|
265
|
+
return new URL(attributeText(href), pageUrl).href;
|
|
266
|
+
} catch {
|
|
267
|
+
return href;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
const ours = /* @__PURE__ */ new Map();
|
|
271
|
+
const others = /* @__PURE__ */ new Set();
|
|
272
|
+
for (const [tag, href] of preloadLinks(html)) if (MARKER_RE.test(tag)) ours.set(resolved(href), href);
|
|
273
|
+
else others.add(resolved(href));
|
|
274
|
+
return [...ours].filter(([url]) => others.has(url)).map(([, href]) => href);
|
|
275
|
+
}
|
|
276
|
+
/** The hrefs the document already preloads. */
|
|
277
|
+
function preloadedHrefs(html) {
|
|
278
|
+
return new Set([...preloadLinks(html)].map(([, href]) => href));
|
|
279
|
+
}
|
|
280
|
+
/** The head elements Animus's tags go after (the charset and viewport
|
|
281
|
+
* metas), the stylesheets they go before, and what holds neither. */
|
|
282
|
+
const HEAD_SCAN_RE = /<!--[\s\S]*?-->|<script\b[\s\S]*?<\/script\s*>|<\/head\s*>|<style\b|<(?:meta|link)\b[^>]*>/gi;
|
|
283
|
+
/** Where Animus's head tags go: after the head's charset and viewport
|
|
284
|
+
* metas, so they cannot push the charset past the 1024 bytes a browser
|
|
285
|
+
* sniffs for it, and before its first stylesheet; -1 without a `<head>`. */
|
|
286
|
+
function headTagOffset(html) {
|
|
287
|
+
const open = /<head\b[^>]*>/i.exec(html);
|
|
288
|
+
if (open === null) return -1;
|
|
289
|
+
const start = open.index + open[0].length;
|
|
290
|
+
let offset = start;
|
|
291
|
+
for (const match of html.slice(start).matchAll(HEAD_SCAN_RE)) {
|
|
292
|
+
const [element] = match;
|
|
293
|
+
const lower = element.toLowerCase();
|
|
294
|
+
if (lower.startsWith("</head") || lower.startsWith("<style")) break;
|
|
295
|
+
if (lower.startsWith("<link")) {
|
|
296
|
+
if ((attribute(element, REL_RE)?.toLowerCase().split(/\s+/))?.includes("stylesheet")) break;
|
|
297
|
+
} else if (lower.startsWith("<meta") && (/\scharset\s*=/i.test(element) || /\shttp-equiv\s*=\s*["']?content-type\b/i.test(element) || /\sname\s*=\s*["']?viewport\b/i.test(element))) offset = start + match.index + element.length;
|
|
298
|
+
}
|
|
299
|
+
return offset;
|
|
300
|
+
}
|
|
301
|
+
/** As `escape-html` escapes, which Vite applies to attribute values. */
|
|
302
|
+
function escapeHtml(value) {
|
|
303
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
304
|
+
}
|
|
305
|
+
/** A tag as Vite serializes it, `children` as written, except that an
|
|
306
|
+
* undefined attribute is left out rather than written "undefined". */
|
|
307
|
+
function serializeTag({ tag, attrs = {}, children }) {
|
|
308
|
+
const serialized = Object.entries(attrs).map(([key, value]) => {
|
|
309
|
+
if (value === true) return ` ${key}`;
|
|
310
|
+
if (value === false || value === void 0) return "";
|
|
311
|
+
return ` ${key}="${escapeHtml(value)}"`;
|
|
312
|
+
}).join("");
|
|
313
|
+
if (tag === "link" || tag === "meta" || tag === "base") return `<${tag}${serialized}>`;
|
|
314
|
+
return `<${tag}${serialized}>${Array.isArray(children) ? "" : children ?? ""}</${tag}>`;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* The hook's result: the tags written after the charset and viewport metas,
|
|
318
|
+
* each on its own line indented as the element it follows, so the charset
|
|
319
|
+
* stays in the first 1024 bytes however long the tags are; as `head-prepend`
|
|
320
|
+
* tags for a document without a `<head>`.
|
|
321
|
+
*/
|
|
322
|
+
function injectHeadTags(html, tags) {
|
|
323
|
+
const offset = headTagOffset(html);
|
|
324
|
+
if (offset === -1) return tags;
|
|
325
|
+
if (tags.length === 0) return html;
|
|
326
|
+
const lineStart = html.lastIndexOf("\n", offset - 1) + 1;
|
|
327
|
+
const indent = /^[ \t]*/.exec(html.slice(lineStart))[0];
|
|
328
|
+
const inserted = tags.map((tag) => `\n${indent}${serializeTag(tag)}`).join("");
|
|
329
|
+
return html.slice(0, offset) + inserted + html.slice(offset);
|
|
330
|
+
}
|
|
331
|
+
/** The preloads for the faces that ask for one, each marked as Animus's;
|
|
332
|
+
* one the document already preloads is left out. */
|
|
333
|
+
function fontPreloadTags(ctx, html) {
|
|
334
|
+
if (!ctx.served?.fontPreloads.length) return [];
|
|
335
|
+
const existing = preloadedHrefs(html);
|
|
336
|
+
return ctx.fontPreloads.filter(({ href }) => !existing.has(href)).map(({ href, type, fetchpriority }) => {
|
|
337
|
+
const attrs = {
|
|
338
|
+
rel: "preload",
|
|
339
|
+
href,
|
|
340
|
+
as: "font"
|
|
341
|
+
};
|
|
342
|
+
if (type !== void 0) attrs.type = type;
|
|
343
|
+
if (fetchpriority !== void 0) attrs.fetchpriority = fetchpriority;
|
|
344
|
+
attrs.crossorigin = true;
|
|
345
|
+
attrs[ANIMUS_PRELOAD_MARKER] = true;
|
|
346
|
+
return {
|
|
347
|
+
tag: "link",
|
|
348
|
+
attrs,
|
|
349
|
+
injectTo: "head-prepend"
|
|
350
|
+
};
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Animus's head tags in document order: the bootstrap script, so it runs
|
|
355
|
+
* before first paint and ahead of every stylesheet, the layer declaration,
|
|
356
|
+
* the font preloads, then the development bridge.
|
|
357
|
+
*/
|
|
358
|
+
function buildIndexHtmlTags(ctx, html = "") {
|
|
359
|
+
const tags = [];
|
|
360
|
+
const bootstrap = ctx.options.appearanceBootstrap;
|
|
361
|
+
if (bootstrap?.code) tags.push({
|
|
362
|
+
tag: "script",
|
|
363
|
+
attrs: { "data-animus-bootstrap": "" },
|
|
364
|
+
children: bootstrap.code,
|
|
365
|
+
injectTo: "head-prepend"
|
|
366
|
+
});
|
|
367
|
+
if (ctx.layerDeclaration) tags.push({
|
|
368
|
+
tag: "style",
|
|
369
|
+
attrs: { "data-animus-layers": "" },
|
|
370
|
+
children: ctx.layerDeclaration,
|
|
371
|
+
injectTo: "head-prepend"
|
|
372
|
+
});
|
|
373
|
+
tags.push(...fontPreloadTags(ctx, html));
|
|
374
|
+
if (!ctx.isProd) tags.push({
|
|
375
|
+
tag: "script",
|
|
376
|
+
attrs: {
|
|
377
|
+
type: "module",
|
|
378
|
+
src: BRIDGE_SCRIPT_SRC,
|
|
379
|
+
"data-animus-bridge": ""
|
|
380
|
+
},
|
|
381
|
+
injectTo: "head-prepend"
|
|
382
|
+
});
|
|
383
|
+
return tags;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* A built file's URL in a page, as Vite writes its own links: the host's
|
|
387
|
+
* `renderBuiltUrl` first, then relative to the page under a relative base,
|
|
388
|
+
* else under the base.
|
|
389
|
+
*/
|
|
390
|
+
function builtUrl(ctx, page, fileName) {
|
|
391
|
+
let relative = ctx.base === "" || ctx.base === "./";
|
|
392
|
+
const rendered = ctx.renderBuiltUrl?.(fileName, {
|
|
393
|
+
hostId: page,
|
|
394
|
+
hostType: "html",
|
|
395
|
+
type: "asset",
|
|
396
|
+
ssr: false
|
|
397
|
+
});
|
|
398
|
+
if (rendered instanceof Object) {
|
|
399
|
+
if (rendered.runtime !== void 0) throw new Error(`[animus-extract] renderBuiltUrl returned { runtime } for ${fileName}, which a page's <link> cannot load`);
|
|
400
|
+
if (rendered.relative !== void 0) relative = rendered.relative;
|
|
401
|
+
} else if (rendered) return rendered;
|
|
402
|
+
if (relative) return `${path.posix.join(path.posix.relative(page, "").slice(0, -2), "./")}${fileName}`;
|
|
403
|
+
return `${decodeURI(ctx.base).replace(/\/$/, "")}/${fileName}`;
|
|
404
|
+
}
|
|
405
|
+
/** `tag`, a stylesheet link, linking `href` instead, with `attributes`. */
|
|
406
|
+
function linkingInstead(tag, href, attributes = "") {
|
|
407
|
+
return tag.replace(HREF_RE, ` href="${escapeHtml(href)}"`).replace(/\s*\/?>$/, `${attributes}>`);
|
|
408
|
+
}
|
|
409
|
+
/** The slice `file` holds, by its id, or a path to it from the root, as
|
|
410
|
+
* Vite versions spell it. */
|
|
411
|
+
function sliceIdOf(file, sliceIds) {
|
|
412
|
+
if (file.type !== "asset") return void 0;
|
|
413
|
+
return sliceIds.find((slice) => file.originalFileNames.some((name) => name.endsWith(slice)));
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Puts a split build's slices where the single stylesheet would have been.
|
|
417
|
+
* The stylesheet module held only a marker rule, so it kept its place in
|
|
418
|
+
* Vite's CSS: the file holding the marker is cut there, and each page's
|
|
419
|
+
* link to it becomes the file's CSS before the marker, the slices in
|
|
420
|
+
* order, then its CSS after the marker, in a file of its own when CSS
|
|
421
|
+
* precedes the marker too. A carrier left empty is kept, unlinked, for a
|
|
422
|
+
* lazy chunk that names it. The build fails when no page links the
|
|
423
|
+
* carrier: its stylesheet loads with a lazy chunk, or no page is built.
|
|
424
|
+
*/
|
|
425
|
+
function placeStylesheetSlices(ctx, bundle, sliceIds, emitAsset, replace) {
|
|
426
|
+
const fileOf = /* @__PURE__ */ new Map();
|
|
427
|
+
const pages = [];
|
|
428
|
+
const carriers = [];
|
|
429
|
+
for (const file of Object.values(bundle)) {
|
|
430
|
+
if (file.type !== "asset") continue;
|
|
431
|
+
if (file.fileName.endsWith(".html")) pages.push(file);
|
|
432
|
+
if (file.fileName.endsWith(".css") && SPLIT_STYLESHEET_MARKER_RE.test(String(file.source))) carriers.push(file);
|
|
433
|
+
const id = sliceIdOf(file, sliceIds);
|
|
434
|
+
if (id === void 0) continue;
|
|
435
|
+
const replacement = replace?.(file);
|
|
436
|
+
if (replacement === void 0 || replacement === null) {
|
|
437
|
+
fileOf.set(id, file.fileName);
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
delete bundle[file.fileName];
|
|
441
|
+
fileOf.set(id, replacement);
|
|
442
|
+
}
|
|
443
|
+
const slices = sliceIds.map((id) => {
|
|
444
|
+
const fileName = fileOf.get(id);
|
|
445
|
+
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.`);
|
|
446
|
+
return fileName;
|
|
447
|
+
});
|
|
448
|
+
if (carriers.length === 0) {
|
|
449
|
+
for (const fileName of slices) delete bundle[fileName];
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
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.`);
|
|
453
|
+
const carrier = carriers[0];
|
|
454
|
+
const text = String(carrier.source);
|
|
455
|
+
const marker = SPLIT_STYLESHEET_MARKER_RE.exec(text);
|
|
456
|
+
const before = text.slice(0, marker.index);
|
|
457
|
+
const after = text.slice(marker.index + marker[0].length);
|
|
458
|
+
const precedes = before.trim() !== "";
|
|
459
|
+
const follows = after.trim() !== "";
|
|
460
|
+
carrier.source = precedes ? before : after;
|
|
461
|
+
const rest = precedes && follows ? emitAsset(carrier.names[0] ?? "index.css", after) : null;
|
|
462
|
+
const sequence = [
|
|
463
|
+
...precedes ? [null] : [],
|
|
464
|
+
...slices,
|
|
465
|
+
...follows ? [rest] : []
|
|
466
|
+
];
|
|
467
|
+
let linked = false;
|
|
468
|
+
for (const page of pages) {
|
|
469
|
+
const html = Buffer.from(page.source).toString("utf8");
|
|
470
|
+
const carrierUrl = builtUrl(ctx, page.fileName, carrier.fileName);
|
|
471
|
+
page.source = html.replace(LINK_TAG_RE, (tag, offset) => {
|
|
472
|
+
const rel = attribute(tag, REL_RE)?.toLowerCase().split(/\s+/) ?? [];
|
|
473
|
+
const href = attribute(tag, HREF_RE);
|
|
474
|
+
if (!rel.includes("stylesheet") || href === void 0) return tag;
|
|
475
|
+
if (attributeText(href) !== carrierUrl) return tag;
|
|
476
|
+
linked = true;
|
|
477
|
+
const lineStart = html.lastIndexOf("\n", offset - 1) + 1;
|
|
478
|
+
const indent = /^[ \t]*/.exec(html.slice(lineStart))[0];
|
|
479
|
+
return sequence.map((fileName) => fileName === null ? tag : linkingInstead(tag, builtUrl(ctx, page.fileName, fileName), fileName === rest ? "" : " data-animus-stylesheet")).join(`\n${indent}`);
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
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.`);
|
|
483
|
+
}
|
|
484
|
+
//#endregion
|
|
485
|
+
//#region src/bundle-removal.ts
|
|
486
|
+
/**
|
|
487
|
+
* The removal of every component no output file of this client build
|
|
488
|
+
* includes, or `null` where the build keeps every component: it bundles
|
|
489
|
+
* another environment beside the client (`otherEnvironments`), whose output
|
|
490
|
+
* may render what the client's does not; it leaves a module external; it
|
|
491
|
+
* carries data the scan cannot read as text; or an output file other than
|
|
492
|
+
* Vite's `manifests` names a stylesheet slice, which a replacement would
|
|
493
|
+
* leave naming a deleted file. Every output file but the slices
|
|
494
|
+
* (`sliceIds`) and media is evidence, data URLs decoded.
|
|
495
|
+
*/
|
|
496
|
+
function bundleRemoval(ctx, bundle, sliceIds, context) {
|
|
497
|
+
const manifest = ctx.storedManifest;
|
|
498
|
+
if (!manifest) return null;
|
|
499
|
+
const keep = (why) => {
|
|
500
|
+
ctx.info(`kept every component's CSS: ${why}`);
|
|
501
|
+
return null;
|
|
502
|
+
};
|
|
503
|
+
const blocker = removalBlocker(bundle, context.otherEnvironments);
|
|
504
|
+
if (blocker !== null) return keep(blocker);
|
|
505
|
+
const slices = new Set(Object.values(bundle).filter((file) => sliceIdOf(file, sliceIds) !== void 0).map((file) => file.fileName));
|
|
506
|
+
const { texts, unreadable } = (0, _animus_ui_extract_pipeline.outputEvidence)(Object.values(bundle).map((file) => file.type === "chunk" ? {
|
|
507
|
+
fileName: file.fileName,
|
|
508
|
+
code: file.code
|
|
509
|
+
} : {
|
|
510
|
+
fileName: file.fileName,
|
|
511
|
+
bytes: Buffer.from(file.source)
|
|
512
|
+
}), slices);
|
|
513
|
+
if (unreadable !== null) return keep(`${unreadable} holds data the scan cannot read as text, which may name a class`);
|
|
514
|
+
for (const { fileName, text } of texts) for (const slice of slices) if (occurrences(text, node_path.posix.basename(slice)) > (context.manifests.has(fileName) ? occurrences(text, JSON.stringify(slice).slice(1, -1)) : 0)) return keep(`${fileName} names ${slice}, which a replacement would leave it naming`);
|
|
515
|
+
const components = manifest.components;
|
|
516
|
+
const removed = (0, _animus_ui_extract_pipeline.unbundledComponents)(components, (0, _animus_ui_extract_pipeline.shippedClasses)(texts.map(({ text }) => text), Object.values(components).map((component) => component.class_name)), new Set(Object.keys(ctx.options.staticCss?.components ?? {})));
|
|
517
|
+
const classes = new Set(removed.values());
|
|
518
|
+
let characters = 0;
|
|
519
|
+
const renamed = /* @__PURE__ */ new Map();
|
|
520
|
+
const went = /* @__PURE__ */ new Set();
|
|
521
|
+
const kept = /* @__PURE__ */ new Map();
|
|
522
|
+
const unread = /* @__PURE__ */ new Set();
|
|
523
|
+
return {
|
|
524
|
+
replace(file) {
|
|
525
|
+
const css = Buffer.from(file.source).toString("utf8");
|
|
526
|
+
let removal;
|
|
527
|
+
try {
|
|
528
|
+
removal = (0, _animus_ui_extract_pipeline.removeComponentRules)(css, classes, {
|
|
529
|
+
targets: ctx.lcssTargets,
|
|
530
|
+
keepDirSelector: ctx.options.keepDirSelector
|
|
531
|
+
});
|
|
532
|
+
} catch (error) {
|
|
533
|
+
ctx.warn(`[animus-extract] removeUnbundledComponents kept ${file.fileName} whole: Lightning CSS could not read it (${error instanceof Error ? error.message : String(error)})`);
|
|
534
|
+
for (const name of classes) if (css.includes(name)) unread.add(name);
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
for (const name of removal.went) went.add(name);
|
|
538
|
+
for (const [name, reason] of removal.kept) (0, _animus_ui_extract_pipeline.noteKept)(kept, name, reason);
|
|
539
|
+
const { css: pruned } = removal;
|
|
540
|
+
if (pruned === null) return null;
|
|
541
|
+
characters += css.length - pruned.length;
|
|
542
|
+
const extension = node_path.posix.extname(file.fileName);
|
|
543
|
+
const fileName = `${file.fileName.slice(0, -extension.length)}-${(0, _animus_ui_extract_pipeline.contentHash)(pruned).slice(0, 8)}${extension}`;
|
|
544
|
+
context.emit({
|
|
545
|
+
type: "asset",
|
|
546
|
+
fileName,
|
|
547
|
+
name: file.names[0],
|
|
548
|
+
originalFileName: file.originalFileNames[0],
|
|
549
|
+
source: pruned
|
|
550
|
+
});
|
|
551
|
+
renamed.set(file.fileName, fileName);
|
|
552
|
+
return fileName;
|
|
553
|
+
},
|
|
554
|
+
finish() {
|
|
555
|
+
for (const file of Object.values(bundle)) {
|
|
556
|
+
const imported = file.viteMetadata?.importedCss;
|
|
557
|
+
for (const [before, after] of renamed) if (imported?.delete(before)) imported.add(after);
|
|
558
|
+
if (file.type !== "asset" || !context.manifests.has(file.fileName)) continue;
|
|
559
|
+
let text = Buffer.from(file.source).toString("utf8");
|
|
560
|
+
for (const [before, after] of renamed) text = text.replaceAll(JSON.stringify(before).slice(1, -1), JSON.stringify(after).slice(1, -1));
|
|
561
|
+
file.source = text;
|
|
562
|
+
}
|
|
563
|
+
let count = 0;
|
|
564
|
+
let ruleless = 0;
|
|
565
|
+
const whole = /* @__PURE__ */ new Map();
|
|
566
|
+
for (const [id, className] of removed) {
|
|
567
|
+
const reason = kept.get(className) ?? (unread.has(className) ? "unreadable" : void 0);
|
|
568
|
+
if (went.has(className)) {
|
|
569
|
+
count += 1;
|
|
570
|
+
ctx.trace(`removed ${id} (${className}): no output file includes it`);
|
|
571
|
+
} else if (reason === void 0) {
|
|
572
|
+
ruleless += 1;
|
|
573
|
+
ctx.trace(`${id} (${className}): no output file includes it, and no rule names it`);
|
|
574
|
+
} else {
|
|
575
|
+
whole.set(reason, (whole.get(reason) ?? 0) + 1);
|
|
576
|
+
ctx.trace(`kept ${id} (${className}) whole, though no output file includes it: ${KEPT_WHOLE[reason]}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const keptWhole = [...whole].map(([reason, n]) => `${KEPT_WHOLE[reason]}: ${n}`).join(", ");
|
|
580
|
+
const wholeCount = [...whole.values()].reduce((sum, n) => sum + n, 0);
|
|
581
|
+
ctx.info(`removed the CSS of ${count} of ${Object.keys(components).length} components no output file includes (${characters} characters of the stylesheet)${wholeCount > 0 ? `; kept ${wholeCount} more whole (${keptWhole})` : ""}${ruleless > 0 ? `; with no rules to remove: ${ruleless}` : ""}`);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
/** Each reason, as the trace and the build's report print it. */
|
|
586
|
+
const KEPT_WHOLE = {
|
|
587
|
+
"shared-list": "shares a selector list with a kept component",
|
|
588
|
+
nested: "a rule naming it holds nested rules removal cannot prove unused",
|
|
589
|
+
conditional: "named only where a selector can match without it, or in a pseudo-class argument removal does not read, such as :not(), :has(), :host(), or an :is() or :where() with an alternative that does not need it",
|
|
590
|
+
unreadable: "in a stylesheet Lightning CSS could not read"
|
|
591
|
+
};
|
|
592
|
+
/** How many times `needle` occurs in `text`. */
|
|
593
|
+
function occurrences(text, needle) {
|
|
594
|
+
let count = 0;
|
|
595
|
+
for (let at = text.indexOf(needle); at !== -1; at = text.indexOf(needle, at + 1)) count += 1;
|
|
596
|
+
return count;
|
|
597
|
+
}
|
|
598
|
+
/** Why a client build keeps every component, or `null`. */
|
|
599
|
+
function removalBlocker(bundle, otherEnvironments) {
|
|
600
|
+
if (otherEnvironments.length > 0) return `this build also bundles ${otherEnvironments.join(", ")}, whose output may render what the client's does not`;
|
|
601
|
+
for (const file of Object.values(bundle)) {
|
|
602
|
+
if (file.type !== "chunk") continue;
|
|
603
|
+
const external = [...file.imports, ...file.dynamicImports].find((imported) => !(imported in bundle));
|
|
604
|
+
if (external !== void 0) return `the build leaves ${external} external, which may render components no output file includes`;
|
|
605
|
+
}
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
//#endregion
|
|
185
609
|
//#region src/config.ts
|
|
186
610
|
function applyResolvedConfig(ctx, config) {
|
|
187
611
|
ctx.isProd = config.command === "build";
|
|
@@ -218,51 +642,15 @@ function applyResolvedConfig(ctx, config) {
|
|
|
218
642
|
pattern: entry.find,
|
|
219
643
|
target: entry.replacement,
|
|
220
644
|
kind: "prefix"
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
const built = (0, _animus_ui_extract_pipeline.buildPathAliasesJson)(pairs, ctx.rootDir);
|
|
224
|
-
if (built) {
|
|
225
|
-
ctx.pathAliasesJson = built.json;
|
|
226
|
-
ctx.log(`Path aliases forwarded: ${built.count} entries`);
|
|
227
|
-
}
|
|
228
|
-
ctx.createSession();
|
|
229
|
-
}
|
|
230
|
-
//#endregion
|
|
231
|
-
//#region src/constants.ts
|
|
232
|
-
/**
|
|
233
|
-
* The namespace every virtual module here lives under; the `transform` guard
|
|
234
|
-
* matches on this same string so a rename cannot strand it.
|
|
235
|
-
*/
|
|
236
|
-
const VIRTUAL_PREFIX = "virtual:animus/";
|
|
237
|
-
const VIRTUAL_CSS_ID = `${VIRTUAL_PREFIX}styles.css`;
|
|
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?/;
|
|
251
|
-
const VIRTUAL_COMPONENTS_ID = `${VIRTUAL_PREFIX}components.js`;
|
|
252
|
-
const RESOLVED_COMPONENTS_ID = `\0${VIRTUAL_COMPONENTS_ID}`;
|
|
253
|
-
const VIRTUAL_BRIDGE_ID = `${VIRTUAL_PREFIX}hmr-bridge.js`;
|
|
254
|
-
const RESOLVED_BRIDGE_ID = `\0${VIRTUAL_BRIDGE_ID}`;
|
|
255
|
-
/**
|
|
256
|
-
* Vite reserves `/@id/` for module ids that are not file paths and strips the
|
|
257
|
-
* prefix before `resolveId`, so the unprefixed specifier travels here.
|
|
258
|
-
*/
|
|
259
|
-
const BRIDGE_SCRIPT_SRC = `/@id/${VIRTUAL_BRIDGE_ID}`;
|
|
260
|
-
const VIRTUAL_SYSTEM_PROPS_ID = `${VIRTUAL_PREFIX}system-props`;
|
|
261
|
-
const RESOLVED_SYSTEM_PROPS_ID = `\0${VIRTUAL_SYSTEM_PROPS_ID}`;
|
|
262
|
-
/** The faces this build preloads, with the URL each file is preloaded at:
|
|
263
|
-
* the module every host serves under this id. */
|
|
264
|
-
const VIRTUAL_FONT_PRELOADS_ID = _animus_ui_extract_session.FONT_PRELOADS_MODULE_ID;
|
|
265
|
-
const RESOLVED_FONT_PRELOADS_ID = `\0${VIRTUAL_FONT_PRELOADS_ID}`;
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
const built = (0, _animus_ui_extract_pipeline.buildPathAliasesJson)(pairs, ctx.rootDir);
|
|
648
|
+
if (built) {
|
|
649
|
+
ctx.pathAliasesJson = built.json;
|
|
650
|
+
ctx.log(`Path aliases forwarded: ${built.count} entries`);
|
|
651
|
+
}
|
|
652
|
+
ctx.createSession();
|
|
653
|
+
}
|
|
266
654
|
//#endregion
|
|
267
655
|
//#region src/hot-update-events.ts
|
|
268
656
|
/**
|
|
@@ -1368,255 +1756,6 @@ function invalidateStaleModules(ctx, environment, modules, analyzed) {
|
|
|
1368
1756
|
}
|
|
1369
1757
|
}
|
|
1370
1758
|
//#endregion
|
|
1371
|
-
//#region src/index-html.ts
|
|
1372
|
-
const LINK_TAG_RE = /<link\b[^>]*>/gi;
|
|
1373
|
-
/** Marks the preloads Animus writes, so another preload of the same file
|
|
1374
|
-
* can be told from Animus's own. */
|
|
1375
|
-
const ANIMUS_PRELOAD_MARKER = "data-animus-preload";
|
|
1376
|
-
const MARKER_RE = /\sdata-animus-preload(?=[\s=/>])/i;
|
|
1377
|
-
const REL_RE = /\srel\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
|
|
1378
|
-
const HREF_RE = /\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
|
|
1379
|
-
function attribute(tag, re) {
|
|
1380
|
-
const match = re.exec(tag);
|
|
1381
|
-
return match ? match[1] ?? match[2] ?? match[3] : void 0;
|
|
1382
|
-
}
|
|
1383
|
-
/** Each `<link rel="preload">` in `html`, with its href. */
|
|
1384
|
-
function* preloadLinks(html) {
|
|
1385
|
-
for (const [tag] of html.matchAll(LINK_TAG_RE)) {
|
|
1386
|
-
const rel = attribute(tag, REL_RE)?.toLowerCase().split(/\s+/) ?? [];
|
|
1387
|
-
const href = attribute(tag, HREF_RE);
|
|
1388
|
-
if (rel.includes("preload") && href !== void 0) yield [tag, href];
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
const ENTITY_RE = /&(?:#x([0-9a-f]+)|#(\d+)|(amp|lt|gt|quot|apos));/gi;
|
|
1392
|
-
const NAMED_ENTITIES = /* @__PURE__ */ new Map([
|
|
1393
|
-
["amp", "&"],
|
|
1394
|
-
["lt", "<"],
|
|
1395
|
-
["gt", ">"],
|
|
1396
|
-
["quot", "\""],
|
|
1397
|
-
["apos", "'"]
|
|
1398
|
-
]);
|
|
1399
|
-
/** An attribute value as the browser reads it: character references decoded. */
|
|
1400
|
-
function attributeText(value) {
|
|
1401
|
-
return value.replace(ENTITY_RE, (_, hex, decimal, named) => named === void 0 ? String.fromCodePoint(Number.parseInt(hex ?? decimal, hex ? 16 : 10)) : NAMED_ENTITIES.get(named.toLowerCase()));
|
|
1402
|
-
}
|
|
1403
|
-
/**
|
|
1404
|
-
* The hrefs a finished document preloads both through Animus's tag and
|
|
1405
|
-
* through another, which the page wrote or a hook running after Animus's
|
|
1406
|
-
* added: the browser may then fetch the file twice. Each href is compared
|
|
1407
|
-
* as the browser resolves it against `pageUrl`, the URL the page is served
|
|
1408
|
-
* at, and reported as Animus wrote it.
|
|
1409
|
-
*/
|
|
1410
|
-
function duplicatedFontPreloads(html, pageUrl) {
|
|
1411
|
-
const resolved = (href) => {
|
|
1412
|
-
try {
|
|
1413
|
-
return new URL(attributeText(href), pageUrl).href;
|
|
1414
|
-
} catch {
|
|
1415
|
-
return href;
|
|
1416
|
-
}
|
|
1417
|
-
};
|
|
1418
|
-
const ours = /* @__PURE__ */ new Map();
|
|
1419
|
-
const others = /* @__PURE__ */ new Set();
|
|
1420
|
-
for (const [tag, href] of preloadLinks(html)) if (MARKER_RE.test(tag)) ours.set(resolved(href), href);
|
|
1421
|
-
else others.add(resolved(href));
|
|
1422
|
-
return [...ours].filter(([url]) => others.has(url)).map(([, href]) => href);
|
|
1423
|
-
}
|
|
1424
|
-
/** The hrefs the document already preloads. */
|
|
1425
|
-
function preloadedHrefs(html) {
|
|
1426
|
-
return new Set([...preloadLinks(html)].map(([, href]) => href));
|
|
1427
|
-
}
|
|
1428
|
-
/** The head elements Animus's tags go after (the charset and viewport
|
|
1429
|
-
* metas), the stylesheets they go before, and what holds neither. */
|
|
1430
|
-
const HEAD_SCAN_RE = /<!--[\s\S]*?-->|<script\b[\s\S]*?<\/script\s*>|<\/head\s*>|<style\b|<(?:meta|link)\b[^>]*>/gi;
|
|
1431
|
-
/** Where Animus's head tags go: after the head's charset and viewport
|
|
1432
|
-
* metas, so they cannot push the charset past the 1024 bytes a browser
|
|
1433
|
-
* sniffs for it, and before its first stylesheet; -1 without a `<head>`. */
|
|
1434
|
-
function headTagOffset(html) {
|
|
1435
|
-
const open = /<head\b[^>]*>/i.exec(html);
|
|
1436
|
-
if (open === null) return -1;
|
|
1437
|
-
const start = open.index + open[0].length;
|
|
1438
|
-
let offset = start;
|
|
1439
|
-
for (const match of html.slice(start).matchAll(HEAD_SCAN_RE)) {
|
|
1440
|
-
const [element] = match;
|
|
1441
|
-
const lower = element.toLowerCase();
|
|
1442
|
-
if (lower.startsWith("</head") || lower.startsWith("<style")) break;
|
|
1443
|
-
if (lower.startsWith("<link")) {
|
|
1444
|
-
if ((attribute(element, REL_RE)?.toLowerCase().split(/\s+/))?.includes("stylesheet")) break;
|
|
1445
|
-
} else if (lower.startsWith("<meta") && (/\scharset\s*=/i.test(element) || /\shttp-equiv\s*=\s*["']?content-type\b/i.test(element) || /\sname\s*=\s*["']?viewport\b/i.test(element))) offset = start + match.index + element.length;
|
|
1446
|
-
}
|
|
1447
|
-
return offset;
|
|
1448
|
-
}
|
|
1449
|
-
/** As `escape-html` escapes, which Vite applies to attribute values. */
|
|
1450
|
-
function escapeHtml(value) {
|
|
1451
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1452
|
-
}
|
|
1453
|
-
/** A tag as Vite serializes it, `children` as written, except that an
|
|
1454
|
-
* undefined attribute is left out rather than written "undefined". */
|
|
1455
|
-
function serializeTag({ tag, attrs = {}, children }) {
|
|
1456
|
-
const serialized = Object.entries(attrs).map(([key, value]) => {
|
|
1457
|
-
if (value === true) return ` ${key}`;
|
|
1458
|
-
if (value === false || value === void 0) return "";
|
|
1459
|
-
return ` ${key}="${escapeHtml(value)}"`;
|
|
1460
|
-
}).join("");
|
|
1461
|
-
if (tag === "link" || tag === "meta" || tag === "base") return `<${tag}${serialized}>`;
|
|
1462
|
-
return `<${tag}${serialized}>${Array.isArray(children) ? "" : children ?? ""}</${tag}>`;
|
|
1463
|
-
}
|
|
1464
|
-
/**
|
|
1465
|
-
* The hook's result: the tags written after the charset and viewport metas,
|
|
1466
|
-
* each on its own line indented as the element it follows, so the charset
|
|
1467
|
-
* stays in the first 1024 bytes however long the tags are; as `head-prepend`
|
|
1468
|
-
* tags for a document without a `<head>`.
|
|
1469
|
-
*/
|
|
1470
|
-
function injectHeadTags(html, tags) {
|
|
1471
|
-
const offset = headTagOffset(html);
|
|
1472
|
-
if (offset === -1) return tags;
|
|
1473
|
-
if (tags.length === 0) return html;
|
|
1474
|
-
const lineStart = html.lastIndexOf("\n", offset - 1) + 1;
|
|
1475
|
-
const indent = /^[ \t]*/.exec(html.slice(lineStart))[0];
|
|
1476
|
-
const inserted = tags.map((tag) => `\n${indent}${serializeTag(tag)}`).join("");
|
|
1477
|
-
return html.slice(0, offset) + inserted + html.slice(offset);
|
|
1478
|
-
}
|
|
1479
|
-
/** The preloads for the faces that ask for one, each marked as Animus's;
|
|
1480
|
-
* one the document already preloads is left out. */
|
|
1481
|
-
function fontPreloadTags(ctx, html) {
|
|
1482
|
-
if (!ctx.served?.fontPreloads.length) return [];
|
|
1483
|
-
const existing = preloadedHrefs(html);
|
|
1484
|
-
return ctx.fontPreloads.filter(({ href }) => !existing.has(href)).map(({ href, type, fetchpriority }) => {
|
|
1485
|
-
const attrs = {
|
|
1486
|
-
rel: "preload",
|
|
1487
|
-
href,
|
|
1488
|
-
as: "font"
|
|
1489
|
-
};
|
|
1490
|
-
if (type !== void 0) attrs.type = type;
|
|
1491
|
-
if (fetchpriority !== void 0) attrs.fetchpriority = fetchpriority;
|
|
1492
|
-
attrs.crossorigin = true;
|
|
1493
|
-
attrs[ANIMUS_PRELOAD_MARKER] = true;
|
|
1494
|
-
return {
|
|
1495
|
-
tag: "link",
|
|
1496
|
-
attrs,
|
|
1497
|
-
injectTo: "head-prepend"
|
|
1498
|
-
};
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
/**
|
|
1502
|
-
* Animus's head tags in document order: the bootstrap script, so it runs
|
|
1503
|
-
* before first paint and ahead of every stylesheet, the layer declaration,
|
|
1504
|
-
* the font preloads, then the development bridge.
|
|
1505
|
-
*/
|
|
1506
|
-
function buildIndexHtmlTags(ctx, html = "") {
|
|
1507
|
-
const tags = [];
|
|
1508
|
-
const bootstrap = ctx.options.appearanceBootstrap;
|
|
1509
|
-
if (bootstrap?.code) tags.push({
|
|
1510
|
-
tag: "script",
|
|
1511
|
-
attrs: { "data-animus-bootstrap": "" },
|
|
1512
|
-
children: bootstrap.code,
|
|
1513
|
-
injectTo: "head-prepend"
|
|
1514
|
-
});
|
|
1515
|
-
if (ctx.layerDeclaration) tags.push({
|
|
1516
|
-
tag: "style",
|
|
1517
|
-
attrs: { "data-animus-layers": "" },
|
|
1518
|
-
children: ctx.layerDeclaration,
|
|
1519
|
-
injectTo: "head-prepend"
|
|
1520
|
-
});
|
|
1521
|
-
tags.push(...fontPreloadTags(ctx, html));
|
|
1522
|
-
if (!ctx.isProd) tags.push({
|
|
1523
|
-
tag: "script",
|
|
1524
|
-
attrs: {
|
|
1525
|
-
type: "module",
|
|
1526
|
-
src: BRIDGE_SCRIPT_SRC,
|
|
1527
|
-
"data-animus-bridge": ""
|
|
1528
|
-
},
|
|
1529
|
-
injectTo: "head-prepend"
|
|
1530
|
-
});
|
|
1531
|
-
return tags;
|
|
1532
|
-
}
|
|
1533
|
-
/**
|
|
1534
|
-
* A built file's URL in a page, as Vite writes its own links: the host's
|
|
1535
|
-
* `renderBuiltUrl` first, then relative to the page under a relative base,
|
|
1536
|
-
* else under the base.
|
|
1537
|
-
*/
|
|
1538
|
-
function builtUrl(ctx, page, fileName) {
|
|
1539
|
-
let relative = ctx.base === "" || ctx.base === "./";
|
|
1540
|
-
const rendered = ctx.renderBuiltUrl?.(fileName, {
|
|
1541
|
-
hostId: page,
|
|
1542
|
-
hostType: "html",
|
|
1543
|
-
type: "asset",
|
|
1544
|
-
ssr: false
|
|
1545
|
-
});
|
|
1546
|
-
if (rendered instanceof Object) {
|
|
1547
|
-
if (rendered.runtime !== void 0) throw new Error(`[animus-extract] renderBuiltUrl returned { runtime } for ${fileName}, which a page's <link> cannot load`);
|
|
1548
|
-
if (rendered.relative !== void 0) relative = rendered.relative;
|
|
1549
|
-
} else if (rendered) return rendered;
|
|
1550
|
-
if (relative) return `${path.posix.join(path.posix.relative(page, "").slice(0, -2), "./")}${fileName}`;
|
|
1551
|
-
return `${decodeURI(ctx.base).replace(/\/$/, "")}/${fileName}`;
|
|
1552
|
-
}
|
|
1553
|
-
/** `tag`, a stylesheet link, linking `href` instead, with `attributes`. */
|
|
1554
|
-
function linkingInstead(tag, href, attributes = "") {
|
|
1555
|
-
return tag.replace(HREF_RE, ` href="${escapeHtml(href)}"`).replace(/\s*\/?>$/, `${attributes}>`);
|
|
1556
|
-
}
|
|
1557
|
-
/**
|
|
1558
|
-
* Puts a split build's slices where the single stylesheet would have been.
|
|
1559
|
-
* The stylesheet module held only a marker rule, so it kept its place in
|
|
1560
|
-
* Vite's CSS: the file holding the marker is cut there, and each page's
|
|
1561
|
-
* link to it becomes the file's CSS before the marker, the slices in
|
|
1562
|
-
* order, then its CSS after the marker, in a file of its own when CSS
|
|
1563
|
-
* precedes the marker too. A carrier left empty is kept, unlinked, for a
|
|
1564
|
-
* lazy chunk that names it. The build fails when no page links the
|
|
1565
|
-
* carrier: its stylesheet loads with a lazy chunk, or no page is built.
|
|
1566
|
-
*/
|
|
1567
|
-
function placeStylesheetSlices(ctx, bundle, sliceIds, emitAsset) {
|
|
1568
|
-
const fileOf = /* @__PURE__ */ new Map();
|
|
1569
|
-
const pages = [];
|
|
1570
|
-
const carriers = [];
|
|
1571
|
-
for (const file of Object.values(bundle)) {
|
|
1572
|
-
if (file.type !== "asset") continue;
|
|
1573
|
-
if (file.fileName.endsWith(".html")) pages.push(file);
|
|
1574
|
-
if (file.fileName.endsWith(".css") && SPLIT_STYLESHEET_MARKER_RE.test(String(file.source))) carriers.push(file);
|
|
1575
|
-
const id = sliceIds.find((slice) => file.originalFileNames.some((name) => name.endsWith(slice)));
|
|
1576
|
-
if (id !== void 0) fileOf.set(id, file.fileName);
|
|
1577
|
-
}
|
|
1578
|
-
const slices = sliceIds.map((id) => {
|
|
1579
|
-
const fileName = fileOf.get(id);
|
|
1580
|
-
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.`);
|
|
1581
|
-
return fileName;
|
|
1582
|
-
});
|
|
1583
|
-
if (carriers.length === 0) {
|
|
1584
|
-
for (const fileName of slices) delete bundle[fileName];
|
|
1585
|
-
return;
|
|
1586
|
-
}
|
|
1587
|
-
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.`);
|
|
1588
|
-
const carrier = carriers[0];
|
|
1589
|
-
const text = String(carrier.source);
|
|
1590
|
-
const marker = SPLIT_STYLESHEET_MARKER_RE.exec(text);
|
|
1591
|
-
const before = text.slice(0, marker.index);
|
|
1592
|
-
const after = text.slice(marker.index + marker[0].length);
|
|
1593
|
-
const precedes = before.trim() !== "";
|
|
1594
|
-
const follows = after.trim() !== "";
|
|
1595
|
-
carrier.source = precedes ? before : after;
|
|
1596
|
-
const rest = precedes && follows ? emitAsset(carrier.names[0] ?? "index.css", after) : null;
|
|
1597
|
-
const sequence = [
|
|
1598
|
-
...precedes ? [null] : [],
|
|
1599
|
-
...slices,
|
|
1600
|
-
...follows ? [rest] : []
|
|
1601
|
-
];
|
|
1602
|
-
let linked = false;
|
|
1603
|
-
for (const page of pages) {
|
|
1604
|
-
const html = Buffer.from(page.source).toString("utf8");
|
|
1605
|
-
const carrierUrl = builtUrl(ctx, page.fileName, carrier.fileName);
|
|
1606
|
-
page.source = html.replace(LINK_TAG_RE, (tag, offset) => {
|
|
1607
|
-
const rel = attribute(tag, REL_RE)?.toLowerCase().split(/\s+/) ?? [];
|
|
1608
|
-
const href = attribute(tag, HREF_RE);
|
|
1609
|
-
if (!rel.includes("stylesheet") || href === void 0) return tag;
|
|
1610
|
-
if (attributeText(href) !== carrierUrl) return tag;
|
|
1611
|
-
linked = true;
|
|
1612
|
-
const lineStart = html.lastIndexOf("\n", offset - 1) + 1;
|
|
1613
|
-
const indent = /^[ \t]*/.exec(html.slice(lineStart))[0];
|
|
1614
|
-
return sequence.map((fileName) => fileName === null ? tag : linkingInstead(tag, builtUrl(ctx, page.fileName, fileName), fileName === rest ? "" : " data-animus-stylesheet")).join(`\n${indent}`);
|
|
1615
|
-
});
|
|
1616
|
-
}
|
|
1617
|
-
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.`);
|
|
1618
|
-
}
|
|
1619
|
-
//#endregion
|
|
1620
1759
|
//#region src/quarantine-plugin.ts
|
|
1621
1760
|
/**
|
|
1622
1761
|
* layergate's Vite plugin for the `quarantine` option, loaded on first use:
|
|
@@ -1836,7 +1975,8 @@ function animusExtract(options) {
|
|
|
1836
1975
|
(0, _animus_ui_extract_pipeline.assertKnownOptionKeys)(options, [
|
|
1837
1976
|
"verify",
|
|
1838
1977
|
"appearanceBootstrap",
|
|
1839
|
-
"quarantine"
|
|
1978
|
+
"quarantine",
|
|
1979
|
+
"removeUnbundledComponents"
|
|
1840
1980
|
], [{
|
|
1841
1981
|
key: "root",
|
|
1842
1982
|
reason: "the Vite driver derives its root from the resolved Vite config"
|
|
@@ -1844,6 +1984,8 @@ function animusExtract(options) {
|
|
|
1844
1984
|
onUnknownKey: "warn",
|
|
1845
1985
|
warn: (message) => console.warn(`[animus-extract] ${message}`)
|
|
1846
1986
|
});
|
|
1987
|
+
const removes = options.removeUnbundledComponents === true;
|
|
1988
|
+
if (removes && options.stylesheets !== "split") throw new _animus_ui_extract_pipeline.AnimusConfigError("removeUnbundledComponents needs stylesheets: 'split': it removes CSS from the stylesheet's own files, which only a split build emits after its scripts.");
|
|
1847
1989
|
const vendor = options.quarantine ? quarantinePlugin(options.quarantine, options.layers) : null;
|
|
1848
1990
|
const ctx = new PluginContext(vendor ? {
|
|
1849
1991
|
...options,
|
|
@@ -1855,6 +1997,8 @@ function animusExtract(options) {
|
|
|
1855
1997
|
const layergate = await vendor?.plugin();
|
|
1856
1998
|
return layergate ? await layergate.stylesheetHead.call(context, RESOLVED_CSS_ID) + sheet : sheet;
|
|
1857
1999
|
}
|
|
2000
|
+
let otherEnvironments = [];
|
|
2001
|
+
let manifests = /* @__PURE__ */ new Set();
|
|
1858
2002
|
let slices = /* @__PURE__ */ new Map();
|
|
1859
2003
|
let linkedSlices = [];
|
|
1860
2004
|
return {
|
|
@@ -1888,6 +2032,9 @@ function animusExtract(options) {
|
|
|
1888
2032
|
},
|
|
1889
2033
|
async configResolved(config) {
|
|
1890
2034
|
applyResolvedConfig(ctx, config);
|
|
2035
|
+
otherEnvironments = config.builder ? Object.keys(config.environments).filter((name) => name !== "client") : [];
|
|
2036
|
+
const { manifest, ssrManifest } = config.build;
|
|
2037
|
+
manifests = /* @__PURE__ */ new Set([...manifest === true ? [".vite/manifest.json"] : manifest ? [manifest] : [], ...ssrManifest === true ? [".vite/ssr-manifest.json"] : ssrManifest ? [ssrManifest] : []]);
|
|
1891
2038
|
(await vendor?.plugin())?.configResolved.call(this, config);
|
|
1892
2039
|
},
|
|
1893
2040
|
async buildEnd() {
|
|
@@ -1957,11 +2104,20 @@ function animusExtract(options) {
|
|
|
1957
2104
|
generateBundle: {
|
|
1958
2105
|
order: "post",
|
|
1959
2106
|
handler(_output, bundle) {
|
|
1960
|
-
|
|
2107
|
+
const emitAsset = (name, source) => this.getFileName(this.emitFile({
|
|
1961
2108
|
type: "asset",
|
|
1962
2109
|
name,
|
|
1963
2110
|
source
|
|
1964
|
-
}))
|
|
2111
|
+
}));
|
|
2112
|
+
if (linkedSlices.length > 0 && isClient(this)) {
|
|
2113
|
+
const removal = removes ? bundleRemoval(ctx, bundle, linkedSlices, {
|
|
2114
|
+
otherEnvironments,
|
|
2115
|
+
manifests,
|
|
2116
|
+
emit: (asset) => this.emitFile(asset)
|
|
2117
|
+
}) : null;
|
|
2118
|
+
placeStylesheetSlices(ctx, bundle, linkedSlices, emitAsset, removal ? (file) => removal.replace(file) : void 0);
|
|
2119
|
+
removal?.finish();
|
|
2120
|
+
}
|
|
1965
2121
|
if (ctx.servedDirSelector && !ctx.warnedLoweredDir && isClient(this)) {
|
|
1966
2122
|
const sheets = Object.values(bundle).flatMap((file) => file.type === "asset" && file.fileName.endsWith(".css") ? [file.source] : []);
|
|
1967
2123
|
if (sheets.length > 0 && sheets.every((source) => !Buffer.from(source).toString("utf8").includes(":dir("))) {
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,16 @@ export interface AnimusExtractOptions {
|
|
|
44
44
|
* hash. Needs a page Vite builds from HTML to link the stylesheet; the
|
|
45
45
|
* dev server keeps one sheet. */
|
|
46
46
|
stylesheets?: StylesheetDelivery;
|
|
47
|
+
/** With `stylesheets: 'split'`, removes from the stylesheet's files the
|
|
48
|
+
* CSS of every component whose definition no output file includes, so it
|
|
49
|
+
* can never render; a component `staticCss` declares, and a parent of
|
|
50
|
+
* one kept, stay. A build that bundles another environment beside the
|
|
51
|
+
* client, or leaves a module external, keeps every component. Scripts a
|
|
52
|
+
* plugin emits after Animus's `generateBundle` are not seen, and a
|
|
53
|
+
* stylesheet shared with code outside the build (micro-frontends, module
|
|
54
|
+
* federation) is unsupported with this on. Off by default, and in
|
|
55
|
+
* development. */
|
|
56
|
+
removeUnbundledComponents?: boolean;
|
|
47
57
|
/**
|
|
48
58
|
* Substrings, or globs when `*`/`?` present. Replaces the defaults `dist`,
|
|
49
59
|
* `.test.`, `.spec.`; `node_modules`, `.next`, `.animus` always apply.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0CA,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;;;;yBAIqB;IACrB,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC;;;;;;;sCAOkC;IAClC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;;;;;;uBAQmB;IACnB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;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;;;;yDAIqD;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;0DAMsD;IACtD,eAAe,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC;4DACwD;IACxD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC;;;;;0DAKsD;IACtD,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,CA8UnE;eAEc,aAAa"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@animus-ui/vite-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.51",
|
|
4
4
|
"description": "Animus static CSS extraction Vite plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"animus",
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"compile": "bun check"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@animus-ui/extract": "0.1.
|
|
46
|
+
"@animus-ui/extract": "0.1.51",
|
|
47
47
|
"browserslist": "^4.28.8",
|
|
48
48
|
"lightningcss": "^1.33.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@animus-ui/assertions": "0.1.
|
|
52
|
-
"@animus-ui/layergate": "0.1.
|
|
51
|
+
"@animus-ui/assertions": "0.1.51",
|
|
52
|
+
"@animus-ui/layergate": "0.1.51"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@animus-ui/layergate": "0.1.
|
|
55
|
+
"@animus-ui/layergate": "0.1.51",
|
|
56
56
|
"vite": ">=8 <9"
|
|
57
57
|
},
|
|
58
58
|
"peerDependenciesMeta": {
|