unhead 3.1.3 → 3.1.4
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/client.d.mts +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.mjs +4 -4
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.mjs +3 -3
- package/dist/legacy.d.mts +3 -3
- package/dist/legacy.d.ts +3 -3
- package/dist/legacy.mjs +6 -6
- package/dist/parser.d.mts +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.mjs +1 -3
- package/dist/plugins.d.mts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.mjs +4 -4
- package/dist/scripts.d.mts +4 -4
- package/dist/scripts.d.ts +4 -4
- package/dist/scripts.mjs +1 -1
- package/dist/server.d.mts +8 -7
- package/dist/server.d.ts +8 -7
- package/dist/server.mjs +3 -8
- package/dist/shared/{unhead.CnNMu1HU.d.ts → unhead.71V9w6oU.d.ts} +1 -1
- package/dist/shared/{unhead.Bz11580x.d.mts → unhead.B8_fLxlB.d.mts} +50 -3
- package/dist/shared/{unhead.Bz11580x.d.ts → unhead.B8_fLxlB.d.ts} +50 -3
- package/dist/shared/{unhead.BjuLn3hu.mjs → unhead.BBvzuk-m.mjs} +1 -1
- package/dist/shared/{unhead.CH30252c.mjs → unhead.BZYKjYpn.mjs} +1 -1
- package/dist/shared/{unhead.jqONLOUN.d.ts → unhead.BaYoUAzl.d.ts} +2 -2
- package/dist/shared/{unhead.Brajh4vg.d.mts → unhead.BwirKaJy.d.mts} +1 -1
- package/dist/shared/{unhead.JWUDzlIs.mjs → unhead.CBkhoTGw.mjs} +3 -1
- package/dist/shared/{unhead.CG80LYNi.d.mts → unhead.CcQjGQML.d.mts} +1 -1
- package/dist/shared/{unhead.DzSj5qjO.mjs → unhead.Cdnk2khL.mjs} +39 -14
- package/dist/shared/{unhead.ekDpYRjs.d.mts → unhead.ClQ7OJ-0.d.mts} +2 -2
- package/dist/shared/{unhead.f0Z4Ygga.d.ts → unhead.D3uyoS-Z.d.ts} +1 -1
- package/dist/shared/{unhead.eQfSuvE2.mjs → unhead.DCW7mbD5.mjs} +1 -1
- package/dist/shared/{unhead.BnlR_jz2.d.mts → unhead.DTAcYAas.d.mts} +1 -1
- package/dist/shared/{unhead.DjnbVGfW.d.mts → unhead.DhfYK-VF.d.mts} +2 -2
- package/dist/shared/{unhead.A4ndrqqe.mjs → unhead.Doc2Fa-a.mjs} +1 -1
- package/dist/shared/{unhead.CJY-UeEt.mjs → unhead.DqXjmljN.mjs} +3 -3
- package/dist/shared/{unhead.CJ5MDR84.d.ts → unhead.Dur2vr49.d.ts} +1 -1
- package/dist/shared/{unhead.CKu1VBXp.d.ts → unhead.Dz8_vfOe.d.ts} +2 -2
- package/dist/shared/{unhead.Dc4-12pQ.d.ts → unhead.HonJKaMo.d.ts} +1 -1
- package/dist/shared/{unhead.ebqUBTt1.mjs → unhead.WR8XDfSi.mjs} +9 -1
- package/dist/shared/{unhead.BHr5MNkJ.d.ts → unhead.fHrXv4hy.d.ts} +2 -2
- package/dist/shared/{unhead.BNptCUyv.d.mts → unhead.rdR8o82F.d.mts} +1 -1
- package/dist/shared/{unhead.B3gLwi_2.mjs → unhead.yYqx02R-.mjs} +34 -52
- package/dist/shared/{unhead.ByB97_5N.d.mts → unhead.zmorwZFX.d.mts} +2 -2
- package/dist/stream/client.d.mts +3 -3
- package/dist/stream/client.d.ts +3 -3
- package/dist/stream/iife.global.js +1 -1
- package/dist/stream/iife.mjs +2 -2
- package/dist/stream/server.d.mts +3 -3
- package/dist/stream/server.d.ts +3 -3
- package/dist/stream/server.mjs +2 -2
- package/dist/types.d.mts +6 -6
- package/dist/types.d.ts +6 -6
- package/dist/utils.d.mts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.mjs +2 -2
- package/dist/validate.mjs +1 -1
- package/package.json +2 -24
|
@@ -2,6 +2,7 @@ import { U as UniqueTags, c as TagsWithInnerContent, M as MetaTagsArrayable, H a
|
|
|
2
2
|
import { c as callHook } from './unhead.mB5lMBMV.mjs';
|
|
3
3
|
|
|
4
4
|
const META_NOREWRITE_RE = /^(?:viewport|description|keywords|robots)$/;
|
|
5
|
+
const META_KEY_ATTRS = ["name", "property", "http-equiv"];
|
|
5
6
|
function isMetaArrayDupeKey(v) {
|
|
6
7
|
return MetaTagsArrayable.has(v.split(":")[1]);
|
|
7
8
|
}
|
|
@@ -20,7 +21,7 @@ function dedupeKey(tag) {
|
|
|
20
21
|
if (props.charset)
|
|
21
22
|
return "charset";
|
|
22
23
|
if (t === "meta") {
|
|
23
|
-
for (const n of
|
|
24
|
+
for (const n of META_KEY_ATTRS) {
|
|
24
25
|
const v = props[n];
|
|
25
26
|
if (v !== void 0)
|
|
26
27
|
return `meta:${v}${(typeof v !== "string" || !v.includes(":")) && !META_NOREWRITE_RE.test(v) && key ? `:key:${key}` : ""}`;
|
|
@@ -136,12 +137,16 @@ function normalizeEntryToTags(input, propResolvers) {
|
|
|
136
137
|
return [];
|
|
137
138
|
if (typeof input === "function")
|
|
138
139
|
input = input();
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
let resolve;
|
|
141
|
+
if (propResolvers.length) {
|
|
142
|
+
resolve = (key, val) => {
|
|
143
|
+
for (let i = 0; i < propResolvers.length; i++)
|
|
144
|
+
val = propResolvers[i](key, val);
|
|
145
|
+
return val;
|
|
146
|
+
};
|
|
147
|
+
input = resolve(void 0, input);
|
|
148
|
+
}
|
|
149
|
+
input = walkResolver(input, resolve);
|
|
145
150
|
const tags = [];
|
|
146
151
|
for (const key in input) {
|
|
147
152
|
const value = input[key];
|
|
@@ -155,6 +160,8 @@ function normalizeEntryToTags(input, propResolvers) {
|
|
|
155
160
|
const LT_RE = /</g;
|
|
156
161
|
const SCRIPT_END_RE = /<\/script/g;
|
|
157
162
|
const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w;
|
|
163
|
+
const DEFAULT_TAG_WEIGHT = () => 100;
|
|
164
|
+
const TAG_MUTATING_HOOK_RE = /^tags:|:render/;
|
|
158
165
|
function dedupeTags(ctx) {
|
|
159
166
|
let hasFlatMeta = false;
|
|
160
167
|
for (const next of ctx.tags.sort(sortTags)) {
|
|
@@ -200,28 +207,32 @@ function resolveTitleTemplate(ctx, head) {
|
|
|
200
207
|
}
|
|
201
208
|
}
|
|
202
209
|
function sanitizeTags(tags) {
|
|
203
|
-
|
|
210
|
+
const out = [];
|
|
211
|
+
for (let t of tags) {
|
|
204
212
|
const { innerHTML, tag, props } = t;
|
|
205
213
|
if (!ValidHeadTags.has(tag) || !Object.keys(props).length && !innerHTML && !t.textContent)
|
|
206
|
-
|
|
214
|
+
continue;
|
|
207
215
|
if (tag === "meta" && !props.content && !props["http-equiv"] && !props.charset)
|
|
208
|
-
|
|
216
|
+
continue;
|
|
209
217
|
if (tag === "script" && (innerHTML || t.textContent)) {
|
|
210
218
|
const type = String(props.type);
|
|
211
219
|
const isJsonLike = type.endsWith("json") || type === "importmap" || type === "speculationrules";
|
|
212
220
|
const escape = (content) => isJsonLike ? (typeof content === "string" ? content : JSON.stringify(content)).replace(LT_RE, "\\u003C") : typeof content === "string" ? content.replace(SCRIPT_END_RE, "<\\/script") : content;
|
|
221
|
+
t = { ...t };
|
|
213
222
|
if (innerHTML)
|
|
214
223
|
t.innerHTML = escape(innerHTML);
|
|
215
224
|
if (t.textContent)
|
|
216
225
|
t.textContent = escape(t.textContent);
|
|
217
226
|
t._d = dedupeKey(t);
|
|
218
227
|
}
|
|
219
|
-
|
|
220
|
-
}
|
|
228
|
+
out.push(t);
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
221
231
|
}
|
|
222
232
|
function resolveTags(head, options) {
|
|
223
|
-
const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ??
|
|
233
|
+
const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ?? DEFAULT_TAG_WEIGHT;
|
|
224
234
|
const ctx = { tagMap: /* @__PURE__ */ new Map(), tags: [] };
|
|
235
|
+
const hooks = head.hooks?._hooks || {};
|
|
225
236
|
const entries = [...head.entries.values()];
|
|
226
237
|
for (const e of entries) {
|
|
227
238
|
if (e._pending !== void 0) {
|
|
@@ -248,7 +259,21 @@ function resolveTags(head, options) {
|
|
|
248
259
|
});
|
|
249
260
|
}
|
|
250
261
|
}
|
|
251
|
-
|
|
262
|
+
let needsClone = false;
|
|
263
|
+
for (const k in hooks) {
|
|
264
|
+
if (TAG_MUTATING_HOOK_RE.test(k) && hooks[k]?.some((f) => !f._nonMutating)) {
|
|
265
|
+
needsClone = true;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
ctx.tags = needsClone ? entries.flatMap((e) => (e._tags || []).map((t) => {
|
|
270
|
+
const props = { ...t.props };
|
|
271
|
+
if (props.class instanceof Set)
|
|
272
|
+
props.class = new Set(props.class);
|
|
273
|
+
if (props.style instanceof Map)
|
|
274
|
+
props.style = new Map(props.style);
|
|
275
|
+
return { ...t, props };
|
|
276
|
+
})) : entries.flatMap((e) => e._tags || []);
|
|
252
277
|
const hasFlatMeta = dedupeTags(ctx);
|
|
253
278
|
resolveTitleTemplate(ctx, head);
|
|
254
279
|
ctx.tags = [...ctx.tagMap.values()];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HookableCore } from 'hookable';
|
|
2
|
-
import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.
|
|
3
|
-
import { aw as ResolvableHead } from './unhead.
|
|
2
|
+
import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.rdR8o82F.mjs';
|
|
3
|
+
import { aw as ResolvableHead } from './unhead.B8_fLxlB.mjs';
|
|
4
4
|
|
|
5
5
|
interface ServerUnhead<T = ResolvableHead> extends Unhead<T, SSRHeadPayload> {
|
|
6
6
|
hooks: HookableCore<ServerHeadHooks>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { at as RawInput, aw as ResolvableHead, aI as ResolvableValue, aB as ResolvableProperties, G as GenericLink, D as DataKeys, aK as SchemaAugmentations, a6 as MetaGeneric, t as GenericScript, b2 as UnheadHtmlAttributes, b1 as UnheadBodyAttributesWithoutEvents } from './unhead.
|
|
1
|
+
import { at as RawInput, aw as ResolvableHead, aI as ResolvableValue, aB as ResolvableProperties, G as GenericLink, D as DataKeys, aK as SchemaAugmentations, a6 as MetaGeneric, t as GenericScript, b2 as UnheadHtmlAttributes, b1 as UnheadBodyAttributesWithoutEvents } from './unhead.B8_fLxlB.js';
|
|
2
2
|
|
|
3
3
|
type Base = RawInput<'base'>;
|
|
4
4
|
type HtmlAttributes = RawInput<'htmlAttrs'>;
|
|
@@ -111,7 +111,7 @@ function useScript(head, _input, _options) {
|
|
|
111
111
|
const loadPromise = new Promise((resolve) => {
|
|
112
112
|
if (head.ssr)
|
|
113
113
|
return;
|
|
114
|
-
const emit = (api) =>
|
|
114
|
+
const emit = (api) => queueMicrotask(() => resolve(api));
|
|
115
115
|
const unhook = head.hooks?.hook("script:updated", ({ script: script2 }) => {
|
|
116
116
|
const status = script2.status;
|
|
117
117
|
if (script2.id === id && (status === "loaded" || status === "error")) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.
|
|
1
|
+
import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.rdR8o82F.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Load third-party scripts with SSR support and a proxied API.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HookableCore } from 'hookable';
|
|
2
|
-
import { U as Unhead, C as ClientHeadHooks, c as CreateClientHeadOptions } from './unhead.
|
|
3
|
-
import { aw as ResolvableHead } from './unhead.
|
|
2
|
+
import { U as Unhead, C as ClientHeadHooks, c as CreateClientHeadOptions } from './unhead.rdR8o82F.mjs';
|
|
3
|
+
import { aw as ResolvableHead } from './unhead.B8_fLxlB.mjs';
|
|
4
4
|
|
|
5
5
|
interface ClientUnhead<T = ResolvableHead> extends Unhead<T, boolean> {
|
|
6
6
|
hooks: HookableCore<ClientHeadHooks>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { c as createUnhead, r as registerPlugin } from './unhead.CfgPMHXt.mjs';
|
|
2
|
+
import { b as TagPriorityAliases } from './unhead.fg-0ge_u.mjs';
|
|
2
3
|
import { a as createHooks } from './unhead.mB5lMBMV.mjs';
|
|
3
|
-
import { c as createDomRenderer } from './unhead.
|
|
4
|
+
import { c as createDomRenderer } from './unhead.BBvzuk-m.mjs';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
const tagWeight = (tag) => typeof tag.tagPriority === "number" ? tag.tagPriority : 100 + (P[tag.tagPriority] || 0);
|
|
6
|
+
const tagWeight = (tag) => typeof tag.tagPriority === "number" ? tag.tagPriority : 100 + (TagPriorityAliases[tag.tagPriority] || 0);
|
|
7
7
|
function createHead(options = {}) {
|
|
8
8
|
options.document = options.document || (typeof window !== "undefined" ? document : void 0);
|
|
9
9
|
const renderer = options.render || createDomRenderer({ document: options.document });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HookableCore } from 'hookable';
|
|
2
|
-
import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.
|
|
3
|
-
import { aw as ResolvableHead } from './unhead.
|
|
2
|
+
import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.71V9w6oU.js';
|
|
3
|
+
import { aw as ResolvableHead } from './unhead.B8_fLxlB.js';
|
|
4
4
|
|
|
5
5
|
interface ServerUnhead<T = ResolvableHead> extends Unhead<T, SSRHeadPayload> {
|
|
6
6
|
hooks: HookableCore<ServerHeadHooks>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.
|
|
1
|
+
import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.71V9w6oU.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Load third-party scripts with SSR support and a proxied API.
|
|
@@ -12,7 +12,8 @@ const URL_META_KEYS = /* @__PURE__ */ new Set([
|
|
|
12
12
|
"twitter:image",
|
|
13
13
|
"twitter:image:src",
|
|
14
14
|
"twitter:player",
|
|
15
|
-
"twitter:player:stream"
|
|
15
|
+
"twitter:player:stream",
|
|
16
|
+
"payment:success_url"
|
|
16
17
|
]);
|
|
17
18
|
const KNOWN_META_PROPERTIES = /* @__PURE__ */ new Set([
|
|
18
19
|
"article:author",
|
|
@@ -53,6 +54,13 @@ const KNOWN_META_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
53
54
|
"og:video:type",
|
|
54
55
|
"og:video:url",
|
|
55
56
|
"og:video:width",
|
|
57
|
+
"payment:amount",
|
|
58
|
+
"payment:currency",
|
|
59
|
+
"payment:description",
|
|
60
|
+
"payment:expires_at",
|
|
61
|
+
"payment:id",
|
|
62
|
+
"payment:status",
|
|
63
|
+
"payment:success_url",
|
|
56
64
|
"profile:first_name",
|
|
57
65
|
"profile:gender",
|
|
58
66
|
"profile:last_name",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.
|
|
2
|
-
import { aw as ResolvableHead } from './unhead.
|
|
1
|
+
import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.71V9w6oU.js';
|
|
2
|
+
import { aw as ResolvableHead } from './unhead.B8_fLxlB.js';
|
|
3
3
|
|
|
4
4
|
declare function createUnhead<T = ResolvableHead, R = unknown>(renderer: HeadRenderer<R>, resolvedOptions?: CreateHeadOptions): Unhead<T, R>;
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HookableCore } from 'hookable';
|
|
2
|
-
import { t as GenericScript, aN as ScriptHttpEvents, D as DataKeys, a1 as MaybeEventFnHandlers, z as HttpEventAttributes, aK as SchemaAugmentations, v as HeadTag, aw as ResolvableHead, aX as TagPosition, aY as TagPriority, ar as ProcessesTemplateParams, aJ as ResolvesDuplicates, a_ as TemplateParams } from './unhead.
|
|
2
|
+
import { t as GenericScript, aN as ScriptHttpEvents, D as DataKeys, a1 as MaybeEventFnHandlers, z as HttpEventAttributes, aK as SchemaAugmentations, v as HeadTag, aw as ResolvableHead, aX as TagPosition, aY as TagPriority, ar as ProcessesTemplateParams, aJ as ResolvesDuplicates, a_ as TemplateParams } from './unhead.B8_fLxlB.mjs';
|
|
3
3
|
|
|
4
4
|
type UseScriptStatus = 'awaitingLoad' | 'loading' | 'loaded' | 'error' | 'removed';
|
|
5
5
|
type UseScriptContext<T extends Record<symbol | string, any>> = ScriptInstance<T>;
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { c as createUnhead, r as registerPlugin } from './unhead.CfgPMHXt.mjs';
|
|
2
2
|
import { c as callHook, a as createHooks } from './unhead.mB5lMBMV.mjs';
|
|
3
|
-
import { r as resolveTags } from './unhead.
|
|
3
|
+
import { r as resolveTags } from './unhead.Cdnk2khL.mjs';
|
|
4
4
|
import { b as TagPriorityAliases, c as TagsWithInnerContent, a as SelfClosingTags } from './unhead.fg-0ge_u.mjs';
|
|
5
5
|
|
|
6
6
|
const TAG_WEIGHTS = { base: -10, title: 10 };
|
|
7
|
-
const
|
|
8
|
-
meta: { "content-security-policy": -30, "charset": -20, "viewport": -15 },
|
|
9
|
-
link: { "preconnect": 20, "stylesheet": 60, "preload": 70, "modulepreload": 70, "prefetch": 90, "dns-prefetch": 90, "prerender": 90 },
|
|
10
|
-
script: { importmap: 25, async: 30, defer: 80, sync: 50, speculationrules: 90 },
|
|
11
|
-
style: { imported: 40, sync: 60 }
|
|
12
|
-
};
|
|
7
|
+
const LINK_WEIGHTS = { "preconnect": 20, "stylesheet": 60, "preload": 70, "modulepreload": 70, "prefetch": 90, "dns-prefetch": 90, "prerender": 90 };
|
|
13
8
|
const ImportStyleRe = /@import/;
|
|
14
9
|
const isTruthy = (v) => v === "" || v === true;
|
|
15
10
|
function capoTagWeight(tag) {
|
|
@@ -20,32 +15,32 @@ function capoTagWeight(tag) {
|
|
|
20
15
|
if (tag.tag in TAG_WEIGHTS) {
|
|
21
16
|
weight = TAG_WEIGHTS[tag.tag];
|
|
22
17
|
} else if (tag.tag === "meta") {
|
|
23
|
-
|
|
24
|
-
if (t)
|
|
25
|
-
weight = CAPO_WEIGHTS.meta[t];
|
|
18
|
+
weight = tag.props["http-equiv"] === "content-security-policy" ? -30 : tag.props.charset ? -20 : tag.props.name === "viewport" ? -15 : weight;
|
|
26
19
|
} else if (tag.tag === "link" && tag.props.rel) {
|
|
27
|
-
weight =
|
|
20
|
+
weight = LINK_WEIGHTS[tag.props.rel];
|
|
28
21
|
} else if (tag.tag === "script") {
|
|
29
22
|
const type = String(tag.props.type);
|
|
23
|
+
const json = type.endsWith("json");
|
|
30
24
|
if (type === "importmap")
|
|
31
|
-
weight =
|
|
25
|
+
weight = 25;
|
|
32
26
|
else if (type === "speculationrules")
|
|
33
|
-
weight =
|
|
27
|
+
weight = 90;
|
|
34
28
|
else if (isTruthy(tag.props.async))
|
|
35
|
-
weight =
|
|
36
|
-
else if (tag.props.src && !isTruthy(tag.props.defer) &&
|
|
37
|
-
weight =
|
|
38
|
-
else if (isTruthy(tag.props.defer) && tag.props.src
|
|
39
|
-
weight =
|
|
29
|
+
weight = 30;
|
|
30
|
+
else if (tag.props.src && !isTruthy(tag.props.defer) && type !== "module" && !json || (tag.innerHTML || tag.textContent) && !json)
|
|
31
|
+
weight = 50;
|
|
32
|
+
else if (isTruthy(tag.props.defer) && tag.props.src || type === "module")
|
|
33
|
+
weight = 80;
|
|
40
34
|
} else if (tag.tag === "style") {
|
|
41
|
-
weight = tag.innerHTML && ImportStyleRe.test(tag.innerHTML) ?
|
|
35
|
+
weight = tag.innerHTML && ImportStyleRe.test(tag.innerHTML) ? 40 : 60;
|
|
42
36
|
}
|
|
43
37
|
return (weight || 100) + offset;
|
|
44
38
|
}
|
|
45
39
|
|
|
46
40
|
const DOUBLE_QUOTE_RE = /"/g;
|
|
47
41
|
function encodeAttribute(value) {
|
|
48
|
-
|
|
42
|
+
const s = typeof value === "string" ? value : String(value);
|
|
43
|
+
return s.includes('"') ? s.replace(DOUBLE_QUOTE_RE, """) : s;
|
|
49
44
|
}
|
|
50
45
|
function propsToString(props) {
|
|
51
46
|
let attrs = "";
|
|
@@ -64,25 +59,10 @@ function propsToString(props) {
|
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
const ESCAPE_HTML_RE = /[&<>"'/]/g;
|
|
62
|
+
const CLOSE_TAG_RE = {};
|
|
63
|
+
const ESCAPE_HTML_MAP = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/" };
|
|
67
64
|
function escapeHtml(str) {
|
|
68
|
-
return str.replace(ESCAPE_HTML_RE, (
|
|
69
|
-
switch (char) {
|
|
70
|
-
case "&":
|
|
71
|
-
return "&";
|
|
72
|
-
case "<":
|
|
73
|
-
return "<";
|
|
74
|
-
case ">":
|
|
75
|
-
return ">";
|
|
76
|
-
case '"':
|
|
77
|
-
return """;
|
|
78
|
-
case "'":
|
|
79
|
-
return "'";
|
|
80
|
-
case "/":
|
|
81
|
-
return "/";
|
|
82
|
-
default:
|
|
83
|
-
return char;
|
|
84
|
-
}
|
|
85
|
-
});
|
|
65
|
+
return str.replace(ESCAPE_HTML_RE, (c) => ESCAPE_HTML_MAP[c]);
|
|
86
66
|
}
|
|
87
67
|
function tagToString(tag) {
|
|
88
68
|
const attrs = propsToString(tag.props);
|
|
@@ -90,7 +70,7 @@ function tagToString(tag) {
|
|
|
90
70
|
if (!TagsWithInnerContent.has(tag.tag))
|
|
91
71
|
return SelfClosingTags.has(tag.tag) ? openTag : `${openTag}</${tag.tag}>`;
|
|
92
72
|
let content = String(tag.textContent || tag.innerHTML || "");
|
|
93
|
-
content = tag.tag === "title" ? escapeHtml(content) : content.replace(new RegExp(`</${tag.tag}`, "gi"), `<\\/${tag.tag}`);
|
|
73
|
+
content = tag.tag === "title" ? escapeHtml(content) : content.replace(CLOSE_TAG_RE[tag.tag] ||= new RegExp(`</${tag.tag}`, "gi"), `<\\/${tag.tag}`);
|
|
94
74
|
return SelfClosingTags.has(tag.tag) ? openTag : `${openTag}${content}</${tag.tag}>`;
|
|
95
75
|
}
|
|
96
76
|
|
|
@@ -183,22 +163,24 @@ function createHead(options = {}) {
|
|
|
183
163
|
};
|
|
184
164
|
options.plugins?.forEach((p) => registerPlugin(head, p));
|
|
185
165
|
head._ssrPayload = {};
|
|
166
|
+
const payloadHook = (ctx) => {
|
|
167
|
+
let payload = {};
|
|
168
|
+
if (Object.keys(head._ssrPayload || {}).length > 0) {
|
|
169
|
+
payload = { ...head._ssrPayload };
|
|
170
|
+
}
|
|
171
|
+
if (Object.values(payload).some(Boolean)) {
|
|
172
|
+
ctx.tags.push({
|
|
173
|
+
tag: "script",
|
|
174
|
+
innerHTML: JSON.stringify(payload),
|
|
175
|
+
props: { id: "unhead:payload", type: "application/json" }
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
payloadHook._nonMutating = true;
|
|
186
180
|
registerPlugin(head, {
|
|
187
181
|
key: "server",
|
|
188
182
|
hooks: {
|
|
189
|
-
"tags:resolve":
|
|
190
|
-
let payload = {};
|
|
191
|
-
if (Object.keys(head._ssrPayload || {}).length > 0) {
|
|
192
|
-
payload = { ...head._ssrPayload };
|
|
193
|
-
}
|
|
194
|
-
if (Object.values(payload).some(Boolean)) {
|
|
195
|
-
ctx.tags.push({
|
|
196
|
-
tag: "script",
|
|
197
|
-
innerHTML: JSON.stringify(payload),
|
|
198
|
-
props: { id: "unhead:payload", type: "application/json" }
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
183
|
+
"tags:resolve": payloadHook
|
|
202
184
|
}
|
|
203
185
|
});
|
|
204
186
|
return head;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.
|
|
2
|
-
import { aw as ResolvableHead } from './unhead.
|
|
1
|
+
import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.rdR8o82F.mjs';
|
|
2
|
+
import { aw as ResolvableHead } from './unhead.B8_fLxlB.mjs';
|
|
3
3
|
|
|
4
4
|
declare function createUnhead<T = ResolvableHead, R = unknown>(renderer: HeadRenderer<R>, resolvedOptions?: CreateHeadOptions): Unhead<T, R>;
|
|
5
5
|
|
package/dist/stream/client.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as ClientUnhead } from '../shared/unhead.
|
|
2
|
-
import { aP as SerializableHead, aw as ResolvableHead } from '../shared/unhead.
|
|
3
|
-
import { U as Unhead, c as CreateClientHeadOptions } from '../shared/unhead.
|
|
1
|
+
import { C as ClientUnhead } from '../shared/unhead.DhfYK-VF.mjs';
|
|
2
|
+
import { aP as SerializableHead, aw as ResolvableHead } from '../shared/unhead.B8_fLxlB.mjs';
|
|
3
|
+
import { U as Unhead, c as CreateClientHeadOptions } from '../shared/unhead.rdR8o82F.mjs';
|
|
4
4
|
import 'hookable';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/stream/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as ClientUnhead } from '../shared/unhead.
|
|
2
|
-
import { aP as SerializableHead, aw as ResolvableHead } from '../shared/unhead.
|
|
3
|
-
import { U as Unhead, c as CreateClientHeadOptions } from '../shared/unhead.
|
|
1
|
+
import { C as ClientUnhead } from '../shared/unhead.BaYoUAzl.js';
|
|
2
|
+
import { aP as SerializableHead, aw as ResolvableHead } from '../shared/unhead.B8_fLxlB.js';
|
|
3
|
+
import { U as Unhead, c as CreateClientHeadOptions } from '../shared/unhead.71V9w6oU.js';
|
|
4
4
|
import 'hookable';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var __unhead_iife__ = (function (exports) { 'use strict'; const DupeableTags = new Set(["link", "style", "script", "noscript"]); const TagsWithInnerContent = new Set(["title", "titleTemplate", "script", "style", "noscript"]); const HasElementTags = new Set(["base", "meta", "link", "style", "script", "noscript"]); const ValidHeadTags = new Set(["title", "base", "htmlAttrs", "bodyAttrs", "meta", "link", "style", "script", "noscript"]); const UniqueTags = new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]); const TagConfigKeys = new Set(["key", "tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"]); const UsesMergeStrategy = new Set(["templateParams", "htmlAttrs", "bodyAttrs"]); const MetaTagsArrayable = new Set([ "theme-color", "google-site-verification", "og", "article", "book", "profile", "twitter", "author" ]); function callHook(head, hook, ctx) { return head.hooks?.callHook(hook, ctx); } const META_NOREWRITE_RE = /^(?:viewport|description|keywords|robots)$/; function isMetaArrayDupeKey(v) { return MetaTagsArrayable.has(v.split(":")[1]); } function dedupeKey(tag) { const { props, tag: t, key } = tag; if (UniqueTags.has(t)) return t; if (t === "link" && props.rel === "canonical") return "canonical"; if (t === "link" && props.rel === "alternate") { if (props.hreflang) return `alternate:${props.hreflang}`; if (props.type) return `alternate:${props.type}:${props.href || ""}`; } if (props.charset) return "charset"; if (t === "meta") { for (const n of ["name", "property", "http-equiv"]) { const v = props[n]; if (v !== void 0) return `meta:${v}${(typeof v !== "string" || !v.includes(":")) && !META_NOREWRITE_RE.test(v) && key ? `:key:${key}` : ""}`; } } if (key) return `${t}:key:${key}`; if (props.id) return `${t}:id:${props.id}`; if (t === "link" && props.rel === "alternate") return `alternate:${props.href || ""}`; return TagsWithInnerContent.has(t) && (tag.textContent || tag.innerHTML) ? `${t}:content:${tag.textContent || tag.innerHTML}` : void 0; } function hashTag(tag) { return tag._h || tag._d || tag.textContent || tag.innerHTML || `${tag.tag}:${Object.entries(tag.props).map(([k, v]) => `${k}:${String(v)}`).join()}`; } function walkResolver(val, resolve, key) { if (key === "_resolver") return val; if (typeof val === "function" && (!key || key !== "titleTemplate" && !key.startsWith("on"))) val = val(); const v = resolve ? resolve(key, val) : val; if (Array.isArray(v)) return v.map((r) => walkResolver(r, resolve)); if (v?.constructor === Object) { const next = {}; for (const k in v) { if (k === "__proto__" || k === "constructor" || k === "prototype") continue; next[k] = walkResolver(v[k], resolve, k); } return next; } return v; } function normalizeStyleClassProps(key, value) { const isStyle = key === "style"; const store = isStyle ? new Map() : new Set(); const add = (v) => { if (!v) return; if (isStyle) { const i = v.indexOf(":"); i > 0 && store.set(v.slice(0, i).trim(), v.slice(i + 1).trim()); } else { v.split(" ").forEach((c) => c && store.add(c)); } }; if (typeof value === "string") { (isStyle ? value.split(";") : [value]).forEach(add); } else if (Array.isArray(value)) { value.forEach(add); } else if (value && typeof value === "object") { for (const k in value) { const v = value[k]; v && v !== "false" && (isStyle ? store.set(k.trim(), String(v)) : add(k)); } } return store; } function normalizeProps(tag, input) { tag.props = tag.props || {}; if (!input) return tag; if (tag.tag === "templateParams") { tag.props = input; return tag; } const isHtmlTag = HasElementTags.has(tag.tag) || tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"; for (const prop in input) { if (prop === "__proto__" || prop === "constructor" || prop === "prototype") continue; const value = input[prop]; if (value === null) { tag.props[prop] = null; } else if (prop === "class" || prop === "style") { tag.props[prop] = normalizeStyleClassProps(prop, value); } else if (TagConfigKeys.has(prop)) { if ((prop === "textContent" || prop === "innerHTML") && typeof value === "object") { const type = input.type || "application/json"; if (type.endsWith("json") || type === "speculationrules" || type === "importmap") { tag.props.type = input.type = type; tag[prop] = JSON.stringify(value); } } else { tag[prop] = value; } } else if (value !== void 0) { const isData = prop.startsWith("data-"); const key = isHtmlTag && !isData ? prop.toLowerCase() : prop; const str = String(value); const isMeta = tag.tag === "meta" && key === "content"; tag.props[key] = str === "true" || str === "" ? isData || isMeta ? str : true : !value && isData && str === "false" ? "false" : value; } } return tag; } function normalizeTag(tagName, _input) { const input = typeof _input === "object" && typeof _input !== "function" ? _input : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: _input }; const tag = normalizeProps({ tag: tagName, props: {} }, input); if (tag.key && DupeableTags.has(tag.tag)) tag.props["data-hid"] = tag._h = tag.key; if (tag.tag === "script" && typeof tag.innerHTML === "object") { tag.innerHTML = JSON.stringify(tag.innerHTML); tag.props.type = tag.props.type || "application/json"; } return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag; } function normalizeEntryToTags(input, propResolvers) { if (!input) return []; if (typeof input === "function") input = input(); const resolvers = (key, val) => { for (const r of propResolvers) val = r(key, val); return val; }; input = walkResolver(resolvers(void 0, input), resolvers); const tags = []; for (const key in input) { const value = input[key]; if (value !== void 0) { for (const v of Array.isArray(value) ? value : [value]) tags.push(normalizeTag(key, v)); } } return tags.flat(); } const LT_RE = /</g; const SCRIPT_END_RE = /<\/script/g; const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w; function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); const prev = ctx.tagMap.get(k); if (!prev) { ctx.tagMap.set(k, next); continue; } const strategy = next.tagDuplicateStrategy || (UsesMergeStrategy.has(next.tag) ? "merge" : null) || (next.key && next.key === prev.key ? "merge" : null); if (strategy === "merge") { const props = { ...prev.props }; for (const p in next.props) { props[p] = p === "style" ? new Map([...prev.props.style || new Map(), ...next.props[p]]) : p === "class" ? new Set([...prev.props.class || [], ...next.props[p]]) : next.props[p]; } ctx.tagMap.set(k, { ...next, props }); } else if (next._p >> 10 === prev._p >> 10 && next.tag === "meta" && isMetaArrayDupeKey(k)) { ctx.tagMap.set(k, Object.assign([...Array.isArray(prev) ? prev : [prev], next], next)); hasFlatMeta = true; } else if (next._w === prev._w ? next._p > prev._p : next._w < prev._w) { ctx.tagMap.set(k, next); } } return hasFlatMeta; } function resolveTitleTemplate(ctx, head) { const title = ctx.tagMap.get("title"); const tpl = ctx.tagMap.get("titleTemplate"); head._title = title?.textContent; if (!tpl) return; const fn = tpl.textContent; head._titleTemplate = fn; if (!fn) return; let v = typeof fn === "function" ? fn(title?.textContent) : fn; if (typeof v === "string" && !head.plugins.has("template-params")) v = v.replace("%s", title?.textContent || ""); if (title) { v === null ? ctx.tagMap.delete("title") : ctx.tagMap.set("title", { ...title, textContent: v }); } else { ctx.tagMap.set("titleTemplate", { ...tpl, tag: "title", textContent: v }); } } function sanitizeTags(tags) { return tags.filter((t) => { const { innerHTML, tag, props } = t; if (!ValidHeadTags.has(tag) || !Object.keys(props).length && !innerHTML && !t.textContent) return false; if (tag === "meta" && !props.content && !props["http-equiv"] && !props.charset) return false; if (tag === "script" && (innerHTML || t.textContent)) { const type = String(props.type); const isJsonLike = type.endsWith("json") || type === "importmap" || type === "speculationrules"; const escape = (content) => isJsonLike ? (typeof content === "string" ? content : JSON.stringify(content)).replace(LT_RE, "\\u003C") : typeof content === "string" ? content.replace(SCRIPT_END_RE, "<\\/script") : content; if (innerHTML) t.innerHTML = escape(innerHTML); if (t.textContent) t.textContent = escape(t.textContent); t._d = dedupeKey(t); } return true; }); } function resolveTags(head, options) { const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ?? (() => 100); const ctx = { tagMap: new Map(), tags: [] }; const entries = [...head.entries.values()]; for (const e of entries) { if (e._pending !== void 0) { e.input = e._pending; delete e._pending; delete e._tags; } } callHook(head, "entries:resolve", { entries, ...ctx }); for (const e of entries) { if (!e._tags) { const normalizeCtx = { tags: normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []).map((t) => Object.assign(t, e.options)), entry: e }; callHook(head, "entries:normalize", normalizeCtx); e._tags = normalizeCtx.tags.map((t, i) => { t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); return t; }); } } ctx.tags = entries.flatMap((e) => (e._tags || []).map((t) => ({ ...t, props: { ...t.props } }))); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); ctx.tags = [...ctx.tagMap.values()]; if (hasFlatMeta) ctx.tags = ctx.tags.flat().sort(sortTags); callHook(head, "tags:beforeResolve", ctx); callHook(head, "tags:resolve", ctx); callHook(head, "tags:afterResolve", ctx); return sanitizeTags(ctx.tags); } const WHITESPACE_RE = /\s+/; function createDomRenderer(options = {}) { return (head) => _renderDOMHead(head, options); } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; if (!dom || !head.dirty && ![...head.entries.values()].some((e) => e._pending !== void 0)) return false; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, "dom:beforeRender", beforeRenderCtx); if (!beforeRenderCtx.shouldRender || head._du) return false; head._du = true; let state = head._dom; if (!state) { state = { _t: dom.title, _e: new Map([["htmlAttrs", dom.documentElement], ["bodyAttrs", dom.body]]), _p: {}, _s: {} }; for (const el of [...dom.body.children, ...dom.head.children]) { const tag = el.tagName.toLowerCase(); if (!HasElementTags.has(tag)) continue; const props = { innerHTML: el.innerHTML }; for (const n of el.getAttributeNames()) props[n] = el.getAttribute(n); const next = normalizeProps({ tag, props: {} }, props); next.key = el.getAttribute("data-hid") || void 0; let k = next._d = dedupeKey(next) || hashTag(next); let c = 1; while (state._e.has(k)) k = `${next._d}:${c++}`; state._e.set(k, el); } for (const entry of head.entries.values()) { if (entry._o !== void 0) { const orig = entry._o; for (const t of ["bodyAttrs", "htmlAttrs"]) { const cls = orig[t]?.class; if (typeof cls === "string") { const $el = state._e.get(t); for (const c of cls.split(WHITESPACE_RE)) { if (c) state._p[`${t}:attr:class:${c}`] = () => $el.classList.remove(c); } } } delete entry._o; } } } else { state._p = { ...state._s }; } state._s = {}; function track(id, scope, fn) { const k = `${id}:${scope}`; state._s[k] = fn; delete state._p[k]; } function trackCtx({ id, $el, tag }) { const isAttr = tag.tag.endsWith("Attrs"); state._e.set(id, $el); if (!isAttr) { if (tag.textContent && tag.textContent !== $el.textContent) $el.textContent = tag.textContent; if (tag.innerHTML && tag.innerHTML !== $el.innerHTML) $el.innerHTML = tag.innerHTML; track(id, "el", () => { $el?.remove(); state._e.delete(id); }); } for (const k in tag.props) { const v = tag.props[k]; if (k[0] === "o" && k[1] === "n" && typeof v === "function") { const ev = k.slice(2); if ($el?.dataset?.[`${k}fired`]) v.call($el, new Event(ev)); if ($el.getAttribute(`data-${k}`) !== "") { (tag.tag === "bodyAttrs" ? dom.defaultView : $el).addEventListener(ev, v.bind($el)); $el.setAttribute(`data-${k}`, ""); } continue; } const ck = `attr:${k}`; if (k === "class" && v) { for (const c of v) { if (isAttr) track(id, `${ck}:${c}`, () => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === "style" && v) { for (const [sk, sv] of v) { track(id, `${ck}:${sk}`, () => $el.style.removeProperty(sk)); $el.style.setProperty(sk, sv); } } else if (v !== false && v !== null) { if ($el.getAttribute(k) !== v) $el.setAttribute(k, v === true ? "" : String(v)); if (isAttr) track(id, ck, () => $el.removeAttribute(k)); } } } const pending = []; const frag = {}; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = new Map(); for (const tag of rawTags) { const count = dupeKeyCounter.get(tag._d) || 0; const id = (count ? `${tag._d}:${count}` : tag._d) || tag._h; const ctx = { tag, id, shouldRender: true }; if (tag._d && isMetaArrayDupeKey(tag._d)) dupeKeyCounter.set(tag._d, count + 1); tags.push(ctx); if (tag.tag === "title") { dom.title = tag.textContent; track("title", "", () => dom.title = state._t); continue; } ctx.$el = state._e.get(id); if (ctx.$el) trackCtx(ctx); else if (HasElementTags.has(tag.tag)) pending.push(ctx); } for (const ctx of pending) { ctx.$el = dom.createElement(ctx.tag.tag); trackCtx(ctx); (frag[ctx.tag.tagPosition || "head"] ??= dom.createDocumentFragment()).appendChild(ctx.$el); } if (frag.head) dom.head.appendChild(frag.head); if (frag.bodyOpen) dom.body.insertBefore(frag.bodyOpen, dom.body.firstChild); if (frag.bodyClose) dom.body.appendChild(frag.bodyClose); for (const k in state._p) state._p[k](); head._dom = state; callHook(head, "dom:rendered", { renders: tags }); head._du = false; head.dirty = false; return true; } function registerPlugin(head, p) { const plugin = typeof p === "function" ? p(head) : p; const key = plugin.key || String(head.plugins.size + 1); if (!head.plugins.get(key)) { head.plugins.set(key, plugin); for (const k in plugin.hooks || {}) head.hooks?.hook(k, plugin.hooks[k]); } } function createUnhead(renderer, resolvedOptions = {}) { const ssr = !resolvedOptions.document; const entries = new Map(); const plugins = new Map(); const head = { _entryCount: 1, plugins, resolvedOptions, ssr, entries, render: () => renderer(head), use: (p) => registerPlugin(head, p), push(input, _options) { const _i = _options?._index ?? head._entryCount++; const options = _options ? { ..._options } : {}; delete options.head; delete options.onRendered; const entry = { _i, input, options }; entries.set(_i, entry); const active = { _i, dispose() { entries.delete(_i); }, patch(input2) { if (ssr) { entry.input = input2; delete entry._tags; } else { entry._pending = input2; } if (!entries.has(_i)) entries.set(_i, entry); } }; return active; } }; resolvedOptions.init?.forEach((e) => e && head.push(e)); return head; } const DEFAULT_STREAM_KEY = "__unhead__"; function init(options = {}) { const { streamKey = DEFAULT_STREAM_KEY } = options; const win = typeof window !== "undefined" ? window : void 0; if (!win) return; const queue = win[streamKey]; if (queue?._head) return queue._head; const doc = typeof document !== "undefined" ? document : void 0; const head = createUnhead(createDomRenderer(), { document: doc }); let hydrationLocked = true; queueMicrotask(() => { hydrationLocked = false; }); function pushStreamed(entry) { const active = head.push(entry); const stored = head.entries.get(active._i); if (stored) stored._streamed = true; } if (queue?._q) { for (const entries of queue._q) { for (const entry of entries) { pushStreamed(entry); } } head.dirty = true; head.render(); } win[streamKey] = { _q: queue?._q || [], _head: head, _hydrationLocked: () => hydrationLocked, push: (entries) => { for (const entry of entries) { pushStreamed(entry); } head.dirty = true; head.render(); } }; return head; } init(); exports.init = init; return exports; })({});
|
|
1
|
+
var __unhead_iife__ = (function (exports) { 'use strict'; const DupeableTags = new Set(["link", "style", "script", "noscript"]); const TagsWithInnerContent = new Set(["title", "titleTemplate", "script", "style", "noscript"]); const HasElementTags = new Set(["base", "meta", "link", "style", "script", "noscript"]); const ValidHeadTags = new Set(["title", "base", "htmlAttrs", "bodyAttrs", "meta", "link", "style", "script", "noscript"]); const UniqueTags = new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]); const TagConfigKeys = new Set(["key", "tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"]); const UsesMergeStrategy = new Set(["templateParams", "htmlAttrs", "bodyAttrs"]); const MetaTagsArrayable = new Set([ "theme-color", "google-site-verification", "og", "article", "book", "profile", "twitter", "author" ]); function callHook(head, hook, ctx) { return head.hooks?.callHook(hook, ctx); } const META_NOREWRITE_RE = /^(?:viewport|description|keywords|robots)$/; const META_KEY_ATTRS = ["name", "property", "http-equiv"]; function isMetaArrayDupeKey(v) { return MetaTagsArrayable.has(v.split(":")[1]); } function dedupeKey(tag) { const { props, tag: t, key } = tag; if (UniqueTags.has(t)) return t; if (t === "link" && props.rel === "canonical") return "canonical"; if (t === "link" && props.rel === "alternate") { if (props.hreflang) return `alternate:${props.hreflang}`; if (props.type) return `alternate:${props.type}:${props.href || ""}`; } if (props.charset) return "charset"; if (t === "meta") { for (const n of META_KEY_ATTRS) { const v = props[n]; if (v !== void 0) return `meta:${v}${(typeof v !== "string" || !v.includes(":")) && !META_NOREWRITE_RE.test(v) && key ? `:key:${key}` : ""}`; } } if (key) return `${t}:key:${key}`; if (props.id) return `${t}:id:${props.id}`; if (t === "link" && props.rel === "alternate") return `alternate:${props.href || ""}`; return TagsWithInnerContent.has(t) && (tag.textContent || tag.innerHTML) ? `${t}:content:${tag.textContent || tag.innerHTML}` : void 0; } function hashTag(tag) { return tag._h || tag._d || tag.textContent || tag.innerHTML || `${tag.tag}:${Object.entries(tag.props).map(([k, v]) => `${k}:${String(v)}`).join()}`; } function walkResolver(val, resolve, key) { if (key === "_resolver") return val; if (typeof val === "function" && (!key || key !== "titleTemplate" && !key.startsWith("on"))) val = val(); const v = resolve ? resolve(key, val) : val; if (Array.isArray(v)) return v.map((r) => walkResolver(r, resolve)); if (v?.constructor === Object) { const next = {}; for (const k in v) { if (k === "__proto__" || k === "constructor" || k === "prototype") continue; next[k] = walkResolver(v[k], resolve, k); } return next; } return v; } function normalizeStyleClassProps(key, value) { const isStyle = key === "style"; const store = isStyle ? new Map() : new Set(); const add = (v) => { if (!v) return; if (isStyle) { const i = v.indexOf(":"); i > 0 && store.set(v.slice(0, i).trim(), v.slice(i + 1).trim()); } else { v.split(" ").forEach((c) => c && store.add(c)); } }; if (typeof value === "string") { (isStyle ? value.split(";") : [value]).forEach(add); } else if (Array.isArray(value)) { value.forEach(add); } else if (value && typeof value === "object") { for (const k in value) { const v = value[k]; v && v !== "false" && (isStyle ? store.set(k.trim(), String(v)) : add(k)); } } return store; } function normalizeProps(tag, input) { tag.props = tag.props || {}; if (!input) return tag; if (tag.tag === "templateParams") { tag.props = input; return tag; } const isHtmlTag = HasElementTags.has(tag.tag) || tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"; for (const prop in input) { if (prop === "__proto__" || prop === "constructor" || prop === "prototype") continue; const value = input[prop]; if (value === null) { tag.props[prop] = null; } else if (prop === "class" || prop === "style") { tag.props[prop] = normalizeStyleClassProps(prop, value); } else if (TagConfigKeys.has(prop)) { if ((prop === "textContent" || prop === "innerHTML") && typeof value === "object") { const type = input.type || "application/json"; if (type.endsWith("json") || type === "speculationrules" || type === "importmap") { tag.props.type = input.type = type; tag[prop] = JSON.stringify(value); } } else { tag[prop] = value; } } else if (value !== void 0) { const isData = prop.startsWith("data-"); const key = isHtmlTag && !isData ? prop.toLowerCase() : prop; const str = String(value); const isMeta = tag.tag === "meta" && key === "content"; tag.props[key] = str === "true" || str === "" ? isData || isMeta ? str : true : !value && isData && str === "false" ? "false" : value; } } return tag; } function normalizeTag(tagName, _input) { const input = typeof _input === "object" && typeof _input !== "function" ? _input : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: _input }; const tag = normalizeProps({ tag: tagName, props: {} }, input); if (tag.key && DupeableTags.has(tag.tag)) tag.props["data-hid"] = tag._h = tag.key; if (tag.tag === "script" && typeof tag.innerHTML === "object") { tag.innerHTML = JSON.stringify(tag.innerHTML); tag.props.type = tag.props.type || "application/json"; } return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag; } function normalizeEntryToTags(input, propResolvers) { if (!input) return []; if (typeof input === "function") input = input(); let resolve; if (propResolvers.length) { resolve = (key, val) => { for (let i = 0; i < propResolvers.length; i++) val = propResolvers[i](key, val); return val; }; input = resolve(void 0, input); } input = walkResolver(input, resolve); const tags = []; for (const key in input) { const value = input[key]; if (value !== void 0) { for (const v of Array.isArray(value) ? value : [value]) tags.push(normalizeTag(key, v)); } } return tags.flat(); } const LT_RE = /</g; const SCRIPT_END_RE = /<\/script/g; const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w; const DEFAULT_TAG_WEIGHT = () => 100; const TAG_MUTATING_HOOK_RE = /^tags:|:render/; function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); const prev = ctx.tagMap.get(k); if (!prev) { ctx.tagMap.set(k, next); continue; } const strategy = next.tagDuplicateStrategy || (UsesMergeStrategy.has(next.tag) ? "merge" : null) || (next.key && next.key === prev.key ? "merge" : null); if (strategy === "merge") { const props = { ...prev.props }; for (const p in next.props) { props[p] = p === "style" ? new Map([...prev.props.style || new Map(), ...next.props[p]]) : p === "class" ? new Set([...prev.props.class || [], ...next.props[p]]) : next.props[p]; } ctx.tagMap.set(k, { ...next, props }); } else if (next._p >> 10 === prev._p >> 10 && next.tag === "meta" && isMetaArrayDupeKey(k)) { ctx.tagMap.set(k, Object.assign([...Array.isArray(prev) ? prev : [prev], next], next)); hasFlatMeta = true; } else if (next._w === prev._w ? next._p > prev._p : next._w < prev._w) { ctx.tagMap.set(k, next); } } return hasFlatMeta; } function resolveTitleTemplate(ctx, head) { const title = ctx.tagMap.get("title"); const tpl = ctx.tagMap.get("titleTemplate"); head._title = title?.textContent; if (!tpl) return; const fn = tpl.textContent; head._titleTemplate = fn; if (!fn) return; let v = typeof fn === "function" ? fn(title?.textContent) : fn; if (typeof v === "string" && !head.plugins.has("template-params")) v = v.replace("%s", title?.textContent || ""); if (title) { v === null ? ctx.tagMap.delete("title") : ctx.tagMap.set("title", { ...title, textContent: v }); } else { ctx.tagMap.set("titleTemplate", { ...tpl, tag: "title", textContent: v }); } } function sanitizeTags(tags) { const out = []; for (let t of tags) { const { innerHTML, tag, props } = t; if (!ValidHeadTags.has(tag) || !Object.keys(props).length && !innerHTML && !t.textContent) continue; if (tag === "meta" && !props.content && !props["http-equiv"] && !props.charset) continue; if (tag === "script" && (innerHTML || t.textContent)) { const type = String(props.type); const isJsonLike = type.endsWith("json") || type === "importmap" || type === "speculationrules"; const escape = (content) => isJsonLike ? (typeof content === "string" ? content : JSON.stringify(content)).replace(LT_RE, "\\u003C") : typeof content === "string" ? content.replace(SCRIPT_END_RE, "<\\/script") : content; t = { ...t }; if (innerHTML) t.innerHTML = escape(innerHTML); if (t.textContent) t.textContent = escape(t.textContent); t._d = dedupeKey(t); } out.push(t); } return out; } function resolveTags(head, options) { const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ?? DEFAULT_TAG_WEIGHT; const ctx = { tagMap: new Map(), tags: [] }; const hooks = head.hooks?._hooks || {}; const entries = [...head.entries.values()]; for (const e of entries) { if (e._pending !== void 0) { e.input = e._pending; delete e._pending; delete e._tags; } } callHook(head, "entries:resolve", { entries, ...ctx }); for (const e of entries) { if (!e._tags) { const normalizeCtx = { tags: normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []).map((t) => Object.assign(t, e.options)), entry: e }; callHook(head, "entries:normalize", normalizeCtx); e._tags = normalizeCtx.tags.map((t, i) => { t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); return t; }); } } let needsClone = false; for (const k in hooks) { if (TAG_MUTATING_HOOK_RE.test(k) && hooks[k]?.some((f) => !f._nonMutating)) { needsClone = true; break; } } ctx.tags = needsClone ? entries.flatMap((e) => (e._tags || []).map((t) => { const props = { ...t.props }; if (props.class instanceof Set) props.class = new Set(props.class); if (props.style instanceof Map) props.style = new Map(props.style); return { ...t, props }; })) : entries.flatMap((e) => e._tags || []); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); ctx.tags = [...ctx.tagMap.values()]; if (hasFlatMeta) ctx.tags = ctx.tags.flat().sort(sortTags); callHook(head, "tags:beforeResolve", ctx); callHook(head, "tags:resolve", ctx); callHook(head, "tags:afterResolve", ctx); return sanitizeTags(ctx.tags); } const WHITESPACE_RE = /\s+/; function createDomRenderer(options = {}) { return (head) => _renderDOMHead(head, options); } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; if (!dom || !head.dirty && ![...head.entries.values()].some((e) => e._pending !== void 0)) return false; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, "dom:beforeRender", beforeRenderCtx); if (!beforeRenderCtx.shouldRender || head._du) return false; head._du = true; let state = head._dom; if (!state) { state = { _t: dom.title, _e: new Map([["htmlAttrs", dom.documentElement], ["bodyAttrs", dom.body]]), _p: {}, _s: {} }; for (const el of [...dom.body.children, ...dom.head.children]) { const tag = el.tagName.toLowerCase(); if (!HasElementTags.has(tag)) continue; const props = { innerHTML: el.innerHTML }; for (const n of el.getAttributeNames()) props[n] = el.getAttribute(n); const next = normalizeProps({ tag, props: {} }, props); next.key = el.getAttribute("data-hid") || void 0; let k = next._d = dedupeKey(next) || hashTag(next); let c = 1; while (state._e.has(k)) k = `${next._d}:${c++}`; state._e.set(k, el); } for (const entry of head.entries.values()) { if (entry._o !== void 0) { const orig = entry._o; for (const t of ["bodyAttrs", "htmlAttrs"]) { const cls = orig[t]?.class; if (typeof cls === "string") { const $el = state._e.get(t); for (const c of cls.split(WHITESPACE_RE)) { if (c) state._p[`${t}:attr:class:${c}`] = () => $el.classList.remove(c); } } } delete entry._o; } } } else { state._p = { ...state._s }; } state._s = {}; function track(id, scope, fn) { const k = `${id}:${scope}`; state._s[k] = fn; delete state._p[k]; } function trackCtx({ id, $el, tag }) { const isAttr = tag.tag.endsWith("Attrs"); state._e.set(id, $el); if (!isAttr) { if (tag.textContent && tag.textContent !== $el.textContent) $el.textContent = tag.textContent; if (tag.innerHTML && tag.innerHTML !== $el.innerHTML) $el.innerHTML = tag.innerHTML; track(id, "el", () => { $el?.remove(); state._e.delete(id); }); } for (const k in tag.props) { const v = tag.props[k]; if (k[0] === "o" && k[1] === "n" && typeof v === "function") { const ev = k.slice(2); if ($el?.dataset?.[`${k}fired`]) v.call($el, new Event(ev)); if ($el.getAttribute(`data-${k}`) !== "") { (tag.tag === "bodyAttrs" ? dom.defaultView : $el).addEventListener(ev, v.bind($el)); $el.setAttribute(`data-${k}`, ""); } continue; } const ck = `attr:${k}`; if (k === "class" && v) { for (const c of v) { if (isAttr) track(id, `${ck}:${c}`, () => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === "style" && v) { for (const [sk, sv] of v) { track(id, `${ck}:${sk}`, () => $el.style.removeProperty(sk)); $el.style.setProperty(sk, sv); } } else if (v !== false && v !== null) { if ($el.getAttribute(k) !== v) $el.setAttribute(k, v === true ? "" : String(v)); if (isAttr) track(id, ck, () => $el.removeAttribute(k)); } } } const pending = []; const frag = {}; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = new Map(); for (const tag of rawTags) { const count = dupeKeyCounter.get(tag._d) || 0; const id = (count ? `${tag._d}:${count}` : tag._d) || tag._h; const ctx = { tag, id, shouldRender: true }; if (tag._d && isMetaArrayDupeKey(tag._d)) dupeKeyCounter.set(tag._d, count + 1); tags.push(ctx); if (tag.tag === "title") { dom.title = tag.textContent; track("title", "", () => dom.title = state._t); continue; } ctx.$el = state._e.get(id); if (ctx.$el) trackCtx(ctx); else if (HasElementTags.has(tag.tag)) pending.push(ctx); } for (const ctx of pending) { ctx.$el = dom.createElement(ctx.tag.tag); trackCtx(ctx); (frag[ctx.tag.tagPosition || "head"] ??= dom.createDocumentFragment()).appendChild(ctx.$el); } if (frag.head) dom.head.appendChild(frag.head); if (frag.bodyOpen) dom.body.insertBefore(frag.bodyOpen, dom.body.firstChild); if (frag.bodyClose) dom.body.appendChild(frag.bodyClose); for (const k in state._p) state._p[k](); head._dom = state; callHook(head, "dom:rendered", { renders: tags }); head._du = false; head.dirty = false; return true; } function registerPlugin(head, p) { const plugin = typeof p === "function" ? p(head) : p; const key = plugin.key || String(head.plugins.size + 1); if (!head.plugins.get(key)) { head.plugins.set(key, plugin); for (const k in plugin.hooks || {}) head.hooks?.hook(k, plugin.hooks[k]); } } function createUnhead(renderer, resolvedOptions = {}) { const ssr = !resolvedOptions.document; const entries = new Map(); const plugins = new Map(); const head = { _entryCount: 1, plugins, resolvedOptions, ssr, entries, render: () => renderer(head), use: (p) => registerPlugin(head, p), push(input, _options) { const _i = _options?._index ?? head._entryCount++; const options = _options ? { ..._options } : {}; delete options.head; delete options.onRendered; const entry = { _i, input, options }; entries.set(_i, entry); const active = { _i, dispose() { entries.delete(_i); }, patch(input2) { if (ssr) { entry.input = input2; delete entry._tags; } else { entry._pending = input2; } if (!entries.has(_i)) entries.set(_i, entry); } }; return active; } }; resolvedOptions.init?.forEach((e) => e && head.push(e)); return head; } const DEFAULT_STREAM_KEY = "__unhead__"; function init(options = {}) { const { streamKey = DEFAULT_STREAM_KEY } = options; const win = typeof window !== "undefined" ? window : void 0; if (!win) return; const queue = win[streamKey]; if (queue?._head) return queue._head; const doc = typeof document !== "undefined" ? document : void 0; const head = createUnhead(createDomRenderer(), { document: doc }); let hydrationLocked = true; queueMicrotask(() => { hydrationLocked = false; }); function pushStreamed(entry) { const active = head.push(entry); const stored = head.entries.get(active._i); if (stored) stored._streamed = true; } if (queue?._q) { for (const entries of queue._q) { for (const entry of entries) { pushStreamed(entry); } } head.dirty = true; head.render(); } win[streamKey] = { _q: queue?._q || [], _head: head, _hydrationLocked: () => hydrationLocked, push: (entries) => { for (const entry of entries) { pushStreamed(entry); } head.dirty = true; head.render(); } }; return head; } init(); exports.init = init; return exports; })({});
|
package/dist/stream/iife.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const streamingIifeCode = "var __unhead_iife__ = (function (exports) { 'use strict'; const DupeableTags = new Set([\"link\", \"style\", \"script\", \"noscript\"]); const TagsWithInnerContent = new Set([\"title\", \"titleTemplate\", \"script\", \"style\", \"noscript\"]); const HasElementTags = new Set([\"base\", \"meta\", \"link\", \"style\", \"script\", \"noscript\"]); const ValidHeadTags = new Set([\"title\", \"base\", \"htmlAttrs\", \"bodyAttrs\", \"meta\", \"link\", \"style\", \"script\", \"noscript\"]); const UniqueTags = new Set([\"base\", \"title\", \"titleTemplate\", \"bodyAttrs\", \"htmlAttrs\", \"templateParams\"]); const TagConfigKeys = new Set([\"key\", \"tagPosition\", \"tagPriority\", \"tagDuplicateStrategy\", \"innerHTML\", \"textContent\", \"processTemplateParams\"]); const UsesMergeStrategy = new Set([\"templateParams\", \"htmlAttrs\", \"bodyAttrs\"]); const MetaTagsArrayable = new Set([ \"theme-color\", \"google-site-verification\", \"og\", \"article\", \"book\", \"profile\", \"twitter\", \"author\" ]); function callHook(head, hook, ctx) { return head.hooks?.callHook(hook, ctx); } const META_NOREWRITE_RE = /^(?:viewport|description|keywords|robots)$/; function isMetaArrayDupeKey(v) { return MetaTagsArrayable.has(v.split(\":\")[1]); } function dedupeKey(tag) { const { props, tag: t, key } = tag; if (UniqueTags.has(t)) return t; if (t === \"link\" && props.rel === \"canonical\") return \"canonical\"; if (t === \"link\" && props.rel === \"alternate\") { if (props.hreflang) return `alternate:${props.hreflang}`; if (props.type) return `alternate:${props.type}:${props.href || \"\"}`; } if (props.charset) return \"charset\"; if (t === \"meta\") { for (const n of [\"name\", \"property\", \"http-equiv\"]) { const v = props[n]; if (v !== void 0) return `meta:${v}${(typeof v !== \"string\" || !v.includes(\":\")) && !META_NOREWRITE_RE.test(v) && key ? `:key:${key}` : \"\"}`; } } if (key) return `${t}:key:${key}`; if (props.id) return `${t}:id:${props.id}`; if (t === \"link\" && props.rel === \"alternate\") return `alternate:${props.href || \"\"}`; return TagsWithInnerContent.has(t) && (tag.textContent || tag.innerHTML) ? `${t}:content:${tag.textContent || tag.innerHTML}` : void 0; } function hashTag(tag) { return tag._h || tag._d || tag.textContent || tag.innerHTML || `${tag.tag}:${Object.entries(tag.props).map(([k, v]) => `${k}:${String(v)}`).join()}`; } function walkResolver(val, resolve, key) { if (key === \"_resolver\") return val; if (typeof val === \"function\" && (!key || key !== \"titleTemplate\" && !key.startsWith(\"on\"))) val = val(); const v = resolve ? resolve(key, val) : val; if (Array.isArray(v)) return v.map((r) => walkResolver(r, resolve)); if (v?.constructor === Object) { const next = {}; for (const k in v) { if (k === \"__proto__\" || k === \"constructor\" || k === \"prototype\") continue; next[k] = walkResolver(v[k], resolve, k); } return next; } return v; } function normalizeStyleClassProps(key, value) { const isStyle = key === \"style\"; const store = isStyle ? new Map() : new Set(); const add = (v) => { if (!v) return; if (isStyle) { const i = v.indexOf(\":\"); i > 0 && store.set(v.slice(0, i).trim(), v.slice(i + 1).trim()); } else { v.split(\" \").forEach((c) => c && store.add(c)); } }; if (typeof value === \"string\") { (isStyle ? value.split(\";\") : [value]).forEach(add); } else if (Array.isArray(value)) { value.forEach(add); } else if (value && typeof value === \"object\") { for (const k in value) { const v = value[k]; v && v !== \"false\" && (isStyle ? store.set(k.trim(), String(v)) : add(k)); } } return store; } function normalizeProps(tag, input) { tag.props = tag.props || {}; if (!input) return tag; if (tag.tag === \"templateParams\") { tag.props = input; return tag; } const isHtmlTag = HasElementTags.has(tag.tag) || tag.tag === \"htmlAttrs\" || tag.tag === \"bodyAttrs\"; for (const prop in input) { if (prop === \"__proto__\" || prop === \"constructor\" || prop === \"prototype\") continue; const value = input[prop]; if (value === null) { tag.props[prop] = null; } else if (prop === \"class\" || prop === \"style\") { tag.props[prop] = normalizeStyleClassProps(prop, value); } else if (TagConfigKeys.has(prop)) { if ((prop === \"textContent\" || prop === \"innerHTML\") && typeof value === \"object\") { const type = input.type || \"application/json\"; if (type.endsWith(\"json\") || type === \"speculationrules\" || type === \"importmap\") { tag.props.type = input.type = type; tag[prop] = JSON.stringify(value); } } else { tag[prop] = value; } } else if (value !== void 0) { const isData = prop.startsWith(\"data-\"); const key = isHtmlTag && !isData ? prop.toLowerCase() : prop; const str = String(value); const isMeta = tag.tag === \"meta\" && key === \"content\"; tag.props[key] = str === \"true\" || str === \"\" ? isData || isMeta ? str : true : !value && isData && str === \"false\" ? \"false\" : value; } } return tag; } function normalizeTag(tagName, _input) { const input = typeof _input === \"object\" && typeof _input !== \"function\" ? _input : { [tagName === \"script\" || tagName === \"noscript\" || tagName === \"style\" ? \"innerHTML\" : \"textContent\"]: _input }; const tag = normalizeProps({ tag: tagName, props: {} }, input); if (tag.key && DupeableTags.has(tag.tag)) tag.props[\"data-hid\"] = tag._h = tag.key; if (tag.tag === \"script\" && typeof tag.innerHTML === \"object\") { tag.innerHTML = JSON.stringify(tag.innerHTML); tag.props.type = tag.props.type || \"application/json\"; } return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag; } function normalizeEntryToTags(input, propResolvers) { if (!input) return []; if (typeof input === \"function\") input = input(); const resolvers = (key, val) => { for (const r of propResolvers) val = r(key, val); return val; }; input = walkResolver(resolvers(void 0, input), resolvers); const tags = []; for (const key in input) { const value = input[key]; if (value !== void 0) { for (const v of Array.isArray(value) ? value : [value]) tags.push(normalizeTag(key, v)); } } return tags.flat(); } const LT_RE = /</g; const SCRIPT_END_RE = /<\\/script/g; const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w; function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); const prev = ctx.tagMap.get(k); if (!prev) { ctx.tagMap.set(k, next); continue; } const strategy = next.tagDuplicateStrategy || (UsesMergeStrategy.has(next.tag) ? \"merge\" : null) || (next.key && next.key === prev.key ? \"merge\" : null); if (strategy === \"merge\") { const props = { ...prev.props }; for (const p in next.props) { props[p] = p === \"style\" ? new Map([...prev.props.style || new Map(), ...next.props[p]]) : p === \"class\" ? new Set([...prev.props.class || [], ...next.props[p]]) : next.props[p]; } ctx.tagMap.set(k, { ...next, props }); } else if (next._p >> 10 === prev._p >> 10 && next.tag === \"meta\" && isMetaArrayDupeKey(k)) { ctx.tagMap.set(k, Object.assign([...Array.isArray(prev) ? prev : [prev], next], next)); hasFlatMeta = true; } else if (next._w === prev._w ? next._p > prev._p : next._w < prev._w) { ctx.tagMap.set(k, next); } } return hasFlatMeta; } function resolveTitleTemplate(ctx, head) { const title = ctx.tagMap.get(\"title\"); const tpl = ctx.tagMap.get(\"titleTemplate\"); head._title = title?.textContent; if (!tpl) return; const fn = tpl.textContent; head._titleTemplate = fn; if (!fn) return; let v = typeof fn === \"function\" ? fn(title?.textContent) : fn; if (typeof v === \"string\" && !head.plugins.has(\"template-params\")) v = v.replace(\"%s\", title?.textContent || \"\"); if (title) { v === null ? ctx.tagMap.delete(\"title\") : ctx.tagMap.set(\"title\", { ...title, textContent: v }); } else { ctx.tagMap.set(\"titleTemplate\", { ...tpl, tag: \"title\", textContent: v }); } } function sanitizeTags(tags) { return tags.filter((t) => { const { innerHTML, tag, props } = t; if (!ValidHeadTags.has(tag) || !Object.keys(props).length && !innerHTML && !t.textContent) return false; if (tag === \"meta\" && !props.content && !props[\"http-equiv\"] && !props.charset) return false; if (tag === \"script\" && (innerHTML || t.textContent)) { const type = String(props.type); const isJsonLike = type.endsWith(\"json\") || type === \"importmap\" || type === \"speculationrules\"; const escape = (content) => isJsonLike ? (typeof content === \"string\" ? content : JSON.stringify(content)).replace(LT_RE, \"\\\\u003C\") : typeof content === \"string\" ? content.replace(SCRIPT_END_RE, \"<\\\\/script\") : content; if (innerHTML) t.innerHTML = escape(innerHTML); if (t.textContent) t.textContent = escape(t.textContent); t._d = dedupeKey(t); } return true; }); } function resolveTags(head, options) { const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ?? (() => 100); const ctx = { tagMap: new Map(), tags: [] }; const entries = [...head.entries.values()]; for (const e of entries) { if (e._pending !== void 0) { e.input = e._pending; delete e._pending; delete e._tags; } } callHook(head, \"entries:resolve\", { entries, ...ctx }); for (const e of entries) { if (!e._tags) { const normalizeCtx = { tags: normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []).map((t) => Object.assign(t, e.options)), entry: e }; callHook(head, \"entries:normalize\", normalizeCtx); e._tags = normalizeCtx.tags.map((t, i) => { t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); return t; }); } } ctx.tags = entries.flatMap((e) => (e._tags || []).map((t) => ({ ...t, props: { ...t.props } }))); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); ctx.tags = [...ctx.tagMap.values()]; if (hasFlatMeta) ctx.tags = ctx.tags.flat().sort(sortTags); callHook(head, \"tags:beforeResolve\", ctx); callHook(head, \"tags:resolve\", ctx); callHook(head, \"tags:afterResolve\", ctx); return sanitizeTags(ctx.tags); } const WHITESPACE_RE = /\\s+/; function createDomRenderer(options = {}) { return (head) => _renderDOMHead(head, options); } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; if (!dom || !head.dirty && ![...head.entries.values()].some((e) => e._pending !== void 0)) return false; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, \"dom:beforeRender\", beforeRenderCtx); if (!beforeRenderCtx.shouldRender || head._du) return false; head._du = true; let state = head._dom; if (!state) { state = { _t: dom.title, _e: new Map([[\"htmlAttrs\", dom.documentElement], [\"bodyAttrs\", dom.body]]), _p: {}, _s: {} }; for (const el of [...dom.body.children, ...dom.head.children]) { const tag = el.tagName.toLowerCase(); if (!HasElementTags.has(tag)) continue; const props = { innerHTML: el.innerHTML }; for (const n of el.getAttributeNames()) props[n] = el.getAttribute(n); const next = normalizeProps({ tag, props: {} }, props); next.key = el.getAttribute(\"data-hid\") || void 0; let k = next._d = dedupeKey(next) || hashTag(next); let c = 1; while (state._e.has(k)) k = `${next._d}:${c++}`; state._e.set(k, el); } for (const entry of head.entries.values()) { if (entry._o !== void 0) { const orig = entry._o; for (const t of [\"bodyAttrs\", \"htmlAttrs\"]) { const cls = orig[t]?.class; if (typeof cls === \"string\") { const $el = state._e.get(t); for (const c of cls.split(WHITESPACE_RE)) { if (c) state._p[`${t}:attr:class:${c}`] = () => $el.classList.remove(c); } } } delete entry._o; } } } else { state._p = { ...state._s }; } state._s = {}; function track(id, scope, fn) { const k = `${id}:${scope}`; state._s[k] = fn; delete state._p[k]; } function trackCtx({ id, $el, tag }) { const isAttr = tag.tag.endsWith(\"Attrs\"); state._e.set(id, $el); if (!isAttr) { if (tag.textContent && tag.textContent !== $el.textContent) $el.textContent = tag.textContent; if (tag.innerHTML && tag.innerHTML !== $el.innerHTML) $el.innerHTML = tag.innerHTML; track(id, \"el\", () => { $el?.remove(); state._e.delete(id); }); } for (const k in tag.props) { const v = tag.props[k]; if (k[0] === \"o\" && k[1] === \"n\" && typeof v === \"function\") { const ev = k.slice(2); if ($el?.dataset?.[`${k}fired`]) v.call($el, new Event(ev)); if ($el.getAttribute(`data-${k}`) !== \"\") { (tag.tag === \"bodyAttrs\" ? dom.defaultView : $el).addEventListener(ev, v.bind($el)); $el.setAttribute(`data-${k}`, \"\"); } continue; } const ck = `attr:${k}`; if (k === \"class\" && v) { for (const c of v) { if (isAttr) track(id, `${ck}:${c}`, () => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === \"style\" && v) { for (const [sk, sv] of v) { track(id, `${ck}:${sk}`, () => $el.style.removeProperty(sk)); $el.style.setProperty(sk, sv); } } else if (v !== false && v !== null) { if ($el.getAttribute(k) !== v) $el.setAttribute(k, v === true ? \"\" : String(v)); if (isAttr) track(id, ck, () => $el.removeAttribute(k)); } } } const pending = []; const frag = {}; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = new Map(); for (const tag of rawTags) { const count = dupeKeyCounter.get(tag._d) || 0; const id = (count ? `${tag._d}:${count}` : tag._d) || tag._h; const ctx = { tag, id, shouldRender: true }; if (tag._d && isMetaArrayDupeKey(tag._d)) dupeKeyCounter.set(tag._d, count + 1); tags.push(ctx); if (tag.tag === \"title\") { dom.title = tag.textContent; track(\"title\", \"\", () => dom.title = state._t); continue; } ctx.$el = state._e.get(id); if (ctx.$el) trackCtx(ctx); else if (HasElementTags.has(tag.tag)) pending.push(ctx); } for (const ctx of pending) { ctx.$el = dom.createElement(ctx.tag.tag); trackCtx(ctx); (frag[ctx.tag.tagPosition || \"head\"] ??= dom.createDocumentFragment()).appendChild(ctx.$el); } if (frag.head) dom.head.appendChild(frag.head); if (frag.bodyOpen) dom.body.insertBefore(frag.bodyOpen, dom.body.firstChild); if (frag.bodyClose) dom.body.appendChild(frag.bodyClose); for (const k in state._p) state._p[k](); head._dom = state; callHook(head, \"dom:rendered\", { renders: tags }); head._du = false; head.dirty = false; return true; } function registerPlugin(head, p) { const plugin = typeof p === \"function\" ? p(head) : p; const key = plugin.key || String(head.plugins.size + 1); if (!head.plugins.get(key)) { head.plugins.set(key, plugin); for (const k in plugin.hooks || {}) head.hooks?.hook(k, plugin.hooks[k]); } } function createUnhead(renderer, resolvedOptions = {}) { const ssr = !resolvedOptions.document; const entries = new Map(); const plugins = new Map(); const head = { _entryCount: 1, plugins, resolvedOptions, ssr, entries, render: () => renderer(head), use: (p) => registerPlugin(head, p), push(input, _options) { const _i = _options?._index ?? head._entryCount++; const options = _options ? { ..._options } : {}; delete options.head; delete options.onRendered; const entry = { _i, input, options }; entries.set(_i, entry); const active = { _i, dispose() { entries.delete(_i); }, patch(input2) { if (ssr) { entry.input = input2; delete entry._tags; } else { entry._pending = input2; } if (!entries.has(_i)) entries.set(_i, entry); } }; return active; } }; resolvedOptions.init?.forEach((e) => e && head.push(e)); return head; } const DEFAULT_STREAM_KEY = \"__unhead__\"; function init(options = {}) { const { streamKey = DEFAULT_STREAM_KEY } = options; const win = typeof window !== \"undefined\" ? window : void 0; if (!win) return; const queue = win[streamKey]; if (queue?._head) return queue._head; const doc = typeof document !== \"undefined\" ? document : void 0; const head = createUnhead(createDomRenderer(), { document: doc }); let hydrationLocked = true; queueMicrotask(() => { hydrationLocked = false; }); function pushStreamed(entry) { const active = head.push(entry); const stored = head.entries.get(active._i); if (stored) stored._streamed = true; } if (queue?._q) { for (const entries of queue._q) { for (const entry of entries) { pushStreamed(entry); } } head.dirty = true; head.render(); } win[streamKey] = { _q: queue?._q || [], _head: head, _hydrationLocked: () => hydrationLocked, push: (entries) => { for (const entry of entries) { pushStreamed(entry); } head.dirty = true; head.render(); } }; return head; } init(); exports.init = init; return exports; })({});";
|
|
2
|
-
export const streamingIifeSize =
|
|
1
|
+
export const streamingIifeCode = "var __unhead_iife__ = (function (exports) { 'use strict'; const DupeableTags = new Set([\"link\", \"style\", \"script\", \"noscript\"]); const TagsWithInnerContent = new Set([\"title\", \"titleTemplate\", \"script\", \"style\", \"noscript\"]); const HasElementTags = new Set([\"base\", \"meta\", \"link\", \"style\", \"script\", \"noscript\"]); const ValidHeadTags = new Set([\"title\", \"base\", \"htmlAttrs\", \"bodyAttrs\", \"meta\", \"link\", \"style\", \"script\", \"noscript\"]); const UniqueTags = new Set([\"base\", \"title\", \"titleTemplate\", \"bodyAttrs\", \"htmlAttrs\", \"templateParams\"]); const TagConfigKeys = new Set([\"key\", \"tagPosition\", \"tagPriority\", \"tagDuplicateStrategy\", \"innerHTML\", \"textContent\", \"processTemplateParams\"]); const UsesMergeStrategy = new Set([\"templateParams\", \"htmlAttrs\", \"bodyAttrs\"]); const MetaTagsArrayable = new Set([ \"theme-color\", \"google-site-verification\", \"og\", \"article\", \"book\", \"profile\", \"twitter\", \"author\" ]); function callHook(head, hook, ctx) { return head.hooks?.callHook(hook, ctx); } const META_NOREWRITE_RE = /^(?:viewport|description|keywords|robots)$/; const META_KEY_ATTRS = [\"name\", \"property\", \"http-equiv\"]; function isMetaArrayDupeKey(v) { return MetaTagsArrayable.has(v.split(\":\")[1]); } function dedupeKey(tag) { const { props, tag: t, key } = tag; if (UniqueTags.has(t)) return t; if (t === \"link\" && props.rel === \"canonical\") return \"canonical\"; if (t === \"link\" && props.rel === \"alternate\") { if (props.hreflang) return `alternate:${props.hreflang}`; if (props.type) return `alternate:${props.type}:${props.href || \"\"}`; } if (props.charset) return \"charset\"; if (t === \"meta\") { for (const n of META_KEY_ATTRS) { const v = props[n]; if (v !== void 0) return `meta:${v}${(typeof v !== \"string\" || !v.includes(\":\")) && !META_NOREWRITE_RE.test(v) && key ? `:key:${key}` : \"\"}`; } } if (key) return `${t}:key:${key}`; if (props.id) return `${t}:id:${props.id}`; if (t === \"link\" && props.rel === \"alternate\") return `alternate:${props.href || \"\"}`; return TagsWithInnerContent.has(t) && (tag.textContent || tag.innerHTML) ? `${t}:content:${tag.textContent || tag.innerHTML}` : void 0; } function hashTag(tag) { return tag._h || tag._d || tag.textContent || tag.innerHTML || `${tag.tag}:${Object.entries(tag.props).map(([k, v]) => `${k}:${String(v)}`).join()}`; } function walkResolver(val, resolve, key) { if (key === \"_resolver\") return val; if (typeof val === \"function\" && (!key || key !== \"titleTemplate\" && !key.startsWith(\"on\"))) val = val(); const v = resolve ? resolve(key, val) : val; if (Array.isArray(v)) return v.map((r) => walkResolver(r, resolve)); if (v?.constructor === Object) { const next = {}; for (const k in v) { if (k === \"__proto__\" || k === \"constructor\" || k === \"prototype\") continue; next[k] = walkResolver(v[k], resolve, k); } return next; } return v; } function normalizeStyleClassProps(key, value) { const isStyle = key === \"style\"; const store = isStyle ? new Map() : new Set(); const add = (v) => { if (!v) return; if (isStyle) { const i = v.indexOf(\":\"); i > 0 && store.set(v.slice(0, i).trim(), v.slice(i + 1).trim()); } else { v.split(\" \").forEach((c) => c && store.add(c)); } }; if (typeof value === \"string\") { (isStyle ? value.split(\";\") : [value]).forEach(add); } else if (Array.isArray(value)) { value.forEach(add); } else if (value && typeof value === \"object\") { for (const k in value) { const v = value[k]; v && v !== \"false\" && (isStyle ? store.set(k.trim(), String(v)) : add(k)); } } return store; } function normalizeProps(tag, input) { tag.props = tag.props || {}; if (!input) return tag; if (tag.tag === \"templateParams\") { tag.props = input; return tag; } const isHtmlTag = HasElementTags.has(tag.tag) || tag.tag === \"htmlAttrs\" || tag.tag === \"bodyAttrs\"; for (const prop in input) { if (prop === \"__proto__\" || prop === \"constructor\" || prop === \"prototype\") continue; const value = input[prop]; if (value === null) { tag.props[prop] = null; } else if (prop === \"class\" || prop === \"style\") { tag.props[prop] = normalizeStyleClassProps(prop, value); } else if (TagConfigKeys.has(prop)) { if ((prop === \"textContent\" || prop === \"innerHTML\") && typeof value === \"object\") { const type = input.type || \"application/json\"; if (type.endsWith(\"json\") || type === \"speculationrules\" || type === \"importmap\") { tag.props.type = input.type = type; tag[prop] = JSON.stringify(value); } } else { tag[prop] = value; } } else if (value !== void 0) { const isData = prop.startsWith(\"data-\"); const key = isHtmlTag && !isData ? prop.toLowerCase() : prop; const str = String(value); const isMeta = tag.tag === \"meta\" && key === \"content\"; tag.props[key] = str === \"true\" || str === \"\" ? isData || isMeta ? str : true : !value && isData && str === \"false\" ? \"false\" : value; } } return tag; } function normalizeTag(tagName, _input) { const input = typeof _input === \"object\" && typeof _input !== \"function\" ? _input : { [tagName === \"script\" || tagName === \"noscript\" || tagName === \"style\" ? \"innerHTML\" : \"textContent\"]: _input }; const tag = normalizeProps({ tag: tagName, props: {} }, input); if (tag.key && DupeableTags.has(tag.tag)) tag.props[\"data-hid\"] = tag._h = tag.key; if (tag.tag === \"script\" && typeof tag.innerHTML === \"object\") { tag.innerHTML = JSON.stringify(tag.innerHTML); tag.props.type = tag.props.type || \"application/json\"; } return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag; } function normalizeEntryToTags(input, propResolvers) { if (!input) return []; if (typeof input === \"function\") input = input(); let resolve; if (propResolvers.length) { resolve = (key, val) => { for (let i = 0; i < propResolvers.length; i++) val = propResolvers[i](key, val); return val; }; input = resolve(void 0, input); } input = walkResolver(input, resolve); const tags = []; for (const key in input) { const value = input[key]; if (value !== void 0) { for (const v of Array.isArray(value) ? value : [value]) tags.push(normalizeTag(key, v)); } } return tags.flat(); } const LT_RE = /</g; const SCRIPT_END_RE = /<\\/script/g; const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w; const DEFAULT_TAG_WEIGHT = () => 100; const TAG_MUTATING_HOOK_RE = /^tags:|:render/; function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); const prev = ctx.tagMap.get(k); if (!prev) { ctx.tagMap.set(k, next); continue; } const strategy = next.tagDuplicateStrategy || (UsesMergeStrategy.has(next.tag) ? \"merge\" : null) || (next.key && next.key === prev.key ? \"merge\" : null); if (strategy === \"merge\") { const props = { ...prev.props }; for (const p in next.props) { props[p] = p === \"style\" ? new Map([...prev.props.style || new Map(), ...next.props[p]]) : p === \"class\" ? new Set([...prev.props.class || [], ...next.props[p]]) : next.props[p]; } ctx.tagMap.set(k, { ...next, props }); } else if (next._p >> 10 === prev._p >> 10 && next.tag === \"meta\" && isMetaArrayDupeKey(k)) { ctx.tagMap.set(k, Object.assign([...Array.isArray(prev) ? prev : [prev], next], next)); hasFlatMeta = true; } else if (next._w === prev._w ? next._p > prev._p : next._w < prev._w) { ctx.tagMap.set(k, next); } } return hasFlatMeta; } function resolveTitleTemplate(ctx, head) { const title = ctx.tagMap.get(\"title\"); const tpl = ctx.tagMap.get(\"titleTemplate\"); head._title = title?.textContent; if (!tpl) return; const fn = tpl.textContent; head._titleTemplate = fn; if (!fn) return; let v = typeof fn === \"function\" ? fn(title?.textContent) : fn; if (typeof v === \"string\" && !head.plugins.has(\"template-params\")) v = v.replace(\"%s\", title?.textContent || \"\"); if (title) { v === null ? ctx.tagMap.delete(\"title\") : ctx.tagMap.set(\"title\", { ...title, textContent: v }); } else { ctx.tagMap.set(\"titleTemplate\", { ...tpl, tag: \"title\", textContent: v }); } } function sanitizeTags(tags) { const out = []; for (let t of tags) { const { innerHTML, tag, props } = t; if (!ValidHeadTags.has(tag) || !Object.keys(props).length && !innerHTML && !t.textContent) continue; if (tag === \"meta\" && !props.content && !props[\"http-equiv\"] && !props.charset) continue; if (tag === \"script\" && (innerHTML || t.textContent)) { const type = String(props.type); const isJsonLike = type.endsWith(\"json\") || type === \"importmap\" || type === \"speculationrules\"; const escape = (content) => isJsonLike ? (typeof content === \"string\" ? content : JSON.stringify(content)).replace(LT_RE, \"\\\\u003C\") : typeof content === \"string\" ? content.replace(SCRIPT_END_RE, \"<\\\\/script\") : content; t = { ...t }; if (innerHTML) t.innerHTML = escape(innerHTML); if (t.textContent) t.textContent = escape(t.textContent); t._d = dedupeKey(t); } out.push(t); } return out; } function resolveTags(head, options) { const weightFn = options?.tagWeight ?? head.resolvedOptions._tagWeight ?? DEFAULT_TAG_WEIGHT; const ctx = { tagMap: new Map(), tags: [] }; const hooks = head.hooks?._hooks || {}; const entries = [...head.entries.values()]; for (const e of entries) { if (e._pending !== void 0) { e.input = e._pending; delete e._pending; delete e._tags; } } callHook(head, \"entries:resolve\", { entries, ...ctx }); for (const e of entries) { if (!e._tags) { const normalizeCtx = { tags: normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []).map((t) => Object.assign(t, e.options)), entry: e }; callHook(head, \"entries:normalize\", normalizeCtx); e._tags = normalizeCtx.tags.map((t, i) => { t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); return t; }); } } let needsClone = false; for (const k in hooks) { if (TAG_MUTATING_HOOK_RE.test(k) && hooks[k]?.some((f) => !f._nonMutating)) { needsClone = true; break; } } ctx.tags = needsClone ? entries.flatMap((e) => (e._tags || []).map((t) => { const props = { ...t.props }; if (props.class instanceof Set) props.class = new Set(props.class); if (props.style instanceof Map) props.style = new Map(props.style); return { ...t, props }; })) : entries.flatMap((e) => e._tags || []); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); ctx.tags = [...ctx.tagMap.values()]; if (hasFlatMeta) ctx.tags = ctx.tags.flat().sort(sortTags); callHook(head, \"tags:beforeResolve\", ctx); callHook(head, \"tags:resolve\", ctx); callHook(head, \"tags:afterResolve\", ctx); return sanitizeTags(ctx.tags); } const WHITESPACE_RE = /\\s+/; function createDomRenderer(options = {}) { return (head) => _renderDOMHead(head, options); } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; if (!dom || !head.dirty && ![...head.entries.values()].some((e) => e._pending !== void 0)) return false; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, \"dom:beforeRender\", beforeRenderCtx); if (!beforeRenderCtx.shouldRender || head._du) return false; head._du = true; let state = head._dom; if (!state) { state = { _t: dom.title, _e: new Map([[\"htmlAttrs\", dom.documentElement], [\"bodyAttrs\", dom.body]]), _p: {}, _s: {} }; for (const el of [...dom.body.children, ...dom.head.children]) { const tag = el.tagName.toLowerCase(); if (!HasElementTags.has(tag)) continue; const props = { innerHTML: el.innerHTML }; for (const n of el.getAttributeNames()) props[n] = el.getAttribute(n); const next = normalizeProps({ tag, props: {} }, props); next.key = el.getAttribute(\"data-hid\") || void 0; let k = next._d = dedupeKey(next) || hashTag(next); let c = 1; while (state._e.has(k)) k = `${next._d}:${c++}`; state._e.set(k, el); } for (const entry of head.entries.values()) { if (entry._o !== void 0) { const orig = entry._o; for (const t of [\"bodyAttrs\", \"htmlAttrs\"]) { const cls = orig[t]?.class; if (typeof cls === \"string\") { const $el = state._e.get(t); for (const c of cls.split(WHITESPACE_RE)) { if (c) state._p[`${t}:attr:class:${c}`] = () => $el.classList.remove(c); } } } delete entry._o; } } } else { state._p = { ...state._s }; } state._s = {}; function track(id, scope, fn) { const k = `${id}:${scope}`; state._s[k] = fn; delete state._p[k]; } function trackCtx({ id, $el, tag }) { const isAttr = tag.tag.endsWith(\"Attrs\"); state._e.set(id, $el); if (!isAttr) { if (tag.textContent && tag.textContent !== $el.textContent) $el.textContent = tag.textContent; if (tag.innerHTML && tag.innerHTML !== $el.innerHTML) $el.innerHTML = tag.innerHTML; track(id, \"el\", () => { $el?.remove(); state._e.delete(id); }); } for (const k in tag.props) { const v = tag.props[k]; if (k[0] === \"o\" && k[1] === \"n\" && typeof v === \"function\") { const ev = k.slice(2); if ($el?.dataset?.[`${k}fired`]) v.call($el, new Event(ev)); if ($el.getAttribute(`data-${k}`) !== \"\") { (tag.tag === \"bodyAttrs\" ? dom.defaultView : $el).addEventListener(ev, v.bind($el)); $el.setAttribute(`data-${k}`, \"\"); } continue; } const ck = `attr:${k}`; if (k === \"class\" && v) { for (const c of v) { if (isAttr) track(id, `${ck}:${c}`, () => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === \"style\" && v) { for (const [sk, sv] of v) { track(id, `${ck}:${sk}`, () => $el.style.removeProperty(sk)); $el.style.setProperty(sk, sv); } } else if (v !== false && v !== null) { if ($el.getAttribute(k) !== v) $el.setAttribute(k, v === true ? \"\" : String(v)); if (isAttr) track(id, ck, () => $el.removeAttribute(k)); } } } const pending = []; const frag = {}; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = new Map(); for (const tag of rawTags) { const count = dupeKeyCounter.get(tag._d) || 0; const id = (count ? `${tag._d}:${count}` : tag._d) || tag._h; const ctx = { tag, id, shouldRender: true }; if (tag._d && isMetaArrayDupeKey(tag._d)) dupeKeyCounter.set(tag._d, count + 1); tags.push(ctx); if (tag.tag === \"title\") { dom.title = tag.textContent; track(\"title\", \"\", () => dom.title = state._t); continue; } ctx.$el = state._e.get(id); if (ctx.$el) trackCtx(ctx); else if (HasElementTags.has(tag.tag)) pending.push(ctx); } for (const ctx of pending) { ctx.$el = dom.createElement(ctx.tag.tag); trackCtx(ctx); (frag[ctx.tag.tagPosition || \"head\"] ??= dom.createDocumentFragment()).appendChild(ctx.$el); } if (frag.head) dom.head.appendChild(frag.head); if (frag.bodyOpen) dom.body.insertBefore(frag.bodyOpen, dom.body.firstChild); if (frag.bodyClose) dom.body.appendChild(frag.bodyClose); for (const k in state._p) state._p[k](); head._dom = state; callHook(head, \"dom:rendered\", { renders: tags }); head._du = false; head.dirty = false; return true; } function registerPlugin(head, p) { const plugin = typeof p === \"function\" ? p(head) : p; const key = plugin.key || String(head.plugins.size + 1); if (!head.plugins.get(key)) { head.plugins.set(key, plugin); for (const k in plugin.hooks || {}) head.hooks?.hook(k, plugin.hooks[k]); } } function createUnhead(renderer, resolvedOptions = {}) { const ssr = !resolvedOptions.document; const entries = new Map(); const plugins = new Map(); const head = { _entryCount: 1, plugins, resolvedOptions, ssr, entries, render: () => renderer(head), use: (p) => registerPlugin(head, p), push(input, _options) { const _i = _options?._index ?? head._entryCount++; const options = _options ? { ..._options } : {}; delete options.head; delete options.onRendered; const entry = { _i, input, options }; entries.set(_i, entry); const active = { _i, dispose() { entries.delete(_i); }, patch(input2) { if (ssr) { entry.input = input2; delete entry._tags; } else { entry._pending = input2; } if (!entries.has(_i)) entries.set(_i, entry); } }; return active; } }; resolvedOptions.init?.forEach((e) => e && head.push(e)); return head; } const DEFAULT_STREAM_KEY = \"__unhead__\"; function init(options = {}) { const { streamKey = DEFAULT_STREAM_KEY } = options; const win = typeof window !== \"undefined\" ? window : void 0; if (!win) return; const queue = win[streamKey]; if (queue?._head) return queue._head; const doc = typeof document !== \"undefined\" ? document : void 0; const head = createUnhead(createDomRenderer(), { document: doc }); let hydrationLocked = true; queueMicrotask(() => { hydrationLocked = false; }); function pushStreamed(entry) { const active = head.push(entry); const stored = head.entries.get(active._i); if (stored) stored._streamed = true; } if (queue?._q) { for (const entries of queue._q) { for (const entry of entries) { pushStreamed(entry); } } head.dirty = true; head.render(); } win[streamKey] = { _q: queue?._q || [], _head: head, _hydrationLocked: () => hydrationLocked, push: (entries) => { for (const entry of entries) { pushStreamed(entry); } head.dirty = true; head.render(); } }; return head; } init(); exports.init = init; return exports; })({});";
|
|
2
|
+
export const streamingIifeSize = 16723;
|
package/dist/stream/server.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as ServerUnhead } from '../shared/unhead.
|
|
2
|
-
import { f as CreateStreamableServerHeadOptions, U as Unhead, s as SSRHeadPayload } from '../shared/unhead.
|
|
3
|
-
import { aw as ResolvableHead } from '../shared/unhead.
|
|
1
|
+
import { S as ServerUnhead } from '../shared/unhead.ClQ7OJ-0.mjs';
|
|
2
|
+
import { f as CreateStreamableServerHeadOptions, U as Unhead, s as SSRHeadPayload } from '../shared/unhead.rdR8o82F.mjs';
|
|
3
|
+
import { aw as ResolvableHead } from '../shared/unhead.B8_fLxlB.mjs';
|
|
4
4
|
import 'hookable';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/stream/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as ServerUnhead } from '../shared/unhead.
|
|
2
|
-
import { f as CreateStreamableServerHeadOptions, U as Unhead, s as SSRHeadPayload } from '../shared/unhead.
|
|
3
|
-
import { aw as ResolvableHead } from '../shared/unhead.
|
|
1
|
+
import { S as ServerUnhead } from '../shared/unhead.Dz8_vfOe.js';
|
|
2
|
+
import { f as CreateStreamableServerHeadOptions, U as Unhead, s as SSRHeadPayload } from '../shared/unhead.71V9w6oU.js';
|
|
3
|
+
import { aw as ResolvableHead } from '../shared/unhead.B8_fLxlB.js';
|
|
4
4
|
import 'hookable';
|
|
5
5
|
|
|
6
6
|
/**
|