@unhead/shared 1.9.16 → 1.10.0-beta.1
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 +184 -97
- package/dist/index.d.cts +17 -14
- package/dist/index.d.mts +17 -14
- package/dist/index.d.ts +17 -14
- package/dist/index.mjs +184 -98
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4,17 +4,17 @@ function asArray$1(value) {
|
|
|
4
4
|
return Array.isArray(value) ? value : [value];
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
const SelfClosingTags = ["meta", "link", "base"];
|
|
8
|
-
const TagsWithInnerContent = ["title", "titleTemplate", "script", "style", "noscript"];
|
|
9
|
-
const HasElementTags = [
|
|
7
|
+
const SelfClosingTags = /* @__PURE__ */ new Set(["meta", "link", "base"]);
|
|
8
|
+
const TagsWithInnerContent = /* @__PURE__ */ new Set(["title", "titleTemplate", "script", "style", "noscript"]);
|
|
9
|
+
const HasElementTags = /* @__PURE__ */ new Set([
|
|
10
10
|
"base",
|
|
11
11
|
"meta",
|
|
12
12
|
"link",
|
|
13
13
|
"style",
|
|
14
14
|
"script",
|
|
15
15
|
"noscript"
|
|
16
|
-
];
|
|
17
|
-
const ValidHeadTags = [
|
|
16
|
+
]);
|
|
17
|
+
const ValidHeadTags = /* @__PURE__ */ new Set([
|
|
18
18
|
"title",
|
|
19
19
|
"titleTemplate",
|
|
20
20
|
"templateParams",
|
|
@@ -26,9 +26,9 @@ const ValidHeadTags = [
|
|
|
26
26
|
"style",
|
|
27
27
|
"script",
|
|
28
28
|
"noscript"
|
|
29
|
-
];
|
|
30
|
-
const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"];
|
|
31
|
-
const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "children", "innerHTML", "textContent", "processTemplateParams"];
|
|
29
|
+
]);
|
|
30
|
+
const UniqueTags = /* @__PURE__ */ new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]);
|
|
31
|
+
const TagConfigKeys = /* @__PURE__ */ new Set(["tagPosition", "tagPriority", "tagDuplicateStrategy", "children", "innerHTML", "textContent", "processTemplateParams"]);
|
|
32
32
|
const IsBrowser = typeof window !== "undefined";
|
|
33
33
|
const composableNames = [
|
|
34
34
|
"getActiveHead",
|
|
@@ -51,26 +51,34 @@ function hashCode(s) {
|
|
|
51
51
|
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
|
|
52
52
|
}
|
|
53
53
|
function hashTag(tag) {
|
|
54
|
-
|
|
54
|
+
if (tag._h) {
|
|
55
|
+
return tag._h;
|
|
56
|
+
}
|
|
57
|
+
if (tag._d) {
|
|
58
|
+
return hashCode(tag._d);
|
|
59
|
+
}
|
|
60
|
+
let content = `${tag.tag}:${tag.textContent || tag.innerHTML || ""}:`;
|
|
61
|
+
for (const key in tag.props) {
|
|
62
|
+
content += `${key}:${tag.props[key]},`;
|
|
63
|
+
}
|
|
64
|
+
return hashCode(content);
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
|
|
67
|
+
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
68
|
+
function tagDedupeKey(tag) {
|
|
58
69
|
const { props, tag: tagName } = tag;
|
|
59
|
-
if (UniqueTags.
|
|
70
|
+
if (UniqueTags.has(tagName))
|
|
60
71
|
return tagName;
|
|
61
72
|
if (tagName === "link" && props.rel === "canonical")
|
|
62
73
|
return "canonical";
|
|
63
74
|
if (props.charset)
|
|
64
75
|
return "charset";
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
for (const n of
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
if (fn && !fn(val))
|
|
72
|
-
return false;
|
|
73
|
-
return `${tagName}:${n}:${val}`;
|
|
76
|
+
if (props.id) {
|
|
77
|
+
return `${tagName}:id:${props.id}`;
|
|
78
|
+
}
|
|
79
|
+
for (const n of allowedMetaProperties) {
|
|
80
|
+
if (props[n] !== void 0) {
|
|
81
|
+
return `${tagName}:${n}:${props[n]}`;
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
84
|
return false;
|
|
@@ -252,15 +260,16 @@ const MetaPackingSchema = {
|
|
|
252
260
|
metaKey: "http-equiv"
|
|
253
261
|
}
|
|
254
262
|
};
|
|
255
|
-
const openGraphNamespaces = [
|
|
263
|
+
const openGraphNamespaces = /* @__PURE__ */ new Set([
|
|
256
264
|
"og",
|
|
257
265
|
"book",
|
|
258
266
|
"article",
|
|
259
267
|
"profile"
|
|
260
|
-
];
|
|
268
|
+
]);
|
|
261
269
|
function resolveMetaKeyType(key) {
|
|
262
|
-
const fKey = fixKeyCase(key)
|
|
263
|
-
|
|
270
|
+
const fKey = fixKeyCase(key);
|
|
271
|
+
const prefixIndex = fKey.indexOf(":");
|
|
272
|
+
if (openGraphNamespaces.has(fKey.substring(0, prefixIndex)))
|
|
264
273
|
return "property";
|
|
265
274
|
return MetaPackingSchema[key]?.metaKey || "name";
|
|
266
275
|
}
|
|
@@ -269,8 +278,9 @@ function resolveMetaKeyValue(key) {
|
|
|
269
278
|
}
|
|
270
279
|
function fixKeyCase(key) {
|
|
271
280
|
const updated = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
272
|
-
const
|
|
273
|
-
|
|
281
|
+
const prefixIndex = updated.indexOf("-");
|
|
282
|
+
const fKey = updated.substring(0, prefixIndex);
|
|
283
|
+
if (fKey === "twitter" || openGraphNamespaces.has(fKey))
|
|
274
284
|
return key.replace(/([A-Z])/g, ":$1").toLowerCase();
|
|
275
285
|
return updated;
|
|
276
286
|
}
|
|
@@ -281,8 +291,12 @@ function changeKeyCasingDeep(input) {
|
|
|
281
291
|
if (typeof input !== "object" || Array.isArray(input))
|
|
282
292
|
return input;
|
|
283
293
|
const output = {};
|
|
284
|
-
for (const
|
|
285
|
-
|
|
294
|
+
for (const key in input) {
|
|
295
|
+
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
output[fixKeyCase(key)] = changeKeyCasingDeep(input[key]);
|
|
299
|
+
}
|
|
286
300
|
return output;
|
|
287
301
|
}
|
|
288
302
|
function resolvePackedMetaObjectValue(value, key) {
|
|
@@ -304,24 +318,31 @@ function resolvePackedMetaObjectValue(value, key) {
|
|
|
304
318
|
}
|
|
305
319
|
);
|
|
306
320
|
}
|
|
307
|
-
const ObjectArrayEntries = ["og:image", "og:video", "og:audio", "twitter:image"];
|
|
321
|
+
const ObjectArrayEntries = /* @__PURE__ */ new Set(["og:image", "og:video", "og:audio", "twitter:image"]);
|
|
308
322
|
function sanitize(input) {
|
|
309
323
|
const out = {};
|
|
310
|
-
|
|
324
|
+
for (const k2 in input) {
|
|
325
|
+
if (!Object.prototype.hasOwnProperty.call(input, k2)) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const v = input[k2];
|
|
311
329
|
if (String(v) !== "false" && k2)
|
|
312
330
|
out[k2] = v;
|
|
313
|
-
}
|
|
331
|
+
}
|
|
314
332
|
return out;
|
|
315
333
|
}
|
|
316
334
|
function handleObjectEntry(key, v) {
|
|
317
335
|
const value = sanitize(v);
|
|
318
336
|
const fKey = fixKeyCase(key);
|
|
319
337
|
const attr = resolveMetaKeyType(fKey);
|
|
320
|
-
if (ObjectArrayEntries.
|
|
338
|
+
if (ObjectArrayEntries.has(fKey)) {
|
|
321
339
|
const input = {};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
340
|
+
for (const k2 in value) {
|
|
341
|
+
if (!Object.prototype.hasOwnProperty.call(value, k2)) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
input[`${key}${k2 === "url" ? "" : `${k2[0].toUpperCase()}${k2.slice(1)}`}`] = value[k2];
|
|
345
|
+
}
|
|
325
346
|
return unpackMeta(input).sort((a, b) => (a[attr]?.length || 0) - (b[attr]?.length || 0));
|
|
326
347
|
}
|
|
327
348
|
return [{ [attr]: fKey, ...value }];
|
|
@@ -329,23 +350,27 @@ function handleObjectEntry(key, v) {
|
|
|
329
350
|
function unpackMeta(input) {
|
|
330
351
|
const extras = [];
|
|
331
352
|
const primitives = {};
|
|
332
|
-
|
|
353
|
+
for (const key in input) {
|
|
354
|
+
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
const value = input[key];
|
|
333
358
|
if (!Array.isArray(value)) {
|
|
334
359
|
if (typeof value === "object" && value) {
|
|
335
|
-
if (ObjectArrayEntries.
|
|
360
|
+
if (ObjectArrayEntries.has(fixKeyCase(key))) {
|
|
336
361
|
extras.push(...handleObjectEntry(key, value));
|
|
337
|
-
|
|
362
|
+
continue;
|
|
338
363
|
}
|
|
339
364
|
primitives[key] = sanitize(value);
|
|
340
365
|
} else {
|
|
341
366
|
primitives[key] = value;
|
|
342
367
|
}
|
|
343
|
-
|
|
368
|
+
continue;
|
|
344
369
|
}
|
|
345
|
-
|
|
370
|
+
for (const v of value) {
|
|
346
371
|
extras.push(...typeof v === "string" ? unpackMeta({ [key]: v }) : handleObjectEntry(key, v));
|
|
347
|
-
}
|
|
348
|
-
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
349
374
|
const meta = unpackToArray(primitives, {
|
|
350
375
|
key({ key }) {
|
|
351
376
|
return resolveMetaKeyType(key);
|
|
@@ -437,7 +462,7 @@ function whitelistSafeInput(input) {
|
|
|
437
462
|
const link = acceptDataAttrs(meta);
|
|
438
463
|
WhitelistAttributes.link.forEach((key2) => {
|
|
439
464
|
const val = meta[key2];
|
|
440
|
-
if (key2 === "rel" &&
|
|
465
|
+
if (key2 === "rel" && (val === "stylesheet" || val === "canonical" || val === "modulepreload" || val === "prerender" || val === "preload" || val === "prefetch"))
|
|
441
466
|
return;
|
|
442
467
|
if (key2 === "href") {
|
|
443
468
|
if (val.includes("javascript:") || val.includes("data:"))
|
|
@@ -489,25 +514,36 @@ function whitelistSafeInput(input) {
|
|
|
489
514
|
return filtered;
|
|
490
515
|
}
|
|
491
516
|
|
|
492
|
-
|
|
517
|
+
function thenable(val, thenFn) {
|
|
518
|
+
if (val instanceof Promise) {
|
|
519
|
+
return val.then(thenFn);
|
|
520
|
+
}
|
|
521
|
+
return thenFn(val);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function normaliseTag(tagName, input, e, normalizedProps) {
|
|
525
|
+
const props = normalizedProps || normaliseProps(
|
|
526
|
+
// explicitly check for an object
|
|
527
|
+
// @ts-expect-error untyped
|
|
528
|
+
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
529
|
+
tagName === "templateParams" || tagName === "titleTemplate"
|
|
530
|
+
);
|
|
531
|
+
if (props instanceof Promise) {
|
|
532
|
+
return props.then((val) => normaliseTag(tagName, input, e, val));
|
|
533
|
+
}
|
|
493
534
|
const tag = {
|
|
494
535
|
tag: tagName,
|
|
495
|
-
props
|
|
496
|
-
// explicitly check for an object
|
|
497
|
-
// @ts-expect-error untyped
|
|
498
|
-
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [["script", "noscript", "style"].includes(tagName) ? "innerHTML" : "textContent"]: input },
|
|
499
|
-
["templateParams", "titleTemplate"].includes(tagName)
|
|
500
|
-
)
|
|
536
|
+
props
|
|
501
537
|
};
|
|
502
|
-
|
|
503
|
-
const val =
|
|
504
|
-
if (
|
|
505
|
-
if (!
|
|
538
|
+
for (const k of TagConfigKeys) {
|
|
539
|
+
const val = tag.props[k] !== void 0 ? tag.props[k] : e[k];
|
|
540
|
+
if (val !== void 0) {
|
|
541
|
+
if (!(k === "innerHTML" || k === "textContent" || k === "children") || TagsWithInnerContent.has(tag.tag)) {
|
|
506
542
|
tag[k === "children" ? "innerHTML" : k] = val;
|
|
507
543
|
}
|
|
508
544
|
delete tag.props[k];
|
|
509
545
|
}
|
|
510
|
-
}
|
|
546
|
+
}
|
|
511
547
|
if (tag.props.body) {
|
|
512
548
|
tag.tagPosition = "bodyClose";
|
|
513
549
|
delete tag.props.body;
|
|
@@ -525,17 +561,22 @@ function normaliseStyleClassProps(key, v) {
|
|
|
525
561
|
if (typeof v === "object" && !Array.isArray(v)) {
|
|
526
562
|
v = Object.entries(v).filter(([, v2]) => v2).map(([k, v2]) => key === "style" ? `${k}:${v2}` : k);
|
|
527
563
|
}
|
|
528
|
-
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => c.trim())
|
|
564
|
+
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => Boolean(c.trim())).join(sep);
|
|
529
565
|
}
|
|
530
|
-
|
|
531
|
-
for (
|
|
532
|
-
|
|
566
|
+
function nestedNormaliseProps(props, virtual, keys, startIndex) {
|
|
567
|
+
for (let i = startIndex; i < keys.length; i += 1) {
|
|
568
|
+
const k = keys[i];
|
|
569
|
+
if (k === "class" || k === "style") {
|
|
533
570
|
props[k] = normaliseStyleClassProps(k, props[k]);
|
|
534
571
|
continue;
|
|
535
572
|
}
|
|
536
|
-
if (props[k] instanceof Promise)
|
|
537
|
-
props[k]
|
|
538
|
-
|
|
573
|
+
if (props[k] instanceof Promise) {
|
|
574
|
+
return props[k].then((val) => {
|
|
575
|
+
props[k] = val;
|
|
576
|
+
return nestedNormaliseProps(props, virtual, keys, i);
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
if (!virtual && !TagConfigKeys.has(k)) {
|
|
539
580
|
const v = String(props[k]);
|
|
540
581
|
const isDataKey = k.startsWith("data-");
|
|
541
582
|
if (v === "true" || v === "") {
|
|
@@ -548,21 +589,60 @@ async function normaliseProps(props, virtual) {
|
|
|
548
589
|
}
|
|
549
590
|
}
|
|
550
591
|
}
|
|
592
|
+
}
|
|
593
|
+
function normaliseProps(props, virtual = false) {
|
|
594
|
+
const resolvedProps = nestedNormaliseProps(props, virtual, Object.keys(props), 0);
|
|
595
|
+
if (resolvedProps instanceof Promise) {
|
|
596
|
+
return resolvedProps.then(() => props);
|
|
597
|
+
}
|
|
551
598
|
return props;
|
|
552
599
|
}
|
|
553
600
|
const TagEntityBits = 10;
|
|
554
|
-
|
|
601
|
+
function nestedNormaliseEntryTags(headTags, tagPromises, startIndex) {
|
|
602
|
+
for (let i = startIndex; i < tagPromises.length; i += 1) {
|
|
603
|
+
const tags = tagPromises[i];
|
|
604
|
+
if (tags instanceof Promise) {
|
|
605
|
+
return tags.then((val) => {
|
|
606
|
+
tagPromises[i] = val;
|
|
607
|
+
return nestedNormaliseEntryTags(headTags, tagPromises, i);
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
if (Array.isArray(tags)) {
|
|
611
|
+
headTags.push(...tags);
|
|
612
|
+
} else {
|
|
613
|
+
headTags.push(tags);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
function normaliseEntryTags(e) {
|
|
555
618
|
const tagPromises = [];
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
619
|
+
const input = e.resolvedInput;
|
|
620
|
+
for (const k in input) {
|
|
621
|
+
if (!Object.prototype.hasOwnProperty.call(input, k)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const v = input[k];
|
|
625
|
+
if (v === void 0 || !ValidHeadTags.has(k)) {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (Array.isArray(v)) {
|
|
629
|
+
for (const props of v) {
|
|
630
|
+
tagPromises.push(normaliseTag(k, props, e));
|
|
631
|
+
}
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
tagPromises.push(normaliseTag(k, v, e));
|
|
635
|
+
}
|
|
636
|
+
if (tagPromises.length === 0) {
|
|
637
|
+
return [];
|
|
638
|
+
}
|
|
639
|
+
const headTags = [];
|
|
640
|
+
return thenable(nestedNormaliseEntryTags(headTags, tagPromises, 0), () => headTags.map((t, i) => {
|
|
561
641
|
t._e = e._i;
|
|
562
642
|
e.mode && (t._m = e.mode);
|
|
563
643
|
t._p = (e._i << TagEntityBits) + i;
|
|
564
644
|
return t;
|
|
565
|
-
});
|
|
645
|
+
}));
|
|
566
646
|
}
|
|
567
647
|
|
|
568
648
|
const TAG_WEIGHTS = {
|
|
@@ -577,66 +657,72 @@ const TAG_ALIASES = {
|
|
|
577
657
|
low: 20
|
|
578
658
|
};
|
|
579
659
|
function tagWeight(tag) {
|
|
580
|
-
let weight = 100;
|
|
581
660
|
const priority = tag.tagPriority;
|
|
582
661
|
if (typeof priority === "number")
|
|
583
662
|
return priority;
|
|
663
|
+
let weight = 100;
|
|
584
664
|
if (tag.tag === "meta") {
|
|
585
665
|
if (tag.props["http-equiv"] === "content-security-policy")
|
|
586
666
|
weight = -30;
|
|
587
|
-
if (tag.props.charset)
|
|
667
|
+
else if (tag.props.charset)
|
|
588
668
|
weight = -20;
|
|
589
|
-
if (tag.props.name === "viewport")
|
|
669
|
+
else if (tag.props.name === "viewport")
|
|
590
670
|
weight = -15;
|
|
591
671
|
} else if (tag.tag === "link" && tag.props.rel === "preconnect") {
|
|
592
672
|
weight = 20;
|
|
593
673
|
} else if (tag.tag in TAG_WEIGHTS) {
|
|
594
674
|
weight = TAG_WEIGHTS[tag.tag];
|
|
595
675
|
}
|
|
596
|
-
if (
|
|
676
|
+
if (priority && priority in TAG_ALIASES) {
|
|
597
677
|
return weight + TAG_ALIASES[priority];
|
|
598
678
|
}
|
|
599
679
|
return weight;
|
|
600
680
|
}
|
|
601
681
|
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
602
682
|
|
|
603
|
-
const NetworkEvents = ["onload", "onerror", "onabort", "onprogress", "onloadstart"];
|
|
604
|
-
const ScriptNetworkEvents = ["onload", "onerror"];
|
|
683
|
+
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
684
|
+
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
605
685
|
|
|
606
686
|
const sepSub = "%separator";
|
|
687
|
+
function sub(p, token) {
|
|
688
|
+
let val;
|
|
689
|
+
if (token === "s" || token === "pageTitle") {
|
|
690
|
+
val = p.pageTitle;
|
|
691
|
+
} else if (token.includes(".")) {
|
|
692
|
+
const dotIndex = token.indexOf(".");
|
|
693
|
+
val = p[token.substring(0, dotIndex)]?.[token.substring(dotIndex + 1)];
|
|
694
|
+
} else {
|
|
695
|
+
val = p[token];
|
|
696
|
+
}
|
|
697
|
+
return val !== void 0 ? (val || "").replace(/"/g, '\\"') : void 0;
|
|
698
|
+
}
|
|
699
|
+
const sepSubRe = new RegExp(`${sepSub}(?:\\s*${sepSub})*`, "g");
|
|
607
700
|
function processTemplateParams(s, p, sep) {
|
|
608
701
|
if (typeof s !== "string" || !s.includes("%"))
|
|
609
702
|
return s;
|
|
610
|
-
function sub(token) {
|
|
611
|
-
let val;
|
|
612
|
-
if (["s", "pageTitle"].includes(token)) {
|
|
613
|
-
val = p.pageTitle;
|
|
614
|
-
} else if (token.includes(".")) {
|
|
615
|
-
val = token.split(".").reduce((acc, key) => acc ? acc[key] || void 0 : void 0, p);
|
|
616
|
-
} else {
|
|
617
|
-
val = p[token];
|
|
618
|
-
}
|
|
619
|
-
return typeof val !== "undefined" ? (val || "").replace(/"/g, '\\"') : false;
|
|
620
|
-
}
|
|
621
703
|
let decoded = s;
|
|
622
704
|
try {
|
|
623
705
|
decoded = decodeURI(s);
|
|
624
706
|
} catch {
|
|
625
707
|
}
|
|
626
|
-
const tokens =
|
|
627
|
-
tokens
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
708
|
+
const tokens = decoded.match(/%\w+(?:\.\w+)?/g);
|
|
709
|
+
if (!tokens) {
|
|
710
|
+
return s;
|
|
711
|
+
}
|
|
712
|
+
const hasSepSub = s.includes(sepSub);
|
|
713
|
+
s = s.replace(/%\w+(?:\.\w+)?/g, (token) => {
|
|
714
|
+
if (token === sepSub || !tokens.includes(token)) {
|
|
715
|
+
return token;
|
|
631
716
|
}
|
|
632
|
-
|
|
633
|
-
|
|
717
|
+
const re = sub(p, token.slice(1));
|
|
718
|
+
return re !== void 0 ? re : token;
|
|
719
|
+
}).trim();
|
|
720
|
+
if (hasSepSub) {
|
|
634
721
|
if (s.endsWith(sepSub))
|
|
635
|
-
s = s.slice(0, -sepSub.length)
|
|
722
|
+
s = s.slice(0, -sepSub.length);
|
|
636
723
|
if (s.startsWith(sepSub))
|
|
637
|
-
s = s.slice(sepSub.length)
|
|
638
|
-
s = s.replace(
|
|
639
|
-
s = processTemplateParams(s, { separator: sep }, sep);
|
|
724
|
+
s = s.slice(sepSub.length);
|
|
725
|
+
s = s.replace(sepSubRe, sep).trim();
|
|
640
726
|
}
|
|
641
727
|
return s;
|
|
642
728
|
}
|
|
@@ -671,5 +757,6 @@ exports.resolvePackedMetaObjectValue = resolvePackedMetaObjectValue;
|
|
|
671
757
|
exports.resolveTitleTemplate = resolveTitleTemplate;
|
|
672
758
|
exports.tagDedupeKey = tagDedupeKey;
|
|
673
759
|
exports.tagWeight = tagWeight;
|
|
760
|
+
exports.thenable = thenable;
|
|
674
761
|
exports.unpackMeta = unpackMeta;
|
|
675
762
|
exports.whitelistSafeInput = whitelistSafeInput;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,12 +3,12 @@ import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, MaybeArray, He
|
|
|
3
3
|
type Arrayable<T> = T | Array<T>;
|
|
4
4
|
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
5
5
|
|
|
6
|
-
declare const SelfClosingTags: string
|
|
7
|
-
declare const TagsWithInnerContent: string
|
|
8
|
-
declare const HasElementTags: string
|
|
9
|
-
declare const ValidHeadTags: string
|
|
10
|
-
declare const UniqueTags: string
|
|
11
|
-
declare const TagConfigKeys: string
|
|
6
|
+
declare const SelfClosingTags: Set<string>;
|
|
7
|
+
declare const TagsWithInnerContent: Set<string>;
|
|
8
|
+
declare const HasElementTags: Set<string>;
|
|
9
|
+
declare const ValidHeadTags: Set<string>;
|
|
10
|
+
declare const UniqueTags: Set<string>;
|
|
11
|
+
declare const TagConfigKeys: Set<string>;
|
|
12
12
|
declare const IsBrowser: boolean;
|
|
13
13
|
declare const composableNames: string[];
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
|
17
17
|
declare function hashCode(s: string): string;
|
|
18
18
|
declare function hashTag(tag: HeadTag): string;
|
|
19
19
|
|
|
20
|
-
declare function tagDedupeKey<T extends HeadTag>(tag: T
|
|
20
|
+
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
21
21
|
|
|
22
22
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
23
23
|
|
|
@@ -37,11 +37,14 @@ declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlat
|
|
|
37
37
|
|
|
38
38
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
type Thenable<T> = Promise<T> | T;
|
|
41
|
+
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
42
|
+
|
|
43
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
41
44
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
42
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
45
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Thenable<T['props']>;
|
|
43
46
|
declare const TagEntityBits = 10;
|
|
44
|
-
declare function normaliseEntryTags<T extends
|
|
47
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): Thenable<HeadTag[]>;
|
|
45
48
|
|
|
46
49
|
declare const TAG_WEIGHTS: {
|
|
47
50
|
readonly base: -10;
|
|
@@ -52,15 +55,15 @@ declare const TAG_ALIASES: {
|
|
|
52
55
|
readonly high: -10;
|
|
53
56
|
readonly low: 20;
|
|
54
57
|
};
|
|
55
|
-
declare function tagWeight<T extends HeadTag>(tag: T):
|
|
58
|
+
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
56
59
|
declare const SortModifiers: {
|
|
57
60
|
prefix: string;
|
|
58
61
|
offset: number;
|
|
59
62
|
}[];
|
|
60
63
|
|
|
61
|
-
declare const NetworkEvents: string
|
|
62
|
-
declare const ScriptNetworkEvents: string
|
|
64
|
+
declare const NetworkEvents: Set<string>;
|
|
65
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
63
66
|
|
|
64
67
|
declare function processTemplateParams(s: string, p: TemplateParams, sep: string): string;
|
|
65
68
|
|
|
66
|
-
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, unpackMeta, whitelistSafeInput };
|
|
69
|
+
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, type Thenable, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, thenable, unpackMeta, whitelistSafeInput };
|
package/dist/index.d.mts
CHANGED
|
@@ -3,12 +3,12 @@ import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, MaybeArray, He
|
|
|
3
3
|
type Arrayable<T> = T | Array<T>;
|
|
4
4
|
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
5
5
|
|
|
6
|
-
declare const SelfClosingTags: string
|
|
7
|
-
declare const TagsWithInnerContent: string
|
|
8
|
-
declare const HasElementTags: string
|
|
9
|
-
declare const ValidHeadTags: string
|
|
10
|
-
declare const UniqueTags: string
|
|
11
|
-
declare const TagConfigKeys: string
|
|
6
|
+
declare const SelfClosingTags: Set<string>;
|
|
7
|
+
declare const TagsWithInnerContent: Set<string>;
|
|
8
|
+
declare const HasElementTags: Set<string>;
|
|
9
|
+
declare const ValidHeadTags: Set<string>;
|
|
10
|
+
declare const UniqueTags: Set<string>;
|
|
11
|
+
declare const TagConfigKeys: Set<string>;
|
|
12
12
|
declare const IsBrowser: boolean;
|
|
13
13
|
declare const composableNames: string[];
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
|
17
17
|
declare function hashCode(s: string): string;
|
|
18
18
|
declare function hashTag(tag: HeadTag): string;
|
|
19
19
|
|
|
20
|
-
declare function tagDedupeKey<T extends HeadTag>(tag: T
|
|
20
|
+
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
21
21
|
|
|
22
22
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
23
23
|
|
|
@@ -37,11 +37,14 @@ declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlat
|
|
|
37
37
|
|
|
38
38
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
type Thenable<T> = Promise<T> | T;
|
|
41
|
+
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
42
|
+
|
|
43
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
41
44
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
42
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
45
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Thenable<T['props']>;
|
|
43
46
|
declare const TagEntityBits = 10;
|
|
44
|
-
declare function normaliseEntryTags<T extends
|
|
47
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): Thenable<HeadTag[]>;
|
|
45
48
|
|
|
46
49
|
declare const TAG_WEIGHTS: {
|
|
47
50
|
readonly base: -10;
|
|
@@ -52,15 +55,15 @@ declare const TAG_ALIASES: {
|
|
|
52
55
|
readonly high: -10;
|
|
53
56
|
readonly low: 20;
|
|
54
57
|
};
|
|
55
|
-
declare function tagWeight<T extends HeadTag>(tag: T):
|
|
58
|
+
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
56
59
|
declare const SortModifiers: {
|
|
57
60
|
prefix: string;
|
|
58
61
|
offset: number;
|
|
59
62
|
}[];
|
|
60
63
|
|
|
61
|
-
declare const NetworkEvents: string
|
|
62
|
-
declare const ScriptNetworkEvents: string
|
|
64
|
+
declare const NetworkEvents: Set<string>;
|
|
65
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
63
66
|
|
|
64
67
|
declare function processTemplateParams(s: string, p: TemplateParams, sep: string): string;
|
|
65
68
|
|
|
66
|
-
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, unpackMeta, whitelistSafeInput };
|
|
69
|
+
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, type Thenable, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, thenable, unpackMeta, whitelistSafeInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, MaybeArray, He
|
|
|
3
3
|
type Arrayable<T> = T | Array<T>;
|
|
4
4
|
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
5
5
|
|
|
6
|
-
declare const SelfClosingTags: string
|
|
7
|
-
declare const TagsWithInnerContent: string
|
|
8
|
-
declare const HasElementTags: string
|
|
9
|
-
declare const ValidHeadTags: string
|
|
10
|
-
declare const UniqueTags: string
|
|
11
|
-
declare const TagConfigKeys: string
|
|
6
|
+
declare const SelfClosingTags: Set<string>;
|
|
7
|
+
declare const TagsWithInnerContent: Set<string>;
|
|
8
|
+
declare const HasElementTags: Set<string>;
|
|
9
|
+
declare const ValidHeadTags: Set<string>;
|
|
10
|
+
declare const UniqueTags: Set<string>;
|
|
11
|
+
declare const TagConfigKeys: Set<string>;
|
|
12
12
|
declare const IsBrowser: boolean;
|
|
13
13
|
declare const composableNames: string[];
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
|
17
17
|
declare function hashCode(s: string): string;
|
|
18
18
|
declare function hashTag(tag: HeadTag): string;
|
|
19
19
|
|
|
20
|
-
declare function tagDedupeKey<T extends HeadTag>(tag: T
|
|
20
|
+
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
21
21
|
|
|
22
22
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
23
23
|
|
|
@@ -37,11 +37,14 @@ declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlat
|
|
|
37
37
|
|
|
38
38
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
type Thenable<T> = Promise<T> | T;
|
|
41
|
+
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
42
|
+
|
|
43
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
41
44
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
42
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
45
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Thenable<T['props']>;
|
|
43
46
|
declare const TagEntityBits = 10;
|
|
44
|
-
declare function normaliseEntryTags<T extends
|
|
47
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): Thenable<HeadTag[]>;
|
|
45
48
|
|
|
46
49
|
declare const TAG_WEIGHTS: {
|
|
47
50
|
readonly base: -10;
|
|
@@ -52,15 +55,15 @@ declare const TAG_ALIASES: {
|
|
|
52
55
|
readonly high: -10;
|
|
53
56
|
readonly low: 20;
|
|
54
57
|
};
|
|
55
|
-
declare function tagWeight<T extends HeadTag>(tag: T):
|
|
58
|
+
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
56
59
|
declare const SortModifiers: {
|
|
57
60
|
prefix: string;
|
|
58
61
|
offset: number;
|
|
59
62
|
}[];
|
|
60
63
|
|
|
61
|
-
declare const NetworkEvents: string
|
|
62
|
-
declare const ScriptNetworkEvents: string
|
|
64
|
+
declare const NetworkEvents: Set<string>;
|
|
65
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
63
66
|
|
|
64
67
|
declare function processTemplateParams(s: string, p: TemplateParams, sep: string): string;
|
|
65
68
|
|
|
66
|
-
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, unpackMeta, whitelistSafeInput };
|
|
69
|
+
export { type Arrayable, HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, type Thenable, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, thenable, unpackMeta, whitelistSafeInput };
|
package/dist/index.mjs
CHANGED
|
@@ -2,17 +2,17 @@ function asArray$1(value) {
|
|
|
2
2
|
return Array.isArray(value) ? value : [value];
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
const SelfClosingTags = ["meta", "link", "base"];
|
|
6
|
-
const TagsWithInnerContent = ["title", "titleTemplate", "script", "style", "noscript"];
|
|
7
|
-
const HasElementTags = [
|
|
5
|
+
const SelfClosingTags = /* @__PURE__ */ new Set(["meta", "link", "base"]);
|
|
6
|
+
const TagsWithInnerContent = /* @__PURE__ */ new Set(["title", "titleTemplate", "script", "style", "noscript"]);
|
|
7
|
+
const HasElementTags = /* @__PURE__ */ new Set([
|
|
8
8
|
"base",
|
|
9
9
|
"meta",
|
|
10
10
|
"link",
|
|
11
11
|
"style",
|
|
12
12
|
"script",
|
|
13
13
|
"noscript"
|
|
14
|
-
];
|
|
15
|
-
const ValidHeadTags = [
|
|
14
|
+
]);
|
|
15
|
+
const ValidHeadTags = /* @__PURE__ */ new Set([
|
|
16
16
|
"title",
|
|
17
17
|
"titleTemplate",
|
|
18
18
|
"templateParams",
|
|
@@ -24,9 +24,9 @@ const ValidHeadTags = [
|
|
|
24
24
|
"style",
|
|
25
25
|
"script",
|
|
26
26
|
"noscript"
|
|
27
|
-
];
|
|
28
|
-
const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"];
|
|
29
|
-
const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "children", "innerHTML", "textContent", "processTemplateParams"];
|
|
27
|
+
]);
|
|
28
|
+
const UniqueTags = /* @__PURE__ */ new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]);
|
|
29
|
+
const TagConfigKeys = /* @__PURE__ */ new Set(["tagPosition", "tagPriority", "tagDuplicateStrategy", "children", "innerHTML", "textContent", "processTemplateParams"]);
|
|
30
30
|
const IsBrowser = typeof window !== "undefined";
|
|
31
31
|
const composableNames = [
|
|
32
32
|
"getActiveHead",
|
|
@@ -49,26 +49,34 @@ function hashCode(s) {
|
|
|
49
49
|
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
|
|
50
50
|
}
|
|
51
51
|
function hashTag(tag) {
|
|
52
|
-
|
|
52
|
+
if (tag._h) {
|
|
53
|
+
return tag._h;
|
|
54
|
+
}
|
|
55
|
+
if (tag._d) {
|
|
56
|
+
return hashCode(tag._d);
|
|
57
|
+
}
|
|
58
|
+
let content = `${tag.tag}:${tag.textContent || tag.innerHTML || ""}:`;
|
|
59
|
+
for (const key in tag.props) {
|
|
60
|
+
content += `${key}:${tag.props[key]},`;
|
|
61
|
+
}
|
|
62
|
+
return hashCode(content);
|
|
53
63
|
}
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
66
|
+
function tagDedupeKey(tag) {
|
|
56
67
|
const { props, tag: tagName } = tag;
|
|
57
|
-
if (UniqueTags.
|
|
68
|
+
if (UniqueTags.has(tagName))
|
|
58
69
|
return tagName;
|
|
59
70
|
if (tagName === "link" && props.rel === "canonical")
|
|
60
71
|
return "canonical";
|
|
61
72
|
if (props.charset)
|
|
62
73
|
return "charset";
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
for (const n of
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
if (fn && !fn(val))
|
|
70
|
-
return false;
|
|
71
|
-
return `${tagName}:${n}:${val}`;
|
|
74
|
+
if (props.id) {
|
|
75
|
+
return `${tagName}:id:${props.id}`;
|
|
76
|
+
}
|
|
77
|
+
for (const n of allowedMetaProperties) {
|
|
78
|
+
if (props[n] !== void 0) {
|
|
79
|
+
return `${tagName}:${n}:${props[n]}`;
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
return false;
|
|
@@ -250,15 +258,16 @@ const MetaPackingSchema = {
|
|
|
250
258
|
metaKey: "http-equiv"
|
|
251
259
|
}
|
|
252
260
|
};
|
|
253
|
-
const openGraphNamespaces = [
|
|
261
|
+
const openGraphNamespaces = /* @__PURE__ */ new Set([
|
|
254
262
|
"og",
|
|
255
263
|
"book",
|
|
256
264
|
"article",
|
|
257
265
|
"profile"
|
|
258
|
-
];
|
|
266
|
+
]);
|
|
259
267
|
function resolveMetaKeyType(key) {
|
|
260
|
-
const fKey = fixKeyCase(key)
|
|
261
|
-
|
|
268
|
+
const fKey = fixKeyCase(key);
|
|
269
|
+
const prefixIndex = fKey.indexOf(":");
|
|
270
|
+
if (openGraphNamespaces.has(fKey.substring(0, prefixIndex)))
|
|
262
271
|
return "property";
|
|
263
272
|
return MetaPackingSchema[key]?.metaKey || "name";
|
|
264
273
|
}
|
|
@@ -267,8 +276,9 @@ function resolveMetaKeyValue(key) {
|
|
|
267
276
|
}
|
|
268
277
|
function fixKeyCase(key) {
|
|
269
278
|
const updated = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
270
|
-
const
|
|
271
|
-
|
|
279
|
+
const prefixIndex = updated.indexOf("-");
|
|
280
|
+
const fKey = updated.substring(0, prefixIndex);
|
|
281
|
+
if (fKey === "twitter" || openGraphNamespaces.has(fKey))
|
|
272
282
|
return key.replace(/([A-Z])/g, ":$1").toLowerCase();
|
|
273
283
|
return updated;
|
|
274
284
|
}
|
|
@@ -279,8 +289,12 @@ function changeKeyCasingDeep(input) {
|
|
|
279
289
|
if (typeof input !== "object" || Array.isArray(input))
|
|
280
290
|
return input;
|
|
281
291
|
const output = {};
|
|
282
|
-
for (const
|
|
283
|
-
|
|
292
|
+
for (const key in input) {
|
|
293
|
+
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
output[fixKeyCase(key)] = changeKeyCasingDeep(input[key]);
|
|
297
|
+
}
|
|
284
298
|
return output;
|
|
285
299
|
}
|
|
286
300
|
function resolvePackedMetaObjectValue(value, key) {
|
|
@@ -302,24 +316,31 @@ function resolvePackedMetaObjectValue(value, key) {
|
|
|
302
316
|
}
|
|
303
317
|
);
|
|
304
318
|
}
|
|
305
|
-
const ObjectArrayEntries = ["og:image", "og:video", "og:audio", "twitter:image"];
|
|
319
|
+
const ObjectArrayEntries = /* @__PURE__ */ new Set(["og:image", "og:video", "og:audio", "twitter:image"]);
|
|
306
320
|
function sanitize(input) {
|
|
307
321
|
const out = {};
|
|
308
|
-
|
|
322
|
+
for (const k2 in input) {
|
|
323
|
+
if (!Object.prototype.hasOwnProperty.call(input, k2)) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const v = input[k2];
|
|
309
327
|
if (String(v) !== "false" && k2)
|
|
310
328
|
out[k2] = v;
|
|
311
|
-
}
|
|
329
|
+
}
|
|
312
330
|
return out;
|
|
313
331
|
}
|
|
314
332
|
function handleObjectEntry(key, v) {
|
|
315
333
|
const value = sanitize(v);
|
|
316
334
|
const fKey = fixKeyCase(key);
|
|
317
335
|
const attr = resolveMetaKeyType(fKey);
|
|
318
|
-
if (ObjectArrayEntries.
|
|
336
|
+
if (ObjectArrayEntries.has(fKey)) {
|
|
319
337
|
const input = {};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
338
|
+
for (const k2 in value) {
|
|
339
|
+
if (!Object.prototype.hasOwnProperty.call(value, k2)) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
input[`${key}${k2 === "url" ? "" : `${k2[0].toUpperCase()}${k2.slice(1)}`}`] = value[k2];
|
|
343
|
+
}
|
|
323
344
|
return unpackMeta(input).sort((a, b) => (a[attr]?.length || 0) - (b[attr]?.length || 0));
|
|
324
345
|
}
|
|
325
346
|
return [{ [attr]: fKey, ...value }];
|
|
@@ -327,23 +348,27 @@ function handleObjectEntry(key, v) {
|
|
|
327
348
|
function unpackMeta(input) {
|
|
328
349
|
const extras = [];
|
|
329
350
|
const primitives = {};
|
|
330
|
-
|
|
351
|
+
for (const key in input) {
|
|
352
|
+
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const value = input[key];
|
|
331
356
|
if (!Array.isArray(value)) {
|
|
332
357
|
if (typeof value === "object" && value) {
|
|
333
|
-
if (ObjectArrayEntries.
|
|
358
|
+
if (ObjectArrayEntries.has(fixKeyCase(key))) {
|
|
334
359
|
extras.push(...handleObjectEntry(key, value));
|
|
335
|
-
|
|
360
|
+
continue;
|
|
336
361
|
}
|
|
337
362
|
primitives[key] = sanitize(value);
|
|
338
363
|
} else {
|
|
339
364
|
primitives[key] = value;
|
|
340
365
|
}
|
|
341
|
-
|
|
366
|
+
continue;
|
|
342
367
|
}
|
|
343
|
-
|
|
368
|
+
for (const v of value) {
|
|
344
369
|
extras.push(...typeof v === "string" ? unpackMeta({ [key]: v }) : handleObjectEntry(key, v));
|
|
345
|
-
}
|
|
346
|
-
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
347
372
|
const meta = unpackToArray(primitives, {
|
|
348
373
|
key({ key }) {
|
|
349
374
|
return resolveMetaKeyType(key);
|
|
@@ -435,7 +460,7 @@ function whitelistSafeInput(input) {
|
|
|
435
460
|
const link = acceptDataAttrs(meta);
|
|
436
461
|
WhitelistAttributes.link.forEach((key2) => {
|
|
437
462
|
const val = meta[key2];
|
|
438
|
-
if (key2 === "rel" &&
|
|
463
|
+
if (key2 === "rel" && (val === "stylesheet" || val === "canonical" || val === "modulepreload" || val === "prerender" || val === "preload" || val === "prefetch"))
|
|
439
464
|
return;
|
|
440
465
|
if (key2 === "href") {
|
|
441
466
|
if (val.includes("javascript:") || val.includes("data:"))
|
|
@@ -487,25 +512,36 @@ function whitelistSafeInput(input) {
|
|
|
487
512
|
return filtered;
|
|
488
513
|
}
|
|
489
514
|
|
|
490
|
-
|
|
515
|
+
function thenable(val, thenFn) {
|
|
516
|
+
if (val instanceof Promise) {
|
|
517
|
+
return val.then(thenFn);
|
|
518
|
+
}
|
|
519
|
+
return thenFn(val);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function normaliseTag(tagName, input, e, normalizedProps) {
|
|
523
|
+
const props = normalizedProps || normaliseProps(
|
|
524
|
+
// explicitly check for an object
|
|
525
|
+
// @ts-expect-error untyped
|
|
526
|
+
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
527
|
+
tagName === "templateParams" || tagName === "titleTemplate"
|
|
528
|
+
);
|
|
529
|
+
if (props instanceof Promise) {
|
|
530
|
+
return props.then((val) => normaliseTag(tagName, input, e, val));
|
|
531
|
+
}
|
|
491
532
|
const tag = {
|
|
492
533
|
tag: tagName,
|
|
493
|
-
props
|
|
494
|
-
// explicitly check for an object
|
|
495
|
-
// @ts-expect-error untyped
|
|
496
|
-
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [["script", "noscript", "style"].includes(tagName) ? "innerHTML" : "textContent"]: input },
|
|
497
|
-
["templateParams", "titleTemplate"].includes(tagName)
|
|
498
|
-
)
|
|
534
|
+
props
|
|
499
535
|
};
|
|
500
|
-
|
|
501
|
-
const val =
|
|
502
|
-
if (
|
|
503
|
-
if (!
|
|
536
|
+
for (const k of TagConfigKeys) {
|
|
537
|
+
const val = tag.props[k] !== void 0 ? tag.props[k] : e[k];
|
|
538
|
+
if (val !== void 0) {
|
|
539
|
+
if (!(k === "innerHTML" || k === "textContent" || k === "children") || TagsWithInnerContent.has(tag.tag)) {
|
|
504
540
|
tag[k === "children" ? "innerHTML" : k] = val;
|
|
505
541
|
}
|
|
506
542
|
delete tag.props[k];
|
|
507
543
|
}
|
|
508
|
-
}
|
|
544
|
+
}
|
|
509
545
|
if (tag.props.body) {
|
|
510
546
|
tag.tagPosition = "bodyClose";
|
|
511
547
|
delete tag.props.body;
|
|
@@ -523,17 +559,22 @@ function normaliseStyleClassProps(key, v) {
|
|
|
523
559
|
if (typeof v === "object" && !Array.isArray(v)) {
|
|
524
560
|
v = Object.entries(v).filter(([, v2]) => v2).map(([k, v2]) => key === "style" ? `${k}:${v2}` : k);
|
|
525
561
|
}
|
|
526
|
-
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => c.trim())
|
|
562
|
+
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => Boolean(c.trim())).join(sep);
|
|
527
563
|
}
|
|
528
|
-
|
|
529
|
-
for (
|
|
530
|
-
|
|
564
|
+
function nestedNormaliseProps(props, virtual, keys, startIndex) {
|
|
565
|
+
for (let i = startIndex; i < keys.length; i += 1) {
|
|
566
|
+
const k = keys[i];
|
|
567
|
+
if (k === "class" || k === "style") {
|
|
531
568
|
props[k] = normaliseStyleClassProps(k, props[k]);
|
|
532
569
|
continue;
|
|
533
570
|
}
|
|
534
|
-
if (props[k] instanceof Promise)
|
|
535
|
-
props[k]
|
|
536
|
-
|
|
571
|
+
if (props[k] instanceof Promise) {
|
|
572
|
+
return props[k].then((val) => {
|
|
573
|
+
props[k] = val;
|
|
574
|
+
return nestedNormaliseProps(props, virtual, keys, i);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
if (!virtual && !TagConfigKeys.has(k)) {
|
|
537
578
|
const v = String(props[k]);
|
|
538
579
|
const isDataKey = k.startsWith("data-");
|
|
539
580
|
if (v === "true" || v === "") {
|
|
@@ -546,21 +587,60 @@ async function normaliseProps(props, virtual) {
|
|
|
546
587
|
}
|
|
547
588
|
}
|
|
548
589
|
}
|
|
590
|
+
}
|
|
591
|
+
function normaliseProps(props, virtual = false) {
|
|
592
|
+
const resolvedProps = nestedNormaliseProps(props, virtual, Object.keys(props), 0);
|
|
593
|
+
if (resolvedProps instanceof Promise) {
|
|
594
|
+
return resolvedProps.then(() => props);
|
|
595
|
+
}
|
|
549
596
|
return props;
|
|
550
597
|
}
|
|
551
598
|
const TagEntityBits = 10;
|
|
552
|
-
|
|
599
|
+
function nestedNormaliseEntryTags(headTags, tagPromises, startIndex) {
|
|
600
|
+
for (let i = startIndex; i < tagPromises.length; i += 1) {
|
|
601
|
+
const tags = tagPromises[i];
|
|
602
|
+
if (tags instanceof Promise) {
|
|
603
|
+
return tags.then((val) => {
|
|
604
|
+
tagPromises[i] = val;
|
|
605
|
+
return nestedNormaliseEntryTags(headTags, tagPromises, i);
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
if (Array.isArray(tags)) {
|
|
609
|
+
headTags.push(...tags);
|
|
610
|
+
} else {
|
|
611
|
+
headTags.push(tags);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
function normaliseEntryTags(e) {
|
|
553
616
|
const tagPromises = [];
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
617
|
+
const input = e.resolvedInput;
|
|
618
|
+
for (const k in input) {
|
|
619
|
+
if (!Object.prototype.hasOwnProperty.call(input, k)) {
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
const v = input[k];
|
|
623
|
+
if (v === void 0 || !ValidHeadTags.has(k)) {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (Array.isArray(v)) {
|
|
627
|
+
for (const props of v) {
|
|
628
|
+
tagPromises.push(normaliseTag(k, props, e));
|
|
629
|
+
}
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
tagPromises.push(normaliseTag(k, v, e));
|
|
633
|
+
}
|
|
634
|
+
if (tagPromises.length === 0) {
|
|
635
|
+
return [];
|
|
636
|
+
}
|
|
637
|
+
const headTags = [];
|
|
638
|
+
return thenable(nestedNormaliseEntryTags(headTags, tagPromises, 0), () => headTags.map((t, i) => {
|
|
559
639
|
t._e = e._i;
|
|
560
640
|
e.mode && (t._m = e.mode);
|
|
561
641
|
t._p = (e._i << TagEntityBits) + i;
|
|
562
642
|
return t;
|
|
563
|
-
});
|
|
643
|
+
}));
|
|
564
644
|
}
|
|
565
645
|
|
|
566
646
|
const TAG_WEIGHTS = {
|
|
@@ -575,68 +655,74 @@ const TAG_ALIASES = {
|
|
|
575
655
|
low: 20
|
|
576
656
|
};
|
|
577
657
|
function tagWeight(tag) {
|
|
578
|
-
let weight = 100;
|
|
579
658
|
const priority = tag.tagPriority;
|
|
580
659
|
if (typeof priority === "number")
|
|
581
660
|
return priority;
|
|
661
|
+
let weight = 100;
|
|
582
662
|
if (tag.tag === "meta") {
|
|
583
663
|
if (tag.props["http-equiv"] === "content-security-policy")
|
|
584
664
|
weight = -30;
|
|
585
|
-
if (tag.props.charset)
|
|
665
|
+
else if (tag.props.charset)
|
|
586
666
|
weight = -20;
|
|
587
|
-
if (tag.props.name === "viewport")
|
|
667
|
+
else if (tag.props.name === "viewport")
|
|
588
668
|
weight = -15;
|
|
589
669
|
} else if (tag.tag === "link" && tag.props.rel === "preconnect") {
|
|
590
670
|
weight = 20;
|
|
591
671
|
} else if (tag.tag in TAG_WEIGHTS) {
|
|
592
672
|
weight = TAG_WEIGHTS[tag.tag];
|
|
593
673
|
}
|
|
594
|
-
if (
|
|
674
|
+
if (priority && priority in TAG_ALIASES) {
|
|
595
675
|
return weight + TAG_ALIASES[priority];
|
|
596
676
|
}
|
|
597
677
|
return weight;
|
|
598
678
|
}
|
|
599
679
|
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
600
680
|
|
|
601
|
-
const NetworkEvents = ["onload", "onerror", "onabort", "onprogress", "onloadstart"];
|
|
602
|
-
const ScriptNetworkEvents = ["onload", "onerror"];
|
|
681
|
+
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
682
|
+
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
603
683
|
|
|
604
684
|
const sepSub = "%separator";
|
|
685
|
+
function sub(p, token) {
|
|
686
|
+
let val;
|
|
687
|
+
if (token === "s" || token === "pageTitle") {
|
|
688
|
+
val = p.pageTitle;
|
|
689
|
+
} else if (token.includes(".")) {
|
|
690
|
+
const dotIndex = token.indexOf(".");
|
|
691
|
+
val = p[token.substring(0, dotIndex)]?.[token.substring(dotIndex + 1)];
|
|
692
|
+
} else {
|
|
693
|
+
val = p[token];
|
|
694
|
+
}
|
|
695
|
+
return val !== void 0 ? (val || "").replace(/"/g, '\\"') : void 0;
|
|
696
|
+
}
|
|
697
|
+
const sepSubRe = new RegExp(`${sepSub}(?:\\s*${sepSub})*`, "g");
|
|
605
698
|
function processTemplateParams(s, p, sep) {
|
|
606
699
|
if (typeof s !== "string" || !s.includes("%"))
|
|
607
700
|
return s;
|
|
608
|
-
function sub(token) {
|
|
609
|
-
let val;
|
|
610
|
-
if (["s", "pageTitle"].includes(token)) {
|
|
611
|
-
val = p.pageTitle;
|
|
612
|
-
} else if (token.includes(".")) {
|
|
613
|
-
val = token.split(".").reduce((acc, key) => acc ? acc[key] || void 0 : void 0, p);
|
|
614
|
-
} else {
|
|
615
|
-
val = p[token];
|
|
616
|
-
}
|
|
617
|
-
return typeof val !== "undefined" ? (val || "").replace(/"/g, '\\"') : false;
|
|
618
|
-
}
|
|
619
701
|
let decoded = s;
|
|
620
702
|
try {
|
|
621
703
|
decoded = decodeURI(s);
|
|
622
704
|
} catch {
|
|
623
705
|
}
|
|
624
|
-
const tokens =
|
|
625
|
-
tokens
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
706
|
+
const tokens = decoded.match(/%\w+(?:\.\w+)?/g);
|
|
707
|
+
if (!tokens) {
|
|
708
|
+
return s;
|
|
709
|
+
}
|
|
710
|
+
const hasSepSub = s.includes(sepSub);
|
|
711
|
+
s = s.replace(/%\w+(?:\.\w+)?/g, (token) => {
|
|
712
|
+
if (token === sepSub || !tokens.includes(token)) {
|
|
713
|
+
return token;
|
|
629
714
|
}
|
|
630
|
-
|
|
631
|
-
|
|
715
|
+
const re = sub(p, token.slice(1));
|
|
716
|
+
return re !== void 0 ? re : token;
|
|
717
|
+
}).trim();
|
|
718
|
+
if (hasSepSub) {
|
|
632
719
|
if (s.endsWith(sepSub))
|
|
633
|
-
s = s.slice(0, -sepSub.length)
|
|
720
|
+
s = s.slice(0, -sepSub.length);
|
|
634
721
|
if (s.startsWith(sepSub))
|
|
635
|
-
s = s.slice(sepSub.length)
|
|
636
|
-
s = s.replace(
|
|
637
|
-
s = processTemplateParams(s, { separator: sep }, sep);
|
|
722
|
+
s = s.slice(sepSub.length);
|
|
723
|
+
s = s.replace(sepSubRe, sep).trim();
|
|
638
724
|
}
|
|
639
725
|
return s;
|
|
640
726
|
}
|
|
641
727
|
|
|
642
|
-
export { HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray$1 as asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, unpackMeta, whitelistSafeInput };
|
|
728
|
+
export { HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray$1 as asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, thenable, unpackMeta, whitelistSafeInput };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unhead/shared",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.10.0-beta.1",
|
|
5
5
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@unhead/schema": "1.
|
|
37
|
+
"@unhead/schema": "1.10.0-beta.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"packrup": "^0.1.2"
|