@astroscope/node 3.1.0 → 3.1.1
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/index.js +1 -1
- package/dist/islands-middleware-entrypoint.js +26 -6
- package/dist/islands-middleware-entrypoint.js.map +1 -1
- package/dist/{prerendered-Z-Qi-FFK.js → prerendered-IQFslGSg.js} +2 -2
- package/dist/{prerendered-Z-Qi-FFK.js.map → prerendered-IQFslGSg.js.map} +1 -1
- package/dist/{transform-Bz5z5w2Y.js → transform-YUFkHwZC.js} +17 -8
- package/dist/{transform-Bz5z5w2Y.js.map → transform-YUFkHwZC.js.map} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -904,7 +904,7 @@ function node(options = {}) {
|
|
|
904
904
|
if (islandsEnabled) {
|
|
905
905
|
const manifestPath = path.join(fileURLToPath(astroConfig.build.server), "chunks", "islands-manifest.json");
|
|
906
906
|
if (fs.existsSync(manifestPath)) {
|
|
907
|
-
const { transformPrerenderedHtml } = await import("./prerendered-
|
|
907
|
+
const { transformPrerenderedHtml } = await import("./prerendered-IQFslGSg.js");
|
|
908
908
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
909
909
|
const transformed = transformPrerenderedHtml(fileURLToPath(astroConfig.build.client), manifest);
|
|
910
910
|
if (transformed > 0) logger.info(`island preloading applied to ${transformed} prerendered page(s)`);
|
|
@@ -2,7 +2,7 @@ import { n as log } from "./log-B69HEBvg.js";
|
|
|
2
2
|
import { t as getDocumentEmitters } from "./emitters-C20tjKLp.js";
|
|
3
3
|
import { t as getRequestRouteData } from "./route-store-DVSmOa34.js";
|
|
4
4
|
import { n as installRouteIslands } from "./routes-D1o_WrJ5.js";
|
|
5
|
-
import { n as createPageTransformStream, t as createIslandsTransformer } from "./transform-
|
|
5
|
+
import { n as createPageTransformStream, t as createIslandsTransformer } from "./transform-YUFkHwZC.js";
|
|
6
6
|
import { manifest } from "virtual:@astroscope/node/islands-manifest";
|
|
7
7
|
//#region src/islands/middleware.ts
|
|
8
8
|
/**
|
|
@@ -10,10 +10,15 @@ import { manifest } from "virtual:@astroscope/node/islands-manifest";
|
|
|
10
10
|
* rewriter (when a manifest exists — prod with preloading enabled) plus the
|
|
11
11
|
* document emissions registered by other packages, head scripts inserted after
|
|
12
12
|
* `<head>` and end scripts appended once the rewriter finished. Non-page routes
|
|
13
|
-
* (an endpoint or proxy catch-all returning html), non-html responses
|
|
14
|
-
* already-encoded bodies
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* (an endpoint or proxy catch-all returning html), non-html responses,
|
|
14
|
+
* already-encoded bodies and html declaring a charset other than utf-8 pass
|
|
15
|
+
* through untouched: the transform decodes and re-encodes the body as utf-8, so
|
|
16
|
+
* it cannot preserve any other encoding. Astro renders pages through a
|
|
17
|
+
* `TextEncoder` and labels them a bare `text/html`, so a transformed response
|
|
18
|
+
* gets `charset=utf-8` stated explicitly — a browser only pre-scans the first
|
|
19
|
+
* bytes for a `<meta charset>`, and a large head emission would push the tag
|
|
20
|
+
* past that window. Injected bytes invalidate a pre-computed length, so
|
|
21
|
+
* `content-length` is dropped — streamed responses never carry one anyway.
|
|
17
22
|
*/
|
|
18
23
|
function createIslandsMiddleware(manifest) {
|
|
19
24
|
let transformer;
|
|
@@ -24,7 +29,7 @@ function createIslandsMiddleware(manifest) {
|
|
|
24
29
|
const route = getRequestRouteData(context);
|
|
25
30
|
if (route && route.type !== "page") return response;
|
|
26
31
|
const contentType = response.headers.get("content-type") ?? "";
|
|
27
|
-
if (!response.body || !contentType
|
|
32
|
+
if (!response.body || !isHtml(contentType) || !isUtf8Compatible(contentType) || response.headers.has("content-encoding")) return response;
|
|
28
33
|
const heads = [];
|
|
29
34
|
const ends = [];
|
|
30
35
|
for (const emitter of emitters) try {
|
|
@@ -43,6 +48,7 @@ function createIslandsMiddleware(manifest) {
|
|
|
43
48
|
});
|
|
44
49
|
const headers = new Headers(response.headers);
|
|
45
50
|
headers.delete("content-length");
|
|
51
|
+
headers.set("content-type", withUtf8Charset(contentType));
|
|
46
52
|
return new Response(response.body.pipeThrough(stream), {
|
|
47
53
|
status: response.status,
|
|
48
54
|
statusText: response.statusText,
|
|
@@ -50,6 +56,20 @@ function createIslandsMiddleware(manifest) {
|
|
|
50
56
|
});
|
|
51
57
|
};
|
|
52
58
|
}
|
|
59
|
+
function isHtml(contentType) {
|
|
60
|
+
return contentType.toLowerCase().includes("text/html");
|
|
61
|
+
}
|
|
62
|
+
function charsetOf(contentType) {
|
|
63
|
+
return /;\s*charset\s*=\s*"?([^";\s]+)/i.exec(contentType)?.[1]?.toLowerCase();
|
|
64
|
+
}
|
|
65
|
+
/** no declared charset means astro's utf-8 encoder produced the body */
|
|
66
|
+
function isUtf8Compatible(contentType) {
|
|
67
|
+
const charset = charsetOf(contentType);
|
|
68
|
+
return charset === void 0 || charset === "utf-8" || charset === "utf8";
|
|
69
|
+
}
|
|
70
|
+
function withUtf8Charset(contentType) {
|
|
71
|
+
return charsetOf(contentType) === void 0 ? `${contentType.trim()}; charset=utf-8` : contentType;
|
|
72
|
+
}
|
|
53
73
|
//#endregion
|
|
54
74
|
//#region src/islands/middleware-entrypoint.ts
|
|
55
75
|
installRouteIslands(manifest);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"islands-middleware-entrypoint.js","names":[],"sources":["../src/islands/middleware.ts","../src/islands/middleware-entrypoint.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRouteData } from '../server/route-store.js';\nimport { getDocumentEmitters } from './emitters.js';\nimport { type IslandsTransformer, createIslandsTransformer, createPageTransformStream } from './transform.js';\nimport type { IslandsManifest } from './types.js';\n\n/**\n * Streams every html page response through the delivery pipeline: the islands\n * rewriter (when a manifest exists — prod with preloading enabled) plus the\n * document emissions registered by other packages, head scripts inserted after\n * `<head>` and end scripts appended once the rewriter finished. Non-page routes\n * (an endpoint or proxy catch-all returning html), non-html responses
|
|
1
|
+
{"version":3,"file":"islands-middleware-entrypoint.js","names":[],"sources":["../src/islands/middleware.ts","../src/islands/middleware-entrypoint.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRouteData } from '../server/route-store.js';\nimport { getDocumentEmitters } from './emitters.js';\nimport { type IslandsTransformer, createIslandsTransformer, createPageTransformStream } from './transform.js';\nimport type { IslandsManifest } from './types.js';\n\n/**\n * Streams every html page response through the delivery pipeline: the islands\n * rewriter (when a manifest exists — prod with preloading enabled) plus the\n * document emissions registered by other packages, head scripts inserted after\n * `<head>` and end scripts appended once the rewriter finished. Non-page routes\n * (an endpoint or proxy catch-all returning html), non-html responses,\n * already-encoded bodies and html declaring a charset other than utf-8 pass\n * through untouched: the transform decodes and re-encodes the body as utf-8, so\n * it cannot preserve any other encoding. Astro renders pages through a\n * `TextEncoder` and labels them a bare `text/html`, so a transformed response\n * gets `charset=utf-8` stated explicitly — a browser only pre-scans the first\n * bytes for a `<meta charset>`, and a large head emission would push the tag\n * past that window. Injected bytes invalidate a pre-computed length, so\n * `content-length` is dropped — streamed responses never carry one anyway.\n */\nexport function createIslandsMiddleware(manifest: IslandsManifest | null): MiddlewareHandler {\n let transformer: IslandsTransformer | undefined;\n\n return async (context, next) => {\n const response = await next();\n const emitters = getDocumentEmitters();\n\n if (!manifest && emitters.length === 0) {\n return response;\n }\n\n const route = getRequestRouteData(context);\n\n if (route && route.type !== 'page') {\n return response;\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n\n if (\n !response.body ||\n !isHtml(contentType) ||\n !isUtf8Compatible(contentType) ||\n response.headers.has('content-encoding')\n ) {\n return response;\n }\n\n const heads: string[] = [];\n const ends: (() => string | null)[] = [];\n\n for (const emitter of emitters) {\n try {\n const emission = emitter(context);\n\n if (emission?.head) {\n heads.push(emission.head);\n }\n\n if (emission?.end) {\n ends.push(emission.end);\n }\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error }, 'document emitter failed');\n }\n }\n\n if (!manifest && heads.length === 0 && ends.length === 0) {\n return response;\n }\n\n if (manifest) {\n transformer ??= createIslandsTransformer(manifest);\n }\n\n const stream = createPageTransformStream({\n rewriter: transformer?.createDocumentRewriter(context),\n heads,\n ends,\n });\n\n const headers = new Headers(response.headers);\n\n headers.delete('content-length');\n headers.set('content-type', withUtf8Charset(contentType));\n\n return new Response(response.body.pipeThrough(stream), {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n };\n}\n\nfunction isHtml(contentType: string): boolean {\n return contentType.toLowerCase().includes('text/html');\n}\n\nfunction charsetOf(contentType: string): string | undefined {\n const match = /;\\s*charset\\s*=\\s*\"?([^\";\\s]+)/i.exec(contentType);\n\n return match?.[1]?.toLowerCase();\n}\n\n/** no declared charset means astro's utf-8 encoder produced the body */\nfunction isUtf8Compatible(contentType: string): boolean {\n const charset = charsetOf(contentType);\n\n return charset === undefined || charset === 'utf-8' || charset === 'utf8';\n}\n\nfunction withUtf8Charset(contentType: string): string {\n return charsetOf(contentType) === undefined ? `${contentType.trim()}; charset=utf-8` : contentType;\n}\n","import { manifest } from 'virtual:@astroscope/node/islands-manifest';\nimport { createIslandsMiddleware } from './middleware.js';\nimport { installRouteIslands } from './routes.js';\n\ninstallRouteIslands(manifest);\n\nexport const onRequest = createIslandsMiddleware(manifest);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,wBAAwB,UAAqD;CAC3F,IAAI;CAEJ,OAAO,OAAO,SAAS,SAAS;EAC9B,MAAM,WAAW,MAAM,KAAK;EAC5B,MAAM,WAAW,oBAAoB;EAErC,IAAI,CAAC,YAAY,SAAS,WAAW,GACnC,OAAO;EAGT,MAAM,QAAQ,oBAAoB,OAAO;EAEzC,IAAI,SAAS,MAAM,SAAS,QAC1B,OAAO;EAGT,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;EAE5D,IACE,CAAC,SAAS,QACV,CAAC,OAAO,WAAW,KACnB,CAAC,iBAAiB,WAAW,KAC7B,SAAS,QAAQ,IAAI,kBAAkB,GAEvC,OAAO;EAGT,MAAM,QAAkB,CAAC;EACzB,MAAM,OAAgC,CAAC;EAEvC,KAAK,MAAM,WAAW,UACpB,IAAI;GACF,MAAM,WAAW,QAAQ,OAAO;GAEhC,IAAI,UAAU,MACZ,MAAM,KAAK,SAAS,IAAI;GAG1B,IAAI,UAAU,KACZ,KAAK,KAAK,SAAS,GAAG;EAE1B,SAAS,OAAO;GAEd,IAAI,MAAM,EAAE,KAAK,MAAM,GAAG,yBAAyB;EACrD;EAGF,IAAI,CAAC,YAAY,MAAM,WAAW,KAAK,KAAK,WAAW,GACrD,OAAO;EAGT,IAAI,UACF,gBAAgB,yBAAyB,QAAQ;EAGnD,MAAM,SAAS,0BAA0B;GACvC,UAAU,aAAa,uBAAuB,OAAO;GACrD;GACA;EACF,CAAC;EAED,MAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;EAE5C,QAAQ,OAAO,gBAAgB;EAC/B,QAAQ,IAAI,gBAAgB,gBAAgB,WAAW,CAAC;EAExD,OAAO,IAAI,SAAS,SAAS,KAAK,YAAY,MAAM,GAAG;GACrD,QAAQ,SAAS;GACjB,YAAY,SAAS;GACrB;EACF,CAAC;CACH;AACF;AAEA,SAAS,OAAO,aAA8B;CAC5C,OAAO,YAAY,YAAY,CAAC,CAAC,SAAS,WAAW;AACvD;AAEA,SAAS,UAAU,aAAyC;CAG1D,OAFc,kCAAkC,KAAK,WAE1C,CAAC,GAAG,EAAE,EAAE,YAAY;AACjC;;AAGA,SAAS,iBAAiB,aAA8B;CACtD,MAAM,UAAU,UAAU,WAAW;CAErC,OAAO,YAAY,KAAA,KAAa,YAAY,WAAW,YAAY;AACrE;AAEA,SAAS,gBAAgB,aAA6B;CACpD,OAAO,UAAU,WAAW,MAAM,KAAA,IAAY,GAAG,YAAY,KAAK,EAAE,mBAAmB;AACzF;;;AChHA,oBAAoB,QAAQ;AAE5B,MAAa,YAAY,wBAAwB,QAAQ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createIslandsTransformer } from "./transform-
|
|
1
|
+
import { t as createIslandsTransformer } from "./transform-YUFkHwZC.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
//#region src/islands/prerendered.ts
|
|
@@ -31,4 +31,4 @@ function transformPrerenderedHtml(clientDir, manifest) {
|
|
|
31
31
|
//#endregion
|
|
32
32
|
export { transformPrerenderedHtml };
|
|
33
33
|
|
|
34
|
-
//# sourceMappingURL=prerendered-
|
|
34
|
+
//# sourceMappingURL=prerendered-IQFslGSg.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerendered-
|
|
1
|
+
{"version":3,"file":"prerendered-IQFslGSg.js","names":[],"sources":["../src/islands/prerendered.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { createIslandsTransformer } from './transform.js';\nimport type { IslandsManifest } from './types.js';\n\nfunction* walkHtmlFiles(dir: string): Generator<string> {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n yield* walkHtmlFiles(full);\n } else if (entry.isFile() && entry.name.endsWith('.html')) {\n yield full;\n }\n }\n}\n\n/**\n * Prerendered pages never pass through the middleware — they get the same rewrite\n * once, at build time, before the client dir is compressed. Runs without a request\n * context, so registered emitters that need one contribute nothing here.\n */\nexport function transformPrerenderedHtml(clientDir: string, manifest: IslandsManifest): number {\n const transformer = createIslandsTransformer(manifest);\n let transformed = 0;\n\n for (const file of walkHtmlFiles(clientDir)) {\n const html = fs.readFileSync(file, 'utf-8');\n const rewriter = transformer.createDocumentRewriter();\n const result = rewriter.write(html) + rewriter.end();\n\n if (result !== html) {\n fs.writeFileSync(file, result);\n transformed++;\n }\n }\n\n return transformed;\n}\n"],"mappings":";;;;AAKA,UAAU,cAAc,KAAgC;CACtD,KAAK,MAAM,SAAS,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;EAChE,MAAM,OAAO,KAAK,KAAK,KAAK,MAAM,IAAI;EAEtC,IAAI,MAAM,YAAY,GACpB,OAAO,cAAc,IAAI;OACpB,IAAI,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,OAAO,GACtD,MAAM;CAEV;AACF;;;;;;AAOA,SAAgB,yBAAyB,WAAmB,UAAmC;CAC7F,MAAM,cAAc,yBAAyB,QAAQ;CACrD,IAAI,cAAc;CAElB,KAAK,MAAM,QAAQ,cAAc,SAAS,GAAG;EAC3C,MAAM,OAAO,GAAG,aAAa,MAAM,OAAO;EAC1C,MAAM,WAAW,YAAY,uBAAuB;EACpD,MAAM,SAAS,SAAS,MAAM,IAAI,IAAI,SAAS,IAAI;EAEnD,IAAI,WAAW,MAAM;GACnB,GAAG,cAAc,MAAM,MAAM;GAC7B;EACF;CACF;CAEA,OAAO;AACT"}
|
|
@@ -550,11 +550,22 @@ function createIslandsTransformer(manifest) {
|
|
|
550
550
|
return { createDocumentRewriter };
|
|
551
551
|
}
|
|
552
552
|
/**
|
|
553
|
+
* Head content goes before `</head>`, falling back to right after `<head>`, then
|
|
554
|
+
* the document start. End of head rather than start: meta charset, title etc come first
|
|
555
|
+
*/
|
|
556
|
+
function insertIntoHead(html, content) {
|
|
557
|
+
const close = html.search(/<\/head\s*>/i);
|
|
558
|
+
if (close !== -1) return html.slice(0, close) + content + html.slice(close);
|
|
559
|
+
const open = /<head[^>]*>/i.exec(html);
|
|
560
|
+
const at = open ? open.index + open[0].length : 0;
|
|
561
|
+
return html.slice(0, at) + content + html.slice(at);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
553
564
|
* The single streaming pass over an html page response: chunks go through the
|
|
554
|
-
* islands rewriter (when present), head content is inserted
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
565
|
+
* islands rewriter (when present), head content is inserted into `<head>` (which
|
|
566
|
+
* buffers the whole document — head content is dev-style delivery, where
|
|
567
|
+
* throughput is irrelevant), and end factories run last, strictly after every
|
|
568
|
+
* island passed the rewriter.
|
|
558
569
|
*/
|
|
559
570
|
function createPageTransformStream(options) {
|
|
560
571
|
const { rewriter, heads, ends } = options;
|
|
@@ -576,9 +587,7 @@ function createPageTransformStream(options) {
|
|
|
576
587
|
if (rewriter) tail = (tail ? rewriter.write(tail) : "") + rewriter.end();
|
|
577
588
|
if (buffered) {
|
|
578
589
|
const html = buffered.join("") + tail;
|
|
579
|
-
|
|
580
|
-
const at = head ? head.index + head[0].length : 0;
|
|
581
|
-
enqueue(controller, html.slice(0, at) + heads.join("") + html.slice(at));
|
|
590
|
+
enqueue(controller, insertIntoHead(html, heads.join("")));
|
|
582
591
|
} else enqueue(controller, tail);
|
|
583
592
|
for (const end of ends) try {
|
|
584
593
|
enqueue(controller, end() ?? "");
|
|
@@ -591,4 +600,4 @@ function createPageTransformStream(options) {
|
|
|
591
600
|
//#endregion
|
|
592
601
|
export { createPageTransformStream as n, createIslandsTransformer as t };
|
|
593
602
|
|
|
594
|
-
//# sourceMappingURL=transform-
|
|
603
|
+
//# sourceMappingURL=transform-YUFkHwZC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-Bz5z5w2Y.js","names":[],"sources":["../src/islands/rewriter.ts","../src/islands/transform.ts"],"sourcesContent":["/**\n * Streaming scanner that prepends handler html before `<astro-island …>` opening\n * tags. Everything else, the tag included, passes through byte-verbatim.\n *\n * It tokenizes only as far as needed to know when `<` starts an element. The\n * invariant is asymmetric: a missed island costs a preload, a false positive\n * would inject into a script or attribute — every deviation from the WHATWG\n * tokenizer errs towards not injecting, and the parse5 oracle test checks that.\n */\n\nexport type IslandTagRewrite = {\n /** html emitted immediately before the island opening tag */\n prepend?: string | undefined;\n};\n\nexport type IslandTagHandler = (attrs: Record<string, string>) => IslandTagRewrite | null;\n\nexport type IslandRewriter = {\n write(chunk: string): string;\n end(): string;\n};\n\nconst ISLAND = 'astro-island';\n// raw text by name alone, also inside `<svg>`/`<math>` where the browser would not — a real island cannot sit there\nconst RAW_TEXT = new Set(['style', 'textarea', 'title', 'xmp', 'iframe', 'noembed', 'noframes', 'noscript']);\n\n// longest marker a raw-text scan must be able to complete across a chunk boundary: `</script` plus its terminator\nconst RAW_TAIL = 9;\n\n// the named references astro's escaper emits; any other stays literal, which at worst mismatches a manifest url\nconst NAMED_ENTITIES: Record<string, string> = { amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\" };\n\n// numeric references in the C1 control range map to windows-1252 code points\nconst C1_REMAP: Record<number, number> = {\n 0x80: 0x20ac,\n 0x82: 0x201a,\n 0x83: 0x0192,\n 0x84: 0x201e,\n 0x85: 0x2026,\n 0x86: 0x2020,\n 0x87: 0x2021,\n 0x88: 0x02c6,\n 0x89: 0x2030,\n 0x8a: 0x0160,\n 0x8b: 0x2039,\n 0x8c: 0x0152,\n 0x8e: 0x017d,\n 0x91: 0x2018,\n 0x92: 0x2019,\n 0x93: 0x201c,\n 0x94: 0x201d,\n 0x95: 0x2022,\n 0x96: 0x2013,\n 0x97: 0x2014,\n 0x98: 0x02dc,\n 0x99: 0x2122,\n 0x9a: 0x0161,\n 0x9b: 0x203a,\n 0x9c: 0x0153,\n 0x9e: 0x017e,\n 0x9f: 0x0178,\n};\n\ntype Mode =\n | { kind: 'data' }\n | { kind: 'comment'; bangAt: number }\n | { kind: 'cdata' }\n | { kind: 'bogus' }\n | { kind: 'rawtext'; endTag: string }\n | { kind: 'script'; escape: 0 | 1 | 2 }\n | { kind: 'plaintext' };\n\nconst DATA: Mode = { kind: 'data' };\n\nexport function encodeAttribute(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<');\n}\n\nfunction isWhitespace(code: number): boolean {\n return code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0c || code === 0x0d;\n}\n\nfunction isLetter(code: number): boolean {\n return (code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a);\n}\n\n/** whitespace, `/` or `>`: what ends a tag name and what may follow an end tag name in raw text */\nfunction isTagEnd(code: number): boolean {\n return isWhitespace(code) || code === 0x2f || code === 0x3e;\n}\n\nfunction decodeAttribute(value: string): string {\n if (!value.includes('&') && !value.includes('\\r') && !value.includes('\\0')) {\n return value;\n }\n\n return value\n .replace(/\\r\\n?/g, '\\n')\n .replace(/\\0/g, '�')\n .replace(/&(?:#[xX]([0-9a-fA-F]+)|#([0-9]+)|([a-zA-Z][a-zA-Z0-9]*));/g, (match, hex, dec, name) => {\n if (name) {\n return NAMED_ENTITIES[name] ?? match;\n }\n\n const code = parseInt(hex ?? dec, hex ? 16 : 10);\n\n if (code === 0 || code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) {\n return '�';\n }\n\n return String.fromCodePoint(C1_REMAP[code] ?? code);\n });\n}\n\nconst NAMES_BY_LENGTH: Record<number, string[]> = {\n 3: ['xmp'],\n 5: ['style', 'title'],\n 6: ['script', 'iframe'],\n 7: ['noembed'],\n 8: ['noframes', 'noscript', 'textarea', 'template'],\n 9: ['plaintext'],\n 12: [ISLAND],\n};\n\nfunction equalsIgnoreCase(buf: string, start: number, name: string): boolean {\n for (let k = 0; k < name.length; k++) {\n if ((buf.charCodeAt(start + k) | 0x20) !== name.charCodeAt(k)) return false;\n }\n\n return true;\n}\n\n/**\n * reads a tag name from its start (just after `<` or `</`): the end of the name,\n * and the name itself only when it is one the scanner acts on — every other\n * tag passes through without allocating. null when not terminated in `buf`.\n */\nfunction readTagName(buf: string, i: number): { name: string | null; end: number } | null {\n const nameStart = i;\n\n while (i < buf.length && !isTagEnd(buf.charCodeAt(i))) i++;\n\n if (i >= buf.length) return null;\n\n const candidates = NAMES_BY_LENGTH[i - nameStart];\n const name = candidates?.find((candidate) => equalsIgnoreCase(buf, nameStart, candidate)) ?? null;\n\n return { name, end: i };\n}\n\n/**\n * walks a tag's attributes from just after its name to its `>`, collecting them\n * into `attrs` when given; -1 when the tag is not complete in `buf`. Follows the\n * attribute states exactly: a quote opens a value only right after `=` in the\n * attribute-name position, anywhere else it is a plain name or value character.\n */\nfunction scanAttributes(buf: string, i: number, attrs: Record<string, string> | null): number {\n const len = buf.length;\n\n for (;;) {\n while (i < len && (isWhitespace(buf.charCodeAt(i)) || buf.charCodeAt(i) === 0x2f)) i++;\n\n if (i >= len) return -1;\n if (buf.charCodeAt(i) === 0x3e) return i + 1;\n\n const nameStart = i;\n\n // a leading `=` is part of the attribute name\n if (buf.charCodeAt(i) === 0x3d) i++;\n\n while (i < len) {\n const code = buf.charCodeAt(i);\n\n // everything above `>` (letters, `_`, non-ascii) is a name character; only `=`, `/`, `>` and whitespace end it\n if (code <= 0x3e && (code === 0x3d || isTagEnd(code))) break;\n\n i++;\n }\n\n if (i >= len) return -1;\n\n const nameEnd = i;\n\n while (i < len && isWhitespace(buf.charCodeAt(i))) i++;\n\n if (i >= len) return -1;\n\n let valueStart = i;\n let valueEnd = i;\n\n if (buf.charCodeAt(i) === 0x3d) {\n i++;\n\n while (i < len && isWhitespace(buf.charCodeAt(i))) i++;\n\n if (i >= len) return -1;\n\n const quote = buf.charCodeAt(i);\n\n if (quote === 0x22 || quote === 0x27) {\n const close = buf.indexOf(String.fromCharCode(quote), i + 1);\n\n if (close < 0) return -1;\n\n valueStart = i + 1;\n valueEnd = close;\n i = close + 1;\n } else {\n valueStart = i;\n\n while (i < len && !isWhitespace(buf.charCodeAt(i)) && buf.charCodeAt(i) !== 0x3e) i++;\n\n if (i >= len) return -1;\n\n valueEnd = i;\n }\n }\n\n if (attrs) {\n const name = buf.slice(nameStart, nameEnd).toLowerCase();\n\n if (!(name in attrs)) {\n defineLazyAttribute(attrs, name, buf.slice(valueStart, valueEnd));\n }\n }\n }\n}\n\n// values decode on first access: islands carry kilobytes of escaped props the handler never reads\nfunction defineLazyAttribute(attrs: Record<string, string>, name: string, raw: string): void {\n let decoded: string | undefined;\n\n Object.defineProperty(attrs, name, {\n enumerable: true,\n configurable: true,\n get: () => (decoded ??= decodeAttribute(raw)),\n set: (value: string) => {\n decoded = value;\n },\n });\n}\n\ntype ScriptMarker = 'escape-open' | 'end' | 'script-open' | 'none' | 'incomplete';\n\n/** classifies the `<` at `lt` inside script data */\nfunction classifyScriptMarker(buf: string, lt: number): ScriptMarker {\n const rest = buf.slice(lt, lt + RAW_TAIL);\n const lower = rest.toLowerCase();\n\n if (rest.startsWith('<!--')) return 'escape-open';\n if (lower.startsWith('</script') && lower.length > 8 && isTagEnd(lower.charCodeAt(8))) return 'end';\n if (lower.startsWith('<script') && lower.length > 7 && isTagEnd(lower.charCodeAt(7))) return 'script-open';\n\n const incomplete =\n (rest.length < 4 && '<!--'.startsWith(rest)) ||\n (lower.length <= 8 && '</script'.startsWith(lower)) ||\n (lower.length <= 7 && '<script'.startsWith(lower));\n\n return incomplete ? 'incomplete' : 'none';\n}\n\nexport function createIslandRewriter(onIsland: IslandTagHandler): IslandRewriter {\n let mode: Mode = DATA;\n let carry = '';\n // islands inside `<template>` are inert until cloned, so they get nothing\n let templateDepth = 0;\n\n const scan = (buf: string): string => {\n const len = buf.length;\n // output is the input with insertions: everything between `emitted` and the\n // scan position is untouched source, flushed as one slice when something is\n // inserted, held back, or the buffer ends\n let out = '';\n let emitted = 0;\n let i = 0;\n\n const flush = (to: number): void => {\n if (to > emitted) {\n out += buf.slice(emitted, to);\n emitted = to;\n }\n };\n\n // holds `buf` from `at` for the next write\n const hold = (at: number): void => {\n flush(at);\n carry = buf.slice(at);\n emitted = len;\n i = len;\n };\n\n while (i < len) {\n switch (mode.kind) {\n case 'plaintext': {\n i = len;\n break;\n }\n\n case 'bogus': {\n const close = buf.indexOf('>', i);\n\n if (close < 0) {\n i = len;\n } else {\n i = close + 1;\n mode = DATA;\n }\n\n break;\n }\n\n case 'cdata': {\n const close = buf.indexOf(']]>', i);\n\n if (close >= 0) {\n i = close + 3;\n mode = DATA;\n } else {\n hold(Math.max(i, len - 2));\n }\n\n break;\n }\n\n case 'comment': {\n const dashes = buf.indexOf('-->', i);\n const bang = buf.indexOf('--!>', mode.bangAt);\n const close = dashes >= 0 && (bang < 0 || dashes < bang) ? dashes + 3 : bang >= 0 ? bang + 4 : -1;\n\n if (close >= 0) {\n i = close;\n mode = DATA;\n } else {\n // a comment cannot hold an island: keep only what could be a partial closer\n const cut = Math.max(i, len - 3);\n\n hold(cut);\n mode = { kind: 'comment', bangAt: Math.max(0, mode.bangAt - cut) };\n }\n\n break;\n }\n\n case 'rawtext': {\n const { endTag } = mode;\n let k = i;\n let found = -1;\n\n while ((k = buf.indexOf('</', k)) >= 0) {\n if (k + endTag.length >= len) break;\n\n if (equalsIgnoreCase(buf, k, endTag) && isTagEnd(buf.charCodeAt(k + endTag.length))) {\n found = k;\n break;\n }\n\n k += 2;\n }\n\n if (found >= 0) {\n i = found;\n mode = DATA;\n } else {\n hold(Math.max(i, len - endTag.length));\n }\n\n break;\n }\n\n case 'script': {\n let k = i;\n let cut = -1;\n\n while (cut < 0) {\n const lt = buf.indexOf('<', k);\n const dashes = mode.escape === 0 ? -1 : buf.indexOf('-->', k);\n\n if (dashes >= 0 && (lt < 0 || dashes < lt)) {\n mode = { kind: 'script', escape: 0 };\n k = dashes + 3;\n continue;\n }\n\n if (lt < 0) {\n cut = Math.max(k, len - RAW_TAIL + 1);\n break;\n }\n\n const marker = classifyScriptMarker(buf, lt);\n\n if (marker === 'incomplete') {\n cut = lt;\n } else if (marker === 'end' && mode.escape !== 2) {\n i = lt;\n mode = DATA;\n break;\n } else if (marker === 'end') {\n mode = { kind: 'script', escape: 1 };\n k = lt + 8;\n } else if (marker === 'escape-open' && mode.escape === 0) {\n // the opener's own dashes count: `<!-->` leaves the escaped state at once\n mode = { kind: 'script', escape: 1 };\n k = lt + 2;\n } else if (marker === 'script-open' && mode.escape === 1) {\n mode = { kind: 'script', escape: 2 };\n k = lt + 7;\n } else {\n k = lt + 1;\n }\n }\n\n if (cut >= 0) {\n hold(cut);\n }\n\n break;\n }\n\n case 'data': {\n const lt = buf.indexOf('<', i);\n\n if (lt < 0) {\n i = len;\n break;\n }\n\n if (lt + 1 >= len) {\n hold(lt);\n break;\n }\n\n const next = buf.charCodeAt(lt + 1);\n\n if (next === 0x21) {\n if (buf.startsWith('<!--', lt)) {\n i = lt + 2;\n // `-->` may close on the opener's own dashes (`<!-->`), `--!>` needs two more\n mode = { kind: 'comment', bangAt: lt + 4 };\n } else if (buf.startsWith('<![CDATA[', lt)) {\n // cdata is text only in foreign content, where the browser ends it at `]]>`; ending\n // it there everywhere errs towards a missed preload, never towards injecting\n i = lt + 9;\n mode = { kind: 'cdata' };\n } else if (len - lt < 9 && ('<!--'.startsWith(buf.slice(lt)) || '<![CDATA['.startsWith(buf.slice(lt)))) {\n hold(lt);\n } else {\n i = lt + 2;\n mode = { kind: 'bogus' };\n }\n\n break;\n }\n\n if (next === 0x3f) {\n i = lt + 2;\n mode = { kind: 'bogus' };\n break;\n }\n\n if (next === 0x2f) {\n if (lt + 2 >= len) {\n hold(lt);\n break;\n }\n\n const after = buf.charCodeAt(lt + 2);\n\n if (isLetter(after)) {\n const tag = readTagName(buf, lt + 2);\n const end = tag ? scanAttributes(buf, tag.end, null) : -1;\n\n if (end < 0) {\n hold(lt);\n break;\n }\n\n i = end;\n\n if (tag!.name === 'template' && templateDepth > 0) templateDepth--;\n } else if (after === 0x3e) {\n i = lt + 3;\n } else {\n i = lt + 2;\n mode = { kind: 'bogus' };\n }\n\n break;\n }\n\n if (isLetter(next)) {\n const head = readTagName(buf, lt + 1);\n\n if (!head) {\n hold(lt);\n break;\n }\n\n const { name } = head;\n const attrs: Record<string, string> | null = name === ISLAND ? Object.create(null) : null;\n const end = scanAttributes(buf, head.end, attrs);\n\n if (end < 0) {\n hold(lt);\n break;\n }\n\n if (attrs && templateDepth === 0) {\n const rewrite = onIsland(attrs);\n\n if (rewrite?.prepend) {\n flush(lt);\n out += rewrite.prepend;\n }\n }\n\n i = end;\n\n if (name === 'script') mode = { kind: 'script', escape: 0 };\n else if (name !== null && RAW_TEXT.has(name)) mode = { kind: 'rawtext', endTag: `</${name}` };\n else if (name === 'plaintext') mode = { kind: 'plaintext' };\n else if (name === 'template') templateDepth++;\n\n break;\n }\n\n i = lt + 1;\n break;\n }\n }\n }\n\n flush(len);\n\n return out;\n };\n\n return {\n write(chunk) {\n const buf = carry + chunk;\n\n carry = '';\n\n return scan(buf);\n },\n end() {\n const tail = carry;\n\n carry = '';\n\n // whatwg eof-in-tag: a partial tag is never emitted; anything else held back is plain bytes\n return mode.kind === 'data' && /^<\\/?[a-zA-Z]/.test(tail) ? '' : tail;\n },\n };\n}\n","import type { APIContext } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getIslandEmitters } from './emitters.js';\nimport { createChunkGraph } from './graph.js';\nimport { type IslandRewriter, createIslandRewriter, encodeAttribute } from './rewriter.js';\nimport type { IslandEmission, IslandInfo, IslandsManifest } from './types.js';\n\n/**\n * Turns the manifest into per-document rewriters: resolves each island's chunk\n * closures, collects emissions (the built-in preloader plus registered emitters),\n * and applies the emission policy —\n *\n * - immediate directives (`load`, `only`) get `<link rel=\"modulepreload\">` tags\n * before the tag, deduplicated per document; the browser's speculative preload\n * scanner acts on them from raw bytes, ahead of any script.\n * - deferred directives get an inline script before the first island per\n * component that registers `{l: links, i: imports}` on the preload global,\n * keyed by `component-url`; the gate runtime injects the links and eagerly\n * `import()`s the imports by the directive's own scheduling semantics. A script\n * rather than an attribute: it takes effect at parse time and its effect\n * survives the island element being removed — the island tag itself stays\n * untouched.\n *\n * The gate runtime is inlined once, before the first island that needs it —\n * pages without deferred islands never carry it, pages with them install the\n * gates at parse time, without an external fetch to lose.\n */\n\n/** global registry of `{l, i}` entries per component-url, written by the transform, read by the gate runtime */\nexport const PRELOAD_GLOBAL = '__islands__';\n\nconst IMMEDIATE_DIRECTIVES = new Set(['load', 'only']);\n\n/** urls cannot contain `</script>`, but escape `<` anyway so no value ever can */\nfunction jsonForScript(value: unknown): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\ntype ResolvedChunk = { prefix: string; fileName: string };\n\nexport type IslandsTransformer = {\n createDocumentRewriter(context?: APIContext | undefined): IslandRewriter;\n};\n\nexport function createIslandsTransformer(manifest: IslandsManifest): IslandsTransformer {\n const graph = createChunkGraph(manifest);\n const fileNames = Object.keys(manifest.chunks);\n const resolveCache = new Map<string, ResolvedChunk | null>();\n\n // islands carry public urls (base and asset prefix baked in), the manifest holds\n // dist-relative file names — match by suffix at a path boundary, so the observed\n // prefix maps closures and the runtime script back to public urls with no config\n const resolve = (url: string): ResolvedChunk | null => {\n const cached = resolveCache.get(url);\n\n if (cached !== undefined) {\n return cached;\n }\n\n for (const fileName of fileNames) {\n if (url.endsWith(fileName)) {\n const boundary = url.length - fileName.length;\n\n if (boundary === 0 || url[boundary - 1] === '/') {\n const resolved = { prefix: url.slice(0, boundary), fileName };\n\n // only hits are cached\n resolveCache.set(url, resolved);\n\n return resolved;\n }\n }\n }\n\n return null;\n };\n\n // islands repeat across requests: closures with the prefix applied, the link\n // tags and the emitter-free register script are computed once per island and\n // shared — bounded by the manifest, since only resolvable islands are cached\n const islands = new Map<string, IslandInfo>();\n const linkTags = new Map<string, string>();\n const registerScripts = new WeakMap<IslandInfo, string>();\n\n const resolveIsland = (\n componentUrl: string,\n rendererUrl: string | null,\n client: string | null,\n ): IslandInfo | null => {\n const key = `${componentUrl}\\n${rendererUrl ?? ''}\\n${client ?? ''}`;\n const cached = islands.get(key);\n\n if (cached) {\n return cached;\n }\n\n const component = resolve(componentUrl);\n\n if (!component) {\n return null;\n }\n\n const renderer = rendererUrl ? resolve(rendererUrl) : null;\n\n const closureUrls = (closure: (fileName: string) => string[]): string[] => {\n const urls = new Set([componentUrl, ...closure(component.fileName).map((f) => component.prefix + f)]);\n\n if (rendererUrl) {\n urls.add(rendererUrl);\n\n for (const f of renderer ? closure(renderer.fileName) : []) {\n urls.add(renderer!.prefix + f);\n }\n }\n\n return [...urls];\n };\n\n const island: IslandInfo = {\n componentUrl,\n rendererUrl,\n client,\n staticClosure: closureUrls(graph.staticClosure),\n fullClosure: closureUrls(graph.fullClosure),\n };\n\n islands.set(key, island);\n\n return island;\n };\n\n const linkTag = (url: string): string => {\n let tag = linkTags.get(url);\n\n if (tag === undefined) {\n tag = `<link rel=\"modulepreload\" fetchpriority=\"low\" href=\"${encodeAttribute(url)}\">`;\n linkTags.set(url, tag);\n }\n\n return tag;\n };\n\n const registerScript = (componentUrl: string, links: readonly string[], imports: readonly string[]): string => {\n const importSet = new Set(imports);\n const entry: Record<string, readonly string[]> = { l: links.filter((url) => !importSet.has(url)) };\n\n if (imports.length > 0) {\n entry['i'] = imports;\n }\n\n return `<script>(self.${PRELOAD_GLOBAL}??={})[${jsonForScript(componentUrl)}]=${jsonForScript(entry)};</script>`;\n };\n\n const createDocumentRewriter = (context?: APIContext | undefined): IslandRewriter => {\n const emittedLinks = new Set<string>();\n const registeredComponents = new Set<string>();\n let runtimeInjected = false;\n\n return createIslandRewriter((attrs) => {\n const componentUrl = attrs['component-url'];\n\n if (!componentUrl) {\n return null;\n }\n\n const island = resolveIsland(componentUrl, attrs['renderer-url'] || null, attrs['client'] || null);\n\n if (!island) {\n return null;\n }\n\n const emitters = getIslandEmitters();\n let links: readonly string[] = island.staticClosure;\n let imports: readonly string[] = [];\n let html = '';\n\n if (emitters.length > 0) {\n const emissions: IslandEmission[] = [{ links: island.staticClosure }];\n\n for (const emitter of emitters) {\n try {\n const emission = emitter(island, context);\n\n if (emission) {\n emissions.push(emission);\n }\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error, componentUrl }, 'island emitter failed');\n }\n }\n\n links = [...new Set(emissions.flatMap((e) => e.links ?? []))];\n imports = [...new Set(emissions.flatMap((e) => e.imports ?? []))];\n html = emissions.map((e) => e.html ?? '').join('');\n }\n\n const directive = (island.client ?? '').replace(/-x$/, '');\n\n if (IMMEDIATE_DIRECTIVES.has(directive)) {\n let prepend = html;\n\n for (const url of links) {\n if (!emittedLinks.has(url)) {\n emittedLinks.add(url);\n prepend += linkTag(url);\n }\n }\n\n return { prepend: prepend || undefined };\n }\n\n if (registeredComponents.has(componentUrl)) {\n return { prepend: html || undefined };\n }\n\n registeredComponents.add(componentUrl);\n\n const runtime = runtimeInjected ? '' : `<script>${manifest.runtimeSource}</script>`;\n\n runtimeInjected = true;\n\n let register: string;\n\n if (emitters.length > 0) {\n register = registerScript(componentUrl, links, imports);\n } else {\n register = registerScripts.get(island) ?? registerScript(componentUrl, links, imports);\n registerScripts.set(island, register);\n }\n\n return { prepend: runtime + register + html || undefined };\n });\n };\n\n return { createDocumentRewriter };\n}\n\nexport type PageTransformOptions = {\n /** the islands rewriter for this document, when preloading is on (prod with a manifest) */\n rewriter?: IslandRewriter | undefined;\n /** scripts inserted right after the opening `<head>` tag — buffers the response */\n heads: string[];\n /** script factories invoked after the rewriter finished, results appended at stream end */\n ends: (() => string | null)[];\n};\n\n/**\n * The single streaming pass over an html page response: chunks go through the\n * islands rewriter (when present), head content is inserted right after the\n * opening `<head>` tag (which requires buffering the whole document — head\n * content is dev-style delivery, where throughput is irrelevant), and end\n * factories run last, strictly after every island passed the rewriter.\n */\nexport function createPageTransformStream(options: PageTransformOptions): TransformStream<Uint8Array, Uint8Array> {\n const { rewriter, heads, ends } = options;\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n const buffered = heads.length > 0 ? ([] as string[]) : null;\n\n const enqueue = (controller: TransformStreamDefaultController<Uint8Array>, text: string): void => {\n if (text) {\n controller.enqueue(encoder.encode(text));\n }\n };\n\n return new TransformStream({\n transform(chunk, controller) {\n let text = decoder.decode(chunk, { stream: true });\n\n if (rewriter) {\n text = rewriter.write(text);\n }\n\n if (buffered) {\n buffered.push(text);\n } else {\n enqueue(controller, text);\n }\n },\n flush(controller) {\n let tail = decoder.decode();\n\n if (rewriter) {\n tail = (tail ? rewriter.write(tail) : '') + rewriter.end();\n }\n\n if (buffered) {\n const html = buffered.join('') + tail;\n // nothing but the doctype, comments and <html> can precede <head>, so the\n // first match cannot sit inside script raw text\n const head = /<head[^>]*>/i.exec(html);\n const at = head ? head.index + head[0].length : 0;\n\n enqueue(controller, html.slice(0, at) + heads.join('') + html.slice(at));\n } else {\n enqueue(controller, tail);\n }\n\n for (const end of ends) {\n try {\n enqueue(controller, end() ?? '');\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error }, 'document emitter failed');\n }\n }\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform-YUFkHwZC.js","names":[],"sources":["../src/islands/rewriter.ts","../src/islands/transform.ts"],"sourcesContent":["/**\n * Streaming scanner that prepends handler html before `<astro-island …>` opening\n * tags. Everything else, the tag included, passes through byte-verbatim.\n *\n * It tokenizes only as far as needed to know when `<` starts an element. The\n * invariant is asymmetric: a missed island costs a preload, a false positive\n * would inject into a script or attribute — every deviation from the WHATWG\n * tokenizer errs towards not injecting, and the parse5 oracle test checks that.\n */\n\nexport type IslandTagRewrite = {\n /** html emitted immediately before the island opening tag */\n prepend?: string | undefined;\n};\n\nexport type IslandTagHandler = (attrs: Record<string, string>) => IslandTagRewrite | null;\n\nexport type IslandRewriter = {\n write(chunk: string): string;\n end(): string;\n};\n\nconst ISLAND = 'astro-island';\n// raw text by name alone, also inside `<svg>`/`<math>` where the browser would not — a real island cannot sit there\nconst RAW_TEXT = new Set(['style', 'textarea', 'title', 'xmp', 'iframe', 'noembed', 'noframes', 'noscript']);\n\n// longest marker a raw-text scan must be able to complete across a chunk boundary: `</script` plus its terminator\nconst RAW_TAIL = 9;\n\n// the named references astro's escaper emits; any other stays literal, which at worst mismatches a manifest url\nconst NAMED_ENTITIES: Record<string, string> = { amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\" };\n\n// numeric references in the C1 control range map to windows-1252 code points\nconst C1_REMAP: Record<number, number> = {\n 0x80: 0x20ac,\n 0x82: 0x201a,\n 0x83: 0x0192,\n 0x84: 0x201e,\n 0x85: 0x2026,\n 0x86: 0x2020,\n 0x87: 0x2021,\n 0x88: 0x02c6,\n 0x89: 0x2030,\n 0x8a: 0x0160,\n 0x8b: 0x2039,\n 0x8c: 0x0152,\n 0x8e: 0x017d,\n 0x91: 0x2018,\n 0x92: 0x2019,\n 0x93: 0x201c,\n 0x94: 0x201d,\n 0x95: 0x2022,\n 0x96: 0x2013,\n 0x97: 0x2014,\n 0x98: 0x02dc,\n 0x99: 0x2122,\n 0x9a: 0x0161,\n 0x9b: 0x203a,\n 0x9c: 0x0153,\n 0x9e: 0x017e,\n 0x9f: 0x0178,\n};\n\ntype Mode =\n | { kind: 'data' }\n | { kind: 'comment'; bangAt: number }\n | { kind: 'cdata' }\n | { kind: 'bogus' }\n | { kind: 'rawtext'; endTag: string }\n | { kind: 'script'; escape: 0 | 1 | 2 }\n | { kind: 'plaintext' };\n\nconst DATA: Mode = { kind: 'data' };\n\nexport function encodeAttribute(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<');\n}\n\nfunction isWhitespace(code: number): boolean {\n return code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0c || code === 0x0d;\n}\n\nfunction isLetter(code: number): boolean {\n return (code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a);\n}\n\n/** whitespace, `/` or `>`: what ends a tag name and what may follow an end tag name in raw text */\nfunction isTagEnd(code: number): boolean {\n return isWhitespace(code) || code === 0x2f || code === 0x3e;\n}\n\nfunction decodeAttribute(value: string): string {\n if (!value.includes('&') && !value.includes('\\r') && !value.includes('\\0')) {\n return value;\n }\n\n return value\n .replace(/\\r\\n?/g, '\\n')\n .replace(/\\0/g, '�')\n .replace(/&(?:#[xX]([0-9a-fA-F]+)|#([0-9]+)|([a-zA-Z][a-zA-Z0-9]*));/g, (match, hex, dec, name) => {\n if (name) {\n return NAMED_ENTITIES[name] ?? match;\n }\n\n const code = parseInt(hex ?? dec, hex ? 16 : 10);\n\n if (code === 0 || code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) {\n return '�';\n }\n\n return String.fromCodePoint(C1_REMAP[code] ?? code);\n });\n}\n\nconst NAMES_BY_LENGTH: Record<number, string[]> = {\n 3: ['xmp'],\n 5: ['style', 'title'],\n 6: ['script', 'iframe'],\n 7: ['noembed'],\n 8: ['noframes', 'noscript', 'textarea', 'template'],\n 9: ['plaintext'],\n 12: [ISLAND],\n};\n\nfunction equalsIgnoreCase(buf: string, start: number, name: string): boolean {\n for (let k = 0; k < name.length; k++) {\n if ((buf.charCodeAt(start + k) | 0x20) !== name.charCodeAt(k)) return false;\n }\n\n return true;\n}\n\n/**\n * reads a tag name from its start (just after `<` or `</`): the end of the name,\n * and the name itself only when it is one the scanner acts on — every other\n * tag passes through without allocating. null when not terminated in `buf`.\n */\nfunction readTagName(buf: string, i: number): { name: string | null; end: number } | null {\n const nameStart = i;\n\n while (i < buf.length && !isTagEnd(buf.charCodeAt(i))) i++;\n\n if (i >= buf.length) return null;\n\n const candidates = NAMES_BY_LENGTH[i - nameStart];\n const name = candidates?.find((candidate) => equalsIgnoreCase(buf, nameStart, candidate)) ?? null;\n\n return { name, end: i };\n}\n\n/**\n * walks a tag's attributes from just after its name to its `>`, collecting them\n * into `attrs` when given; -1 when the tag is not complete in `buf`. Follows the\n * attribute states exactly: a quote opens a value only right after `=` in the\n * attribute-name position, anywhere else it is a plain name or value character.\n */\nfunction scanAttributes(buf: string, i: number, attrs: Record<string, string> | null): number {\n const len = buf.length;\n\n for (;;) {\n while (i < len && (isWhitespace(buf.charCodeAt(i)) || buf.charCodeAt(i) === 0x2f)) i++;\n\n if (i >= len) return -1;\n if (buf.charCodeAt(i) === 0x3e) return i + 1;\n\n const nameStart = i;\n\n // a leading `=` is part of the attribute name\n if (buf.charCodeAt(i) === 0x3d) i++;\n\n while (i < len) {\n const code = buf.charCodeAt(i);\n\n // everything above `>` (letters, `_`, non-ascii) is a name character; only `=`, `/`, `>` and whitespace end it\n if (code <= 0x3e && (code === 0x3d || isTagEnd(code))) break;\n\n i++;\n }\n\n if (i >= len) return -1;\n\n const nameEnd = i;\n\n while (i < len && isWhitespace(buf.charCodeAt(i))) i++;\n\n if (i >= len) return -1;\n\n let valueStart = i;\n let valueEnd = i;\n\n if (buf.charCodeAt(i) === 0x3d) {\n i++;\n\n while (i < len && isWhitespace(buf.charCodeAt(i))) i++;\n\n if (i >= len) return -1;\n\n const quote = buf.charCodeAt(i);\n\n if (quote === 0x22 || quote === 0x27) {\n const close = buf.indexOf(String.fromCharCode(quote), i + 1);\n\n if (close < 0) return -1;\n\n valueStart = i + 1;\n valueEnd = close;\n i = close + 1;\n } else {\n valueStart = i;\n\n while (i < len && !isWhitespace(buf.charCodeAt(i)) && buf.charCodeAt(i) !== 0x3e) i++;\n\n if (i >= len) return -1;\n\n valueEnd = i;\n }\n }\n\n if (attrs) {\n const name = buf.slice(nameStart, nameEnd).toLowerCase();\n\n if (!(name in attrs)) {\n defineLazyAttribute(attrs, name, buf.slice(valueStart, valueEnd));\n }\n }\n }\n}\n\n// values decode on first access: islands carry kilobytes of escaped props the handler never reads\nfunction defineLazyAttribute(attrs: Record<string, string>, name: string, raw: string): void {\n let decoded: string | undefined;\n\n Object.defineProperty(attrs, name, {\n enumerable: true,\n configurable: true,\n get: () => (decoded ??= decodeAttribute(raw)),\n set: (value: string) => {\n decoded = value;\n },\n });\n}\n\ntype ScriptMarker = 'escape-open' | 'end' | 'script-open' | 'none' | 'incomplete';\n\n/** classifies the `<` at `lt` inside script data */\nfunction classifyScriptMarker(buf: string, lt: number): ScriptMarker {\n const rest = buf.slice(lt, lt + RAW_TAIL);\n const lower = rest.toLowerCase();\n\n if (rest.startsWith('<!--')) return 'escape-open';\n if (lower.startsWith('</script') && lower.length > 8 && isTagEnd(lower.charCodeAt(8))) return 'end';\n if (lower.startsWith('<script') && lower.length > 7 && isTagEnd(lower.charCodeAt(7))) return 'script-open';\n\n const incomplete =\n (rest.length < 4 && '<!--'.startsWith(rest)) ||\n (lower.length <= 8 && '</script'.startsWith(lower)) ||\n (lower.length <= 7 && '<script'.startsWith(lower));\n\n return incomplete ? 'incomplete' : 'none';\n}\n\nexport function createIslandRewriter(onIsland: IslandTagHandler): IslandRewriter {\n let mode: Mode = DATA;\n let carry = '';\n // islands inside `<template>` are inert until cloned, so they get nothing\n let templateDepth = 0;\n\n const scan = (buf: string): string => {\n const len = buf.length;\n // output is the input with insertions: everything between `emitted` and the\n // scan position is untouched source, flushed as one slice when something is\n // inserted, held back, or the buffer ends\n let out = '';\n let emitted = 0;\n let i = 0;\n\n const flush = (to: number): void => {\n if (to > emitted) {\n out += buf.slice(emitted, to);\n emitted = to;\n }\n };\n\n // holds `buf` from `at` for the next write\n const hold = (at: number): void => {\n flush(at);\n carry = buf.slice(at);\n emitted = len;\n i = len;\n };\n\n while (i < len) {\n switch (mode.kind) {\n case 'plaintext': {\n i = len;\n break;\n }\n\n case 'bogus': {\n const close = buf.indexOf('>', i);\n\n if (close < 0) {\n i = len;\n } else {\n i = close + 1;\n mode = DATA;\n }\n\n break;\n }\n\n case 'cdata': {\n const close = buf.indexOf(']]>', i);\n\n if (close >= 0) {\n i = close + 3;\n mode = DATA;\n } else {\n hold(Math.max(i, len - 2));\n }\n\n break;\n }\n\n case 'comment': {\n const dashes = buf.indexOf('-->', i);\n const bang = buf.indexOf('--!>', mode.bangAt);\n const close = dashes >= 0 && (bang < 0 || dashes < bang) ? dashes + 3 : bang >= 0 ? bang + 4 : -1;\n\n if (close >= 0) {\n i = close;\n mode = DATA;\n } else {\n // a comment cannot hold an island: keep only what could be a partial closer\n const cut = Math.max(i, len - 3);\n\n hold(cut);\n mode = { kind: 'comment', bangAt: Math.max(0, mode.bangAt - cut) };\n }\n\n break;\n }\n\n case 'rawtext': {\n const { endTag } = mode;\n let k = i;\n let found = -1;\n\n while ((k = buf.indexOf('</', k)) >= 0) {\n if (k + endTag.length >= len) break;\n\n if (equalsIgnoreCase(buf, k, endTag) && isTagEnd(buf.charCodeAt(k + endTag.length))) {\n found = k;\n break;\n }\n\n k += 2;\n }\n\n if (found >= 0) {\n i = found;\n mode = DATA;\n } else {\n hold(Math.max(i, len - endTag.length));\n }\n\n break;\n }\n\n case 'script': {\n let k = i;\n let cut = -1;\n\n while (cut < 0) {\n const lt = buf.indexOf('<', k);\n const dashes = mode.escape === 0 ? -1 : buf.indexOf('-->', k);\n\n if (dashes >= 0 && (lt < 0 || dashes < lt)) {\n mode = { kind: 'script', escape: 0 };\n k = dashes + 3;\n continue;\n }\n\n if (lt < 0) {\n cut = Math.max(k, len - RAW_TAIL + 1);\n break;\n }\n\n const marker = classifyScriptMarker(buf, lt);\n\n if (marker === 'incomplete') {\n cut = lt;\n } else if (marker === 'end' && mode.escape !== 2) {\n i = lt;\n mode = DATA;\n break;\n } else if (marker === 'end') {\n mode = { kind: 'script', escape: 1 };\n k = lt + 8;\n } else if (marker === 'escape-open' && mode.escape === 0) {\n // the opener's own dashes count: `<!-->` leaves the escaped state at once\n mode = { kind: 'script', escape: 1 };\n k = lt + 2;\n } else if (marker === 'script-open' && mode.escape === 1) {\n mode = { kind: 'script', escape: 2 };\n k = lt + 7;\n } else {\n k = lt + 1;\n }\n }\n\n if (cut >= 0) {\n hold(cut);\n }\n\n break;\n }\n\n case 'data': {\n const lt = buf.indexOf('<', i);\n\n if (lt < 0) {\n i = len;\n break;\n }\n\n if (lt + 1 >= len) {\n hold(lt);\n break;\n }\n\n const next = buf.charCodeAt(lt + 1);\n\n if (next === 0x21) {\n if (buf.startsWith('<!--', lt)) {\n i = lt + 2;\n // `-->` may close on the opener's own dashes (`<!-->`), `--!>` needs two more\n mode = { kind: 'comment', bangAt: lt + 4 };\n } else if (buf.startsWith('<![CDATA[', lt)) {\n // cdata is text only in foreign content, where the browser ends it at `]]>`; ending\n // it there everywhere errs towards a missed preload, never towards injecting\n i = lt + 9;\n mode = { kind: 'cdata' };\n } else if (len - lt < 9 && ('<!--'.startsWith(buf.slice(lt)) || '<![CDATA['.startsWith(buf.slice(lt)))) {\n hold(lt);\n } else {\n i = lt + 2;\n mode = { kind: 'bogus' };\n }\n\n break;\n }\n\n if (next === 0x3f) {\n i = lt + 2;\n mode = { kind: 'bogus' };\n break;\n }\n\n if (next === 0x2f) {\n if (lt + 2 >= len) {\n hold(lt);\n break;\n }\n\n const after = buf.charCodeAt(lt + 2);\n\n if (isLetter(after)) {\n const tag = readTagName(buf, lt + 2);\n const end = tag ? scanAttributes(buf, tag.end, null) : -1;\n\n if (end < 0) {\n hold(lt);\n break;\n }\n\n i = end;\n\n if (tag!.name === 'template' && templateDepth > 0) templateDepth--;\n } else if (after === 0x3e) {\n i = lt + 3;\n } else {\n i = lt + 2;\n mode = { kind: 'bogus' };\n }\n\n break;\n }\n\n if (isLetter(next)) {\n const head = readTagName(buf, lt + 1);\n\n if (!head) {\n hold(lt);\n break;\n }\n\n const { name } = head;\n const attrs: Record<string, string> | null = name === ISLAND ? Object.create(null) : null;\n const end = scanAttributes(buf, head.end, attrs);\n\n if (end < 0) {\n hold(lt);\n break;\n }\n\n if (attrs && templateDepth === 0) {\n const rewrite = onIsland(attrs);\n\n if (rewrite?.prepend) {\n flush(lt);\n out += rewrite.prepend;\n }\n }\n\n i = end;\n\n if (name === 'script') mode = { kind: 'script', escape: 0 };\n else if (name !== null && RAW_TEXT.has(name)) mode = { kind: 'rawtext', endTag: `</${name}` };\n else if (name === 'plaintext') mode = { kind: 'plaintext' };\n else if (name === 'template') templateDepth++;\n\n break;\n }\n\n i = lt + 1;\n break;\n }\n }\n }\n\n flush(len);\n\n return out;\n };\n\n return {\n write(chunk) {\n const buf = carry + chunk;\n\n carry = '';\n\n return scan(buf);\n },\n end() {\n const tail = carry;\n\n carry = '';\n\n // whatwg eof-in-tag: a partial tag is never emitted; anything else held back is plain bytes\n return mode.kind === 'data' && /^<\\/?[a-zA-Z]/.test(tail) ? '' : tail;\n },\n };\n}\n","import type { APIContext } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getIslandEmitters } from './emitters.js';\nimport { createChunkGraph } from './graph.js';\nimport { type IslandRewriter, createIslandRewriter, encodeAttribute } from './rewriter.js';\nimport type { IslandEmission, IslandInfo, IslandsManifest } from './types.js';\n\n/**\n * Turns the manifest into per-document rewriters: resolves each island's chunk\n * closures, collects emissions (the built-in preloader plus registered emitters),\n * and applies the emission policy —\n *\n * - immediate directives (`load`, `only`) get `<link rel=\"modulepreload\">` tags\n * before the tag, deduplicated per document; the browser's speculative preload\n * scanner acts on them from raw bytes, ahead of any script.\n * - deferred directives get an inline script before the first island per\n * component that registers `{l: links, i: imports}` on the preload global,\n * keyed by `component-url`; the gate runtime injects the links and eagerly\n * `import()`s the imports by the directive's own scheduling semantics. A script\n * rather than an attribute: it takes effect at parse time and its effect\n * survives the island element being removed — the island tag itself stays\n * untouched.\n *\n * The gate runtime is inlined once, before the first island that needs it —\n * pages without deferred islands never carry it, pages with them install the\n * gates at parse time, without an external fetch to lose.\n */\n\n/** global registry of `{l, i}` entries per component-url, written by the transform, read by the gate runtime */\nexport const PRELOAD_GLOBAL = '__islands__';\n\nconst IMMEDIATE_DIRECTIVES = new Set(['load', 'only']);\n\n/** urls cannot contain `</script>`, but escape `<` anyway so no value ever can */\nfunction jsonForScript(value: unknown): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\ntype ResolvedChunk = { prefix: string; fileName: string };\n\nexport type IslandsTransformer = {\n createDocumentRewriter(context?: APIContext | undefined): IslandRewriter;\n};\n\nexport function createIslandsTransformer(manifest: IslandsManifest): IslandsTransformer {\n const graph = createChunkGraph(manifest);\n const fileNames = Object.keys(manifest.chunks);\n const resolveCache = new Map<string, ResolvedChunk | null>();\n\n // islands carry public urls (base and asset prefix baked in), the manifest holds\n // dist-relative file names — match by suffix at a path boundary, so the observed\n // prefix maps closures and the runtime script back to public urls with no config\n const resolve = (url: string): ResolvedChunk | null => {\n const cached = resolveCache.get(url);\n\n if (cached !== undefined) {\n return cached;\n }\n\n for (const fileName of fileNames) {\n if (url.endsWith(fileName)) {\n const boundary = url.length - fileName.length;\n\n if (boundary === 0 || url[boundary - 1] === '/') {\n const resolved = { prefix: url.slice(0, boundary), fileName };\n\n // only hits are cached\n resolveCache.set(url, resolved);\n\n return resolved;\n }\n }\n }\n\n return null;\n };\n\n // islands repeat across requests: closures with the prefix applied, the link\n // tags and the emitter-free register script are computed once per island and\n // shared — bounded by the manifest, since only resolvable islands are cached\n const islands = new Map<string, IslandInfo>();\n const linkTags = new Map<string, string>();\n const registerScripts = new WeakMap<IslandInfo, string>();\n\n const resolveIsland = (\n componentUrl: string,\n rendererUrl: string | null,\n client: string | null,\n ): IslandInfo | null => {\n const key = `${componentUrl}\\n${rendererUrl ?? ''}\\n${client ?? ''}`;\n const cached = islands.get(key);\n\n if (cached) {\n return cached;\n }\n\n const component = resolve(componentUrl);\n\n if (!component) {\n return null;\n }\n\n const renderer = rendererUrl ? resolve(rendererUrl) : null;\n\n const closureUrls = (closure: (fileName: string) => string[]): string[] => {\n const urls = new Set([componentUrl, ...closure(component.fileName).map((f) => component.prefix + f)]);\n\n if (rendererUrl) {\n urls.add(rendererUrl);\n\n for (const f of renderer ? closure(renderer.fileName) : []) {\n urls.add(renderer!.prefix + f);\n }\n }\n\n return [...urls];\n };\n\n const island: IslandInfo = {\n componentUrl,\n rendererUrl,\n client,\n staticClosure: closureUrls(graph.staticClosure),\n fullClosure: closureUrls(graph.fullClosure),\n };\n\n islands.set(key, island);\n\n return island;\n };\n\n const linkTag = (url: string): string => {\n let tag = linkTags.get(url);\n\n if (tag === undefined) {\n tag = `<link rel=\"modulepreload\" fetchpriority=\"low\" href=\"${encodeAttribute(url)}\">`;\n linkTags.set(url, tag);\n }\n\n return tag;\n };\n\n const registerScript = (componentUrl: string, links: readonly string[], imports: readonly string[]): string => {\n const importSet = new Set(imports);\n const entry: Record<string, readonly string[]> = { l: links.filter((url) => !importSet.has(url)) };\n\n if (imports.length > 0) {\n entry['i'] = imports;\n }\n\n return `<script>(self.${PRELOAD_GLOBAL}??={})[${jsonForScript(componentUrl)}]=${jsonForScript(entry)};</script>`;\n };\n\n const createDocumentRewriter = (context?: APIContext | undefined): IslandRewriter => {\n const emittedLinks = new Set<string>();\n const registeredComponents = new Set<string>();\n let runtimeInjected = false;\n\n return createIslandRewriter((attrs) => {\n const componentUrl = attrs['component-url'];\n\n if (!componentUrl) {\n return null;\n }\n\n const island = resolveIsland(componentUrl, attrs['renderer-url'] || null, attrs['client'] || null);\n\n if (!island) {\n return null;\n }\n\n const emitters = getIslandEmitters();\n let links: readonly string[] = island.staticClosure;\n let imports: readonly string[] = [];\n let html = '';\n\n if (emitters.length > 0) {\n const emissions: IslandEmission[] = [{ links: island.staticClosure }];\n\n for (const emitter of emitters) {\n try {\n const emission = emitter(island, context);\n\n if (emission) {\n emissions.push(emission);\n }\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error, componentUrl }, 'island emitter failed');\n }\n }\n\n links = [...new Set(emissions.flatMap((e) => e.links ?? []))];\n imports = [...new Set(emissions.flatMap((e) => e.imports ?? []))];\n html = emissions.map((e) => e.html ?? '').join('');\n }\n\n const directive = (island.client ?? '').replace(/-x$/, '');\n\n if (IMMEDIATE_DIRECTIVES.has(directive)) {\n let prepend = html;\n\n for (const url of links) {\n if (!emittedLinks.has(url)) {\n emittedLinks.add(url);\n prepend += linkTag(url);\n }\n }\n\n return { prepend: prepend || undefined };\n }\n\n if (registeredComponents.has(componentUrl)) {\n return { prepend: html || undefined };\n }\n\n registeredComponents.add(componentUrl);\n\n const runtime = runtimeInjected ? '' : `<script>${manifest.runtimeSource}</script>`;\n\n runtimeInjected = true;\n\n let register: string;\n\n if (emitters.length > 0) {\n register = registerScript(componentUrl, links, imports);\n } else {\n register = registerScripts.get(island) ?? registerScript(componentUrl, links, imports);\n registerScripts.set(island, register);\n }\n\n return { prepend: runtime + register + html || undefined };\n });\n };\n\n return { createDocumentRewriter };\n}\n\nexport type PageTransformOptions = {\n /** the islands rewriter for this document, when preloading is on (prod with a manifest) */\n rewriter?: IslandRewriter | undefined;\n /** scripts inserted at the end of `<head>` — buffers the response */\n heads: string[];\n /** script factories invoked after the rewriter finished, results appended at stream end */\n ends: (() => string | null)[];\n};\n\n/**\n * Head content goes before `</head>`, falling back to right after `<head>`, then\n * the document start. End of head rather than start: meta charset, title etc come first\n */\nexport function insertIntoHead(html: string, content: string): string {\n const close = html.search(/<\\/head\\s*>/i);\n\n if (close !== -1) {\n return html.slice(0, close) + content + html.slice(close);\n }\n\n const open = /<head[^>]*>/i.exec(html);\n const at = open ? open.index + open[0].length : 0;\n\n return html.slice(0, at) + content + html.slice(at);\n}\n\n/**\n * The single streaming pass over an html page response: chunks go through the\n * islands rewriter (when present), head content is inserted into `<head>` (which\n * buffers the whole document — head content is dev-style delivery, where\n * throughput is irrelevant), and end factories run last, strictly after every\n * island passed the rewriter.\n */\nexport function createPageTransformStream(options: PageTransformOptions): TransformStream<Uint8Array, Uint8Array> {\n const { rewriter, heads, ends } = options;\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n const buffered = heads.length > 0 ? ([] as string[]) : null;\n\n const enqueue = (controller: TransformStreamDefaultController<Uint8Array>, text: string): void => {\n if (text) {\n controller.enqueue(encoder.encode(text));\n }\n };\n\n return new TransformStream({\n transform(chunk, controller) {\n let text = decoder.decode(chunk, { stream: true });\n\n if (rewriter) {\n text = rewriter.write(text);\n }\n\n if (buffered) {\n buffered.push(text);\n } else {\n enqueue(controller, text);\n }\n },\n flush(controller) {\n let tail = decoder.decode();\n\n if (rewriter) {\n tail = (tail ? rewriter.write(tail) : '') + rewriter.end();\n }\n\n if (buffered) {\n const html = buffered.join('') + tail;\n\n enqueue(controller, insertIntoHead(html, heads.join('')));\n } else {\n enqueue(controller, tail);\n }\n\n for (const end of ends) {\n try {\n enqueue(controller, end() ?? '');\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error }, 'document emitter failed');\n }\n }\n },\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astroscope/node",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "Opinionated, cloud-friendly Node adapter for Astro: boot lifecycle, health probes, request logging, telemetry, CSRF and static serving run as plain code around server.listen()",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|