@astroscope/node 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/boot.d.ts +2 -2
- package/dist/boot.d.ts.map +1 -1
- package/dist/csrf-middleware-entrypoint.d.ts +1 -2
- package/dist/csrf-middleware-entrypoint.d.ts.map +1 -1
- package/dist/csrf-middleware-entrypoint.js +1 -1
- package/dist/dev-middleware-entrypoint.d.ts +1 -2
- package/dist/dev-middleware-entrypoint.d.ts.map +1 -1
- package/dist/{prepare-CXZsyAVk.js → duplicate-slashes-C6hmOLl9.js} +94 -38
- package/dist/duplicate-slashes-C6hmOLl9.js.map +1 -0
- package/dist/{excludes-pE23EbmQ.js → excludes-10eDopVB.js} +18 -4
- package/dist/excludes-10eDopVB.js.map +1 -0
- package/dist/{excludes-BDiE3eyp.d.ts → excludes-rvkVGg6B.d.ts} +11 -3
- package/dist/excludes-rvkVGg6B.d.ts.map +1 -0
- package/dist/excludes.d.ts +2 -2
- package/dist/excludes.js +2 -2
- package/dist/graph-DdAxiaxa.js +35 -0
- package/dist/graph-DdAxiaxa.js.map +1 -0
- package/dist/health.d.ts +3 -4
- package/dist/health.d.ts.map +1 -1
- package/dist/image-endpoint.d.ts +1 -2
- package/dist/image-endpoint.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -122
- package/dist/index.js.map +1 -1
- package/dist/islands-middleware-entrypoint.d.ts +1 -2
- package/dist/islands-middleware-entrypoint.d.ts.map +1 -1
- package/dist/islands-middleware-entrypoint.js +3 -1
- package/dist/islands-middleware-entrypoint.js.map +1 -1
- package/dist/islands-runtime.iife.js +1 -1
- package/dist/islands.d.ts +57 -2
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +3 -1
- package/dist/log/index.d.ts +5 -5
- package/dist/log/index.d.ts.map +1 -1
- package/dist/native.d.ts +5 -6
- package/dist/native.d.ts.map +1 -1
- package/dist/{prerendered-DVjzWNbW.js → prerendered-Z-Qi-FFK.js} +4 -4
- package/dist/prerendered-Z-Qi-FFK.js.map +1 -0
- package/dist/request-route-DcnZOOM4.js.map +1 -1
- package/dist/route-islands-B53rE5MH.js +73 -0
- package/dist/route-islands-B53rE5MH.js.map +1 -0
- package/dist/route-middleware-entrypoint.d.ts +1 -2
- package/dist/route-middleware-entrypoint.d.ts.map +1 -1
- package/dist/{route-store-CSYR4G5e.d.ts → route-store-neUA2nBb.d.ts} +10 -14
- package/dist/route-store-neUA2nBb.d.ts.map +1 -0
- package/dist/routes-D1o_WrJ5.js +39 -0
- package/dist/routes-D1o_WrJ5.js.map +1 -0
- package/dist/server.d.ts +2 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +68 -45
- package/dist/server.js.map +1 -1
- package/dist/telemetry-B9aziFyQ.js +202 -0
- package/dist/telemetry-B9aziFyQ.js.map +1 -0
- package/dist/telemetry.d.ts +68 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +2 -0
- package/dist/transform-Bz5z5w2Y.js +594 -0
- package/dist/transform-Bz5z5w2Y.js.map +1 -0
- package/package.json +13 -11
- package/dist/excludes-BDiE3eyp.d.ts.map +0 -1
- package/dist/excludes-pE23EbmQ.js.map +0 -1
- package/dist/prepare-CXZsyAVk.js.map +0 -1
- package/dist/prerendered-DVjzWNbW.js.map +0 -1
- package/dist/route-store-CSYR4G5e.d.ts.map +0 -1
- package/dist/strip-build-paths-C6eb1QdG.js +0 -63
- package/dist/strip-build-paths-C6eb1QdG.js.map +0 -1
- package/dist/transform-BqV8SOEm.js +0 -195
- package/dist/transform-BqV8SOEm.js.map +0 -1
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
import { n as log } from "./log-B69HEBvg.js";
|
|
2
|
+
import { n as getIslandEmitters } from "./emitters-C20tjKLp.js";
|
|
3
|
+
import { t as createChunkGraph } from "./graph-DdAxiaxa.js";
|
|
4
|
+
//#region src/islands/rewriter.ts
|
|
5
|
+
const ISLAND = "astro-island";
|
|
6
|
+
const RAW_TEXT = /* @__PURE__ */ new Set([
|
|
7
|
+
"style",
|
|
8
|
+
"textarea",
|
|
9
|
+
"title",
|
|
10
|
+
"xmp",
|
|
11
|
+
"iframe",
|
|
12
|
+
"noembed",
|
|
13
|
+
"noframes",
|
|
14
|
+
"noscript"
|
|
15
|
+
]);
|
|
16
|
+
const RAW_TAIL = 9;
|
|
17
|
+
const NAMED_ENTITIES = {
|
|
18
|
+
amp: "&",
|
|
19
|
+
lt: "<",
|
|
20
|
+
gt: ">",
|
|
21
|
+
quot: "\"",
|
|
22
|
+
apos: "'"
|
|
23
|
+
};
|
|
24
|
+
const C1_REMAP = {
|
|
25
|
+
128: 8364,
|
|
26
|
+
130: 8218,
|
|
27
|
+
131: 402,
|
|
28
|
+
132: 8222,
|
|
29
|
+
133: 8230,
|
|
30
|
+
134: 8224,
|
|
31
|
+
135: 8225,
|
|
32
|
+
136: 710,
|
|
33
|
+
137: 8240,
|
|
34
|
+
138: 352,
|
|
35
|
+
139: 8249,
|
|
36
|
+
140: 338,
|
|
37
|
+
142: 381,
|
|
38
|
+
145: 8216,
|
|
39
|
+
146: 8217,
|
|
40
|
+
147: 8220,
|
|
41
|
+
148: 8221,
|
|
42
|
+
149: 8226,
|
|
43
|
+
150: 8211,
|
|
44
|
+
151: 8212,
|
|
45
|
+
152: 732,
|
|
46
|
+
153: 8482,
|
|
47
|
+
154: 353,
|
|
48
|
+
155: 8250,
|
|
49
|
+
156: 339,
|
|
50
|
+
158: 382,
|
|
51
|
+
159: 376
|
|
52
|
+
};
|
|
53
|
+
const DATA = { kind: "data" };
|
|
54
|
+
function encodeAttribute(value) {
|
|
55
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
56
|
+
}
|
|
57
|
+
function isWhitespace(code) {
|
|
58
|
+
return code === 32 || code === 9 || code === 10 || code === 12 || code === 13;
|
|
59
|
+
}
|
|
60
|
+
function isLetter(code) {
|
|
61
|
+
return code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
62
|
+
}
|
|
63
|
+
/** whitespace, `/` or `>`: what ends a tag name and what may follow an end tag name in raw text */
|
|
64
|
+
function isTagEnd(code) {
|
|
65
|
+
return isWhitespace(code) || code === 47 || code === 62;
|
|
66
|
+
}
|
|
67
|
+
function decodeAttribute(value) {
|
|
68
|
+
if (!value.includes("&") && !value.includes("\r") && !value.includes("\0")) return value;
|
|
69
|
+
return value.replace(/\r\n?/g, "\n").replace(/\0/g, "�").replace(/&(?:#[xX]([0-9a-fA-F]+)|#([0-9]+)|([a-zA-Z][a-zA-Z0-9]*));/g, (match, hex, dec, name) => {
|
|
70
|
+
if (name) return NAMED_ENTITIES[name] ?? match;
|
|
71
|
+
const code = parseInt(hex ?? dec, hex ? 16 : 10);
|
|
72
|
+
if (code === 0 || code > 1114111 || code >= 55296 && code <= 57343) return "�";
|
|
73
|
+
return String.fromCodePoint(C1_REMAP[code] ?? code);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const NAMES_BY_LENGTH = {
|
|
77
|
+
3: ["xmp"],
|
|
78
|
+
5: ["style", "title"],
|
|
79
|
+
6: ["script", "iframe"],
|
|
80
|
+
7: ["noembed"],
|
|
81
|
+
8: [
|
|
82
|
+
"noframes",
|
|
83
|
+
"noscript",
|
|
84
|
+
"textarea",
|
|
85
|
+
"template"
|
|
86
|
+
],
|
|
87
|
+
9: ["plaintext"],
|
|
88
|
+
12: [ISLAND]
|
|
89
|
+
};
|
|
90
|
+
function equalsIgnoreCase(buf, start, name) {
|
|
91
|
+
for (let k = 0; k < name.length; k++) if ((buf.charCodeAt(start + k) | 32) !== name.charCodeAt(k)) return false;
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* reads a tag name from its start (just after `<` or `</`): the end of the name,
|
|
96
|
+
* and the name itself only when it is one the scanner acts on — every other
|
|
97
|
+
* tag passes through without allocating. null when not terminated in `buf`.
|
|
98
|
+
*/
|
|
99
|
+
function readTagName(buf, i) {
|
|
100
|
+
const nameStart = i;
|
|
101
|
+
while (i < buf.length && !isTagEnd(buf.charCodeAt(i))) i++;
|
|
102
|
+
if (i >= buf.length) return null;
|
|
103
|
+
return {
|
|
104
|
+
name: NAMES_BY_LENGTH[i - nameStart]?.find((candidate) => equalsIgnoreCase(buf, nameStart, candidate)) ?? null,
|
|
105
|
+
end: i
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* walks a tag's attributes from just after its name to its `>`, collecting them
|
|
110
|
+
* into `attrs` when given; -1 when the tag is not complete in `buf`. Follows the
|
|
111
|
+
* attribute states exactly: a quote opens a value only right after `=` in the
|
|
112
|
+
* attribute-name position, anywhere else it is a plain name or value character.
|
|
113
|
+
*/
|
|
114
|
+
function scanAttributes(buf, i, attrs) {
|
|
115
|
+
const len = buf.length;
|
|
116
|
+
for (;;) {
|
|
117
|
+
while (i < len && (isWhitespace(buf.charCodeAt(i)) || buf.charCodeAt(i) === 47)) i++;
|
|
118
|
+
if (i >= len) return -1;
|
|
119
|
+
if (buf.charCodeAt(i) === 62) return i + 1;
|
|
120
|
+
const nameStart = i;
|
|
121
|
+
if (buf.charCodeAt(i) === 61) i++;
|
|
122
|
+
while (i < len) {
|
|
123
|
+
const code = buf.charCodeAt(i);
|
|
124
|
+
if (code <= 62 && (code === 61 || isTagEnd(code))) break;
|
|
125
|
+
i++;
|
|
126
|
+
}
|
|
127
|
+
if (i >= len) return -1;
|
|
128
|
+
const nameEnd = i;
|
|
129
|
+
while (i < len && isWhitespace(buf.charCodeAt(i))) i++;
|
|
130
|
+
if (i >= len) return -1;
|
|
131
|
+
let valueStart = i;
|
|
132
|
+
let valueEnd = i;
|
|
133
|
+
if (buf.charCodeAt(i) === 61) {
|
|
134
|
+
i++;
|
|
135
|
+
while (i < len && isWhitespace(buf.charCodeAt(i))) i++;
|
|
136
|
+
if (i >= len) return -1;
|
|
137
|
+
const quote = buf.charCodeAt(i);
|
|
138
|
+
if (quote === 34 || quote === 39) {
|
|
139
|
+
const close = buf.indexOf(String.fromCharCode(quote), i + 1);
|
|
140
|
+
if (close < 0) return -1;
|
|
141
|
+
valueStart = i + 1;
|
|
142
|
+
valueEnd = close;
|
|
143
|
+
i = close + 1;
|
|
144
|
+
} else {
|
|
145
|
+
valueStart = i;
|
|
146
|
+
while (i < len && !isWhitespace(buf.charCodeAt(i)) && buf.charCodeAt(i) !== 62) i++;
|
|
147
|
+
if (i >= len) return -1;
|
|
148
|
+
valueEnd = i;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (attrs) {
|
|
152
|
+
const name = buf.slice(nameStart, nameEnd).toLowerCase();
|
|
153
|
+
if (!(name in attrs)) defineLazyAttribute(attrs, name, buf.slice(valueStart, valueEnd));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function defineLazyAttribute(attrs, name, raw) {
|
|
158
|
+
let decoded;
|
|
159
|
+
Object.defineProperty(attrs, name, {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
configurable: true,
|
|
162
|
+
get: () => decoded ??= decodeAttribute(raw),
|
|
163
|
+
set: (value) => {
|
|
164
|
+
decoded = value;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/** classifies the `<` at `lt` inside script data */
|
|
169
|
+
function classifyScriptMarker(buf, lt) {
|
|
170
|
+
const rest = buf.slice(lt, lt + RAW_TAIL);
|
|
171
|
+
const lower = rest.toLowerCase();
|
|
172
|
+
if (rest.startsWith("<!--")) return "escape-open";
|
|
173
|
+
if (lower.startsWith("<\/script") && lower.length > 8 && isTagEnd(lower.charCodeAt(8))) return "end";
|
|
174
|
+
if (lower.startsWith("<script") && lower.length > 7 && isTagEnd(lower.charCodeAt(7))) return "script-open";
|
|
175
|
+
return rest.length < 4 && "<!--".startsWith(rest) || lower.length <= 8 && "<\/script".startsWith(lower) || lower.length <= 7 && "<script".startsWith(lower) ? "incomplete" : "none";
|
|
176
|
+
}
|
|
177
|
+
function createIslandRewriter(onIsland) {
|
|
178
|
+
let mode = DATA;
|
|
179
|
+
let carry = "";
|
|
180
|
+
let templateDepth = 0;
|
|
181
|
+
const scan = (buf) => {
|
|
182
|
+
const len = buf.length;
|
|
183
|
+
let out = "";
|
|
184
|
+
let emitted = 0;
|
|
185
|
+
let i = 0;
|
|
186
|
+
const flush = (to) => {
|
|
187
|
+
if (to > emitted) {
|
|
188
|
+
out += buf.slice(emitted, to);
|
|
189
|
+
emitted = to;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const hold = (at) => {
|
|
193
|
+
flush(at);
|
|
194
|
+
carry = buf.slice(at);
|
|
195
|
+
emitted = len;
|
|
196
|
+
i = len;
|
|
197
|
+
};
|
|
198
|
+
while (i < len) switch (mode.kind) {
|
|
199
|
+
case "plaintext":
|
|
200
|
+
i = len;
|
|
201
|
+
break;
|
|
202
|
+
case "bogus": {
|
|
203
|
+
const close = buf.indexOf(">", i);
|
|
204
|
+
if (close < 0) i = len;
|
|
205
|
+
else {
|
|
206
|
+
i = close + 1;
|
|
207
|
+
mode = DATA;
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case "cdata": {
|
|
212
|
+
const close = buf.indexOf("]]>", i);
|
|
213
|
+
if (close >= 0) {
|
|
214
|
+
i = close + 3;
|
|
215
|
+
mode = DATA;
|
|
216
|
+
} else hold(Math.max(i, len - 2));
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case "comment": {
|
|
220
|
+
const dashes = buf.indexOf("-->", i);
|
|
221
|
+
const bang = buf.indexOf("--!>", mode.bangAt);
|
|
222
|
+
const close = dashes >= 0 && (bang < 0 || dashes < bang) ? dashes + 3 : bang >= 0 ? bang + 4 : -1;
|
|
223
|
+
if (close >= 0) {
|
|
224
|
+
i = close;
|
|
225
|
+
mode = DATA;
|
|
226
|
+
} else {
|
|
227
|
+
const cut = Math.max(i, len - 3);
|
|
228
|
+
hold(cut);
|
|
229
|
+
mode = {
|
|
230
|
+
kind: "comment",
|
|
231
|
+
bangAt: Math.max(0, mode.bangAt - cut)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
case "rawtext": {
|
|
237
|
+
const { endTag } = mode;
|
|
238
|
+
let k = i;
|
|
239
|
+
let found = -1;
|
|
240
|
+
while ((k = buf.indexOf("</", k)) >= 0) {
|
|
241
|
+
if (k + endTag.length >= len) break;
|
|
242
|
+
if (equalsIgnoreCase(buf, k, endTag) && isTagEnd(buf.charCodeAt(k + endTag.length))) {
|
|
243
|
+
found = k;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
k += 2;
|
|
247
|
+
}
|
|
248
|
+
if (found >= 0) {
|
|
249
|
+
i = found;
|
|
250
|
+
mode = DATA;
|
|
251
|
+
} else hold(Math.max(i, len - endTag.length));
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case "script": {
|
|
255
|
+
let k = i;
|
|
256
|
+
let cut = -1;
|
|
257
|
+
while (cut < 0) {
|
|
258
|
+
const lt = buf.indexOf("<", k);
|
|
259
|
+
const dashes = mode.escape === 0 ? -1 : buf.indexOf("-->", k);
|
|
260
|
+
if (dashes >= 0 && (lt < 0 || dashes < lt)) {
|
|
261
|
+
mode = {
|
|
262
|
+
kind: "script",
|
|
263
|
+
escape: 0
|
|
264
|
+
};
|
|
265
|
+
k = dashes + 3;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (lt < 0) {
|
|
269
|
+
cut = Math.max(k, len - RAW_TAIL + 1);
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
const marker = classifyScriptMarker(buf, lt);
|
|
273
|
+
if (marker === "incomplete") cut = lt;
|
|
274
|
+
else if (marker === "end" && mode.escape !== 2) {
|
|
275
|
+
i = lt;
|
|
276
|
+
mode = DATA;
|
|
277
|
+
break;
|
|
278
|
+
} else if (marker === "end") {
|
|
279
|
+
mode = {
|
|
280
|
+
kind: "script",
|
|
281
|
+
escape: 1
|
|
282
|
+
};
|
|
283
|
+
k = lt + 8;
|
|
284
|
+
} else if (marker === "escape-open" && mode.escape === 0) {
|
|
285
|
+
mode = {
|
|
286
|
+
kind: "script",
|
|
287
|
+
escape: 1
|
|
288
|
+
};
|
|
289
|
+
k = lt + 2;
|
|
290
|
+
} else if (marker === "script-open" && mode.escape === 1) {
|
|
291
|
+
mode = {
|
|
292
|
+
kind: "script",
|
|
293
|
+
escape: 2
|
|
294
|
+
};
|
|
295
|
+
k = lt + 7;
|
|
296
|
+
} else k = lt + 1;
|
|
297
|
+
}
|
|
298
|
+
if (cut >= 0) hold(cut);
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
case "data": {
|
|
302
|
+
const lt = buf.indexOf("<", i);
|
|
303
|
+
if (lt < 0) {
|
|
304
|
+
i = len;
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
if (lt + 1 >= len) {
|
|
308
|
+
hold(lt);
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
const next = buf.charCodeAt(lt + 1);
|
|
312
|
+
if (next === 33) {
|
|
313
|
+
if (buf.startsWith("<!--", lt)) {
|
|
314
|
+
i = lt + 2;
|
|
315
|
+
mode = {
|
|
316
|
+
kind: "comment",
|
|
317
|
+
bangAt: lt + 4
|
|
318
|
+
};
|
|
319
|
+
} else if (buf.startsWith("<![CDATA[", lt)) {
|
|
320
|
+
i = lt + 9;
|
|
321
|
+
mode = { kind: "cdata" };
|
|
322
|
+
} else if (len - lt < 9 && ("<!--".startsWith(buf.slice(lt)) || "<![CDATA[".startsWith(buf.slice(lt)))) hold(lt);
|
|
323
|
+
else {
|
|
324
|
+
i = lt + 2;
|
|
325
|
+
mode = { kind: "bogus" };
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
if (next === 63) {
|
|
330
|
+
i = lt + 2;
|
|
331
|
+
mode = { kind: "bogus" };
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
if (next === 47) {
|
|
335
|
+
if (lt + 2 >= len) {
|
|
336
|
+
hold(lt);
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
const after = buf.charCodeAt(lt + 2);
|
|
340
|
+
if (isLetter(after)) {
|
|
341
|
+
const tag = readTagName(buf, lt + 2);
|
|
342
|
+
const end = tag ? scanAttributes(buf, tag.end, null) : -1;
|
|
343
|
+
if (end < 0) {
|
|
344
|
+
hold(lt);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
i = end;
|
|
348
|
+
if (tag.name === "template" && templateDepth > 0) templateDepth--;
|
|
349
|
+
} else if (after === 62) i = lt + 3;
|
|
350
|
+
else {
|
|
351
|
+
i = lt + 2;
|
|
352
|
+
mode = { kind: "bogus" };
|
|
353
|
+
}
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
if (isLetter(next)) {
|
|
357
|
+
const head = readTagName(buf, lt + 1);
|
|
358
|
+
if (!head) {
|
|
359
|
+
hold(lt);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
const { name } = head;
|
|
363
|
+
const attrs = name === ISLAND ? Object.create(null) : null;
|
|
364
|
+
const end = scanAttributes(buf, head.end, attrs);
|
|
365
|
+
if (end < 0) {
|
|
366
|
+
hold(lt);
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
if (attrs && templateDepth === 0) {
|
|
370
|
+
const rewrite = onIsland(attrs);
|
|
371
|
+
if (rewrite?.prepend) {
|
|
372
|
+
flush(lt);
|
|
373
|
+
out += rewrite.prepend;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
i = end;
|
|
377
|
+
if (name === "script") mode = {
|
|
378
|
+
kind: "script",
|
|
379
|
+
escape: 0
|
|
380
|
+
};
|
|
381
|
+
else if (name !== null && RAW_TEXT.has(name)) mode = {
|
|
382
|
+
kind: "rawtext",
|
|
383
|
+
endTag: `</${name}`
|
|
384
|
+
};
|
|
385
|
+
else if (name === "plaintext") mode = { kind: "plaintext" };
|
|
386
|
+
else if (name === "template") templateDepth++;
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
i = lt + 1;
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
flush(len);
|
|
394
|
+
return out;
|
|
395
|
+
};
|
|
396
|
+
return {
|
|
397
|
+
write(chunk) {
|
|
398
|
+
const buf = carry + chunk;
|
|
399
|
+
carry = "";
|
|
400
|
+
return scan(buf);
|
|
401
|
+
},
|
|
402
|
+
end() {
|
|
403
|
+
const tail = carry;
|
|
404
|
+
carry = "";
|
|
405
|
+
return mode.kind === "data" && /^<\/?[a-zA-Z]/.test(tail) ? "" : tail;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/islands/transform.ts
|
|
411
|
+
/**
|
|
412
|
+
* Turns the manifest into per-document rewriters: resolves each island's chunk
|
|
413
|
+
* closures, collects emissions (the built-in preloader plus registered emitters),
|
|
414
|
+
* and applies the emission policy —
|
|
415
|
+
*
|
|
416
|
+
* - immediate directives (`load`, `only`) get `<link rel="modulepreload">` tags
|
|
417
|
+
* before the tag, deduplicated per document; the browser's speculative preload
|
|
418
|
+
* scanner acts on them from raw bytes, ahead of any script.
|
|
419
|
+
* - deferred directives get an inline script before the first island per
|
|
420
|
+
* component that registers `{l: links, i: imports}` on the preload global,
|
|
421
|
+
* keyed by `component-url`; the gate runtime injects the links and eagerly
|
|
422
|
+
* `import()`s the imports by the directive's own scheduling semantics. A script
|
|
423
|
+
* rather than an attribute: it takes effect at parse time and its effect
|
|
424
|
+
* survives the island element being removed — the island tag itself stays
|
|
425
|
+
* untouched.
|
|
426
|
+
*
|
|
427
|
+
* The gate runtime is inlined once, before the first island that needs it —
|
|
428
|
+
* pages without deferred islands never carry it, pages with them install the
|
|
429
|
+
* gates at parse time, without an external fetch to lose.
|
|
430
|
+
*/
|
|
431
|
+
/** global registry of `{l, i}` entries per component-url, written by the transform, read by the gate runtime */
|
|
432
|
+
const PRELOAD_GLOBAL = "__islands__";
|
|
433
|
+
const IMMEDIATE_DIRECTIVES = /* @__PURE__ */ new Set(["load", "only"]);
|
|
434
|
+
/** urls cannot contain `<\/script>`, but escape `<` anyway so no value ever can */
|
|
435
|
+
function jsonForScript(value) {
|
|
436
|
+
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
437
|
+
}
|
|
438
|
+
function createIslandsTransformer(manifest) {
|
|
439
|
+
const graph = createChunkGraph(manifest);
|
|
440
|
+
const fileNames = Object.keys(manifest.chunks);
|
|
441
|
+
const resolveCache = /* @__PURE__ */ new Map();
|
|
442
|
+
const resolve = (url) => {
|
|
443
|
+
const cached = resolveCache.get(url);
|
|
444
|
+
if (cached !== void 0) return cached;
|
|
445
|
+
for (const fileName of fileNames) if (url.endsWith(fileName)) {
|
|
446
|
+
const boundary = url.length - fileName.length;
|
|
447
|
+
if (boundary === 0 || url[boundary - 1] === "/") {
|
|
448
|
+
const resolved = {
|
|
449
|
+
prefix: url.slice(0, boundary),
|
|
450
|
+
fileName
|
|
451
|
+
};
|
|
452
|
+
resolveCache.set(url, resolved);
|
|
453
|
+
return resolved;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
};
|
|
458
|
+
const islands = /* @__PURE__ */ new Map();
|
|
459
|
+
const linkTags = /* @__PURE__ */ new Map();
|
|
460
|
+
const registerScripts = /* @__PURE__ */ new WeakMap();
|
|
461
|
+
const resolveIsland = (componentUrl, rendererUrl, client) => {
|
|
462
|
+
const key = `${componentUrl}\n${rendererUrl ?? ""}\n${client ?? ""}`;
|
|
463
|
+
const cached = islands.get(key);
|
|
464
|
+
if (cached) return cached;
|
|
465
|
+
const component = resolve(componentUrl);
|
|
466
|
+
if (!component) return null;
|
|
467
|
+
const renderer = rendererUrl ? resolve(rendererUrl) : null;
|
|
468
|
+
const closureUrls = (closure) => {
|
|
469
|
+
const urls = /* @__PURE__ */ new Set([componentUrl, ...closure(component.fileName).map((f) => component.prefix + f)]);
|
|
470
|
+
if (rendererUrl) {
|
|
471
|
+
urls.add(rendererUrl);
|
|
472
|
+
for (const f of renderer ? closure(renderer.fileName) : []) urls.add(renderer.prefix + f);
|
|
473
|
+
}
|
|
474
|
+
return [...urls];
|
|
475
|
+
};
|
|
476
|
+
const island = {
|
|
477
|
+
componentUrl,
|
|
478
|
+
rendererUrl,
|
|
479
|
+
client,
|
|
480
|
+
staticClosure: closureUrls(graph.staticClosure),
|
|
481
|
+
fullClosure: closureUrls(graph.fullClosure)
|
|
482
|
+
};
|
|
483
|
+
islands.set(key, island);
|
|
484
|
+
return island;
|
|
485
|
+
};
|
|
486
|
+
const linkTag = (url) => {
|
|
487
|
+
let tag = linkTags.get(url);
|
|
488
|
+
if (tag === void 0) {
|
|
489
|
+
tag = `<link rel="modulepreload" fetchpriority="low" href="${encodeAttribute(url)}">`;
|
|
490
|
+
linkTags.set(url, tag);
|
|
491
|
+
}
|
|
492
|
+
return tag;
|
|
493
|
+
};
|
|
494
|
+
const registerScript = (componentUrl, links, imports) => {
|
|
495
|
+
const importSet = new Set(imports);
|
|
496
|
+
const entry = { l: links.filter((url) => !importSet.has(url)) };
|
|
497
|
+
if (imports.length > 0) entry["i"] = imports;
|
|
498
|
+
return `<script>(self.${PRELOAD_GLOBAL}??={})[${jsonForScript(componentUrl)}]=${jsonForScript(entry)};<\/script>`;
|
|
499
|
+
};
|
|
500
|
+
const createDocumentRewriter = (context) => {
|
|
501
|
+
const emittedLinks = /* @__PURE__ */ new Set();
|
|
502
|
+
const registeredComponents = /* @__PURE__ */ new Set();
|
|
503
|
+
let runtimeInjected = false;
|
|
504
|
+
return createIslandRewriter((attrs) => {
|
|
505
|
+
const componentUrl = attrs["component-url"];
|
|
506
|
+
if (!componentUrl) return null;
|
|
507
|
+
const island = resolveIsland(componentUrl, attrs["renderer-url"] || null, attrs["client"] || null);
|
|
508
|
+
if (!island) return null;
|
|
509
|
+
const emitters = getIslandEmitters();
|
|
510
|
+
let links = island.staticClosure;
|
|
511
|
+
let imports = [];
|
|
512
|
+
let html = "";
|
|
513
|
+
if (emitters.length > 0) {
|
|
514
|
+
const emissions = [{ links: island.staticClosure }];
|
|
515
|
+
for (const emitter of emitters) try {
|
|
516
|
+
const emission = emitter(island, context);
|
|
517
|
+
if (emission) emissions.push(emission);
|
|
518
|
+
} catch (error) {
|
|
519
|
+
log.error({
|
|
520
|
+
err: error,
|
|
521
|
+
componentUrl
|
|
522
|
+
}, "island emitter failed");
|
|
523
|
+
}
|
|
524
|
+
links = [...new Set(emissions.flatMap((e) => e.links ?? []))];
|
|
525
|
+
imports = [...new Set(emissions.flatMap((e) => e.imports ?? []))];
|
|
526
|
+
html = emissions.map((e) => e.html ?? "").join("");
|
|
527
|
+
}
|
|
528
|
+
const directive = (island.client ?? "").replace(/-x$/, "");
|
|
529
|
+
if (IMMEDIATE_DIRECTIVES.has(directive)) {
|
|
530
|
+
let prepend = html;
|
|
531
|
+
for (const url of links) if (!emittedLinks.has(url)) {
|
|
532
|
+
emittedLinks.add(url);
|
|
533
|
+
prepend += linkTag(url);
|
|
534
|
+
}
|
|
535
|
+
return { prepend: prepend || void 0 };
|
|
536
|
+
}
|
|
537
|
+
if (registeredComponents.has(componentUrl)) return { prepend: html || void 0 };
|
|
538
|
+
registeredComponents.add(componentUrl);
|
|
539
|
+
const runtime = runtimeInjected ? "" : `<script>${manifest.runtimeSource}<\/script>`;
|
|
540
|
+
runtimeInjected = true;
|
|
541
|
+
let register;
|
|
542
|
+
if (emitters.length > 0) register = registerScript(componentUrl, links, imports);
|
|
543
|
+
else {
|
|
544
|
+
register = registerScripts.get(island) ?? registerScript(componentUrl, links, imports);
|
|
545
|
+
registerScripts.set(island, register);
|
|
546
|
+
}
|
|
547
|
+
return { prepend: runtime + register + html || void 0 };
|
|
548
|
+
});
|
|
549
|
+
};
|
|
550
|
+
return { createDocumentRewriter };
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* The single streaming pass over an html page response: chunks go through the
|
|
554
|
+
* islands rewriter (when present), head content is inserted right after the
|
|
555
|
+
* opening `<head>` tag (which requires buffering the whole document — head
|
|
556
|
+
* content is dev-style delivery, where throughput is irrelevant), and end
|
|
557
|
+
* factories run last, strictly after every island passed the rewriter.
|
|
558
|
+
*/
|
|
559
|
+
function createPageTransformStream(options) {
|
|
560
|
+
const { rewriter, heads, ends } = options;
|
|
561
|
+
const decoder = new TextDecoder();
|
|
562
|
+
const encoder = new TextEncoder();
|
|
563
|
+
const buffered = heads.length > 0 ? [] : null;
|
|
564
|
+
const enqueue = (controller, text) => {
|
|
565
|
+
if (text) controller.enqueue(encoder.encode(text));
|
|
566
|
+
};
|
|
567
|
+
return new TransformStream({
|
|
568
|
+
transform(chunk, controller) {
|
|
569
|
+
let text = decoder.decode(chunk, { stream: true });
|
|
570
|
+
if (rewriter) text = rewriter.write(text);
|
|
571
|
+
if (buffered) buffered.push(text);
|
|
572
|
+
else enqueue(controller, text);
|
|
573
|
+
},
|
|
574
|
+
flush(controller) {
|
|
575
|
+
let tail = decoder.decode();
|
|
576
|
+
if (rewriter) tail = (tail ? rewriter.write(tail) : "") + rewriter.end();
|
|
577
|
+
if (buffered) {
|
|
578
|
+
const html = buffered.join("") + tail;
|
|
579
|
+
const head = /<head[^>]*>/i.exec(html);
|
|
580
|
+
const at = head ? head.index + head[0].length : 0;
|
|
581
|
+
enqueue(controller, html.slice(0, at) + heads.join("") + html.slice(at));
|
|
582
|
+
} else enqueue(controller, tail);
|
|
583
|
+
for (const end of ends) try {
|
|
584
|
+
enqueue(controller, end() ?? "");
|
|
585
|
+
} catch (error) {
|
|
586
|
+
log.error({ err: error }, "document emitter failed");
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
//#endregion
|
|
592
|
+
export { createPageTransformStream as n, createIslandsTransformer as t };
|
|
593
|
+
|
|
594
|
+
//# sourceMappingURL=transform-Bz5z5w2Y.js.map
|
|
@@ -0,0 +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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"}
|