@unhead/shared 1.11.15 → 2.0.0-alpha.0
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 +86 -93
- package/dist/index.d.cts +12 -15
- package/dist/index.d.mts +12 -15
- package/dist/index.d.ts +12 -15
- package/dist/index.mjs +86 -93
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const packrup = require('packrup');
|
|
4
4
|
|
|
5
|
-
function asArray(value) {
|
|
6
|
-
return Array.isArray(value) ? value : [value];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
5
|
const SelfClosingTags = /* @__PURE__ */ new Set(["meta", "link", "base"]);
|
|
6
|
+
const DupeableTags = /* @__PURE__ */ new Set(["link", "style", "script", "noscript"]);
|
|
10
7
|
const TagsWithInnerContent = /* @__PURE__ */ new Set(["title", "titleTemplate", "script", "style", "noscript"]);
|
|
11
8
|
const HasElementTags = /* @__PURE__ */ new Set([
|
|
12
9
|
"base",
|
|
@@ -30,10 +27,9 @@ const ValidHeadTags = /* @__PURE__ */ new Set([
|
|
|
30
27
|
"noscript"
|
|
31
28
|
]);
|
|
32
29
|
const UniqueTags = /* @__PURE__ */ new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]);
|
|
33
|
-
const TagConfigKeys = /* @__PURE__ */ new Set(["
|
|
30
|
+
const TagConfigKeys = /* @__PURE__ */ new Set(["key", "tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"]);
|
|
34
31
|
const IsBrowser = typeof window !== "undefined";
|
|
35
32
|
const composableNames = [
|
|
36
|
-
"getActiveHead",
|
|
37
33
|
"useHead",
|
|
38
34
|
"useSeoMeta",
|
|
39
35
|
"useHeadSafe",
|
|
@@ -41,6 +37,8 @@ const composableNames = [
|
|
|
41
37
|
"useServerSeoMeta",
|
|
42
38
|
"useServerHeadSafe"
|
|
43
39
|
];
|
|
40
|
+
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
41
|
+
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
44
42
|
|
|
45
43
|
function defineHeadPlugin(plugin) {
|
|
46
44
|
return plugin;
|
|
@@ -287,40 +285,55 @@ function packMeta(inputs) {
|
|
|
287
285
|
});
|
|
288
286
|
}
|
|
289
287
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
289
|
+
function tagDedupeKey(tag) {
|
|
290
|
+
const { props, tag: tagName } = tag;
|
|
291
|
+
if (UniqueTags.has(tagName))
|
|
292
|
+
return tagName;
|
|
293
|
+
if (tagName === "link" && props.rel === "canonical")
|
|
294
|
+
return "canonical";
|
|
295
|
+
if (props.charset)
|
|
296
|
+
return "charset";
|
|
297
|
+
if (props.id) {
|
|
298
|
+
return `${tagName}:id:${props.id}`;
|
|
293
299
|
}
|
|
294
|
-
|
|
300
|
+
for (const n of allowedMetaProperties) {
|
|
301
|
+
if (props[n] !== undefined) {
|
|
302
|
+
return `${tagName}:${n}:${props[n]}`;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
295
306
|
}
|
|
296
307
|
|
|
297
308
|
function normaliseTag(tagName, input, e, normalizedProps) {
|
|
298
309
|
const props = normalizedProps || normaliseProps(
|
|
299
310
|
// explicitly check for an object
|
|
300
|
-
|
|
301
|
-
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
311
|
+
typeof input === "object" && typeof input !== "function" ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
302
312
|
tagName === "templateParams" || tagName === "titleTemplate"
|
|
303
313
|
);
|
|
304
|
-
if (props instanceof Promise) {
|
|
305
|
-
return props.then((val) => normaliseTag(tagName, input, e, val));
|
|
306
|
-
}
|
|
307
314
|
const tag = {
|
|
308
315
|
tag: tagName,
|
|
309
316
|
props
|
|
310
317
|
};
|
|
311
318
|
for (const k of TagConfigKeys) {
|
|
312
|
-
const val = tag.props[k] !==
|
|
313
|
-
if (val !==
|
|
314
|
-
if (!(k === "innerHTML" || k === "textContent"
|
|
315
|
-
tag[k
|
|
319
|
+
const val = tag.props[k] !== undefined ? tag.props[k] : e[k];
|
|
320
|
+
if (val !== undefined) {
|
|
321
|
+
if (!(k === "innerHTML" || k === "textContent") || TagsWithInnerContent.has(tag.tag)) {
|
|
322
|
+
tag[k] = val;
|
|
316
323
|
}
|
|
317
324
|
delete tag.props[k];
|
|
318
325
|
}
|
|
319
326
|
}
|
|
320
|
-
if (tag.
|
|
321
|
-
tag.
|
|
322
|
-
delete tag.props.body;
|
|
327
|
+
if (tag.key && DupeableTags.has(tag.tag)) {
|
|
328
|
+
tag.props["data-hid"] = tag._h = hashCode(tag.key);
|
|
323
329
|
}
|
|
330
|
+
const generatedKey = tagDedupeKey(tag);
|
|
331
|
+
if (generatedKey && !generatedKey.startsWith("meta:og:") && !generatedKey.startsWith("meta:twitter:")) {
|
|
332
|
+
delete tag.key;
|
|
333
|
+
}
|
|
334
|
+
const dedupe = generatedKey || (tag.key ? `${tag.tag}:${tag.key}` : false);
|
|
335
|
+
if (dedupe)
|
|
336
|
+
tag._d = dedupe;
|
|
324
337
|
if (tag.tag === "script") {
|
|
325
338
|
if (typeof tag.innerHTML === "object") {
|
|
326
339
|
tag.innerHTML = JSON.stringify(tag.innerHTML);
|
|
@@ -336,20 +349,16 @@ function normaliseStyleClassProps(key, v) {
|
|
|
336
349
|
}
|
|
337
350
|
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => Boolean(c.trim())).join(sep);
|
|
338
351
|
}
|
|
339
|
-
function
|
|
340
|
-
for (
|
|
341
|
-
const k = keys[i];
|
|
352
|
+
function normaliseProps(props, virtual = false) {
|
|
353
|
+
for (const k in props) {
|
|
342
354
|
if (k === "class" || k === "style") {
|
|
343
355
|
props[k] = normaliseStyleClassProps(k, props[k]);
|
|
344
356
|
continue;
|
|
345
357
|
}
|
|
346
|
-
if (props[k] instanceof Promise) {
|
|
347
|
-
return props[k].then((val) => {
|
|
348
|
-
props[k] = val;
|
|
349
|
-
return nestedNormaliseProps(props, virtual, keys, i);
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
358
|
if (!virtual && !TagConfigKeys.has(k)) {
|
|
359
|
+
if (typeof props[k] === "function" && !String(k).startsWith("on")) {
|
|
360
|
+
props[k] = props[k]();
|
|
361
|
+
}
|
|
353
362
|
const v = String(props[k]);
|
|
354
363
|
const isDataKey = k.startsWith("data-");
|
|
355
364
|
if (v === "true" || v === "") {
|
|
@@ -362,60 +371,37 @@ function nestedNormaliseProps(props, virtual, keys, startIndex) {
|
|
|
362
371
|
}
|
|
363
372
|
}
|
|
364
373
|
}
|
|
365
|
-
}
|
|
366
|
-
function normaliseProps(props, virtual = false) {
|
|
367
|
-
const resolvedProps = nestedNormaliseProps(props, virtual, Object.keys(props), 0);
|
|
368
|
-
if (resolvedProps instanceof Promise) {
|
|
369
|
-
return resolvedProps.then(() => props);
|
|
370
|
-
}
|
|
371
374
|
return props;
|
|
372
375
|
}
|
|
373
376
|
const TagEntityBits = 10;
|
|
374
|
-
function nestedNormaliseEntryTags(headTags, tagPromises, startIndex) {
|
|
375
|
-
for (let i = startIndex; i < tagPromises.length; i += 1) {
|
|
376
|
-
const tags = tagPromises[i];
|
|
377
|
-
if (tags instanceof Promise) {
|
|
378
|
-
return tags.then((val) => {
|
|
379
|
-
tagPromises[i] = val;
|
|
380
|
-
return nestedNormaliseEntryTags(headTags, tagPromises, i);
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
if (Array.isArray(tags)) {
|
|
384
|
-
headTags.push(...tags);
|
|
385
|
-
} else {
|
|
386
|
-
headTags.push(tags);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
377
|
function normaliseEntryTags(e) {
|
|
391
|
-
const
|
|
378
|
+
const tags = [];
|
|
392
379
|
const input = e.resolvedInput;
|
|
393
380
|
for (const k in input) {
|
|
394
381
|
if (!Object.prototype.hasOwnProperty.call(input, k)) {
|
|
395
382
|
continue;
|
|
396
383
|
}
|
|
397
384
|
const v = input[k];
|
|
398
|
-
if (v ===
|
|
385
|
+
if (v === undefined || !ValidHeadTags.has(k)) {
|
|
399
386
|
continue;
|
|
400
387
|
}
|
|
401
388
|
if (Array.isArray(v)) {
|
|
402
389
|
for (const props of v) {
|
|
403
|
-
|
|
390
|
+
tags.push(normaliseTag(k, props, e));
|
|
404
391
|
}
|
|
405
392
|
continue;
|
|
393
|
+
} else if (typeof v === "function" && k !== "titleTemplate") {
|
|
394
|
+
input[k] = v();
|
|
395
|
+
continue;
|
|
406
396
|
}
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
if (tagPromises.length === 0) {
|
|
410
|
-
return [];
|
|
397
|
+
tags.push(normaliseTag(k, v, e));
|
|
411
398
|
}
|
|
412
|
-
|
|
413
|
-
return thenable(nestedNormaliseEntryTags(headTags, tagPromises, 0), () => headTags.map((t, i) => {
|
|
399
|
+
return tags.flat().map((t, i) => {
|
|
414
400
|
t._e = e._i;
|
|
415
401
|
e.mode && (t._m = e.mode);
|
|
416
402
|
t._p = (e._i << TagEntityBits) + i;
|
|
417
403
|
return t;
|
|
418
|
-
})
|
|
404
|
+
});
|
|
419
405
|
}
|
|
420
406
|
|
|
421
407
|
const WhitelistAttributes = {
|
|
@@ -511,7 +497,7 @@ function whitelistSafeInput(input) {
|
|
|
511
497
|
try {
|
|
512
498
|
const jsonVal = typeof script[s] === "string" ? JSON.parse(script[s]) : script[s];
|
|
513
499
|
safeScript[s] = JSON.stringify(jsonVal, null, 0);
|
|
514
|
-
} catch
|
|
500
|
+
} catch {
|
|
515
501
|
}
|
|
516
502
|
} else {
|
|
517
503
|
safeScript[s] = script[s];
|
|
@@ -527,9 +513,6 @@ function whitelistSafeInput(input) {
|
|
|
527
513
|
return filtered;
|
|
528
514
|
}
|
|
529
515
|
|
|
530
|
-
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
531
|
-
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
532
|
-
|
|
533
516
|
const TAG_WEIGHTS = {
|
|
534
517
|
// tags
|
|
535
518
|
base: -10,
|
|
@@ -541,10 +524,16 @@ const TAG_ALIASES = {
|
|
|
541
524
|
high: -10,
|
|
542
525
|
low: 20
|
|
543
526
|
};
|
|
544
|
-
|
|
527
|
+
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
528
|
+
const importRe = /@import/;
|
|
529
|
+
const isTruthy = (val) => val === "" || val === true;
|
|
530
|
+
function tagWeight(head, tag) {
|
|
545
531
|
const priority = tag.tagPriority;
|
|
546
532
|
if (typeof priority === "number")
|
|
547
533
|
return priority;
|
|
534
|
+
const isScript = tag.tag === "script";
|
|
535
|
+
const isLink = tag.tag === "link";
|
|
536
|
+
const isStyle = tag.tag === "style";
|
|
548
537
|
let weight = 100;
|
|
549
538
|
if (tag.tag === "meta") {
|
|
550
539
|
if (tag.props["http-equiv"] === "content-security-policy")
|
|
@@ -553,7 +542,7 @@ function tagWeight(tag) {
|
|
|
553
542
|
weight = -20;
|
|
554
543
|
else if (tag.props.name === "viewport")
|
|
555
544
|
weight = -15;
|
|
556
|
-
} else if (
|
|
545
|
+
} else if (isLink && tag.props.rel === "preconnect") {
|
|
557
546
|
weight = 20;
|
|
558
547
|
} else if (tag.tag in TAG_WEIGHTS) {
|
|
559
548
|
weight = TAG_WEIGHTS[tag.tag];
|
|
@@ -561,28 +550,28 @@ function tagWeight(tag) {
|
|
|
561
550
|
if (priority && priority in TAG_ALIASES) {
|
|
562
551
|
return weight + TAG_ALIASES[priority];
|
|
563
552
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
567
|
-
|
|
568
|
-
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
569
|
-
function tagDedupeKey(tag) {
|
|
570
|
-
const { props, tag: tagName } = tag;
|
|
571
|
-
if (UniqueTags.has(tagName))
|
|
572
|
-
return tagName;
|
|
573
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
574
|
-
return "canonical";
|
|
575
|
-
if (props.charset)
|
|
576
|
-
return "charset";
|
|
577
|
-
if (props.id) {
|
|
578
|
-
return `${tagName}:id:${props.id}`;
|
|
553
|
+
if (tag.tagPosition && tag.tagPosition !== "head") {
|
|
554
|
+
return weight;
|
|
579
555
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return `${tagName}:${n}:${props[n]}`;
|
|
583
|
-
}
|
|
556
|
+
if (!head.ssr || head.resolvedOptions.disableCapoSorting) {
|
|
557
|
+
return weight;
|
|
584
558
|
}
|
|
585
|
-
|
|
559
|
+
if (isScript && isTruthy(tag.props.async)) {
|
|
560
|
+
weight = 30;
|
|
561
|
+
} else if (isStyle && tag.innerHTML && importRe.test(tag.innerHTML)) {
|
|
562
|
+
weight = 40;
|
|
563
|
+
} else if (isScript && tag.props.src && !isTruthy(tag.props.defer) && !isTruthy(tag.props.async) && tag.props.type !== "module" && !tag.props.type?.endsWith("json")) {
|
|
564
|
+
weight = 50;
|
|
565
|
+
} else if (isLink && tag.props.rel === "stylesheet" || tag.tag === "style") {
|
|
566
|
+
weight = 60;
|
|
567
|
+
} else if (isLink && (tag.props.rel === "preload" || tag.props.rel === "modulepreload")) {
|
|
568
|
+
weight = 70;
|
|
569
|
+
} else if (isScript && isTruthy(tag.props.defer) && tag.props.src && !isTruthy(tag.props.async)) {
|
|
570
|
+
weight = 80;
|
|
571
|
+
} else if (isLink && (tag.props.rel === "prefetch" || tag.props.rel === "dns-prefetch" || tag.props.rel === "prerender")) {
|
|
572
|
+
weight = 90;
|
|
573
|
+
}
|
|
574
|
+
return weight;
|
|
586
575
|
}
|
|
587
576
|
|
|
588
577
|
const sepSub = "%separator";
|
|
@@ -596,10 +585,10 @@ function sub(p, token, isJson = false) {
|
|
|
596
585
|
} else {
|
|
597
586
|
val = p[token];
|
|
598
587
|
}
|
|
599
|
-
if (val !==
|
|
588
|
+
if (val !== undefined) {
|
|
600
589
|
return isJson ? (val || "").replace(/"/g, '\\"') : val || "";
|
|
601
590
|
}
|
|
602
|
-
return
|
|
591
|
+
return undefined;
|
|
603
592
|
}
|
|
604
593
|
const sepSubRe = new RegExp(`${sepSub}(?:\\s*${sepSub})*`, "g");
|
|
605
594
|
function processTemplateParams(s, p, sep, isJson = false) {
|
|
@@ -620,7 +609,7 @@ function processTemplateParams(s, p, sep, isJson = false) {
|
|
|
620
609
|
return token;
|
|
621
610
|
}
|
|
622
611
|
const re = sub(p, token.slice(1), isJson);
|
|
623
|
-
return re !==
|
|
612
|
+
return re !== undefined ? re : token;
|
|
624
613
|
}).trim();
|
|
625
614
|
if (hasSepSub) {
|
|
626
615
|
if (s.endsWith(sepSub))
|
|
@@ -640,6 +629,11 @@ function resolveTitleTemplate(template, title) {
|
|
|
640
629
|
return template;
|
|
641
630
|
}
|
|
642
631
|
|
|
632
|
+
function asArray(value) {
|
|
633
|
+
return Array.isArray(value) ? value : [value];
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
exports.DupeableTags = DupeableTags;
|
|
643
637
|
exports.HasElementTags = HasElementTags;
|
|
644
638
|
exports.IsBrowser = IsBrowser;
|
|
645
639
|
exports.NetworkEvents = NetworkEvents;
|
|
@@ -670,6 +664,5 @@ exports.resolvePackedMetaObjectValue = resolvePackedMetaObjectValue;
|
|
|
670
664
|
exports.resolveTitleTemplate = resolveTitleTemplate;
|
|
671
665
|
exports.tagDedupeKey = tagDedupeKey;
|
|
672
666
|
exports.tagWeight = tagWeight;
|
|
673
|
-
exports.thenable = thenable;
|
|
674
667
|
exports.unpackMeta = unpackMeta;
|
|
675
668
|
exports.whitelistSafeInput = whitelistSafeInput;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, TemplateParams } from '@unhead/schema';
|
|
2
|
-
|
|
3
|
-
type Arrayable<T> = T | Array<T>;
|
|
4
|
-
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
1
|
+
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, Unhead, TemplateParams } from '@unhead/schema';
|
|
5
2
|
|
|
6
3
|
declare const SelfClosingTags: Set<string>;
|
|
4
|
+
declare const DupeableTags: Set<string>;
|
|
7
5
|
declare const TagsWithInnerContent: Set<string>;
|
|
8
6
|
declare const HasElementTags: Set<string>;
|
|
9
7
|
declare const ValidHeadTags: Set<string>;
|
|
@@ -11,6 +9,8 @@ declare const UniqueTags: Set<string>;
|
|
|
11
9
|
declare const TagConfigKeys: Set<string>;
|
|
12
10
|
declare const IsBrowser: boolean;
|
|
13
11
|
declare const composableNames: string[];
|
|
12
|
+
declare const NetworkEvents: Set<string>;
|
|
13
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
14
14
|
|
|
15
15
|
declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
16
16
|
|
|
@@ -31,20 +31,14 @@ declare function unpackMeta<T extends MetaFlatInput>(input: T): Required<Head>['
|
|
|
31
31
|
*/
|
|
32
32
|
declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlatInput;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
36
|
-
|
|
37
|
-
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
34
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): T | T[];
|
|
38
35
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
39
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
36
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): T["props"];
|
|
40
37
|
declare const TagEntityBits = 10;
|
|
41
|
-
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>):
|
|
38
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): HeadTag[];
|
|
42
39
|
|
|
43
40
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
44
41
|
|
|
45
|
-
declare const NetworkEvents: Set<string>;
|
|
46
|
-
declare const ScriptNetworkEvents: Set<string>;
|
|
47
|
-
|
|
48
42
|
declare const TAG_WEIGHTS: {
|
|
49
43
|
readonly base: -10;
|
|
50
44
|
readonly title: 10;
|
|
@@ -54,11 +48,11 @@ declare const TAG_ALIASES: {
|
|
|
54
48
|
readonly high: -10;
|
|
55
49
|
readonly low: 20;
|
|
56
50
|
};
|
|
57
|
-
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
58
51
|
declare const SortModifiers: {
|
|
59
52
|
prefix: string;
|
|
60
53
|
offset: number;
|
|
61
54
|
}[];
|
|
55
|
+
declare function tagWeight<T extends HeadTag>(head: Unhead<any>, tag: T): number;
|
|
62
56
|
|
|
63
57
|
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
64
58
|
|
|
@@ -66,4 +60,7 @@ declare function processTemplateParams(s: string, p: TemplateParams, sep: string
|
|
|
66
60
|
|
|
67
61
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
68
62
|
|
|
69
|
-
|
|
63
|
+
type Arrayable<T> = T | Array<T>;
|
|
64
|
+
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
65
|
+
|
|
66
|
+
export { type Arrayable, DupeableTags, 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 };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, TemplateParams } from '@unhead/schema';
|
|
2
|
-
|
|
3
|
-
type Arrayable<T> = T | Array<T>;
|
|
4
|
-
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
1
|
+
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, Unhead, TemplateParams } from '@unhead/schema';
|
|
5
2
|
|
|
6
3
|
declare const SelfClosingTags: Set<string>;
|
|
4
|
+
declare const DupeableTags: Set<string>;
|
|
7
5
|
declare const TagsWithInnerContent: Set<string>;
|
|
8
6
|
declare const HasElementTags: Set<string>;
|
|
9
7
|
declare const ValidHeadTags: Set<string>;
|
|
@@ -11,6 +9,8 @@ declare const UniqueTags: Set<string>;
|
|
|
11
9
|
declare const TagConfigKeys: Set<string>;
|
|
12
10
|
declare const IsBrowser: boolean;
|
|
13
11
|
declare const composableNames: string[];
|
|
12
|
+
declare const NetworkEvents: Set<string>;
|
|
13
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
14
14
|
|
|
15
15
|
declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
16
16
|
|
|
@@ -31,20 +31,14 @@ declare function unpackMeta<T extends MetaFlatInput>(input: T): Required<Head>['
|
|
|
31
31
|
*/
|
|
32
32
|
declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlatInput;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
36
|
-
|
|
37
|
-
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
34
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): T | T[];
|
|
38
35
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
39
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
36
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): T["props"];
|
|
40
37
|
declare const TagEntityBits = 10;
|
|
41
|
-
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>):
|
|
38
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): HeadTag[];
|
|
42
39
|
|
|
43
40
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
44
41
|
|
|
45
|
-
declare const NetworkEvents: Set<string>;
|
|
46
|
-
declare const ScriptNetworkEvents: Set<string>;
|
|
47
|
-
|
|
48
42
|
declare const TAG_WEIGHTS: {
|
|
49
43
|
readonly base: -10;
|
|
50
44
|
readonly title: 10;
|
|
@@ -54,11 +48,11 @@ declare const TAG_ALIASES: {
|
|
|
54
48
|
readonly high: -10;
|
|
55
49
|
readonly low: 20;
|
|
56
50
|
};
|
|
57
|
-
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
58
51
|
declare const SortModifiers: {
|
|
59
52
|
prefix: string;
|
|
60
53
|
offset: number;
|
|
61
54
|
}[];
|
|
55
|
+
declare function tagWeight<T extends HeadTag>(head: Unhead<any>, tag: T): number;
|
|
62
56
|
|
|
63
57
|
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
64
58
|
|
|
@@ -66,4 +60,7 @@ declare function processTemplateParams(s: string, p: TemplateParams, sep: string
|
|
|
66
60
|
|
|
67
61
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
68
62
|
|
|
69
|
-
|
|
63
|
+
type Arrayable<T> = T | Array<T>;
|
|
64
|
+
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
65
|
+
|
|
66
|
+
export { type Arrayable, DupeableTags, 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, TemplateParams } from '@unhead/schema';
|
|
2
|
-
|
|
3
|
-
type Arrayable<T> = T | Array<T>;
|
|
4
|
-
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
1
|
+
import { HeadPluginInput, HeadTag, BaseMeta, MetaFlatInput, Head, HeadEntry, MaybeArray, HeadSafe, Unhead, TemplateParams } from '@unhead/schema';
|
|
5
2
|
|
|
6
3
|
declare const SelfClosingTags: Set<string>;
|
|
4
|
+
declare const DupeableTags: Set<string>;
|
|
7
5
|
declare const TagsWithInnerContent: Set<string>;
|
|
8
6
|
declare const HasElementTags: Set<string>;
|
|
9
7
|
declare const ValidHeadTags: Set<string>;
|
|
@@ -11,6 +9,8 @@ declare const UniqueTags: Set<string>;
|
|
|
11
9
|
declare const TagConfigKeys: Set<string>;
|
|
12
10
|
declare const IsBrowser: boolean;
|
|
13
11
|
declare const composableNames: string[];
|
|
12
|
+
declare const NetworkEvents: Set<string>;
|
|
13
|
+
declare const ScriptNetworkEvents: Set<string>;
|
|
14
14
|
|
|
15
15
|
declare function defineHeadPlugin(plugin: HeadPluginInput): HeadPluginInput;
|
|
16
16
|
|
|
@@ -31,20 +31,14 @@ declare function unpackMeta<T extends MetaFlatInput>(input: T): Required<Head>['
|
|
|
31
31
|
*/
|
|
32
32
|
declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlatInput;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
declare function thenable<T, R>(val: T, thenFn: (val: Awaited<T>) => R): Promise<R> | R;
|
|
36
|
-
|
|
37
|
-
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): Thenable<T | T[]>;
|
|
34
|
+
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>, normalizedProps?: HeadTag['props']): T | T[];
|
|
38
35
|
declare function normaliseStyleClassProps<T extends 'class' | 'style'>(key: T, v: Required<Required<Head>['htmlAttrs']['class']> | Required<Required<Head>['htmlAttrs']['style']>): string;
|
|
39
|
-
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean):
|
|
36
|
+
declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): T["props"];
|
|
40
37
|
declare const TagEntityBits = 10;
|
|
41
|
-
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>):
|
|
38
|
+
declare function normaliseEntryTags<T extends object = Head>(e: HeadEntry<T>): HeadTag[];
|
|
42
39
|
|
|
43
40
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
44
41
|
|
|
45
|
-
declare const NetworkEvents: Set<string>;
|
|
46
|
-
declare const ScriptNetworkEvents: Set<string>;
|
|
47
|
-
|
|
48
42
|
declare const TAG_WEIGHTS: {
|
|
49
43
|
readonly base: -10;
|
|
50
44
|
readonly title: 10;
|
|
@@ -54,11 +48,11 @@ declare const TAG_ALIASES: {
|
|
|
54
48
|
readonly high: -10;
|
|
55
49
|
readonly low: 20;
|
|
56
50
|
};
|
|
57
|
-
declare function tagWeight<T extends HeadTag>(tag: T): number;
|
|
58
51
|
declare const SortModifiers: {
|
|
59
52
|
prefix: string;
|
|
60
53
|
offset: number;
|
|
61
54
|
}[];
|
|
55
|
+
declare function tagWeight<T extends HeadTag>(head: Unhead<any>, tag: T): number;
|
|
62
56
|
|
|
63
57
|
declare function tagDedupeKey<T extends HeadTag>(tag: T): string | false;
|
|
64
58
|
|
|
@@ -66,4 +60,7 @@ declare function processTemplateParams(s: string, p: TemplateParams, sep: string
|
|
|
66
60
|
|
|
67
61
|
declare function resolveTitleTemplate(template: string | ((title?: string) => string | null) | null, title?: string): string | null;
|
|
68
62
|
|
|
69
|
-
|
|
63
|
+
type Arrayable<T> = T | Array<T>;
|
|
64
|
+
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
65
|
+
|
|
66
|
+
export { type Arrayable, DupeableTags, 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 };
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { unpackToString, unpackToArray, packArray } from 'packrup';
|
|
2
2
|
|
|
3
|
-
function asArray(value) {
|
|
4
|
-
return Array.isArray(value) ? value : [value];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
3
|
const SelfClosingTags = /* @__PURE__ */ new Set(["meta", "link", "base"]);
|
|
4
|
+
const DupeableTags = /* @__PURE__ */ new Set(["link", "style", "script", "noscript"]);
|
|
8
5
|
const TagsWithInnerContent = /* @__PURE__ */ new Set(["title", "titleTemplate", "script", "style", "noscript"]);
|
|
9
6
|
const HasElementTags = /* @__PURE__ */ new Set([
|
|
10
7
|
"base",
|
|
@@ -28,10 +25,9 @@ const ValidHeadTags = /* @__PURE__ */ new Set([
|
|
|
28
25
|
"noscript"
|
|
29
26
|
]);
|
|
30
27
|
const UniqueTags = /* @__PURE__ */ new Set(["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"]);
|
|
31
|
-
const TagConfigKeys = /* @__PURE__ */ new Set(["
|
|
28
|
+
const TagConfigKeys = /* @__PURE__ */ new Set(["key", "tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"]);
|
|
32
29
|
const IsBrowser = typeof window !== "undefined";
|
|
33
30
|
const composableNames = [
|
|
34
|
-
"getActiveHead",
|
|
35
31
|
"useHead",
|
|
36
32
|
"useSeoMeta",
|
|
37
33
|
"useHeadSafe",
|
|
@@ -39,6 +35,8 @@ const composableNames = [
|
|
|
39
35
|
"useServerSeoMeta",
|
|
40
36
|
"useServerHeadSafe"
|
|
41
37
|
];
|
|
38
|
+
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
39
|
+
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
42
40
|
|
|
43
41
|
function defineHeadPlugin(plugin) {
|
|
44
42
|
return plugin;
|
|
@@ -285,40 +283,55 @@ function packMeta(inputs) {
|
|
|
285
283
|
});
|
|
286
284
|
}
|
|
287
285
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
287
|
+
function tagDedupeKey(tag) {
|
|
288
|
+
const { props, tag: tagName } = tag;
|
|
289
|
+
if (UniqueTags.has(tagName))
|
|
290
|
+
return tagName;
|
|
291
|
+
if (tagName === "link" && props.rel === "canonical")
|
|
292
|
+
return "canonical";
|
|
293
|
+
if (props.charset)
|
|
294
|
+
return "charset";
|
|
295
|
+
if (props.id) {
|
|
296
|
+
return `${tagName}:id:${props.id}`;
|
|
291
297
|
}
|
|
292
|
-
|
|
298
|
+
for (const n of allowedMetaProperties) {
|
|
299
|
+
if (props[n] !== undefined) {
|
|
300
|
+
return `${tagName}:${n}:${props[n]}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
293
304
|
}
|
|
294
305
|
|
|
295
306
|
function normaliseTag(tagName, input, e, normalizedProps) {
|
|
296
307
|
const props = normalizedProps || normaliseProps(
|
|
297
308
|
// explicitly check for an object
|
|
298
|
-
|
|
299
|
-
typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
309
|
+
typeof input === "object" && typeof input !== "function" ? { ...input } : { [tagName === "script" || tagName === "noscript" || tagName === "style" ? "innerHTML" : "textContent"]: input },
|
|
300
310
|
tagName === "templateParams" || tagName === "titleTemplate"
|
|
301
311
|
);
|
|
302
|
-
if (props instanceof Promise) {
|
|
303
|
-
return props.then((val) => normaliseTag(tagName, input, e, val));
|
|
304
|
-
}
|
|
305
312
|
const tag = {
|
|
306
313
|
tag: tagName,
|
|
307
314
|
props
|
|
308
315
|
};
|
|
309
316
|
for (const k of TagConfigKeys) {
|
|
310
|
-
const val = tag.props[k] !==
|
|
311
|
-
if (val !==
|
|
312
|
-
if (!(k === "innerHTML" || k === "textContent"
|
|
313
|
-
tag[k
|
|
317
|
+
const val = tag.props[k] !== undefined ? tag.props[k] : e[k];
|
|
318
|
+
if (val !== undefined) {
|
|
319
|
+
if (!(k === "innerHTML" || k === "textContent") || TagsWithInnerContent.has(tag.tag)) {
|
|
320
|
+
tag[k] = val;
|
|
314
321
|
}
|
|
315
322
|
delete tag.props[k];
|
|
316
323
|
}
|
|
317
324
|
}
|
|
318
|
-
if (tag.
|
|
319
|
-
tag.
|
|
320
|
-
delete tag.props.body;
|
|
325
|
+
if (tag.key && DupeableTags.has(tag.tag)) {
|
|
326
|
+
tag.props["data-hid"] = tag._h = hashCode(tag.key);
|
|
321
327
|
}
|
|
328
|
+
const generatedKey = tagDedupeKey(tag);
|
|
329
|
+
if (generatedKey && !generatedKey.startsWith("meta:og:") && !generatedKey.startsWith("meta:twitter:")) {
|
|
330
|
+
delete tag.key;
|
|
331
|
+
}
|
|
332
|
+
const dedupe = generatedKey || (tag.key ? `${tag.tag}:${tag.key}` : false);
|
|
333
|
+
if (dedupe)
|
|
334
|
+
tag._d = dedupe;
|
|
322
335
|
if (tag.tag === "script") {
|
|
323
336
|
if (typeof tag.innerHTML === "object") {
|
|
324
337
|
tag.innerHTML = JSON.stringify(tag.innerHTML);
|
|
@@ -334,20 +347,16 @@ function normaliseStyleClassProps(key, v) {
|
|
|
334
347
|
}
|
|
335
348
|
return String(Array.isArray(v) ? v.join(sep) : v)?.split(sep).filter((c) => Boolean(c.trim())).join(sep);
|
|
336
349
|
}
|
|
337
|
-
function
|
|
338
|
-
for (
|
|
339
|
-
const k = keys[i];
|
|
350
|
+
function normaliseProps(props, virtual = false) {
|
|
351
|
+
for (const k in props) {
|
|
340
352
|
if (k === "class" || k === "style") {
|
|
341
353
|
props[k] = normaliseStyleClassProps(k, props[k]);
|
|
342
354
|
continue;
|
|
343
355
|
}
|
|
344
|
-
if (props[k] instanceof Promise) {
|
|
345
|
-
return props[k].then((val) => {
|
|
346
|
-
props[k] = val;
|
|
347
|
-
return nestedNormaliseProps(props, virtual, keys, i);
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
356
|
if (!virtual && !TagConfigKeys.has(k)) {
|
|
357
|
+
if (typeof props[k] === "function" && !String(k).startsWith("on")) {
|
|
358
|
+
props[k] = props[k]();
|
|
359
|
+
}
|
|
351
360
|
const v = String(props[k]);
|
|
352
361
|
const isDataKey = k.startsWith("data-");
|
|
353
362
|
if (v === "true" || v === "") {
|
|
@@ -360,60 +369,37 @@ function nestedNormaliseProps(props, virtual, keys, startIndex) {
|
|
|
360
369
|
}
|
|
361
370
|
}
|
|
362
371
|
}
|
|
363
|
-
}
|
|
364
|
-
function normaliseProps(props, virtual = false) {
|
|
365
|
-
const resolvedProps = nestedNormaliseProps(props, virtual, Object.keys(props), 0);
|
|
366
|
-
if (resolvedProps instanceof Promise) {
|
|
367
|
-
return resolvedProps.then(() => props);
|
|
368
|
-
}
|
|
369
372
|
return props;
|
|
370
373
|
}
|
|
371
374
|
const TagEntityBits = 10;
|
|
372
|
-
function nestedNormaliseEntryTags(headTags, tagPromises, startIndex) {
|
|
373
|
-
for (let i = startIndex; i < tagPromises.length; i += 1) {
|
|
374
|
-
const tags = tagPromises[i];
|
|
375
|
-
if (tags instanceof Promise) {
|
|
376
|
-
return tags.then((val) => {
|
|
377
|
-
tagPromises[i] = val;
|
|
378
|
-
return nestedNormaliseEntryTags(headTags, tagPromises, i);
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
if (Array.isArray(tags)) {
|
|
382
|
-
headTags.push(...tags);
|
|
383
|
-
} else {
|
|
384
|
-
headTags.push(tags);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
375
|
function normaliseEntryTags(e) {
|
|
389
|
-
const
|
|
376
|
+
const tags = [];
|
|
390
377
|
const input = e.resolvedInput;
|
|
391
378
|
for (const k in input) {
|
|
392
379
|
if (!Object.prototype.hasOwnProperty.call(input, k)) {
|
|
393
380
|
continue;
|
|
394
381
|
}
|
|
395
382
|
const v = input[k];
|
|
396
|
-
if (v ===
|
|
383
|
+
if (v === undefined || !ValidHeadTags.has(k)) {
|
|
397
384
|
continue;
|
|
398
385
|
}
|
|
399
386
|
if (Array.isArray(v)) {
|
|
400
387
|
for (const props of v) {
|
|
401
|
-
|
|
388
|
+
tags.push(normaliseTag(k, props, e));
|
|
402
389
|
}
|
|
403
390
|
continue;
|
|
391
|
+
} else if (typeof v === "function" && k !== "titleTemplate") {
|
|
392
|
+
input[k] = v();
|
|
393
|
+
continue;
|
|
404
394
|
}
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
if (tagPromises.length === 0) {
|
|
408
|
-
return [];
|
|
395
|
+
tags.push(normaliseTag(k, v, e));
|
|
409
396
|
}
|
|
410
|
-
|
|
411
|
-
return thenable(nestedNormaliseEntryTags(headTags, tagPromises, 0), () => headTags.map((t, i) => {
|
|
397
|
+
return tags.flat().map((t, i) => {
|
|
412
398
|
t._e = e._i;
|
|
413
399
|
e.mode && (t._m = e.mode);
|
|
414
400
|
t._p = (e._i << TagEntityBits) + i;
|
|
415
401
|
return t;
|
|
416
|
-
})
|
|
402
|
+
});
|
|
417
403
|
}
|
|
418
404
|
|
|
419
405
|
const WhitelistAttributes = {
|
|
@@ -509,7 +495,7 @@ function whitelistSafeInput(input) {
|
|
|
509
495
|
try {
|
|
510
496
|
const jsonVal = typeof script[s] === "string" ? JSON.parse(script[s]) : script[s];
|
|
511
497
|
safeScript[s] = JSON.stringify(jsonVal, null, 0);
|
|
512
|
-
} catch
|
|
498
|
+
} catch {
|
|
513
499
|
}
|
|
514
500
|
} else {
|
|
515
501
|
safeScript[s] = script[s];
|
|
@@ -525,9 +511,6 @@ function whitelistSafeInput(input) {
|
|
|
525
511
|
return filtered;
|
|
526
512
|
}
|
|
527
513
|
|
|
528
|
-
const NetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror", "onabort", "onprogress", "onloadstart"]);
|
|
529
|
-
const ScriptNetworkEvents = /* @__PURE__ */ new Set(["onload", "onerror"]);
|
|
530
|
-
|
|
531
514
|
const TAG_WEIGHTS = {
|
|
532
515
|
// tags
|
|
533
516
|
base: -10,
|
|
@@ -539,10 +522,16 @@ const TAG_ALIASES = {
|
|
|
539
522
|
high: -10,
|
|
540
523
|
low: 20
|
|
541
524
|
};
|
|
542
|
-
|
|
525
|
+
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
526
|
+
const importRe = /@import/;
|
|
527
|
+
const isTruthy = (val) => val === "" || val === true;
|
|
528
|
+
function tagWeight(head, tag) {
|
|
543
529
|
const priority = tag.tagPriority;
|
|
544
530
|
if (typeof priority === "number")
|
|
545
531
|
return priority;
|
|
532
|
+
const isScript = tag.tag === "script";
|
|
533
|
+
const isLink = tag.tag === "link";
|
|
534
|
+
const isStyle = tag.tag === "style";
|
|
546
535
|
let weight = 100;
|
|
547
536
|
if (tag.tag === "meta") {
|
|
548
537
|
if (tag.props["http-equiv"] === "content-security-policy")
|
|
@@ -551,7 +540,7 @@ function tagWeight(tag) {
|
|
|
551
540
|
weight = -20;
|
|
552
541
|
else if (tag.props.name === "viewport")
|
|
553
542
|
weight = -15;
|
|
554
|
-
} else if (
|
|
543
|
+
} else if (isLink && tag.props.rel === "preconnect") {
|
|
555
544
|
weight = 20;
|
|
556
545
|
} else if (tag.tag in TAG_WEIGHTS) {
|
|
557
546
|
weight = TAG_WEIGHTS[tag.tag];
|
|
@@ -559,28 +548,28 @@ function tagWeight(tag) {
|
|
|
559
548
|
if (priority && priority in TAG_ALIASES) {
|
|
560
549
|
return weight + TAG_ALIASES[priority];
|
|
561
550
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const SortModifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
|
|
565
|
-
|
|
566
|
-
const allowedMetaProperties = ["name", "property", "http-equiv"];
|
|
567
|
-
function tagDedupeKey(tag) {
|
|
568
|
-
const { props, tag: tagName } = tag;
|
|
569
|
-
if (UniqueTags.has(tagName))
|
|
570
|
-
return tagName;
|
|
571
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
572
|
-
return "canonical";
|
|
573
|
-
if (props.charset)
|
|
574
|
-
return "charset";
|
|
575
|
-
if (props.id) {
|
|
576
|
-
return `${tagName}:id:${props.id}`;
|
|
551
|
+
if (tag.tagPosition && tag.tagPosition !== "head") {
|
|
552
|
+
return weight;
|
|
577
553
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
return `${tagName}:${n}:${props[n]}`;
|
|
581
|
-
}
|
|
554
|
+
if (!head.ssr || head.resolvedOptions.disableCapoSorting) {
|
|
555
|
+
return weight;
|
|
582
556
|
}
|
|
583
|
-
|
|
557
|
+
if (isScript && isTruthy(tag.props.async)) {
|
|
558
|
+
weight = 30;
|
|
559
|
+
} else if (isStyle && tag.innerHTML && importRe.test(tag.innerHTML)) {
|
|
560
|
+
weight = 40;
|
|
561
|
+
} else if (isScript && tag.props.src && !isTruthy(tag.props.defer) && !isTruthy(tag.props.async) && tag.props.type !== "module" && !tag.props.type?.endsWith("json")) {
|
|
562
|
+
weight = 50;
|
|
563
|
+
} else if (isLink && tag.props.rel === "stylesheet" || tag.tag === "style") {
|
|
564
|
+
weight = 60;
|
|
565
|
+
} else if (isLink && (tag.props.rel === "preload" || tag.props.rel === "modulepreload")) {
|
|
566
|
+
weight = 70;
|
|
567
|
+
} else if (isScript && isTruthy(tag.props.defer) && tag.props.src && !isTruthy(tag.props.async)) {
|
|
568
|
+
weight = 80;
|
|
569
|
+
} else if (isLink && (tag.props.rel === "prefetch" || tag.props.rel === "dns-prefetch" || tag.props.rel === "prerender")) {
|
|
570
|
+
weight = 90;
|
|
571
|
+
}
|
|
572
|
+
return weight;
|
|
584
573
|
}
|
|
585
574
|
|
|
586
575
|
const sepSub = "%separator";
|
|
@@ -594,10 +583,10 @@ function sub(p, token, isJson = false) {
|
|
|
594
583
|
} else {
|
|
595
584
|
val = p[token];
|
|
596
585
|
}
|
|
597
|
-
if (val !==
|
|
586
|
+
if (val !== undefined) {
|
|
598
587
|
return isJson ? (val || "").replace(/"/g, '\\"') : val || "";
|
|
599
588
|
}
|
|
600
|
-
return
|
|
589
|
+
return undefined;
|
|
601
590
|
}
|
|
602
591
|
const sepSubRe = new RegExp(`${sepSub}(?:\\s*${sepSub})*`, "g");
|
|
603
592
|
function processTemplateParams(s, p, sep, isJson = false) {
|
|
@@ -618,7 +607,7 @@ function processTemplateParams(s, p, sep, isJson = false) {
|
|
|
618
607
|
return token;
|
|
619
608
|
}
|
|
620
609
|
const re = sub(p, token.slice(1), isJson);
|
|
621
|
-
return re !==
|
|
610
|
+
return re !== undefined ? re : token;
|
|
622
611
|
}).trim();
|
|
623
612
|
if (hasSepSub) {
|
|
624
613
|
if (s.endsWith(sepSub))
|
|
@@ -638,4 +627,8 @@ function resolveTitleTemplate(template, title) {
|
|
|
638
627
|
return template;
|
|
639
628
|
}
|
|
640
629
|
|
|
641
|
-
|
|
630
|
+
function asArray(value) {
|
|
631
|
+
return Array.isArray(value) ? value : [value];
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export { DupeableTags, 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 };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unhead/shared",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0-alpha.0",
|
|
5
5
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
@@ -35,11 +35,10 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"packrup": "^0.1.2",
|
|
38
|
-
"@unhead/schema": "
|
|
38
|
+
"@unhead/schema": "2.0.0-alpha.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "unbuild .",
|
|
42
|
-
"stub": "unbuild . --stub"
|
|
43
|
-
"export:sizes": "npx export-size . -r"
|
|
42
|
+
"stub": "unbuild . --stub"
|
|
44
43
|
}
|
|
45
44
|
}
|