unhead 3.1.5 → 3.1.7

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.
Files changed (61) hide show
  1. package/dist/client.d.mts +5 -6
  2. package/dist/client.d.ts +5 -6
  3. package/dist/client.mjs +7 -12
  4. package/dist/index.d.mts +3 -3
  5. package/dist/index.d.ts +3 -3
  6. package/dist/index.mjs +15 -10
  7. package/dist/legacy.d.mts +2 -2
  8. package/dist/legacy.d.ts +2 -2
  9. package/dist/legacy.mjs +9 -9
  10. package/dist/parser.mjs +11 -7
  11. package/dist/plugins.d.mts +2 -2
  12. package/dist/plugins.d.ts +2 -2
  13. package/dist/plugins.mjs +7 -7
  14. package/dist/scripts.d.mts +3 -3
  15. package/dist/scripts.d.ts +3 -3
  16. package/dist/scripts.mjs +2 -3
  17. package/dist/server.d.mts +3 -3
  18. package/dist/server.d.ts +3 -3
  19. package/dist/server.mjs +5 -5
  20. package/dist/shared/{unhead.fg-0ge_u.mjs → unhead.1eoQpFT1.mjs} +6 -1
  21. package/dist/shared/{unhead.CRVUlr67.d.mts → unhead.BIArU35P.d.mts} +1 -1
  22. package/dist/shared/{unhead.BSqa2bYq.mjs → unhead.BNhb5t7_.mjs} +4 -6
  23. package/dist/shared/{unhead.BeIvDlYY.d.mts → unhead.BZy3nXHx.d.mts} +1 -1
  24. package/dist/shared/{unhead.DvIxXxuO.mjs → unhead.Bm4Y6XQI.mjs} +3 -0
  25. package/dist/shared/{unhead.B37CPNIq.d.mts → unhead.Bx2bAQEg.d.mts} +1 -1
  26. package/dist/shared/{unhead.D-W0R71w.mjs → unhead.C-RMAxyM.mjs} +27 -38
  27. package/dist/shared/{unhead.CS8tFxG3.d.mts → unhead.CELAVVhh.d.mts} +3 -5
  28. package/dist/shared/unhead.CHEy9ana.mjs +7 -0
  29. package/dist/shared/{unhead.BhvKU-Uu.d.ts → unhead.CN7FHaDF.d.ts} +1 -1
  30. package/dist/shared/{unhead.H5gLMTHA.mjs → unhead.CR32jx68.mjs} +125 -35
  31. package/dist/shared/{unhead.CBkhoTGw.mjs → unhead.CT1xoGPh.mjs} +1 -1
  32. package/dist/shared/unhead.CaGVnLUe.mjs +231 -0
  33. package/dist/shared/{unhead.YBmQyFpm.d.ts → unhead.Cnhe7n9-.d.ts} +1 -1
  34. package/dist/shared/{unhead.Blkhu0Cr.d.ts → unhead.DQadHCLi.d.ts} +1 -1
  35. package/dist/shared/{unhead.CBj56GgY.d.ts → unhead.Dv-MkoX9.d.ts} +3 -5
  36. package/dist/shared/{unhead.CfgPMHXt.mjs → unhead.WK9wg_ep.mjs} +2 -0
  37. package/dist/shared/{unhead.Doc2Fa-a.mjs → unhead.YIW3bMYK.mjs} +64 -33
  38. package/dist/shared/{unhead.BZYKjYpn.mjs → unhead.b15Kg1OH.mjs} +3 -3
  39. package/dist/shared/{unhead.J7mPNB3E.mjs → unhead.tpXvlPwt.mjs} +53 -34
  40. package/dist/shared/{unhead.BWKj-eGY.d.ts → unhead.xa1ebPBp.d.ts} +1 -1
  41. package/dist/shared/{unhead.BO2PdEL4.d.mts → unhead.zyZmXwAG.d.mts} +1 -1
  42. package/dist/stream/client.d.mts +2 -2
  43. package/dist/stream/client.d.ts +2 -2
  44. package/dist/stream/client.mjs +3 -8
  45. package/dist/stream/iife.d.cts +2 -0
  46. package/dist/stream/iife.global.js +1 -1
  47. package/dist/stream/iife.mjs +2 -2
  48. package/dist/stream/server.d.mts +2 -2
  49. package/dist/stream/server.d.ts +2 -2
  50. package/dist/stream/server.mjs +5 -5
  51. package/dist/stream/unplugin.d.mts +5 -1
  52. package/dist/stream/unplugin.d.ts +5 -1
  53. package/dist/stream/unplugin.mjs +29 -7
  54. package/dist/types.d.mts +2 -2
  55. package/dist/types.d.ts +2 -2
  56. package/dist/utils.d.mts +1 -1
  57. package/dist/utils.d.ts +1 -1
  58. package/dist/utils.mjs +4 -4
  59. package/package.json +3 -3
  60. package/dist/shared/unhead.CT3gGqve.mjs +0 -154
  61. package/dist/shared/unhead.CUXLLRtV.mjs +0 -5
@@ -1,22 +1,27 @@
1
- import { u as unpackMeta } from './unhead.CBkhoTGw.mjs';
2
- import { d as defineHeadPlugin } from './unhead.CUXLLRtV.mjs';
1
+ import { u as unpackMeta } from './unhead.CT1xoGPh.mjs';
2
+ import { d as defineHeadPlugin } from './unhead.CHEy9ana.mjs';
3
+ import { i as isUnsafeKey } from './unhead.1eoQpFT1.mjs';
3
4
 
