@unhead/vue 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +24 -941
- package/dist/index.d.ts +3 -11
- package/dist/index.mjs +7 -922
- package/package.json +9 -8
package/dist/index.cjs
CHANGED
|
@@ -1,740 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const unhead = require('unhead');
|
|
4
4
|
const vue = require('vue');
|
|
5
|
-
|
|
6
|
-
const TagsWithInnerContent = ["script", "style", "noscript"];
|
|
7
|
-
const HasElementTags$1 = [
|
|
8
|
-
"base",
|
|
9
|
-
"meta",
|
|
10
|
-
"link",
|
|
11
|
-
"style",
|
|
12
|
-
"script",
|
|
13
|
-
"noscript"
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
const UniqueTags$1 = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
|
|
17
|
-
function tagDedupeKey$1(tag, fn) {
|
|
18
|
-
const { props, tag: tagName } = tag;
|
|
19
|
-
if (UniqueTags$1.includes(tagName))
|
|
20
|
-
return tagName;
|
|
21
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
22
|
-
return "canonical";
|
|
23
|
-
if (props.charset)
|
|
24
|
-
return "charset";
|
|
25
|
-
const name = ["id"];
|
|
26
|
-
if (tagName === "meta")
|
|
27
|
-
name.push(...["name", "property", "http-equiv"]);
|
|
28
|
-
for (const n of name) {
|
|
29
|
-
if (typeof props[n] !== "undefined") {
|
|
30
|
-
const val = String(props[n]);
|
|
31
|
-
if (fn && !fn(val))
|
|
32
|
-
return false;
|
|
33
|
-
return `${tagName}:${n}:${val}`;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const setAttrs = (ctx, markSideEffect) => {
|
|
40
|
-
const { tag, $el } = ctx;
|
|
41
|
-
if (!$el)
|
|
42
|
-
return;
|
|
43
|
-
Object.entries(tag.props).forEach(([k, value]) => {
|
|
44
|
-
value = String(value);
|
|
45
|
-
const attrSdeKey = `attr:${k}`;
|
|
46
|
-
if (k === "class") {
|
|
47
|
-
if (!value)
|
|
48
|
-
return;
|
|
49
|
-
for (const c of value.split(" ")) {
|
|
50
|
-
const classSdeKey = `${attrSdeKey}:${c}`;
|
|
51
|
-
if (markSideEffect)
|
|
52
|
-
markSideEffect(ctx, classSdeKey, () => $el.classList.remove(c));
|
|
53
|
-
if (!$el.classList.contains(c))
|
|
54
|
-
$el.classList.add(c);
|
|
55
|
-
}
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (markSideEffect && !k.startsWith("data-h-"))
|
|
59
|
-
markSideEffect(ctx, attrSdeKey, () => $el.removeAttribute(k));
|
|
60
|
-
if ($el.getAttribute(k) !== value)
|
|
61
|
-
$el.setAttribute(k, value);
|
|
62
|
-
});
|
|
63
|
-
if (TagsWithInnerContent.includes(tag.tag) && $el.innerHTML !== (tag.children || ""))
|
|
64
|
-
$el.innerHTML = tag.children || "";
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
function hashCode(s) {
|
|
68
|
-
let h = 9;
|
|
69
|
-
for (let i = 0; i < s.length; )
|
|
70
|
-
h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
|
|
71
|
-
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function renderDOMHead(head, options = {}) {
|
|
75
|
-
const ctx = { shouldRender: true };
|
|
76
|
-
await head.hooks.callHook("dom:beforeRender", ctx);
|
|
77
|
-
if (!ctx.shouldRender)
|
|
78
|
-
return;
|
|
79
|
-
const dom = options.document || window.document;
|
|
80
|
-
const staleSideEffects = head._popSideEffectQueue();
|
|
81
|
-
head.headEntries().map((entry) => entry._sde).forEach((sde) => {
|
|
82
|
-
Object.entries(sde).forEach(([key, fn]) => {
|
|
83
|
-
staleSideEffects[key] = fn;
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
const preRenderTag = async (tag) => {
|
|
87
|
-
const entry = head.headEntries().find((e) => e._i === tag._e);
|
|
88
|
-
const renderCtx = {
|
|
89
|
-
renderId: tag._d || hashCode(JSON.stringify({ ...tag, _e: void 0, _p: void 0 })),
|
|
90
|
-
$el: null,
|
|
91
|
-
shouldRender: true,
|
|
92
|
-
tag,
|
|
93
|
-
entry,
|
|
94
|
-
staleSideEffects
|
|
95
|
-
};
|
|
96
|
-
await head.hooks.callHook("dom:beforeRenderTag", renderCtx);
|
|
97
|
-
return renderCtx;
|
|
98
|
-
};
|
|
99
|
-
const renders = [];
|
|
100
|
-
const pendingRenders = {
|
|
101
|
-
body: [],
|
|
102
|
-
head: []
|
|
103
|
-
};
|
|
104
|
-
const markSideEffect = (ctx2, key, fn) => {
|
|
105
|
-
key = `${ctx2.renderId}:${key}`;
|
|
106
|
-
if (ctx2.entry)
|
|
107
|
-
ctx2.entry._sde[key] = fn;
|
|
108
|
-
delete staleSideEffects[key];
|
|
109
|
-
};
|
|
110
|
-
const markEl = (ctx2) => {
|
|
111
|
-
head._elMap[ctx2.renderId] = ctx2.$el;
|
|
112
|
-
renders.push(ctx2);
|
|
113
|
-
markSideEffect(ctx2, "el", () => {
|
|
114
|
-
ctx2.$el?.remove();
|
|
115
|
-
delete head._elMap[ctx2.renderId];
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
for (const t of await head.resolveTags()) {
|
|
119
|
-
const ctx2 = await preRenderTag(t);
|
|
120
|
-
if (!ctx2.shouldRender)
|
|
121
|
-
continue;
|
|
122
|
-
const { tag } = ctx2;
|
|
123
|
-
if (tag.tag === "title") {
|
|
124
|
-
dom.title = tag.children || "";
|
|
125
|
-
renders.push(ctx2);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs") {
|
|
129
|
-
ctx2.$el = dom[tag.tag === "htmlAttrs" ? "documentElement" : "body"];
|
|
130
|
-
setAttrs(ctx2, markSideEffect);
|
|
131
|
-
renders.push(ctx2);
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
ctx2.$el = head._elMap[ctx2.renderId];
|
|
135
|
-
if (!ctx2.$el && tag._hash) {
|
|
136
|
-
ctx2.$el = dom.querySelector(`${tag.tagPosition?.startsWith("body") ? "body" : "head"} > ${tag.tag}[data-h-${tag._hash}]`);
|
|
137
|
-
}
|
|
138
|
-
if (ctx2.$el) {
|
|
139
|
-
if (ctx2.tag._d)
|
|
140
|
-
setAttrs(ctx2);
|
|
141
|
-
markEl(ctx2);
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
ctx2.$el = dom.createElement(tag.tag);
|
|
145
|
-
setAttrs(ctx2);
|
|
146
|
-
pendingRenders[tag.tagPosition?.startsWith("body") ? "body" : "head"].push(ctx2);
|
|
147
|
-
}
|
|
148
|
-
Object.entries(pendingRenders).forEach(([pos, queue]) => {
|
|
149
|
-
if (!queue.length)
|
|
150
|
-
return;
|
|
151
|
-
const children = dom?.[pos]?.children;
|
|
152
|
-
if (!children)
|
|
153
|
-
return;
|
|
154
|
-
for (const $el of [...children].reverse()) {
|
|
155
|
-
const elTag = $el.tagName.toLowerCase();
|
|
156
|
-
if (!HasElementTags$1.includes(elTag))
|
|
157
|
-
continue;
|
|
158
|
-
const dedupeKey = tagDedupeKey$1({
|
|
159
|
-
tag: elTag,
|
|
160
|
-
// convert attributes to object
|
|
161
|
-
props: $el.getAttributeNames().reduce((props, name) => ({ ...props, [name]: $el.getAttribute(name) }), {})
|
|
162
|
-
});
|
|
163
|
-
const matchIdx = queue.findIndex((ctx2) => ctx2 && (ctx2.tag._d === dedupeKey || $el.isEqualNode?.(ctx2.$el)));
|
|
164
|
-
if (matchIdx !== -1) {
|
|
165
|
-
const ctx2 = queue[matchIdx];
|
|
166
|
-
ctx2.$el = $el;
|
|
167
|
-
setAttrs(ctx2);
|
|
168
|
-
markEl(ctx2);
|
|
169
|
-
delete queue[matchIdx];
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
queue.forEach((ctx2) => {
|
|
173
|
-
if (!ctx2.$el)
|
|
174
|
-
return;
|
|
175
|
-
switch (ctx2.tag.tagPosition) {
|
|
176
|
-
case "bodyClose":
|
|
177
|
-
dom.body.appendChild(ctx2.$el);
|
|
178
|
-
break;
|
|
179
|
-
case "bodyOpen":
|
|
180
|
-
dom.body.insertBefore(ctx2.$el, dom.body.firstChild);
|
|
181
|
-
break;
|
|
182
|
-
case "head":
|
|
183
|
-
default:
|
|
184
|
-
dom.head.appendChild(ctx2.$el);
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
markEl(ctx2);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
for (const ctx2 of renders)
|
|
191
|
-
await head.hooks.callHook("dom:renderTag", ctx2);
|
|
192
|
-
Object.values(staleSideEffects).forEach((fn) => fn());
|
|
193
|
-
}
|
|
194
|
-
let domUpdatePromise = null;
|
|
195
|
-
async function debouncedRenderDOMHead(head, options = {}) {
|
|
196
|
-
function doDomUpdate() {
|
|
197
|
-
domUpdatePromise = null;
|
|
198
|
-
return renderDOMHead(head, options);
|
|
199
|
-
}
|
|
200
|
-
const delayFn = options.delayFn || ((fn) => setTimeout(fn, 10));
|
|
201
|
-
return domUpdatePromise = domUpdatePromise || new Promise((resolve) => delayFn(() => resolve(doDomUpdate())));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const index = {
|
|
205
|
-
__proto__: null,
|
|
206
|
-
debouncedRenderDOMHead: debouncedRenderDOMHead,
|
|
207
|
-
get domUpdatePromise () { return domUpdatePromise; },
|
|
208
|
-
hashCode: hashCode,
|
|
209
|
-
renderDOMHead: renderDOMHead
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const ValidHeadTags = [
|
|
213
|
-
"title",
|
|
214
|
-
"titleTemplate",
|
|
215
|
-
"base",
|
|
216
|
-
"htmlAttrs",
|
|
217
|
-
"bodyAttrs",
|
|
218
|
-
"meta",
|
|
219
|
-
"link",
|
|
220
|
-
"style",
|
|
221
|
-
"script",
|
|
222
|
-
"noscript"
|
|
223
|
-
];
|
|
224
|
-
const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"];
|
|
225
|
-
|
|
226
|
-
async function normaliseTag(tagName, input) {
|
|
227
|
-
const tag = { tag: tagName, props: {} };
|
|
228
|
-
if (tagName === "title" || tagName === "titleTemplate") {
|
|
229
|
-
tag.children = input instanceof Promise ? await input : input;
|
|
230
|
-
return tag;
|
|
231
|
-
}
|
|
232
|
-
tag.props = await normaliseProps({ ...input });
|
|
233
|
-
["children", "innerHtml", "innerHTML"].forEach((key) => {
|
|
234
|
-
if (typeof tag.props[key] !== "undefined") {
|
|
235
|
-
tag.children = tag.props[key];
|
|
236
|
-
if (typeof tag.children === "object")
|
|
237
|
-
tag.children = JSON.stringify(tag.children);
|
|
238
|
-
delete tag.props[key];
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => {
|
|
242
|
-
tag[k] = tag.props[k];
|
|
243
|
-
delete tag.props[k];
|
|
244
|
-
});
|
|
245
|
-
if (typeof tag.props.class === "object" && !Array.isArray(tag.props.class)) {
|
|
246
|
-
tag.props.class = Object.keys(tag.props.class).filter((k) => tag.props.class[k]);
|
|
247
|
-
}
|
|
248
|
-
if (Array.isArray(tag.props.class))
|
|
249
|
-
tag.props.class = tag.props.class.join(" ");
|
|
250
|
-
if (tag.props.content && Array.isArray(tag.props.content)) {
|
|
251
|
-
return tag.props.content.map((v, i) => {
|
|
252
|
-
const newTag = { ...tag, props: { ...tag.props } };
|
|
253
|
-
newTag.props.content = v;
|
|
254
|
-
newTag.key = `${tag.props.name || tag.props.property}:${i}`;
|
|
255
|
-
return newTag;
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
return tag;
|
|
259
|
-
}
|
|
260
|
-
async function normaliseProps(props) {
|
|
261
|
-
for (const k of Object.keys(props)) {
|
|
262
|
-
if (props[k] instanceof Promise) {
|
|
263
|
-
props[k] = await props[k];
|
|
264
|
-
}
|
|
265
|
-
if (String(props[k]) === "true") {
|
|
266
|
-
props[k] = "";
|
|
267
|
-
} else if (String(props[k]) === "false") {
|
|
268
|
-
delete props[k];
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return props;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const tagWeight = (tag) => {
|
|
275
|
-
if (typeof tag.tagPriority === "number")
|
|
276
|
-
return tag.tagPriority;
|
|
277
|
-
switch (tag.tagPriority) {
|
|
278
|
-
case "critical":
|
|
279
|
-
return 2;
|
|
280
|
-
case "high":
|
|
281
|
-
return 9;
|
|
282
|
-
case "low":
|
|
283
|
-
return 12;
|
|
284
|
-
}
|
|
285
|
-
switch (tag.tag) {
|
|
286
|
-
case "base":
|
|
287
|
-
return -1;
|
|
288
|
-
case "title":
|
|
289
|
-
return 1;
|
|
290
|
-
case "meta":
|
|
291
|
-
if (tag.props.charset)
|
|
292
|
-
return -2;
|
|
293
|
-
if (tag.props["http-equiv"] === "content-security-policy")
|
|
294
|
-
return 0;
|
|
295
|
-
return 10;
|
|
296
|
-
default:
|
|
297
|
-
return 10;
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
const sortTags = (aTag, bTag) => {
|
|
301
|
-
return tagWeight(aTag) - tagWeight(bTag);
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
|
|
305
|
-
function tagDedupeKey(tag, fn) {
|
|
306
|
-
const { props, tag: tagName } = tag;
|
|
307
|
-
if (UniqueTags.includes(tagName))
|
|
308
|
-
return tagName;
|
|
309
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
310
|
-
return "canonical";
|
|
311
|
-
if (props.charset)
|
|
312
|
-
return "charset";
|
|
313
|
-
const name = ["id"];
|
|
314
|
-
if (tagName === "meta")
|
|
315
|
-
name.push(...["name", "property", "http-equiv"]);
|
|
316
|
-
for (const n of name) {
|
|
317
|
-
if (typeof props[n] !== "undefined") {
|
|
318
|
-
const val = String(props[n]);
|
|
319
|
-
if (fn && !fn(val))
|
|
320
|
-
return false;
|
|
321
|
-
return `${tagName}:${n}:${val}`;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const renderTitleTemplate = (template, title) => {
|
|
328
|
-
if (template == null)
|
|
329
|
-
return title || null;
|
|
330
|
-
if (typeof template === "function")
|
|
331
|
-
return template(title);
|
|
332
|
-
return template.replace("%s", title ?? "");
|
|
333
|
-
};
|
|
334
|
-
function resolveTitleTemplateFromTags(tags) {
|
|
335
|
-
let titleTemplateIdx = tags.findIndex((i) => i.tag === "titleTemplate");
|
|
336
|
-
const titleIdx = tags.findIndex((i) => i.tag === "title");
|
|
337
|
-
if (titleIdx !== -1 && titleTemplateIdx !== -1) {
|
|
338
|
-
const newTitle = renderTitleTemplate(
|
|
339
|
-
tags[titleTemplateIdx].children,
|
|
340
|
-
tags[titleIdx].children
|
|
341
|
-
);
|
|
342
|
-
if (newTitle !== null) {
|
|
343
|
-
tags[titleIdx].children = newTitle || tags[titleIdx].children;
|
|
344
|
-
} else {
|
|
345
|
-
delete tags[titleIdx];
|
|
346
|
-
}
|
|
347
|
-
} else if (titleTemplateIdx !== -1) {
|
|
348
|
-
const newTitle = renderTitleTemplate(
|
|
349
|
-
tags[titleTemplateIdx].children
|
|
350
|
-
);
|
|
351
|
-
if (newTitle !== null) {
|
|
352
|
-
tags[titleTemplateIdx].children = newTitle;
|
|
353
|
-
tags[titleTemplateIdx].tag = "title";
|
|
354
|
-
titleTemplateIdx = -1;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
if (titleTemplateIdx !== -1) {
|
|
358
|
-
delete tags[titleTemplateIdx];
|
|
359
|
-
}
|
|
360
|
-
return tags.filter(Boolean);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const DedupesTagsPlugin = (options) => {
|
|
364
|
-
options = options || {};
|
|
365
|
-
const dedupeKeys = options.dedupeKeys || ["hid", "vmid", "key"];
|
|
366
|
-
return defineHeadPlugin({
|
|
367
|
-
hooks: {
|
|
368
|
-
"tag:normalise": function({ tag }) {
|
|
369
|
-
dedupeKeys.forEach((key) => {
|
|
370
|
-
if (tag.props[key]) {
|
|
371
|
-
tag.key = tag.props[key];
|
|
372
|
-
delete tag.props[key];
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
const dedupe = tag.key ? `${tag.tag}:${tag.key}` : tagDedupeKey(tag);
|
|
376
|
-
if (dedupe)
|
|
377
|
-
tag._d = dedupe;
|
|
378
|
-
},
|
|
379
|
-
"tags:resolve": function(ctx) {
|
|
380
|
-
const deduping = {};
|
|
381
|
-
ctx.tags.forEach((tag) => {
|
|
382
|
-
let dedupeKey = tag._d || tag._p;
|
|
383
|
-
const dupedTag = deduping[dedupeKey];
|
|
384
|
-
if (dupedTag) {
|
|
385
|
-
let strategy = tag?.tagDuplicateStrategy;
|
|
386
|
-
if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"))
|
|
387
|
-
strategy = "merge";
|
|
388
|
-
if (strategy === "merge") {
|
|
389
|
-
const oldProps = dupedTag.props;
|
|
390
|
-
["class", "style"].forEach((key) => {
|
|
391
|
-
if (tag.props[key] && oldProps[key]) {
|
|
392
|
-
if (key === "style" && !oldProps[key].endsWith(";"))
|
|
393
|
-
oldProps[key] += ";";
|
|
394
|
-
tag.props[key] = `${oldProps[key]} ${tag.props[key]}`;
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
deduping[dedupeKey].props = {
|
|
398
|
-
...oldProps,
|
|
399
|
-
...tag.props
|
|
400
|
-
};
|
|
401
|
-
return;
|
|
402
|
-
} else if (tag._e === dupedTag._e) {
|
|
403
|
-
dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
|
|
404
|
-
}
|
|
405
|
-
const propCount = Object.keys(tag.props).length;
|
|
406
|
-
if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
|
|
407
|
-
delete deduping[dedupeKey];
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
deduping[dedupeKey] = tag;
|
|
412
|
-
});
|
|
413
|
-
ctx.tags = Object.values(deduping);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
const SortTagsPlugin = () => {
|
|
420
|
-
return defineHeadPlugin({
|
|
421
|
-
hooks: {
|
|
422
|
-
"tags:resolve": (ctx) => {
|
|
423
|
-
const tagIndexForKey = (key) => ctx.tags.find((tag) => tag._d === key)?._p;
|
|
424
|
-
for (const tag of ctx.tags) {
|
|
425
|
-
if (!tag.tagPriority || typeof tag.tagPriority === "number")
|
|
426
|
-
continue;
|
|
427
|
-
const modifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
428
|
-
for (const { prefix, offset } of modifiers) {
|
|
429
|
-
if (tag.tagPriority.startsWith(prefix)) {
|
|
430
|
-
const key = tag.tagPriority.replace(prefix, "");
|
|
431
|
-
const index = tagIndexForKey(key);
|
|
432
|
-
if (typeof index !== "undefined")
|
|
433
|
-
tag._p = index + offset;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
ctx.tags.sort((a, b) => a._p - b._p).sort(sortTags);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
const TitleTemplatePlugin = () => {
|
|
444
|
-
return defineHeadPlugin({
|
|
445
|
-
hooks: {
|
|
446
|
-
"tags:resolve": (ctx) => {
|
|
447
|
-
ctx.tags = resolveTitleTemplateFromTags(ctx.tags);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
const DeprecatedTagAttrPlugin = () => {
|
|
454
|
-
return defineHeadPlugin({
|
|
455
|
-
hooks: {
|
|
456
|
-
"tag:normalise": function({ tag }) {
|
|
457
|
-
if (typeof tag.props.body !== "undefined") {
|
|
458
|
-
tag.tagPosition = "bodyClose";
|
|
459
|
-
delete tag.props.body;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
const IsBrowser$1 = typeof window !== "undefined";
|
|
467
|
-
|
|
468
|
-
const ProvideTagHashPlugin = () => {
|
|
469
|
-
return defineHeadPlugin({
|
|
470
|
-
hooks: {
|
|
471
|
-
"tag:normalise": (ctx) => {
|
|
472
|
-
const { tag, entry } = ctx;
|
|
473
|
-
const isDynamic = typeof tag.props._dynamic !== "undefined";
|
|
474
|
-
if (!HasElementTags.includes(tag.tag) || !tag.key)
|
|
475
|
-
return;
|
|
476
|
-
tag._hash = hashCode(JSON.stringify({ tag: tag.tag, key: tag.key }));
|
|
477
|
-
if (IsBrowser$1 || getActiveHead()?.resolvedOptions?.document)
|
|
478
|
-
return;
|
|
479
|
-
if (entry._m === "server" || isDynamic) {
|
|
480
|
-
tag.props[`data-h-${tag._hash}`] = "";
|
|
481
|
-
}
|
|
482
|
-
},
|
|
483
|
-
"tags:resolve": (ctx) => {
|
|
484
|
-
ctx.tags = ctx.tags.map((t) => {
|
|
485
|
-
delete t.props._dynamic;
|
|
486
|
-
return t;
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
});
|
|
491
|
-
};
|
|
492
|
-
|
|
493
|
-
const PatchDomOnEntryUpdatesPlugin = (options) => {
|
|
494
|
-
return defineHeadPlugin({
|
|
495
|
-
hooks: {
|
|
496
|
-
"entries:updated": function(head) {
|
|
497
|
-
if (typeof options?.document === "undefined" && typeof window === "undefined")
|
|
498
|
-
return;
|
|
499
|
-
let delayFn = options?.delayFn;
|
|
500
|
-
if (!delayFn && typeof requestAnimationFrame !== "undefined")
|
|
501
|
-
delayFn = requestAnimationFrame;
|
|
502
|
-
Promise.resolve().then(function () { return index; }).then(({ debouncedRenderDOMHead }) => {
|
|
503
|
-
debouncedRenderDOMHead(head, { document: options?.document || window.document, delayFn });
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
};
|
|
509
|
-
|
|
510
|
-
const EventHandlersPlugin = () => {
|
|
511
|
-
const stripEventHandlers = (mode, tag) => {
|
|
512
|
-
const props = {};
|
|
513
|
-
const eventHandlers = {};
|
|
514
|
-
Object.entries(tag.props).forEach(([key, value]) => {
|
|
515
|
-
if (key.startsWith("on") && typeof value === "function")
|
|
516
|
-
eventHandlers[key] = value;
|
|
517
|
-
else
|
|
518
|
-
props[key] = value;
|
|
519
|
-
});
|
|
520
|
-
let delayedSrc;
|
|
521
|
-
if (mode === "dom" && tag.tag === "script" && typeof props.src === "string" && typeof eventHandlers.onload !== "undefined") {
|
|
522
|
-
delayedSrc = props.src;
|
|
523
|
-
delete props.src;
|
|
524
|
-
}
|
|
525
|
-
return { props, eventHandlers, delayedSrc };
|
|
526
|
-
};
|
|
527
|
-
return defineHeadPlugin({
|
|
528
|
-
hooks: {
|
|
529
|
-
"ssr:render": function(ctx) {
|
|
530
|
-
ctx.tags = ctx.tags.map((tag) => {
|
|
531
|
-
tag.props = stripEventHandlers("ssr", tag).props;
|
|
532
|
-
return tag;
|
|
533
|
-
});
|
|
534
|
-
},
|
|
535
|
-
"dom:beforeRenderTag": function(ctx) {
|
|
536
|
-
const { props, eventHandlers, delayedSrc } = stripEventHandlers("dom", ctx.tag);
|
|
537
|
-
if (!Object.keys(eventHandlers).length)
|
|
538
|
-
return;
|
|
539
|
-
ctx.tag.props = props;
|
|
540
|
-
ctx.tag._eventHandlers = eventHandlers;
|
|
541
|
-
ctx.tag._delayedSrc = delayedSrc;
|
|
542
|
-
},
|
|
543
|
-
"dom:renderTag": function(ctx) {
|
|
544
|
-
const $el = ctx.$el;
|
|
545
|
-
if (!ctx.tag._eventHandlers || !$el)
|
|
546
|
-
return;
|
|
547
|
-
const $eventListenerTarget = ctx.tag.tag === "bodyAttrs" && typeof window !== "undefined" ? window : $el;
|
|
548
|
-
Object.entries(ctx.tag._eventHandlers).forEach(([k, value]) => {
|
|
549
|
-
const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
|
|
550
|
-
const eventName = k.slice(2).toLowerCase();
|
|
551
|
-
const eventDedupeKey = `data-h-${eventName}`;
|
|
552
|
-
delete ctx.staleSideEffects[sdeKey];
|
|
553
|
-
if ($el.hasAttribute(eventDedupeKey))
|
|
554
|
-
return;
|
|
555
|
-
const handler = value;
|
|
556
|
-
$el.setAttribute(eventDedupeKey, "");
|
|
557
|
-
$eventListenerTarget.addEventListener(eventName, handler);
|
|
558
|
-
if (ctx.entry) {
|
|
559
|
-
ctx.entry._sde[sdeKey] = () => {
|
|
560
|
-
$eventListenerTarget.removeEventListener(eventName, handler);
|
|
561
|
-
$el.removeAttribute(eventDedupeKey);
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
if (ctx.tag._delayedSrc) {
|
|
566
|
-
$el.setAttribute("src", ctx.tag._delayedSrc);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
function asArray$1(value) {
|
|
574
|
-
return Array.isArray(value) ? value : [value];
|
|
575
|
-
}
|
|
576
|
-
const HasElementTags = [
|
|
577
|
-
"base",
|
|
578
|
-
"meta",
|
|
579
|
-
"link",
|
|
580
|
-
"style",
|
|
581
|
-
"script",
|
|
582
|
-
"noscript"
|
|
583
|
-
];
|
|
584
|
-
|
|
585
|
-
let activeHead;
|
|
586
|
-
const setActiveHead = (head) => activeHead = head;
|
|
587
|
-
const getActiveHead = () => activeHead;
|
|
588
|
-
|
|
589
|
-
const TagEntityBits = 10;
|
|
590
|
-
|
|
591
|
-
async function normaliseEntryTags(e) {
|
|
592
|
-
const tagPromises = [];
|
|
593
|
-
Object.entries(e.resolvedInput || e.input).filter(([k, v]) => typeof v !== "undefined" && ValidHeadTags.includes(k)).forEach(([k, value]) => {
|
|
594
|
-
const v = asArray$1(value);
|
|
595
|
-
tagPromises.push(...v.map((props) => normaliseTag(k, props)).flat());
|
|
596
|
-
});
|
|
597
|
-
return (await Promise.all(tagPromises)).flat().map((t, i) => {
|
|
598
|
-
t._e = e._i;
|
|
599
|
-
t._p = (e._i << TagEntityBits) + i;
|
|
600
|
-
return t;
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
const CorePlugins = () => [
|
|
605
|
-
// dedupe needs to come first
|
|
606
|
-
DedupesTagsPlugin(),
|
|
607
|
-
SortTagsPlugin(),
|
|
608
|
-
TitleTemplatePlugin(),
|
|
609
|
-
ProvideTagHashPlugin(),
|
|
610
|
-
EventHandlersPlugin(),
|
|
611
|
-
DeprecatedTagAttrPlugin()
|
|
612
|
-
];
|
|
613
|
-
const DOMPlugins = (options = {}) => [
|
|
614
|
-
PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn })
|
|
615
|
-
];
|
|
616
|
-
function createHead$1(options = {}) {
|
|
617
|
-
const head = createHeadCore({
|
|
618
|
-
...options,
|
|
619
|
-
plugins: [...DOMPlugins(options), ...options?.plugins || []]
|
|
620
|
-
});
|
|
621
|
-
setActiveHead(head);
|
|
622
|
-
return head;
|
|
623
|
-
}
|
|
624
|
-
function createHeadCore(options = {}) {
|
|
625
|
-
let entries = [];
|
|
626
|
-
let _sde = {};
|
|
627
|
-
let _eid = 0;
|
|
628
|
-
const hooks = hookable.createHooks();
|
|
629
|
-
if (options?.hooks)
|
|
630
|
-
hooks.addHooks(options.hooks);
|
|
631
|
-
options.plugins = [
|
|
632
|
-
...CorePlugins(),
|
|
633
|
-
...options?.plugins || []
|
|
634
|
-
];
|
|
635
|
-
options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
|
|
636
|
-
const updated = () => hooks.callHook("entries:updated", head);
|
|
637
|
-
const head = {
|
|
638
|
-
resolvedOptions: options,
|
|
639
|
-
headEntries() {
|
|
640
|
-
return entries;
|
|
641
|
-
},
|
|
642
|
-
get hooks() {
|
|
643
|
-
return hooks;
|
|
644
|
-
},
|
|
645
|
-
use(plugin) {
|
|
646
|
-
if (plugin.hooks)
|
|
647
|
-
hooks.addHooks(plugin.hooks);
|
|
648
|
-
},
|
|
649
|
-
push(input, options2) {
|
|
650
|
-
const activeEntry = {
|
|
651
|
-
_i: _eid++,
|
|
652
|
-
input,
|
|
653
|
-
_sde: {}
|
|
654
|
-
};
|
|
655
|
-
if (options2?.mode)
|
|
656
|
-
activeEntry._m = options2?.mode;
|
|
657
|
-
entries.push(activeEntry);
|
|
658
|
-
updated();
|
|
659
|
-
return {
|
|
660
|
-
dispose() {
|
|
661
|
-
entries = entries.filter((e) => {
|
|
662
|
-
if (e._i !== activeEntry._i)
|
|
663
|
-
return true;
|
|
664
|
-
_sde = { ..._sde, ...e._sde || {} };
|
|
665
|
-
e._sde = {};
|
|
666
|
-
updated();
|
|
667
|
-
return false;
|
|
668
|
-
});
|
|
669
|
-
},
|
|
670
|
-
// a patch is the same as creating a new entry, just a nice DX
|
|
671
|
-
patch(input2) {
|
|
672
|
-
entries = entries.map((e) => {
|
|
673
|
-
if (e._i === activeEntry._i) {
|
|
674
|
-
activeEntry.input = e.input = input2;
|
|
675
|
-
updated();
|
|
676
|
-
}
|
|
677
|
-
return e;
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
},
|
|
682
|
-
async resolveTags() {
|
|
683
|
-
const resolveCtx = { tags: [], entries: [...entries] };
|
|
684
|
-
await hooks.callHook("entries:resolve", resolveCtx);
|
|
685
|
-
for (const entry of resolveCtx.entries) {
|
|
686
|
-
for (const tag of await normaliseEntryTags(entry)) {
|
|
687
|
-
const tagCtx = { tag, entry };
|
|
688
|
-
await hooks.callHook("tag:normalise", tagCtx);
|
|
689
|
-
resolveCtx.tags.push(tagCtx.tag);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
await hooks.callHook("tags:resolve", resolveCtx);
|
|
693
|
-
return resolveCtx.tags;
|
|
694
|
-
},
|
|
695
|
-
_elMap: {},
|
|
696
|
-
_popSideEffectQueue() {
|
|
697
|
-
const sde = { ..._sde };
|
|
698
|
-
_sde = {};
|
|
699
|
-
return sde;
|
|
700
|
-
}
|
|
701
|
-
};
|
|
702
|
-
head.hooks.callHook("init", head);
|
|
703
|
-
return head;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
function defineHeadPlugin(plugin) {
|
|
707
|
-
return plugin;
|
|
708
|
-
}
|
|
709
|
-
const composableNames = [
|
|
710
|
-
"useHead",
|
|
711
|
-
"useTagTitle",
|
|
712
|
-
"useTagBase",
|
|
713
|
-
"useTagMeta",
|
|
714
|
-
"useTagMetaFlat",
|
|
715
|
-
// alias
|
|
716
|
-
"useSeoMeta",
|
|
717
|
-
"useTagLink",
|
|
718
|
-
"useTagScript",
|
|
719
|
-
"useTagStyle",
|
|
720
|
-
"useTagNoscript",
|
|
721
|
-
"useHtmlAttrs",
|
|
722
|
-
"useBodyAttrs",
|
|
723
|
-
"useTitleTemplate",
|
|
724
|
-
// server only composables
|
|
725
|
-
"useServerHead",
|
|
726
|
-
"useServerTagTitle",
|
|
727
|
-
"useServerTagBase",
|
|
728
|
-
"useServerTagMeta",
|
|
729
|
-
"useServerTagMetaFlat",
|
|
730
|
-
"useServerTagLink",
|
|
731
|
-
"useServerTagScript",
|
|
732
|
-
"useServerTagStyle",
|
|
733
|
-
"useServerTagNoscript",
|
|
734
|
-
"useServerHtmlAttrs",
|
|
735
|
-
"useServerBodyAttrs",
|
|
736
|
-
"useServerTitleTemplate"
|
|
737
|
-
];
|
|
5
|
+
const shared = require('@unhead/shared');
|
|
738
6
|
|
|
739
7
|
function resolveUnref(r) {
|
|
740
8
|
return typeof r === "function" ? r() : vue.unref(r);
|
|
@@ -758,25 +26,22 @@ function resolveUnrefHeadInput(ref, lastKey = "") {
|
|
|
758
26
|
return [k, resolveUnrefHeadInput(v, k)];
|
|
759
27
|
})
|
|
760
28
|
);
|
|
761
|
-
if (dynamic && HasElementTags.includes(String(lastKey)))
|
|
29
|
+
if (dynamic && shared.HasElementTags.includes(String(lastKey)))
|
|
762
30
|
unrefdObj._dynamic = true;
|
|
763
31
|
return unrefdObj;
|
|
764
32
|
}
|
|
765
33
|
return root;
|
|
766
34
|
}
|
|
767
|
-
function asArray(value) {
|
|
768
|
-
return Array.isArray(value) ? value : [value];
|
|
769
|
-
}
|
|
770
35
|
|
|
771
36
|
const Vue3 = vue.version.startsWith("3");
|
|
772
37
|
const IsBrowser = typeof window !== "undefined";
|
|
773
38
|
|
|
774
39
|
const headSymbol = "usehead";
|
|
775
40
|
function injectHead() {
|
|
776
|
-
return vue.getCurrentInstance() && vue.inject(headSymbol) || getActiveHead();
|
|
41
|
+
return vue.getCurrentInstance() && vue.inject(headSymbol) || unhead.getActiveHead();
|
|
777
42
|
}
|
|
778
43
|
function createHead(options = {}) {
|
|
779
|
-
const head = createHead
|
|
44
|
+
const head = unhead.createHead({
|
|
780
45
|
...options,
|
|
781
46
|
// arbitrary delay the dom update for batch updates
|
|
782
47
|
domDelayFn: (fn) => setTimeout(() => vue.nextTick(() => fn()), 10),
|
|
@@ -811,7 +76,7 @@ const VueHeadMixin = {
|
|
|
811
76
|
};
|
|
812
77
|
|
|
813
78
|
const VueReactiveUseHeadPlugin = () => {
|
|
814
|
-
return defineHeadPlugin({
|
|
79
|
+
return shared.defineHeadPlugin({
|
|
815
80
|
hooks: {
|
|
816
81
|
"entries:resolve": function(ctx) {
|
|
817
82
|
for (const entry of ctx.entries)
|
|
@@ -841,197 +106,16 @@ const Vue2ProvideUnheadPlugin = function(_Vue, head) {
|
|
|
841
106
|
});
|
|
842
107
|
};
|
|
843
108
|
|
|
844
|
-
function unpackToArray(input, options) {
|
|
845
|
-
const unpacked = [];
|
|
846
|
-
const kFn = options.resolveKeyData || ((ctx) => ctx.key);
|
|
847
|
-
const vFn = options.resolveValueData || ((ctx) => ctx.value);
|
|
848
|
-
for (const [k, v] of Object.entries(input)) {
|
|
849
|
-
unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => {
|
|
850
|
-
const ctx = { key: k, value: i };
|
|
851
|
-
const val = vFn(ctx);
|
|
852
|
-
if (typeof val === "object")
|
|
853
|
-
return unpackToArray(val, options);
|
|
854
|
-
if (Array.isArray(val))
|
|
855
|
-
return val;
|
|
856
|
-
return {
|
|
857
|
-
[typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx),
|
|
858
|
-
[typeof options.value === "function" ? options.value(ctx) : options.value]: val
|
|
859
|
-
};
|
|
860
|
-
}).flat());
|
|
861
|
-
}
|
|
862
|
-
return unpacked;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
function unpackToString(value, options) {
|
|
866
|
-
return Object.entries(value).map(([key, value2]) => {
|
|
867
|
-
if (typeof value2 === "object")
|
|
868
|
-
value2 = unpackToString(value2, options);
|
|
869
|
-
if (options.resolve) {
|
|
870
|
-
const resolved = options.resolve({ key, value: value2 });
|
|
871
|
-
if (resolved)
|
|
872
|
-
return resolved;
|
|
873
|
-
}
|
|
874
|
-
if (typeof value2 === "number")
|
|
875
|
-
value2 = value2.toString();
|
|
876
|
-
if (typeof value2 === "string" && options.wrapValue) {
|
|
877
|
-
value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`);
|
|
878
|
-
value2 = `${options.wrapValue}${value2}${options.wrapValue}`;
|
|
879
|
-
}
|
|
880
|
-
return `${key}${options.keyValueSeparator || ""}${value2}`;
|
|
881
|
-
}).join(options.entrySeparator || "");
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
const MetaPackingSchema = {
|
|
885
|
-
robots: {
|
|
886
|
-
unpack: {
|
|
887
|
-
keyValueSeparator: ":"
|
|
888
|
-
}
|
|
889
|
-
},
|
|
890
|
-
// Pragma directives
|
|
891
|
-
contentSecurityPolicy: {
|
|
892
|
-
unpack: {
|
|
893
|
-
keyValueSeparator: " ",
|
|
894
|
-
entrySeparator: "; "
|
|
895
|
-
},
|
|
896
|
-
metaKey: "http-equiv"
|
|
897
|
-
},
|
|
898
|
-
fbAppId: {
|
|
899
|
-
keyValue: "fb:app_id",
|
|
900
|
-
metaKey: "property"
|
|
901
|
-
},
|
|
902
|
-
msapplicationTileImage: {
|
|
903
|
-
keyValue: "msapplication-TileImage"
|
|
904
|
-
},
|
|
905
|
-
/**
|
|
906
|
-
* Tile colour for windows
|
|
907
|
-
*/
|
|
908
|
-
msapplicationTileColor: {
|
|
909
|
-
keyValue: "msapplication-TileColor"
|
|
910
|
-
},
|
|
911
|
-
/**
|
|
912
|
-
* URL of a config for windows tile.
|
|
913
|
-
*/
|
|
914
|
-
msapplicationConfig: {
|
|
915
|
-
keyValue: "msapplication-Config"
|
|
916
|
-
},
|
|
917
|
-
charset: {
|
|
918
|
-
metaKey: "charset"
|
|
919
|
-
},
|
|
920
|
-
contentType: {
|
|
921
|
-
metaKey: "http-equiv"
|
|
922
|
-
},
|
|
923
|
-
defaultStyle: {
|
|
924
|
-
metaKey: "http-equiv"
|
|
925
|
-
},
|
|
926
|
-
xUaCompatible: {
|
|
927
|
-
metaKey: "http-equiv"
|
|
928
|
-
},
|
|
929
|
-
refresh: {
|
|
930
|
-
metaKey: "http-equiv"
|
|
931
|
-
}
|
|
932
|
-
};
|
|
933
|
-
function resolveMetaKeyType(key) {
|
|
934
|
-
return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name";
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
const ArrayableInputs = ["Image", "Video", "Audio"];
|
|
938
|
-
function unpackMeta(input) {
|
|
939
|
-
const extras = [];
|
|
940
|
-
ArrayableInputs.forEach((key) => {
|
|
941
|
-
const ogKey = `og:${key.toLowerCase()}`;
|
|
942
|
-
const inputKey = `og${key}`;
|
|
943
|
-
const val = input[inputKey];
|
|
944
|
-
if (typeof val === "object") {
|
|
945
|
-
(Array.isArray(val) ? val : [val]).forEach((entry) => {
|
|
946
|
-
if (!entry)
|
|
947
|
-
return;
|
|
948
|
-
const unpackedEntry = unpackToArray(entry, {
|
|
949
|
-
key: "property",
|
|
950
|
-
value: "content",
|
|
951
|
-
resolveKeyData({ key: key2 }) {
|
|
952
|
-
return fixKeyCase(`${ogKey}${key2 !== "url" ? `:${key2}` : ""}`);
|
|
953
|
-
},
|
|
954
|
-
resolveValueData({ value }) {
|
|
955
|
-
return typeof value === "number" ? value.toString() : value;
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
extras.push(
|
|
959
|
-
...unpackedEntry.sort((a, b) => a.property === ogKey ? -1 : b.property === ogKey ? 1 : 0)
|
|
960
|
-
);
|
|
961
|
-
});
|
|
962
|
-
delete input[inputKey];
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
const meta = unpackToArray(input, {
|
|
966
|
-
key({ key }) {
|
|
967
|
-
return resolveMetaKeyType(key);
|
|
968
|
-
},
|
|
969
|
-
value({ key }) {
|
|
970
|
-
return key === "charset" ? "charset" : "content";
|
|
971
|
-
},
|
|
972
|
-
resolveKeyData({ key }) {
|
|
973
|
-
return MetaPackingSchema[key]?.keyValue || fixKeyCase(key);
|
|
974
|
-
},
|
|
975
|
-
resolveValueData({ value, key }) {
|
|
976
|
-
if (value === null)
|
|
977
|
-
return "_null";
|
|
978
|
-
if (typeof value === "object") {
|
|
979
|
-
const definition = MetaPackingSchema[key];
|
|
980
|
-
if (key === "refresh")
|
|
981
|
-
return `${value.seconds};url=${value.url}`;
|
|
982
|
-
return unpackToString(
|
|
983
|
-
changeKeyCasingDeep(value),
|
|
984
|
-
{
|
|
985
|
-
entrySeparator: ", ",
|
|
986
|
-
keyValueSeparator: "=",
|
|
987
|
-
resolve({ value: value2, key: key2 }) {
|
|
988
|
-
if (value2 === null)
|
|
989
|
-
return "";
|
|
990
|
-
if (typeof value2 === "boolean")
|
|
991
|
-
return `${key2}`;
|
|
992
|
-
},
|
|
993
|
-
...definition?.unpack
|
|
994
|
-
}
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
|
-
return typeof value === "number" ? value.toString() : value;
|
|
998
|
-
}
|
|
999
|
-
});
|
|
1000
|
-
return [...extras, ...meta].filter((v) => typeof v.content === "undefined" || v.content !== "_null");
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
const PropertyPrefixKeys = /^(og|fb)/;
|
|
1004
|
-
const ColonPrefixKeys = /^(og|twitter|fb)/;
|
|
1005
|
-
function fixKeyCase(key) {
|
|
1006
|
-
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1007
|
-
if (ColonPrefixKeys.test(key)) {
|
|
1008
|
-
key = key.replace("secure-url", "secure_url").replace(/-/g, ":");
|
|
1009
|
-
}
|
|
1010
|
-
return key;
|
|
1011
|
-
}
|
|
1012
|
-
function changeKeyCasingDeep(input) {
|
|
1013
|
-
if (Array.isArray(input)) {
|
|
1014
|
-
return input.map((entry) => changeKeyCasingDeep(entry));
|
|
1015
|
-
}
|
|
1016
|
-
if (typeof input !== "object" || Array.isArray(input))
|
|
1017
|
-
return input;
|
|
1018
|
-
const output = {};
|
|
1019
|
-
for (const [key, value] of Object.entries(input))
|
|
1020
|
-
output[fixKeyCase(key)] = changeKeyCasingDeep(value);
|
|
1021
|
-
return output;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
109
|
function clientUseHead(input, options = {}) {
|
|
1025
110
|
const head = injectHead();
|
|
1026
111
|
const deactivated = vue.ref(false);
|
|
1027
112
|
const resolvedInput = vue.ref({});
|
|
1028
113
|
vue.watchEffect(() => {
|
|
1029
|
-
resolvedInput.value = resolveUnrefHeadInput(input);
|
|
114
|
+
resolvedInput.value = deactivated.value ? {} : resolveUnrefHeadInput(input);
|
|
1030
115
|
});
|
|
1031
116
|
const entry = head.push(resolvedInput.value, options);
|
|
1032
|
-
vue.watch(
|
|
1033
|
-
|
|
1034
|
-
entry.patch(e);
|
|
117
|
+
vue.watch(resolvedInput, (e) => {
|
|
118
|
+
entry.patch(e);
|
|
1035
119
|
});
|
|
1036
120
|
const vm = vue.getCurrentInstance();
|
|
1037
121
|
if (vm) {
|
|
@@ -1058,18 +142,18 @@ function useServerHead(input, options = {}) {
|
|
|
1058
142
|
}
|
|
1059
143
|
const useServerTagTitle = (title) => useServerHead({ title });
|
|
1060
144
|
const useServerTitleTemplate = (titleTemplate) => useServerHead({ titleTemplate });
|
|
1061
|
-
const useServerTagMeta = (meta) => useServerHead({ meta: asArray(meta) });
|
|
145
|
+
const useServerTagMeta = (meta) => useServerHead({ meta: shared.asArray(meta) });
|
|
1062
146
|
const useServerTagMetaFlat = (meta) => {
|
|
1063
147
|
const input = vue.ref({});
|
|
1064
148
|
vue.watchEffect(() => {
|
|
1065
|
-
input.value = unpackMeta(resolveUnrefHeadInput(meta));
|
|
149
|
+
input.value = unhead.unpackMeta(resolveUnrefHeadInput(meta));
|
|
1066
150
|
});
|
|
1067
151
|
return useServerHead({ meta: input });
|
|
1068
152
|
};
|
|
1069
|
-
const useServerTagLink = (link) => useServerHead({ link: asArray(link) });
|
|
1070
|
-
const useServerTagScript = (script) => useServerHead({ script: asArray(script) });
|
|
1071
|
-
const useServerTagStyle = (style) => useServerHead({ style: asArray(style) });
|
|
1072
|
-
const useServerTagNoscript = (noscript) => useServerHead({ noscript: asArray(noscript) });
|
|
153
|
+
const useServerTagLink = (link) => useServerHead({ link: shared.asArray(link) });
|
|
154
|
+
const useServerTagScript = (script) => useServerHead({ script: shared.asArray(script) });
|
|
155
|
+
const useServerTagStyle = (style) => useServerHead({ style: shared.asArray(style) });
|
|
156
|
+
const useServerTagNoscript = (noscript) => useServerHead({ noscript: shared.asArray(noscript) });
|
|
1073
157
|
const useServerTagBase = (base) => useServerHead({ base });
|
|
1074
158
|
const useServerHtmlAttrs = (attrs) => useServerHead({ htmlAttrs: attrs });
|
|
1075
159
|
const useServerBodyAttrs = (attrs) => useHead({ bodyAttrs: attrs });
|
|
@@ -1082,7 +166,7 @@ const useSeoMeta = (input) => {
|
|
|
1082
166
|
headInput.value = {
|
|
1083
167
|
title,
|
|
1084
168
|
titleTemplate,
|
|
1085
|
-
meta: unpackMeta(meta)
|
|
169
|
+
meta: unhead.unpackMeta(meta)
|
|
1086
170
|
};
|
|
1087
171
|
});
|
|
1088
172
|
return useHead(headInput);
|
|
@@ -1099,18 +183,18 @@ function useHead(input, options = {}) {
|
|
|
1099
183
|
}
|
|
1100
184
|
const useTagTitle = (title) => useHead({ title });
|
|
1101
185
|
const useTitleTemplate = (titleTemplate) => useHead({ titleTemplate });
|
|
1102
|
-
const useTagMeta = (meta) => useHead({ meta: asArray(meta) });
|
|
186
|
+
const useTagMeta = (meta) => useHead({ meta: shared.asArray(meta) });
|
|
1103
187
|
const useTagMetaFlat = (meta) => {
|
|
1104
188
|
const input = vue.ref({});
|
|
1105
189
|
vue.watchEffect(() => {
|
|
1106
|
-
input.value = unpackMeta(resolveUnrefHeadInput(meta));
|
|
190
|
+
input.value = unhead.unpackMeta(resolveUnrefHeadInput(meta));
|
|
1107
191
|
});
|
|
1108
192
|
return useHead({ meta: input });
|
|
1109
193
|
};
|
|
1110
|
-
const useTagLink = (link) => useHead({ link: asArray(link) });
|
|
1111
|
-
const useTagScript = (script) => useHead({ script: asArray(script) });
|
|
1112
|
-
const useTagStyle = (style) => useHead({ style: asArray(style) });
|
|
1113
|
-
const useTagNoscript = (noscript) => useHead({ noscript: asArray(noscript) });
|
|
194
|
+
const useTagLink = (link) => useHead({ link: shared.asArray(link) });
|
|
195
|
+
const useTagScript = (script) => useHead({ script: shared.asArray(script) });
|
|
196
|
+
const useTagStyle = (style) => useHead({ style: shared.asArray(style) });
|
|
197
|
+
const useTagNoscript = (noscript) => useHead({ noscript: shared.asArray(noscript) });
|
|
1114
198
|
const useTagBase = (base) => useHead({ base });
|
|
1115
199
|
const useHtmlAttrs = (attrs) => useHead({ htmlAttrs: attrs });
|
|
1116
200
|
const useBodyAttrs = (attrs) => useHead({ bodyAttrs: attrs });
|
|
@@ -1119,15 +203,14 @@ const coreComposableNames = [
|
|
|
1119
203
|
"injectHead"
|
|
1120
204
|
];
|
|
1121
205
|
const unheadVueComposablesImports = {
|
|
1122
|
-
"@unhead/vue": [...coreComposableNames, ...composableNames]
|
|
206
|
+
"@unhead/vue": [...coreComposableNames, ...unhead.composableNames]
|
|
1123
207
|
};
|
|
1124
208
|
|
|
209
|
+
exports.createHeadCore = unhead.createHeadCore;
|
|
1125
210
|
exports.Vue2ProvideUnheadPlugin = Vue2ProvideUnheadPlugin;
|
|
1126
211
|
exports.VueHeadMixin = VueHeadMixin;
|
|
1127
212
|
exports.VueReactiveUseHeadPlugin = VueReactiveUseHeadPlugin;
|
|
1128
|
-
exports.asArray = asArray;
|
|
1129
213
|
exports.createHead = createHead;
|
|
1130
|
-
exports.createHeadCore = createHeadCore;
|
|
1131
214
|
exports.headSymbol = headSymbol;
|
|
1132
215
|
exports.injectHead = injectHead;
|
|
1133
216
|
exports.resolveUnrefHeadInput = resolveUnrefHeadInput;
|