@solidjs/web 2.0.0-beta.29 → 2.0.0-beta.30
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/dev.cjs +329 -2
- package/dist/dev.js +329 -3
- package/dist/server.cjs +451 -20
- package/dist/server.js +451 -21
- package/dist/web.cjs +325 -2
- package/dist/web.js +325 -3
- package/frames/dist/client.cjs +177 -34
- package/frames/dist/client.dev.cjs +177 -34
- package/frames/dist/client.dev.js +178 -35
- package/frames/dist/client.js +178 -35
- package/frames/dist/server.cjs +405 -17
- package/frames/dist/server.js +405 -17
- package/package.json +3 -3
- package/types/client.d.ts +20 -0
- package/types/frames/frame-client.d.ts +25 -0
- package/types/frames/frame-transport.d.ts +26 -0
- package/types/index.d.ts +1 -22
- package/types/server.d.ts +50 -0
- package/types-cjs/client.d.cts +20 -0
- package/types-cjs/frames/frame-client.d.cts +25 -0
- package/types-cjs/frames/frame-transport.d.cts +26 -0
- package/types-cjs/index.d.cts +1 -22
- package/types-cjs/server.d.cts +50 -0
package/dist/server.js
CHANGED
|
@@ -100,6 +100,90 @@ function getLocalHeaderScript(id) {
|
|
|
100
100
|
}
|
|
101
101
|
Feature.RegExp;
|
|
102
102
|
|
|
103
|
+
const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
|
|
104
|
+
const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
|
|
105
|
+
const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "icon", "stylesheet"]);
|
|
106
|
+
const RESOURCE_QUALIFIERS = ["as", "crossorigin", "type", "media", "imagesrcset", "imagesizes"];
|
|
107
|
+
const STYLESHEET_FETCH_META = new Set(["crossorigin", "integrity", "referrerpolicy", "fetchpriority"]);
|
|
108
|
+
function evalHeadValue(v) {
|
|
109
|
+
return typeof v === "function" ? v() : v;
|
|
110
|
+
}
|
|
111
|
+
function evalHeadProps(props, presets) {
|
|
112
|
+
const out = {};
|
|
113
|
+
for (const name in props) out[name] = presets && name in presets ? presets[name] : evalHeadValue(props[name]);
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
function classifyHeadTag(desc) {
|
|
117
|
+
const tag = desc.tag;
|
|
118
|
+
if (tag === "link") {
|
|
119
|
+
const rel = evalHeadValue(desc.props && desc.props.rel);
|
|
120
|
+
return {
|
|
121
|
+
resource: RESOURCE_LINK_RELS.has(rel),
|
|
122
|
+
rel
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (tag === "style") return {
|
|
126
|
+
resource: !!(desc.props && "href" in desc.props)
|
|
127
|
+
};
|
|
128
|
+
if (tag === "script") return {
|
|
129
|
+
resource: !!(desc.props && "src" in desc.props)
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
resource: false
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function resourceIdentity(tag, props) {
|
|
136
|
+
let id = "res:" + tag + ":" + (props.rel || "") + ":" + (props.href || props.src || "");
|
|
137
|
+
for (let i = 0; i < RESOURCE_QUALIFIERS.length; i++) {
|
|
138
|
+
const q = RESOURCE_QUALIFIERS[i];
|
|
139
|
+
if (props[q] != null) id += ":" + q + "=" + props[q];
|
|
140
|
+
}
|
|
141
|
+
return id;
|
|
142
|
+
}
|
|
143
|
+
function replaceableIdentity(tag, props, key, unique) {
|
|
144
|
+
if (tag === "title") return "title";
|
|
145
|
+
if (tag === "base") return "base";
|
|
146
|
+
if (tag === "meta" && props.charset != null) return "charset";
|
|
147
|
+
if (key != null) return tag + ":key:" + key;
|
|
148
|
+
if (tag === "meta") {
|
|
149
|
+
if (props.name != null) return "meta:name:" + props.name;
|
|
150
|
+
if (props.property != null) return "meta:property:" + props.property;
|
|
151
|
+
if (props["http-equiv"] != null) return "meta:http-equiv:" + props["http-equiv"];
|
|
152
|
+
return unique;
|
|
153
|
+
}
|
|
154
|
+
if (tag === "link") return "link:" + (props.rel || "") + ":" + (props.href || "");
|
|
155
|
+
return unique;
|
|
156
|
+
}
|
|
157
|
+
function resolveHead(groups) {
|
|
158
|
+
const winners = new Map();
|
|
159
|
+
const sorted = groups.slice().sort((a, b) => a.seq - b.seq);
|
|
160
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
161
|
+
const group = sorted[i];
|
|
162
|
+
const byIdentity = new Map();
|
|
163
|
+
for (let j = 0; j < group.tags.length; j++) {
|
|
164
|
+
const t = group.tags[j];
|
|
165
|
+
let list = byIdentity.get(t.identity);
|
|
166
|
+
if (!list) byIdentity.set(t.identity, list = []);
|
|
167
|
+
list.push(t);
|
|
168
|
+
}
|
|
169
|
+
for (const [identity, tags] of byIdentity) {
|
|
170
|
+
if (identity === "title") {
|
|
171
|
+
if (tags.length > 1) console.warn("Multiple <title> tags in one head group; the last one wins.");
|
|
172
|
+
winners.set(identity, {
|
|
173
|
+
seq: group.seq,
|
|
174
|
+
tags: [tags[tags.length - 1]]
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
winners.set(identity, {
|
|
178
|
+
seq: group.seq,
|
|
179
|
+
tags
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return winners;
|
|
185
|
+
}
|
|
186
|
+
|
|
103
187
|
function joinAssetPath(base, file) {
|
|
104
188
|
if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(file)) return file;
|
|
105
189
|
if (typeof base !== "string" || !base) base = "/";
|
|
@@ -241,14 +325,274 @@ function applyAssetTracking(context, tracking, manifest, noScripts) {
|
|
|
241
325
|
context.resolveAssetsSync = resolve;
|
|
242
326
|
}
|
|
243
327
|
}
|
|
328
|
+
function isCssUrl(url) {
|
|
329
|
+
const q = url.search(/[?#]/);
|
|
330
|
+
return (q === -1 ? url : url.slice(0, q)).endsWith(".css");
|
|
331
|
+
}
|
|
332
|
+
function createHeadRegistry() {
|
|
333
|
+
return {
|
|
334
|
+
pending: [],
|
|
335
|
+
committed: [],
|
|
336
|
+
seq: 0,
|
|
337
|
+
uniq: 0,
|
|
338
|
+
resources: new Set(),
|
|
339
|
+
eagerHtml: "",
|
|
340
|
+
flushed: null,
|
|
341
|
+
shellFlushed: false
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
|
|
345
|
+
const boundary = context._currentBoundaryId || "";
|
|
346
|
+
let replaceable = null;
|
|
347
|
+
for (let i = 0; i < tags.length; i++) {
|
|
348
|
+
const desc = tags[i];
|
|
349
|
+
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
350
|
+
console.warn(`useHead: ignoring non-head tag`, desc);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
const cls = classifyHeadTag(desc);
|
|
354
|
+
if (cls.resource) {
|
|
355
|
+
emitHeadResource(registry, context, tracking, emitResource, nonce, desc, cls.rel);
|
|
356
|
+
} else {
|
|
357
|
+
(replaceable || (replaceable = [])).push(cls.rel !== undefined ? {
|
|
358
|
+
tag: desc.tag,
|
|
359
|
+
props: desc.props,
|
|
360
|
+
key: desc.key,
|
|
361
|
+
rel: cls.rel
|
|
362
|
+
} : desc);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (replaceable) registry.pending.push({
|
|
366
|
+
boundary,
|
|
367
|
+
tags: replaceable
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel) {
|
|
371
|
+
let props;
|
|
372
|
+
try {
|
|
373
|
+
props = evalHeadProps(desc.props || {}, rel !== undefined ? {
|
|
374
|
+
rel
|
|
375
|
+
} : undefined);
|
|
376
|
+
} catch (err) {
|
|
377
|
+
console.warn(`useHead: error evaluating resource tag props`, err);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const identity = resourceIdentity(desc.tag, props);
|
|
381
|
+
if (registry.resources.has(identity)) return;
|
|
382
|
+
registry.resources.add(identity);
|
|
383
|
+
if (desc.tag === "link" && (rel === "stylesheet" || rel === "modulepreload")) {
|
|
384
|
+
let plain = true;
|
|
385
|
+
let gateable = rel === "stylesheet";
|
|
386
|
+
for (const name in props) {
|
|
387
|
+
if (name === "rel" || name === "href") continue;
|
|
388
|
+
plain = false;
|
|
389
|
+
if (!STYLESHEET_FETCH_META.has(name)) gateable = false;
|
|
390
|
+
}
|
|
391
|
+
if (plain && props.href != null) {
|
|
392
|
+
const isCss = isCssUrl(props.href);
|
|
393
|
+
if (rel === "stylesheet" ? isCss : !isCss) {
|
|
394
|
+
context.registerAsset(rel === "stylesheet" ? "style" : "module", props.href);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (gateable && props.href != null) {
|
|
399
|
+
const attrHtml = renderHeadAttrHtml(props);
|
|
400
|
+
const entry = {
|
|
401
|
+
href: props.href,
|
|
402
|
+
attrHtml,
|
|
403
|
+
attrs: headAttrRecord(props)
|
|
404
|
+
};
|
|
405
|
+
if (tracking.currentBoundaryId) {
|
|
406
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
407
|
+
if (!styles) tracking.boundaryStyles.set(tracking.currentBoundaryId, styles = new Set());
|
|
408
|
+
styles.add(entry);
|
|
409
|
+
}
|
|
410
|
+
const markup = `<link${attrHtml}>`;
|
|
411
|
+
if (emitResource) emitResource(markup, entry);else {
|
|
412
|
+
registry.eagerHtml += markup;
|
|
413
|
+
entry.emitted = true;
|
|
414
|
+
}
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
const url = props.href || props.src;
|
|
419
|
+
if (url != null && tracking.emittedAssets.has(url)) return;
|
|
420
|
+
const markup = renderHeadTagMarkup(desc.tag, props, null, nonce);
|
|
421
|
+
if (emitResource) emitResource(markup);else registry.eagerHtml += markup;
|
|
422
|
+
}
|
|
423
|
+
function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
424
|
+
const keep = [];
|
|
425
|
+
const groups = [];
|
|
426
|
+
for (let i = 0; i < registry.pending.length; i++) {
|
|
427
|
+
const reg = registry.pending[i];
|
|
428
|
+
const mine = boundary === "" ? !(isPendingFragment && reg.boundary !== "" && isPendingFragment(reg.boundary)) : reg.boundary === boundary;
|
|
429
|
+
if (!mine) {
|
|
430
|
+
keep.push(reg);
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
const tags = [];
|
|
434
|
+
for (let j = 0; j < reg.tags.length; j++) {
|
|
435
|
+
const desc = reg.tags[j];
|
|
436
|
+
let props, key;
|
|
437
|
+
try {
|
|
438
|
+
props = evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
|
|
439
|
+
rel: desc.rel
|
|
440
|
+
} : undefined);
|
|
441
|
+
key = evalHeadValue(desc.key);
|
|
442
|
+
} catch (err) {
|
|
443
|
+
console.warn(`useHead: error evaluating tag props`, err);
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
|
|
447
|
+
if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
|
|
448
|
+
console.warn(`useHead: <${desc.tag}> (${identity}) registered after shell flush is ignored`);
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
tags.push({
|
|
452
|
+
tag: desc.tag,
|
|
453
|
+
props,
|
|
454
|
+
identity
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (tags.length) groups.push({
|
|
458
|
+
seq: registry.seq++,
|
|
459
|
+
tags
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
registry.pending = keep;
|
|
463
|
+
for (let i = 0; i < groups.length; i++) registry.committed.push(groups[i]);
|
|
464
|
+
return groups;
|
|
465
|
+
}
|
|
466
|
+
function adoptHeadBoundary(registry, childKey, parentKey) {
|
|
467
|
+
for (let i = 0; i < registry.pending.length; i++) {
|
|
468
|
+
if (registry.pending[i].boundary === childKey) registry.pending[i].boundary = parentKey;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function dropHeadBoundary(registry, boundary) {
|
|
472
|
+
registry.pending = registry.pending.filter(reg => reg.boundary !== boundary);
|
|
473
|
+
}
|
|
474
|
+
function headGroupSignature(winner) {
|
|
475
|
+
let sig = "" + winner.seq;
|
|
476
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
477
|
+
const t = winner.tags[i];
|
|
478
|
+
sig += "|" + t.tag + JSON.stringify(t.props);
|
|
479
|
+
}
|
|
480
|
+
return sig;
|
|
481
|
+
}
|
|
482
|
+
function renderShellHead(registry, nonce, isPendingFragment) {
|
|
483
|
+
commitHeadBoundary(registry, "", isPendingFragment);
|
|
484
|
+
registry.shellFlushed = true;
|
|
485
|
+
const winners = resolveHead(registry.committed);
|
|
486
|
+
registry.flushed = new Map();
|
|
487
|
+
let prelude = "";
|
|
488
|
+
let links = "";
|
|
489
|
+
let metas = "";
|
|
490
|
+
let others = "";
|
|
491
|
+
let scripts = "";
|
|
492
|
+
for (const [identity, winner] of winners) {
|
|
493
|
+
registry.flushed.set(identity, headGroupSignature(winner));
|
|
494
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
495
|
+
const t = winner.tags[i];
|
|
496
|
+
const markup = renderHeadTagMarkup(t.tag, t.props, identity, nonce);
|
|
497
|
+
if (identity === "charset" || identity === "base") prelude += markup;else if (t.tag === "link" || t.tag === "style") links += markup;else if (t.tag === "meta") metas += markup;else if (t.tag === "script") scripts += markup;else others += markup;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
prelude,
|
|
502
|
+
html: registry.eagerHtml + links + metas + others + scripts
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
function flushHeadFragment(registry, boundary) {
|
|
506
|
+
const groups = commitHeadBoundary(registry, boundary);
|
|
507
|
+
if (!groups.length) return null;
|
|
508
|
+
const winners = resolveHead(registry.committed);
|
|
509
|
+
const affected = new Set();
|
|
510
|
+
for (let i = 0; i < groups.length; i++) for (let j = 0; j < groups[i].tags.length; j++) affected.add(groups[i].tags[j].identity);
|
|
511
|
+
const ops = [];
|
|
512
|
+
for (const identity of affected) {
|
|
513
|
+
const winner = winners.get(identity);
|
|
514
|
+
const sig = headGroupSignature(winner);
|
|
515
|
+
if (registry.flushed.get(identity) === sig) continue;
|
|
516
|
+
const existed = registry.flushed.has(identity);
|
|
517
|
+
registry.flushed.set(identity, sig);
|
|
518
|
+
if (identity === "title") {
|
|
519
|
+
const children = winner.tags[0].props.children;
|
|
520
|
+
ops.push(["t", children == null ? "" : String(children)]);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
if (existed) ops.push(["r", identity]);
|
|
524
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
525
|
+
const t = winner.tags[i];
|
|
526
|
+
const attrs = {};
|
|
527
|
+
for (const name in t.props) {
|
|
528
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
529
|
+
if (!HEAD_ATTR_NAME.test(name)) {
|
|
530
|
+
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
const v = t.props[name];
|
|
534
|
+
if (v == null || v === false) continue;
|
|
535
|
+
attrs[name] = v === true ? "" : String(v);
|
|
536
|
+
}
|
|
537
|
+
const children = t.props.children;
|
|
538
|
+
ops.push(["a", identity, t.tag, attrs, children == null ? null : String(children)]);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return ops.length ? ops : null;
|
|
542
|
+
}
|
|
543
|
+
function renderHeadAttrHtml(props) {
|
|
544
|
+
let attrs = "";
|
|
545
|
+
for (const name in props) {
|
|
546
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
547
|
+
if (!HEAD_ATTR_NAME.test(name)) {
|
|
548
|
+
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
const v = props[name];
|
|
552
|
+
if (v == null || v === false) continue;
|
|
553
|
+
attrs += v === true ? ` ${name}` : ` ${name}="${escape(String(v), true)}"`;
|
|
554
|
+
}
|
|
555
|
+
return attrs;
|
|
556
|
+
}
|
|
557
|
+
function headAttrRecord(props, skipRelHref) {
|
|
558
|
+
let attrs = null;
|
|
559
|
+
for (const name in props) {
|
|
560
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
561
|
+
if ((name === "rel" || name === "href")) continue;
|
|
562
|
+
if (!HEAD_ATTR_NAME.test(name)) continue;
|
|
563
|
+
const v = props[name];
|
|
564
|
+
if (v == null || v === false) continue;
|
|
565
|
+
(attrs || (attrs = {}))[name] = v === true ? "" : String(v);
|
|
566
|
+
}
|
|
567
|
+
return attrs;
|
|
568
|
+
}
|
|
569
|
+
function renderHeadTagMarkup(tag, props, identity, nonce) {
|
|
570
|
+
let attrs = renderHeadAttrHtml(props);
|
|
571
|
+
if (identity != null) attrs += ` data-dh="${escape(identity, true)}"`;
|
|
572
|
+
if (nonce && (tag === "script" || tag === "style")) attrs += ` nonce="${nonce}"`;
|
|
573
|
+
if (tag === "meta" || tag === "link" || tag === "base") return `<${tag}${attrs}>`;
|
|
574
|
+
let body = props.children == null ? "" : String(props.children);
|
|
575
|
+
if (tag === "script") body = body.replace(/<\/(script)/gi, "<\\/$1");else if (tag === "style") body = escapeStyleContent(body);else body = escape(body);
|
|
576
|
+
return `<${tag}${attrs}>${body}</${tag}>`;
|
|
577
|
+
}
|
|
578
|
+
function useHead(tags) {
|
|
579
|
+
const ctx = sharedConfig.context;
|
|
580
|
+
if (!ctx || !ctx.registerHeadTags) {
|
|
581
|
+
console.warn("useHead() called outside of a server render; registration ignored.");
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
ctx.registerHeadTags(Array.isArray(tags) ? tags : [tags]);
|
|
585
|
+
}
|
|
244
586
|
const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
|
|
245
|
-
const REPLACE_SCRIPT = `function $df(e,n,o,t){if(!(n=document.getElementById(e)))return 0;if(!(o=document.getElementById("pl-"+e)))return(_$HY.dq=_$HY.dq||{})[e]=1,0;for(;o&&(8!==o.nodeType||o.nodeValue!=="pl-"+e);)t=o.nextSibling,o.remove(),o=t;t=o.parentNode,
|
|
587
|
+
const REPLACE_SCRIPT = `function $df(e){return _$HY.f?_$HY.f(e):$dfr(e)}function $dfr(e,n,o,t){if(!(n=document.getElementById(e)))return 0;if(!(o=document.getElementById("pl-"+e)))return(_$HY.dq=_$HY.dq||{})[e]=1,0;for(;o&&(8!==o.nodeType||o.nodeValue!=="pl-"+e);)t=o.nextSibling,o.remove(),o=t;t=o.parentNode,o.replaceWith(n.content),n.remove(),_$HY.fe(e,t),_$HY.hp&&_$HY.hp[e]&&($dh(_$HY.hp[e]),delete _$HY.hp[e]),$dfd();return 1}function $dfl(e,o,n){if(!(o=document.getElementById("pl-"+e)))return(_$HY.dlq=_$HY.dlq||{})[e]=1,0;if(o._$fl)return 1;for(n=o.nextSibling;n;){if(8===n.nodeType&&n.nodeValue==="pl-"+e){o.parentNode&&o.parentNode.insertBefore(o.content.cloneNode(!0),n),o._$fl=1,$dfd();return 1}n=n.nextSibling}return 0}function $dflj(e,i){for(i=0;i<e.length;i++)$dfl(e[i])}function $dfd(e,i){if(e=_$HY.dq){_$HY.dq=0;for(i in e)$df(i)}if(e=_$HY.dlq){_$HY.dlq=0;for(i in e)$dfl(i)}}function $dfs(e,c,d){(_$HY.sc=_$HY.sc||{})[e]=c,d&&((_$HY.sd=_$HY.sd||{})[e]=1)}function $dfg(e,g,i,k){if(!(g=_$HY.sg&&_$HY.sg[e]))return;for(i=0;i<g.length;i++)if(_$HY.sc&&_$HY.sc[g[i]]>0)return;for(i=0;i<g.length;i++)k=g[i],delete _$HY.sg[k],$df(k)}function $dfc(e){if(--_$HY.sc[e]<=0){delete _$HY.sc[e],_$HY.sg&&_$HY.sg[e]?$dfg(e):!(_$HY.sd&&_$HY.sd[e])&&$df(e);_$HY.sd&&delete _$HY.sd[e]}}function $dfj(e,i,n){for(i=0;i<e.length;i++)if(_$HY.sc&&_$HY.sc[e[i]]>0){for(n=0;n<e.length;n++)(_$HY.sg=_$HY.sg||{})[e[n]]=e;return}for(i=0;i<e.length;i++)$df(e[i])}`;
|
|
588
|
+
const HEAD_SCRIPT = `function $dha(o,i,e,n){for(i=0;i<o.length;i++)e=o[i],"t"==e[0]?((n=document.querySelector("title"))||(n=document.createElement("title"),document.head.appendChild(n)),n.textContent=e[1],n.setAttribute("data-dh","title")):"r"==e[0]?$dhr(e[1]):(n=document.createElement(e[2]),Object.keys(e[3]).forEach(function(a){n.setAttribute(a,e[3][a])}),null!=e[4]&&(n.textContent=e[4]),n.setAttribute("data-dh",e[1]),document.head.appendChild(n))}function $dhr(v,l,i){for(l=document.head.querySelectorAll("[data-dh]"),i=0;i<l.length;i++)l[i].getAttribute("data-dh")==v&&l[i].remove()}function $dh(o){_$HY.h?_$HY.h(o):$dha(o)}`;
|
|
246
589
|
function renderToString(code, options = {}) {
|
|
247
590
|
const {
|
|
248
591
|
renderId = "",
|
|
249
592
|
nonce,
|
|
250
593
|
noScripts,
|
|
251
|
-
manifest
|
|
594
|
+
manifest,
|
|
595
|
+
onHead
|
|
252
596
|
} = options;
|
|
253
597
|
let scripts = "";
|
|
254
598
|
const serializer = createHydrationSerializer({
|
|
@@ -264,12 +608,16 @@ function renderToString(code, options = {}) {
|
|
|
264
608
|
onError: options.onError
|
|
265
609
|
});
|
|
266
610
|
const tracking = createAssetTracking();
|
|
611
|
+
const headRegistry = createHeadRegistry();
|
|
267
612
|
sharedConfig.context = {
|
|
268
613
|
assets: [],
|
|
269
614
|
nonce,
|
|
270
615
|
escape: escape,
|
|
271
616
|
resolve: resolveSSRNode,
|
|
272
617
|
ssr: ssr,
|
|
618
|
+
registerHeadTags(tags) {
|
|
619
|
+
registerHeadTags(headRegistry, sharedConfig.context, tracking, null, nonce, tags);
|
|
620
|
+
},
|
|
273
621
|
serialize(id, p) {
|
|
274
622
|
if (sharedConfig.context.noHydrate) return;
|
|
275
623
|
if (p != null && typeof p === "object" && (typeof p.then === "function" || typeof p[Symbol.asyncIterator] === "function")) {
|
|
@@ -305,7 +653,8 @@ function renderToString(code, options = {}) {
|
|
|
305
653
|
sharedConfig.context.noHydrate = true;
|
|
306
654
|
serializer.close();
|
|
307
655
|
const assetsHtml = resolveAssetsHtml(sharedConfig.context.assets);
|
|
308
|
-
|
|
656
|
+
const head = renderShellHead(headRegistry, nonce, null);
|
|
657
|
+
return assembleDocument(html, assetsHtml, tracking.emittedAssets, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
|
|
309
658
|
}
|
|
310
659
|
function renderToStream(code, options = {}) {
|
|
311
660
|
let {
|
|
@@ -314,7 +663,8 @@ function renderToStream(code, options = {}) {
|
|
|
314
663
|
onCompleteAll,
|
|
315
664
|
renderId = "",
|
|
316
665
|
noScripts,
|
|
317
|
-
manifest
|
|
666
|
+
manifest,
|
|
667
|
+
onHead
|
|
318
668
|
} = options;
|
|
319
669
|
let dispose;
|
|
320
670
|
const blockingPromises = new Set();
|
|
@@ -356,8 +706,8 @@ function renderToStream(code, options = {}) {
|
|
|
356
706
|
if (styles.links.length) {
|
|
357
707
|
emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
|
|
358
708
|
writeTasks();
|
|
359
|
-
for (const
|
|
360
|
-
buffer.write(`<link rel="stylesheet" href="${
|
|
709
|
+
for (const entry of styles.links) {
|
|
710
|
+
buffer.write(typeof entry === "string" ? `<link rel="stylesheet" href="${entry}" onload="$dfc('${key}')" onerror="$dfc('${key}')">` : `<link${entry.attrHtml} onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
361
711
|
}
|
|
362
712
|
buffer.write(`<template id="${key}">${value}</template>`);
|
|
363
713
|
} else {
|
|
@@ -375,10 +725,12 @@ function renderToStream(code, options = {}) {
|
|
|
375
725
|
buffer.write(`<link rel="modulepreload" href="${value}">`);
|
|
376
726
|
} else if (type === "inline-style") {
|
|
377
727
|
buffer.write(renderInlineStyle(value, nonce));
|
|
728
|
+
} else if (type === "head-tag") {
|
|
729
|
+
buffer.write(value);
|
|
378
730
|
}
|
|
379
731
|
},
|
|
380
732
|
shell(shellHtml, meta) {
|
|
381
|
-
buffer.write(assembleDocument(shellHtml, meta.assets, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce));
|
|
733
|
+
buffer.write(assembleDocument(shellHtml, meta.assets, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
382
734
|
},
|
|
383
735
|
...options.sink
|
|
384
736
|
};
|
|
@@ -449,10 +801,28 @@ function renderToStream(code, options = {}) {
|
|
|
449
801
|
}
|
|
450
802
|
};
|
|
451
803
|
const tracking = createAssetTracking();
|
|
804
|
+
const headRegistry = createHeadRegistry();
|
|
805
|
+
let headScriptFlushed = false;
|
|
806
|
+
const emitHeadOps = (key, ops) => {
|
|
807
|
+
const payload = JSON.stringify(ops).replace(/</g, "\\u003C");
|
|
808
|
+
emitTask(`${!headScriptFlushed ? HEAD_SCRIPT : ""}(_$HY.hp=_$HY.hp||{})[${JSON.stringify(key)}]=${payload}`);
|
|
809
|
+
headScriptFlushed = true;
|
|
810
|
+
};
|
|
452
811
|
sharedConfig.context = context = {
|
|
453
812
|
async: true,
|
|
454
813
|
assets: [],
|
|
455
814
|
nonce,
|
|
815
|
+
registerHeadTags(tags) {
|
|
816
|
+
registerHeadTags(headRegistry, context, tracking,
|
|
817
|
+
(markup, gateEntry) => {
|
|
818
|
+
if (!firstFlushed) {
|
|
819
|
+
headRegistry.eagerHtml += markup;
|
|
820
|
+
if (gateEntry) gateEntry.emitted = true;
|
|
821
|
+
} else if (!gateEntry || !tracking.currentBoundaryId) {
|
|
822
|
+
sink.asset("head-tag", markup);
|
|
823
|
+
}
|
|
824
|
+
}, nonce, tags);
|
|
825
|
+
},
|
|
456
826
|
registerAsset(type, value) {
|
|
457
827
|
if (type === "inline-style") {
|
|
458
828
|
const entry = tracking.registerInlineStyle(value);
|
|
@@ -543,10 +913,12 @@ function renderToStream(code, options = {}) {
|
|
|
543
913
|
parent.children[key] = value !== undefined ? value : "";
|
|
544
914
|
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
545
915
|
propagateBoundaryStyles(key, parentKey, tracking);
|
|
916
|
+
adoptHeadBoundary(headRegistry, key, parentKey);
|
|
546
917
|
item.resolve();
|
|
547
918
|
return;
|
|
548
919
|
}
|
|
549
920
|
if (!completed) {
|
|
921
|
+
if (error) dropHeadBoundary(headRegistry, key);
|
|
550
922
|
if (!firstFlushed) {
|
|
551
923
|
queue(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
|
|
552
924
|
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
@@ -554,6 +926,8 @@ function renderToStream(code, options = {}) {
|
|
|
554
926
|
} else {
|
|
555
927
|
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
556
928
|
const styles = collectStreamStyles(key, tracking, headStyles);
|
|
929
|
+
const headOps = error ? null : flushHeadFragment(headRegistry, key);
|
|
930
|
+
if (headOps) emitHeadOps(key, headOps);
|
|
557
931
|
sink.fragment(key, value !== undefined ? value : " ", {
|
|
558
932
|
styles,
|
|
559
933
|
revealGroup,
|
|
@@ -641,14 +1015,16 @@ function renderToStream(code, options = {}) {
|
|
|
641
1015
|
const assetsHtml = resolveAssetsHtml(context.assets);
|
|
642
1016
|
headStyles = new Set();
|
|
643
1017
|
for (const url of tracking.emittedAssets) {
|
|
644
|
-
if (url
|
|
1018
|
+
if (isCssUrl(url)) headStyles.add(url);
|
|
645
1019
|
}
|
|
646
1020
|
serializeRootAssets();
|
|
1021
|
+
const head = renderShellHead(headRegistry, nonce, k => registry.has(k));
|
|
647
1022
|
sink.shell(html, {
|
|
648
1023
|
assets: assetsHtml,
|
|
649
1024
|
preloads: tracking.emittedAssets,
|
|
650
1025
|
inlineStyles: tracking.inlineStyles,
|
|
651
|
-
tasks
|
|
1026
|
+
tasks,
|
|
1027
|
+
head
|
|
652
1028
|
});
|
|
653
1029
|
tasks = "";
|
|
654
1030
|
onCompleteShell && onCompleteShell({
|
|
@@ -1148,23 +1524,42 @@ function resolveAssetsHtml(assets) {
|
|
|
1148
1524
|
for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
|
|
1149
1525
|
return out;
|
|
1150
1526
|
}
|
|
1151
|
-
function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts, nonce) {
|
|
1527
|
+
function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
1152
1528
|
const scriptTag = scripts ? `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>` : "";
|
|
1153
|
-
|
|
1529
|
+
const headTagsHtml = headTags ? headTags.html : "";
|
|
1530
|
+
const headPrelude = headTags ? headTags.prelude : "";
|
|
1531
|
+
if (!onHead && !assetsHtml && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
1154
1532
|
if (!scriptTag) return html;
|
|
1155
1533
|
const xs = html.indexOf("<!--xs-->");
|
|
1156
1534
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
1157
1535
|
}
|
|
1536
|
+
if (headPrelude) {
|
|
1537
|
+
const open = html.match(/<head(?:\s[^>]*)?>/);
|
|
1538
|
+
if (open) {
|
|
1539
|
+
const at = open.index + open[0].length;
|
|
1540
|
+
html = html.slice(0, at) + headPrelude + html.slice(at);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1158
1543
|
const headIdx = html.indexOf("</head>");
|
|
1159
1544
|
if (headIdx === -1) {
|
|
1545
|
+
if (onHead) {
|
|
1546
|
+
onHead(headPrelude + headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
1547
|
+
}
|
|
1160
1548
|
if (!scriptTag) return html;
|
|
1161
1549
|
const xs = html.indexOf("<!--xs-->");
|
|
1162
1550
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
1163
1551
|
}
|
|
1164
|
-
|
|
1552
|
+
const head = headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
1553
|
+
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
1554
|
+
const xsIdx = html.indexOf("<!--xs-->");
|
|
1555
|
+
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
1556
|
+
return xsIdx < headIdx ? html.slice(0, xsIdx) + scriptTag + html.slice(xsIdx, headIdx) + head + html.slice(headIdx) : html.slice(0, headIdx) + head + html.slice(headIdx, xsIdx) + scriptTag + html.slice(xsIdx);
|
|
1557
|
+
}
|
|
1558
|
+
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
1559
|
+
let head = "";
|
|
1165
1560
|
if (emittedAssets && emittedAssets.size) {
|
|
1166
1561
|
for (const url of emittedAssets) {
|
|
1167
|
-
head += url
|
|
1562
|
+
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}">` : `<link rel="modulepreload" href="${url}">`;
|
|
1168
1563
|
}
|
|
1169
1564
|
}
|
|
1170
1565
|
if (inlineStyles && inlineStyles.size) {
|
|
@@ -1174,10 +1569,7 @@ function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts
|
|
|
1174
1569
|
head += renderInlineStyle(entry, nonce);
|
|
1175
1570
|
}
|
|
1176
1571
|
}
|
|
1177
|
-
|
|
1178
|
-
const xsIdx = html.indexOf("<!--xs-->");
|
|
1179
|
-
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
1180
|
-
return xsIdx < headIdx ? html.slice(0, xsIdx) + scriptTag + html.slice(xsIdx, headIdx) + head + html.slice(headIdx) : html.slice(0, headIdx) + head + html.slice(headIdx, xsIdx) + scriptTag + html.slice(xsIdx);
|
|
1572
|
+
return head;
|
|
1181
1573
|
}
|
|
1182
1574
|
function serializeFragmentAssets(key, boundaryModules, context) {
|
|
1183
1575
|
const map = boundaryModules.get(key);
|
|
@@ -1207,7 +1599,12 @@ function collectStreamStyles(key, tracking, headStyles) {
|
|
|
1207
1599
|
for (const entry of styles) {
|
|
1208
1600
|
if (typeof entry === "string") {
|
|
1209
1601
|
if (!headStyles || !headStyles.has(entry)) links.push(entry);
|
|
1210
|
-
} else if (
|
|
1602
|
+
} else if (entry.emitted) {
|
|
1603
|
+
continue;
|
|
1604
|
+
} else if (entry.attrHtml !== undefined) {
|
|
1605
|
+
entry.emitted = true;
|
|
1606
|
+
links.push(entry);
|
|
1607
|
+
} else {
|
|
1211
1608
|
entry.emitted = true;
|
|
1212
1609
|
inline.push(entry);
|
|
1213
1610
|
}
|
|
@@ -1467,8 +1864,41 @@ function Portal(props) {
|
|
|
1467
1864
|
if (o?.id != null) getNextChildId(o);
|
|
1468
1865
|
return undefined;
|
|
1469
1866
|
}
|
|
1470
|
-
function
|
|
1471
|
-
|
|
1867
|
+
function registerClientOnlyPreload(moduleUrl) {
|
|
1868
|
+
const ctx = sharedConfig.context;
|
|
1869
|
+
if (!ctx?.registerAsset || !ctx.resolveAssets) return;
|
|
1870
|
+
const registerAsset = ctx.registerAsset;
|
|
1871
|
+
const resolve = ctx.resolveAssets;
|
|
1872
|
+
const apply = assets => {
|
|
1873
|
+
if (!assets) return;
|
|
1874
|
+
for (let i = 0; i < assets.css.length; i++) {
|
|
1875
|
+
const css = assets.css[i];
|
|
1876
|
+
if (typeof css === "string") registerAsset("style", css);else registerAsset("inline-style", css);
|
|
1877
|
+
}
|
|
1878
|
+
for (let i = 0; i < assets.js.length; i++) registerAsset("module", assets.js[i]);
|
|
1879
|
+
};
|
|
1880
|
+
const assets = resolve(moduleUrl);
|
|
1881
|
+
if (assets && typeof assets.then === "function") {
|
|
1882
|
+
const boundary = ctx._currentBoundaryId;
|
|
1883
|
+
assets.then(resolved => {
|
|
1884
|
+
const current = ctx._currentBoundaryId;
|
|
1885
|
+
ctx._currentBoundaryId = boundary;
|
|
1886
|
+
try {
|
|
1887
|
+
apply(resolved);
|
|
1888
|
+
} finally {
|
|
1889
|
+
ctx._currentBoundaryId = current;
|
|
1890
|
+
}
|
|
1891
|
+
},
|
|
1892
|
+
() => {});
|
|
1893
|
+
} else {
|
|
1894
|
+
apply(assets);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
function clientOnly(_fn, _options = {}, moduleUrl) {
|
|
1898
|
+
return props => {
|
|
1899
|
+
if (moduleUrl) registerClientOnlyPreload(moduleUrl);
|
|
1900
|
+
return createMemo(() => props.fallback);
|
|
1901
|
+
};
|
|
1472
1902
|
}
|
|
1473
1903
|
function httpStatus(code, text) {
|
|
1474
1904
|
const event = getRequestEvent();
|
|
@@ -1499,4 +1929,4 @@ function httpHeader(name, value, options) {
|
|
|
1499
1929
|
}
|
|
1500
1930
|
}
|
|
1501
1931
|
|
|
1502
|
-
export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, claimElementTree, notSup as className, clientOnly, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, httpHeader, httpStatus, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
|
|
1932
|
+
export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, claimElementTree, notSup as className, clientOnly, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, httpHeader, httpStatus, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets, useHead };
|