4
5
  const FlatMetaPlugin = /* @__PURE__ */ defineHeadPlugin({
5
6
  key: "flatMeta",
6
7
  hooks: {
7
8
  "entries:normalize": (ctx) => {
9
+ let hasFlatMeta = false;
10
+ const tags = [];
8
11
  const tagsToAdd = [];
9
- ctx.tags = [...ctx.tags.map((t) => {
12
+ for (const t of ctx.tags) {
10
13
  if (t.tag !== "_flatMeta") {
11
- return t;
14
+ tags.push(t);
15
+ continue;
12
16
  }
13
- tagsToAdd.push(...unpackMeta(t.props).map((p) => ({
14
- ...t,
15
- tag: "meta",
16
- props: p
17
- })));
18
- return false;
19
- }).filter(Boolean), ...tagsToAdd];
17
+ hasFlatMeta = true;
18
+ for (const props of unpackMeta(t.props))
19
+ tagsToAdd.push({ ...t, tag: "meta", props });
20
+ }
21
+ if (!hasFlatMeta)
22
+ return;
23
+ for (const tag of tagsToAdd) tags.push(tag);
24
+ ctx.tags = tags;
20
25
  }
21
26
  }
22
27
  });
@@ -31,7 +36,8 @@ const WhitelistAttributes = {
31
36
  link: /* @__PURE__ */ new Set(["color", "crossorigin", "fetchpriority", "href", "hreflang", "imagesrcset", "imagesizes", "integrity", "media", "referrerpolicy", "rel", "sizes", "type"])
32
37
  };
33
38
  const BlockedLinkRels = /* @__PURE__ */ new Set(["canonical", "modulepreload", "prerender", "preload", "prefetch", "dns-prefetch", "preconnect", "manifest", "pingback"]);
34
- const SafeAttrName = /^[a-z][a-z0-9\-]*[a-z0-9]$/i;
39
+ const SafeDataAttrName = /^[a-z][a-z0-9-]*[a-z0-9]$/i;
40
+ const AsciiWhitespace = /[\t\n\f\r ]+/;
35
41
  const HtmlEntityHex = /&#x([0-9a-f]+);?/gi;
36
42
  const HtmlEntityDec = /&#(\d+);?/g;
37
43
  const HtmlEntityNamed = /&(tab|newline|colon|semi|lpar|rpar|sol|bsol|comma|period|excl|num|dollar|percnt|amp|apos|ast|plus|lt|gt|equals|quest|at|lsqb|rsqb|lcub|rcub|vert|hat|grave|tilde|nbsp);?/gi;
@@ -97,7 +103,7 @@ function stripProtoKeys(obj) {
97
103
  if (obj && typeof obj === "object") {
98
104
  const clean = {};
99
105
  for (const key of Object.keys(obj)) {
100
- if (key === "__proto__" || key === "constructor" || key === "prototype")
106
+ if (isUnsafeKey(key))
101
107
  continue;
102
108
  clean[key] = stripProtoKeys(obj[key]);
103
109
  }
@@ -106,9 +112,21 @@ function stripProtoKeys(obj) {
106
112
  return obj;
107
113
  }
108
114
  function acceptDataAttrs(value, allowId = true) {
109
- return Object.fromEntries(
110
- Object.entries(value || {}).filter(([key]) => (allowId && key === "id" || key.startsWith("data-")) && SafeAttrName.test(key))
111
- );
115
+ const next = {};
116
+ if (!value)
117
+ return next;
118
+ const keys = Object.keys(value);
119
+ for (let i = 0; i < keys.length; i++) {
120
+ const key = keys[i];
121
+ const isData = key.startsWith("data-");
122
+ if ((isData || allowId && key === "id") && SafeDataAttrName.test(key))
123
+ next[key] = value[key];
124
+ }
125
+ return next;
126
+ }
127
+ function hasBlockedRel(rel) {
128
+ const tokens = rel.split(AsciiWhitespace);
129
+ return !tokens.some(Boolean) || tokens.some((token) => BlockedLinkRels.has(token.toLowerCase()));
112
130
  }
113
131
  function makeTagSafe(tag) {
114
132
  let next = {};
@@ -156,7 +174,7 @@ function makeTagSafe(tag) {
156
174
  if (!val) {
157
175
  return;
158
176
  }
159
- if (key === "rel" && (typeof val !== "string" || BlockedLinkRels.has(val.toLowerCase()))) {
177
+ if (key === "rel" && (typeof val !== "string" || hasBlockedRel(val))) {
160
178
  return;
161
179
  }
162
180
  if (key === "href" || key === "imagesrcset") {
@@ -211,23 +229,36 @@ function makeTagSafe(tag) {
211
229
  }
212
230
  return tag;
213
231
  }
214
- const SafeInputPlugin = (
215
- /* @PURE */
216
- defineHeadPlugin({
217
- key: "safe",
218
- hooks: {
219
- "entries:normalize": (ctx) => {
220
- if (ctx.entry.options?._safe) {
221
- ctx.tags = ctx.tags.reduce((acc, tag) => {
222
- const safeTag = makeTagSafe(tag);
223
- if (safeTag)
224
- acc.push(safeTag);
225
- return acc;
226
- }, []);
227
- }
232
+ const SafeInputPlugin = /* @__PURE__ */ defineHeadPlugin({
233
+ key: "safe",
234
+ hooks: {
235
+ "entries:normalize": (ctx) => {
236
+ if (ctx.entry.options?._safe) {
237
+ ctx.tags = ctx.tags.reduce((acc, tag) => {
238
+ const safeTag = makeTagSafe(tag);
239
+ if (safeTag)
240
+ acc.push(safeTag);
241
+ return acc;
242
+ }, []);
228
243
  }
244
+ },
245
+ "tags:afterResolve": (ctx) => {
246
+ ctx.tags = ctx.tags.reduce((acc, tag) => {
247
+ if (!tag._safe) {
248
+ acc.push(tag);
249
+ return acc;
250
+ }
251
+ if (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs") {
252
+ acc.push(tag);
253
+ return acc;
254
+ }
255
+ const safeTag = makeTagSafe(tag);
256
+ if (safeTag)
257
+ acc.push(safeTag);
258
+ return acc;
259
+ }, []);
229
260
  }
230
- })
231
- );
261
+ }
262
+ });
232
263
 
233
264
  export { FlatMetaPlugin as F, SafeInputPlugin as S };
@@ -1,9 +1,9 @@
1
- import { d as defineHeadPlugin } from './unhead.CUXLLRtV.mjs';
1
+ import { d as defineHeadPlugin } from './unhead.CHEy9ana.mjs';
2
2
  import { p as processTemplateParams } from './unhead.BGFxPGPQ.mjs';
3
3
 
4
4
  const sortTags = (a, b) => a._w === b._w ? a._p - b._p : a._w - b._w;
5
5
  const formatKey = (k) => !k.includes(":key") ? k.split(":").join(":key:") : k;
6
- const AliasSortingPlugin = defineHeadPlugin({
6
+ const AliasSortingPlugin = /* @__PURE__ */ defineHeadPlugin({
7
7
  key: "aliasSorting",
8
8
  hooks: {
9
9
  "tags:resolve": (ctx) => {
@@ -124,6 +124,6 @@ const TemplateParamsPlugin = /* @__PURE__ */ defineHeadPlugin((head) => {
124
124
  }
125
125
  }
126
126
  };
127
- });
127
+ }, "template-params");
128
128
 
129
129
  export { AliasSortingPlugin as A, PromisesPlugin as P, TemplateParamsPlugin as T };
@@ -1,5 +1,4 @@
1
- import { a as callHook } from './unhead.DvIxXxuO.mjs';
2
- import { S as ScriptNetworkEvents } from './unhead.fg-0ge_u.mjs';
1
+ import { a as callHook } from './unhead.Bm4Y6XQI.mjs';
3
2
 
4
3
  function createNoopedRecordingProxy(instance = {}) {
5
4
  const stack = [];
@@ -59,15 +58,12 @@ function replayProxyRecordings(target, stack) {
59
58
  });
60
59
  }
61
60
 
62
- function resolveScriptKey(input) {
63
- return input.key || input.src || (typeof input.innerHTML === "string" ? input.innerHTML : "");
64
- }
65
- const PreconnectServerModes = ["preconnect", "dns-prefetch"];
66
61
  function useScript(head, _input, _options) {
67
62
  const input = typeof _input === "string" ? { src: _input } : _input;
68
63
  const options = _options || {};
69
- const id = resolveScriptKey(input);
70
- const prevScript = head._scripts?.[id];
64
+ const id = input.key || input.src || (typeof input.innerHTML === "string" ? input.innerHTML : "");
65
+ const scripts = head._scripts || (head._scripts = /* @__PURE__ */ Object.create(null));
66
+ const prevScript = Object.hasOwn(scripts, id) ? scripts[id] : void 0;
71
67
  if (prevScript) {
72
68
  prevScript.setupTriggerHandler(options.trigger);
73
69
  return prevScript;
@@ -79,33 +75,47 @@ function useScript(head, _input, _options) {
79
75
  _events.push({ type: s, timestamp: Date.now() });
80
76
  callHook(head, "script:updated", hookCtx);
81
77
  };
82
- ScriptNetworkEvents.forEach((fn) => {
83
- const k = fn;
84
- const _fn = typeof input[k] === "function" ? input[k].bind(options.eventContext) : null;
85
- input[k] = (e) => {
86
- syncStatus(fn === "onload" ? "loaded" : fn === "onerror" ? "error" : "loading");
87
- _fn?.(e);
88
- };
89
- });
78
+ const onload = typeof input.onload === "function" ? input.onload.bind(options.eventContext) : null;
79
+ input.onload = (e) => {
80
+ syncStatus("loaded");
81
+ onload?.(e);
82
+ };
83
+ const onerror = typeof input.onerror === "function" ? input.onerror.bind(options.eventContext) : null;
84
+ input.onerror = (e) => {
85
+ syncStatus("error");
86
+ onerror?.(e);
87
+ };
90
88
  const _cbs = { loaded: [], error: [] };
91
89
  const _uniqueCbs = /* @__PURE__ */ new Set();
92
90
  const _registerCb = (key, cb, options2) => {
93
91
  if (head.ssr) {
94
92
  return;
95
93
  }
94
+ let uniqueKey;
96
95
  if (options2?.key) {
97
- const key2 = `${options2?.key}:${options2.key}`;
98
- if (_uniqueCbs.has(key2)) {
96
+ uniqueKey = `${key}:${options2.key}`;
97
+ if (_uniqueCbs.has(uniqueKey)) {
99
98
  return;
100
99
  }
101
- _uniqueCbs.add(key2);
100
+ _uniqueCbs.add(uniqueKey);
102
101
  }
103
102
  if (_cbs[key]) {
104
- const i = _cbs[key].push(cb);
105
- return () => _cbs[key]?.splice(i - 1, 1);
103
+ _cbs[key].push(cb);
104
+ return () => {
105
+ const idx = _cbs[key]?.indexOf(cb) ?? -1;
106
+ if (idx !== -1)
107
+ _cbs[key]?.splice(idx, 1);
108
+ if (uniqueKey)
109
+ _uniqueCbs.delete(uniqueKey);
110
+ };
106
111
  }
107
- cb(script.instance);
112
+ if (key === "loaded" && script.status === "loaded")
113
+ cb(script.instance);
114
+ else if (key === "error" && script.status === "error")
115
+ cb();
108
116
  return () => {
117
+ if (uniqueKey)
118
+ _uniqueCbs.delete(uniqueKey);
109
119
  };
110
120
  };
111
121
  const loadPromise = new Promise((resolve) => {
@@ -114,7 +124,7 @@ function useScript(head, _input, _options) {
114
124
  const emit = (api) => queueMicrotask(() => resolve(api));
115
125
  const unhook = head.hooks?.hook("script:updated", ({ script: script2 }) => {
116
126
  const status = script2.status;
117
- if (script2.id === id && (status === "loaded" || status === "error")) {
127
+ if (script2.id === id && (status === "loaded" || status === "error" || status === "removed")) {
118
128
  if (status === "loaded") {
119
129
  if (typeof options.use === "function") {
120
130
  const api = options.use();
@@ -124,7 +134,7 @@ function useScript(head, _input, _options) {
124
134
  } else {
125
135
  emit({});
126
136
  }
127
- } else if (status === "error") {
137
+ } else {
128
138
  resolve(false);
129
139
  }
130
140
  unhook?.();
@@ -142,23 +152,26 @@ function useScript(head, _input, _options) {
142
152
  input,
143
153
  status: "awaitingLoad",
144
154
  remove() {
155
+ const hadEntry = !!script.entry;
145
156
  script._triggerAbortControllers?.forEach((ac) => ac.abort());
146
157
  script._triggerAbortControllers?.clear();
147
158
  script._triggerPromises = [];
148
159
  script._warmupEl?.dispose();
160
+ script._warmupEl = void 0;
149
161
  if (script.entry) {
150
162
  script.entry.dispose();
151
163
  script.entry = void 0;
152
- syncStatus("removed");
153
- delete head._scripts?.[id];
154
- return true;
155
164
  }
156
- return false;
165
+ if (scripts[id] === script)
166
+ delete scripts[id];
167
+ if (script.status !== "removed")
168
+ syncStatus("removed");
169
+ return hadEntry;
157
170
  },
158
171
  warmup(rel) {
159
172
  const { src } = input;
160
173
  const isCrossOrigin = !src.startsWith("/") || src.startsWith("//");
161
- const isPreconnect = rel && PreconnectServerModes.includes(rel);
174
+ const isPreconnect = rel === "preconnect" || rel === "dns-prefetch";
162
175
  let href = src;
163
176
  if (!rel || isPreconnect && !isCrossOrigin) {
164
177
  return;
@@ -228,15 +241,19 @@ function useScript(head, _input, _options) {
228
241
  });
229
242
  script._triggerAbortController = abortController;
230
243
  script._triggerPromises = script._triggerPromises || [];
231
- const idx = script._triggerPromises.push(Promise.race([
244
+ const triggerPromise = Promise.race([
232
245
  trigger.then((v) => typeof v === "undefined" || v ? script.load : void 0),
233
246
  abortPromise
234
247
  ]).catch((error) => {
235
248
  }).then((res) => {
236
249
  res?.();
237
250
  }).finally(() => {
238
- script._triggerPromises?.splice(idx, 1);
239
- }));
251
+ script._triggerAbortControllers?.delete(abortController);
252
+ const idx = script._triggerPromises?.indexOf(triggerPromise) ?? -1;
253
+ if (idx !== -1)
254
+ script._triggerPromises?.splice(idx, 1);
255
+ });
256
+ script._triggerPromises.push(triggerPromise);
240
257
  } else if (typeof trigger === "function") {
241
258
  trigger(script.load);
242
259
  }
@@ -249,7 +266,9 @@ function useScript(head, _input, _options) {
249
266
  _cbs.loaded?.forEach((cb) => cb(api));
250
267
  _cbs.loaded = null;
251
268
  } else {
252
- _cbs.error?.forEach((cb) => cb());
269
+ if (script.status === "error")
270
+ _cbs.error?.forEach((cb) => cb());
271
+ _cbs.loaded = null;
253
272
  _cbs.error = null;
254
273
  }
255
274
  });
@@ -270,7 +289,7 @@ function useScript(head, _input, _options) {
270
289
  script._warmupStrategy = options.warmupStrategy;
271
290
  script.warmup(options.warmupStrategy);
272
291
  }
273
- head._scripts = Object.assign(head._scripts || {}, { [id]: script });
292
+ scripts[id] = script;
274
293
  return script;
275
294
  }
276
295
 
@@ -1,6 +1,6 @@
1
1
  import { HookableCore } from 'hookable';
2
2
  import { R as ResolvableHead } from './unhead.Dl7UHSN0.js';
3
- import { U as Unhead, d as ClientHeadHooks, C as CreateClientHeadOptions } from './unhead.CBj56GgY.js';
3
+ import { U as Unhead, d as ClientHeadHooks, C as CreateClientHeadOptions } from './unhead.Dv-MkoX9.js';
4
4
 
5
5
  interface ClientUnhead<T = ResolvableHead> extends Unhead<T, boolean> {
6
6
  hooks: HookableCore<ClientHeadHooks>;
@@ -1,4 +1,4 @@
1
- import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.CS8tFxG3.mjs';
1
+ import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.CELAVVhh.mjs';
2
2
 
3
3
  /**
4
4
  * Load third-party scripts with SSR support and a proxied API.
@@ -1,5 +1,5 @@
1
- import { C as ClientUnhead } from '../shared/unhead.CRVUlr67.mjs';
2
- import { U as Unhead, C as CreateClientHeadOptions } from '../shared/unhead.CS8tFxG3.mjs';
1
+ import { C as ClientUnhead } from '../shared/unhead.BIArU35P.mjs';
2
+ import { U as Unhead, C as CreateClientHeadOptions } from '../shared/unhead.CELAVVhh.mjs';
3
3
  import { S as SerializableHead, R as ResolvableHead } from '../shared/unhead.Dl7UHSN0.mjs';
4
4
  import 'hookable';
5
5
 
@@ -1,5 +1,5 @@
1
- import { C as ClientUnhead } from '../shared/unhead.BWKj-eGY.js';
2
- import { U as Unhead, C as CreateClientHeadOptions } from '../shared/unhead.CBj56GgY.js';
1
+ import { C as ClientUnhead } from '../shared/unhead.xa1ebPBp.js';
2
+ import { U as Unhead, C as CreateClientHeadOptions } from '../shared/unhead.Dv-MkoX9.js';
3
3
  import { S as SerializableHead, R as ResolvableHead } from '../shared/unhead.Dl7UHSN0.js';
4
4
  import 'hookable';
5
5
 
@@ -1,5 +1,5 @@
1
- import { r as registerPlugin } from '../shared/unhead.CfgPMHXt.mjs';
2
- import { c as createHooks } from '../shared/unhead.DvIxXxuO.mjs';
1
+ import { r as registerPlugin } from '../shared/unhead.WK9wg_ep.mjs';
2
+ import { c as createHooks } from '../shared/unhead.Bm4Y6XQI.mjs';
3
3
  import 'hookable';
4
4
 
5
5
  const DEFAULT_STREAM_KEY = "__unhead__";
@@ -73,12 +73,7 @@ function createStreamableHead(options = {}) {
73
73
  }
74
74
  }
75
75
  });
76
- const initialPayload = rest.document?.head.querySelector('script[id="unhead:payload"]')?.innerHTML || false;
77
- const initEntries = [
78
- initialPayload ? JSON.parse(initialPayload) : false,
79
- ...rest.init || []
80
- ];
81
- initEntries.forEach((e) => e && head.push(e));
76
+ rest.init?.forEach((e) => e && head.push(e));
82
77
  if (streamQueue)
83
78
  streamQueue._head = head;
84
79
  return head;
@@ -0,0 +1,2 @@
1
+ export declare const streamingIifeCode: string;
2
+ export declare const streamingIifeSize: number;
@@ -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)$/; 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; })({});
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 isUnsafeKey(key) { return key === "__proto__" || key === "constructor" || key === "prototype"; } function callHook(head, hook, ctx) { const hooks = head.hooks?._hooks?.[hook]; if (!hooks?.length) return; 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) { const i = v.indexOf(":"); if (i === -1) return false; const j = v.indexOf(":", i + 1); return MetaTagsArrayable.has(v.slice(i + 1, j === -1 ? v.length : j)); } 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) { const identity = tag._h || tag._d || tag.textContent || tag.innerHTML; if (identity) return identity; let hash = `${tag.tag}:`; let separator = ""; for (const key in tag.props) { if (Object.hasOwn(tag.props, key)) { hash += `${separator}${key}:${String(tag.props[key])}`; separator = ","; } } return hash; } 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)) { let out; for (let i = 0; i < v.length; i++) { const r = walkResolver(v[i], resolve); if (out) { out[i] = r; } else if (r !== v[i]) { out = v.slice(0, i); out[i] = r; } } return out || v; } if (v?.constructor === Object) { let next; for (const k in v) { const unsafe = isUnsafeKey(k); const r = unsafe ? void 0 : walkResolver(v[k], resolve, k); if (!next && (unsafe || r !== v[k])) { next = {}; for (const pk in v) { if (pk === k) break; next[pk] = v[pk]; } } if (next && !unsafe) next[k] = r; } return next || v; } return v; } const INVALID_ATTR_NAME_RE = /[\s"'<>/=\x00-\x1F\x7F]/; 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 (isUnsafeKey(prop)) continue; const isData = prop.startsWith("data-"); const isHtmlAttr = isHtmlTag && !TagConfigKeys.has(prop); const key = isHtmlAttr && !isData ? prop.toLowerCase() : prop; if (isHtmlAttr && (!key || INVALID_ATTR_NAME_RE.test(key))) continue; const value = input[prop]; if (value === null) { tag.props[key] = 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 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"; } if (Array.isArray(tag.props.content)) { const tags = []; for (const content of tag.props.content) { tags.push({ ...tag, props: { ...tag.props, content } }); } return tags; } return tag; } function pushNormalizedTag(tags, tag) { if (Array.isArray(tag)) { for (const t of tag) tags.push(t); } else { tags.push(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) { if (Array.isArray(value)) { for (const v of value) pushNormalizedTag(tags, normalizeTag(key, v)); } else { pushNormalizedTag(tags, normalizeTag(key, value)); } } } return tags; } 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; function isEmptyProps(props) { for (const _ in props) return false; return true; } const TAG_MUTATING_HOOK_RE = /^tags:|:render/; function pushEntryTags(ctx, entries, needsClone) { for (const tags of entries) { for (const t of tags) { if (needsClone) { 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); ctx.tags.push({ ...t, props }); } else { ctx.tags.push(t); } } } } function valuesToTags(ctx, sortFlatMeta) { ctx.tags = []; for (const value of ctx.tagMap.values()) { if (Array.isArray(value)) { for (const tag of value) ctx.tags.push(tag); } else { ctx.tags.push(value); } } if (sortFlatMeta) ctx.tags.sort(sortTags); } function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); if (!k) continue; 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) || isEmptyProps(props) && !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 }); const entryTags = []; for (const e of entries) { if (!e._tags) { const tags = normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []); for (const t of tags) Object.assign(t, e.options); const normalizeCtx = { tags, entry: e }; callHook(head, "entries:normalize", normalizeCtx); for (let i = 0; i < normalizeCtx.tags.length; i++) { const t = normalizeCtx.tags[i]; t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); } e._tags = normalizeCtx.tags; } entryTags.push(e._tags); } let needsClone = false; for (const k in hooks) { if (TAG_MUTATING_HOOK_RE.test(k) && hooks[k]?.some((f) => !f._nonMutating)) { needsClone = true; break; } } pushEntryTags(ctx, entryTags, needsClone); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); valuesToTags(ctx, hasFlatMeta); 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 hasPendingEntries(head) { for (const entry of head.entries.values()) { if (entry._pending !== void 0) return true; } return false; } function cleanupDomState(state) { for (const k in state._s) state._s[k](); for (const k in state._p) state._p[k](); state._s = {}; state._p = {}; state._e.clear(); state._l.clear(); } function createDomState(head, dom) { const state = { _d: dom, _t: dom.title, _e: new Map([["htmlAttrs", dom.documentElement], ["bodyAttrs", dom.body]]), _p: {}, _s: {}, _l: new Map() }; 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; const dedupe = dedupeKey(next) || hashTag(next); let k = dedupe; let c = 1; while (state._e.has(k)) k = `${dedupe}:${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); } } } } } return state; } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; const activeState = head._dom; const documentChanged = !!activeState && activeState._d !== dom; if (!dom || !documentChanged && !head.dirty && !hasPendingEntries(head)) return false; if (head._du) return false; const defaultView = dom.defaultView; head._du = true; let didRender = false; try { let track = function(id, scope, fn, fresh) { const k = `${id}:${scope}`; renderState._s[k] = !fresh && renderState._p[k] || fn; delete renderState._p[k]; }, reclaim = function(key) { const prev = renderState._p[key]; delete renderState._p[key]; return prev; }, trackEvent = function(id, k, ev, source, $el, target) { const scope = `event:${k}`; const key = `${id}:${scope}`; const prev = renderState._l.get(key); if (prev && prev[0] === target && prev[1] === ev && prev[2] === source) { track(id, scope, prev[4]); return; } prev?.[4](); const dk = `data-${k}`; const handler = ((e) => source.call($el, e)); const cleanup = () => { target.removeEventListener(ev, handler); if ($el.getAttribute(dk) === "") $el.removeAttribute(dk); if (renderState._l.get(key)?.[3] === handler) renderState._l.delete(key); }; target.addEventListener(ev, handler); renderState._l.set(key, [target, ev, source, handler, cleanup]); $el.setAttribute(dk, ""); track(id, scope, cleanup, true); }, trackCtx = function({ id, $el, tag }) { const isAttr = tag.tag.endsWith("Attrs"); renderState._e.set(id, $el); if (!isAttr) { const text = tag.textContent; if (text != null && text !== "") { if (text !== $el.textContent) $el.textContent = text; track(id, "text", () => { if ($el.textContent === text) $el.textContent = ""; }, true); } const html = tag.innerHTML; if (html != null && html !== "") { if (html !== $el.innerHTML) $el.innerHTML = html; track(id, "html", () => { if ($el.innerHTML === html) $el.innerHTML = ""; }, true); } const elKey = `${id}:el`; renderState._s[elKey] = reclaim(elKey) || (() => { $el?.remove(); renderState._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 (defaultView?.Event || Event)(ev)); trackEvent(id, k, ev, v, $el, tag.tag === "bodyAttrs" && defaultView ? defaultView : $el); continue; } const ck = `${id}:attr:${k}`; if (k === "class" && v) { for (const c of v) { const key = `${ck}:${c}`; renderState._s[key] = reclaim(key) || (() => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === "style" && v) { for (const [sk, sv] of v) { const key = `${ck}:${sk}`; renderState._s[key] = reclaim(key) || (() => $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)); renderState._s[ck] = reclaim(ck) || (() => $el.removeAttribute(k)); } } }; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, "dom:beforeRender", beforeRenderCtx); if (!beforeRenderCtx.shouldRender) return false; let state = head._dom; if (state?._d !== dom) { if (state) cleanupDomState(state); state = void 0; } if (!state) { state = createDomState(head, dom); } else { state._p = state._s; } state._s = {}; const renderState = state; const pending = []; const frag = {}; head.dirty = false; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = {}; for (const tag of rawTags) { const count = dupeKeyCounter[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[tag._d] = count + 1; tags.push(ctx); if (tag.tag === "title") { dom.title = tag.textContent; track("title", "", () => dom.title = renderState._t); continue; } ctx.$el = renderState._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 renderState._p) renderState._p[k](); head._dom = renderState; didRender = true; callHook(head, "dom:rendered", { renders: tags }); } catch (e) { head.dirty = true; throw e; } finally { head._du = false; } if (didRender && (head.dirty || hasPendingEntries(head))) _renderDOMHead(head, options); return didRender; } function registerPlugin(head, p) { if (typeof p === "function" && p.key && head.plugins.has(p.key)) return; 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; } exports.init = init; return exports; })({});__unhead_iife__.init();
@@ -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)$/; 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;
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 isUnsafeKey(key) { return key === \"__proto__\" || key === \"constructor\" || key === \"prototype\"; } function callHook(head, hook, ctx) { const hooks = head.hooks?._hooks?.[hook]; if (!hooks?.length) return; 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) { const i = v.indexOf(\":\"); if (i === -1) return false; const j = v.indexOf(\":\", i + 1); return MetaTagsArrayable.has(v.slice(i + 1, j === -1 ? v.length : j)); } 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) { const identity = tag._h || tag._d || tag.textContent || tag.innerHTML; if (identity) return identity; let hash = `${tag.tag}:`; let separator = \"\"; for (const key in tag.props) { if (Object.hasOwn(tag.props, key)) { hash += `${separator}${key}:${String(tag.props[key])}`; separator = \",\"; } } return hash; } 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)) { let out; for (let i = 0; i < v.length; i++) { const r = walkResolver(v[i], resolve); if (out) { out[i] = r; } else if (r !== v[i]) { out = v.slice(0, i); out[i] = r; } } return out || v; } if (v?.constructor === Object) { let next; for (const k in v) { const unsafe = isUnsafeKey(k); const r = unsafe ? void 0 : walkResolver(v[k], resolve, k); if (!next && (unsafe || r !== v[k])) { next = {}; for (const pk in v) { if (pk === k) break; next[pk] = v[pk]; } } if (next && !unsafe) next[k] = r; } return next || v; } return v; } const INVALID_ATTR_NAME_RE = /[\\s\"'<>/=\\x00-\\x1F\\x7F]/; 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 (isUnsafeKey(prop)) continue; const isData = prop.startsWith(\"data-\"); const isHtmlAttr = isHtmlTag && !TagConfigKeys.has(prop); const key = isHtmlAttr && !isData ? prop.toLowerCase() : prop; if (isHtmlAttr && (!key || INVALID_ATTR_NAME_RE.test(key))) continue; const value = input[prop]; if (value === null) { tag.props[key] = 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 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\"; } if (Array.isArray(tag.props.content)) { const tags = []; for (const content of tag.props.content) { tags.push({ ...tag, props: { ...tag.props, content } }); } return tags; } return tag; } function pushNormalizedTag(tags, tag) { if (Array.isArray(tag)) { for (const t of tag) tags.push(t); } else { tags.push(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) { if (Array.isArray(value)) { for (const v of value) pushNormalizedTag(tags, normalizeTag(key, v)); } else { pushNormalizedTag(tags, normalizeTag(key, value)); } } } return tags; } 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; function isEmptyProps(props) { for (const _ in props) return false; return true; } const TAG_MUTATING_HOOK_RE = /^tags:|:render/; function pushEntryTags(ctx, entries, needsClone) { for (const tags of entries) { for (const t of tags) { if (needsClone) { 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); ctx.tags.push({ ...t, props }); } else { ctx.tags.push(t); } } } } function valuesToTags(ctx, sortFlatMeta) { ctx.tags = []; for (const value of ctx.tagMap.values()) { if (Array.isArray(value)) { for (const tag of value) ctx.tags.push(tag); } else { ctx.tags.push(value); } } if (sortFlatMeta) ctx.tags.sort(sortTags); } function dedupeTags(ctx) { let hasFlatMeta = false; for (const next of ctx.tags.sort(sortTags)) { const k = next._d || hashTag(next); if (!k) continue; 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) || isEmptyProps(props) && !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 }); const entryTags = []; for (const e of entries) { if (!e._tags) { const tags = normalizeEntryToTags(e.input, head.resolvedOptions.propResolvers || []); for (const t of tags) Object.assign(t, e.options); const normalizeCtx = { tags, entry: e }; callHook(head, \"entries:normalize\", normalizeCtx); for (let i = 0; i < normalizeCtx.tags.length; i++) { const t = normalizeCtx.tags[i]; t._w = weightFn(t); t._p = (e._i << 10) + i; t._d = dedupeKey(t); if (!t._d) t._h = hashTag(t); } e._tags = normalizeCtx.tags; } entryTags.push(e._tags); } let needsClone = false; for (const k in hooks) { if (TAG_MUTATING_HOOK_RE.test(k) && hooks[k]?.some((f) => !f._nonMutating)) { needsClone = true; break; } } pushEntryTags(ctx, entryTags, needsClone); const hasFlatMeta = dedupeTags(ctx); resolveTitleTemplate(ctx, head); valuesToTags(ctx, hasFlatMeta); 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 hasPendingEntries(head) { for (const entry of head.entries.values()) { if (entry._pending !== void 0) return true; } return false; } function cleanupDomState(state) { for (const k in state._s) state._s[k](); for (const k in state._p) state._p[k](); state._s = {}; state._p = {}; state._e.clear(); state._l.clear(); } function createDomState(head, dom) { const state = { _d: dom, _t: dom.title, _e: new Map([[\"htmlAttrs\", dom.documentElement], [\"bodyAttrs\", dom.body]]), _p: {}, _s: {}, _l: new Map() }; 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; const dedupe = dedupeKey(next) || hashTag(next); let k = dedupe; let c = 1; while (state._e.has(k)) k = `${dedupe}:${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); } } } } } return state; } function _renderDOMHead(head, options = {}) { const dom = options.document || head.resolvedOptions.document; const activeState = head._dom; const documentChanged = !!activeState && activeState._d !== dom; if (!dom || !documentChanged && !head.dirty && !hasPendingEntries(head)) return false; if (head._du) return false; const defaultView = dom.defaultView; head._du = true; let didRender = false; try { let track = function(id, scope, fn, fresh) { const k = `${id}:${scope}`; renderState._s[k] = !fresh && renderState._p[k] || fn; delete renderState._p[k]; }, reclaim = function(key) { const prev = renderState._p[key]; delete renderState._p[key]; return prev; }, trackEvent = function(id, k, ev, source, $el, target) { const scope = `event:${k}`; const key = `${id}:${scope}`; const prev = renderState._l.get(key); if (prev && prev[0] === target && prev[1] === ev && prev[2] === source) { track(id, scope, prev[4]); return; } prev?.[4](); const dk = `data-${k}`; const handler = ((e) => source.call($el, e)); const cleanup = () => { target.removeEventListener(ev, handler); if ($el.getAttribute(dk) === \"\") $el.removeAttribute(dk); if (renderState._l.get(key)?.[3] === handler) renderState._l.delete(key); }; target.addEventListener(ev, handler); renderState._l.set(key, [target, ev, source, handler, cleanup]); $el.setAttribute(dk, \"\"); track(id, scope, cleanup, true); }, trackCtx = function({ id, $el, tag }) { const isAttr = tag.tag.endsWith(\"Attrs\"); renderState._e.set(id, $el); if (!isAttr) { const text = tag.textContent; if (text != null && text !== \"\") { if (text !== $el.textContent) $el.textContent = text; track(id, \"text\", () => { if ($el.textContent === text) $el.textContent = \"\"; }, true); } const html = tag.innerHTML; if (html != null && html !== \"\") { if (html !== $el.innerHTML) $el.innerHTML = html; track(id, \"html\", () => { if ($el.innerHTML === html) $el.innerHTML = \"\"; }, true); } const elKey = `${id}:el`; renderState._s[elKey] = reclaim(elKey) || (() => { $el?.remove(); renderState._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 (defaultView?.Event || Event)(ev)); trackEvent(id, k, ev, v, $el, tag.tag === \"bodyAttrs\" && defaultView ? defaultView : $el); continue; } const ck = `${id}:attr:${k}`; if (k === \"class\" && v) { for (const c of v) { const key = `${ck}:${c}`; renderState._s[key] = reclaim(key) || (() => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } } else if (k === \"style\" && v) { for (const [sk, sv] of v) { const key = `${ck}:${sk}`; renderState._s[key] = reclaim(key) || (() => $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)); renderState._s[ck] = reclaim(ck) || (() => $el.removeAttribute(k)); } } }; const beforeRenderCtx = { shouldRender: true, tags: [] }; callHook(head, \"dom:beforeRender\", beforeRenderCtx); if (!beforeRenderCtx.shouldRender) return false; let state = head._dom; if (state?._d !== dom) { if (state) cleanupDomState(state); state = void 0; } if (!state) { state = createDomState(head, dom); } else { state._p = state._s; } state._s = {}; const renderState = state; const pending = []; const frag = {}; head.dirty = false; const rawTags = resolveTags(head, options.tagWeight ? { tagWeight: options.tagWeight } : void 0); const tags = []; const dupeKeyCounter = {}; for (const tag of rawTags) { const count = dupeKeyCounter[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[tag._d] = count + 1; tags.push(ctx); if (tag.tag === \"title\") { dom.title = tag.textContent; track(\"title\", \"\", () => dom.title = renderState._t); continue; } ctx.$el = renderState._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 renderState._p) renderState._p[k](); head._dom = renderState; didRender = true; callHook(head, \"dom:rendered\", { renders: tags }); } catch (e) { head.dirty = true; throw e; } finally { head._du = false; } if (didRender && (head.dirty || hasPendingEntries(head))) _renderDOMHead(head, options); return didRender; } function registerPlugin(head, p) { if (typeof p === \"function\" && p.key && head.plugins.has(p.key)) return; 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; } exports.init = init; return exports; })({});__unhead_iife__.init();";
2
+ export const streamingIifeSize = 20484;
@@ -1,5 +1,5 @@
1
- import { S as ServerUnhead } from '../shared/unhead.B37CPNIq.mjs';
2
- import { e as CreateStreamableServerHeadOptions, U as Unhead, S as SSRHeadPayload } from '../shared/unhead.CS8tFxG3.mjs';
1
+ import { S as ServerUnhead } from '../shared/unhead.Bx2bAQEg.mjs';
2
+ import { e as CreateStreamableServerHeadOptions, U as Unhead, S as SSRHeadPayload } from '../shared/unhead.CELAVVhh.mjs';
3
3
  import { R as ResolvableHead } from '../shared/unhead.Dl7UHSN0.mjs';
4
4
  import 'hookable';
5
5
 
@@ -1,5 +1,5 @@
1
- import { S as ServerUnhead } from '../shared/unhead.Blkhu0Cr.js';
2
- import { e as CreateStreamableServerHeadOptions, U as Unhead, S as SSRHeadPayload } from '../shared/unhead.CBj56GgY.js';
1
+ import { S as ServerUnhead } from '../shared/unhead.DQadHCLi.js';
2
+ import { e as CreateStreamableServerHeadOptions, U as Unhead, S as SSRHeadPayload } from '../shared/unhead.Dv-MkoX9.js';
3
3
  import { R as ResolvableHead } from '../shared/unhead.Dl7UHSN0.js';
4
4
  import 'hookable';
5
5