unhead 1.1.9 → 1.1.11
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 +134 -35
- package/dist/index.d.ts +4 -16
- package/dist/index.mjs +141 -39
- package/package.json +7 -5
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const hookable = require('hookable');
|
|
4
4
|
const dom = require('@unhead/dom');
|
|
5
5
|
const shared = require('@unhead/shared');
|
|
6
|
-
const packrup = require('packrup');
|
|
7
6
|
|
|
8
7
|
const TAG_WEIGHTS = {
|
|
9
8
|
// aliases
|
|
@@ -391,6 +390,102 @@ const useServerHtmlAttrs = (attrs) => useServerHead({ htmlAttrs: attrs });
|
|
|
391
390
|
const useServerBodyAttrs = (attrs) => useServerHead({ bodyAttrs: attrs });
|
|
392
391
|
const useServerTitleTemplate = (titleTemplate) => useServerHead({ titleTemplate });
|
|
393
392
|
|
|
393
|
+
function asArray(input) {
|
|
394
|
+
return Array.isArray(input) ? input : [input];
|
|
395
|
+
}
|
|
396
|
+
const InternalKeySymbol = "_$key";
|
|
397
|
+
function packObject(input, options) {
|
|
398
|
+
const keys = Object.keys(input);
|
|
399
|
+
let [k, v] = keys;
|
|
400
|
+
options = options || {};
|
|
401
|
+
options.key = options.key || k;
|
|
402
|
+
options.value = options.value || v;
|
|
403
|
+
options.resolveKey = options.resolveKey || ((k2) => k2);
|
|
404
|
+
const resolveKey = (index) => {
|
|
405
|
+
const arr = asArray(options?.[index]);
|
|
406
|
+
return arr.find((k2) => {
|
|
407
|
+
if (typeof k2 === "string" && k2.includes(".")) {
|
|
408
|
+
return k2;
|
|
409
|
+
}
|
|
410
|
+
return k2 && keys.includes(k2);
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
const resolveValue = (k2, input2) => {
|
|
414
|
+
if (k2.includes(".")) {
|
|
415
|
+
const paths = k2.split(".");
|
|
416
|
+
let val = input2;
|
|
417
|
+
for (const path of paths)
|
|
418
|
+
val = val[path];
|
|
419
|
+
return val;
|
|
420
|
+
}
|
|
421
|
+
return input2[k2];
|
|
422
|
+
};
|
|
423
|
+
k = resolveKey("key") || k;
|
|
424
|
+
v = resolveKey("value") || v;
|
|
425
|
+
const dedupeKeyPrefix = input.key ? `${InternalKeySymbol}${input.key}-` : "";
|
|
426
|
+
let keyValue = resolveValue(k, input);
|
|
427
|
+
keyValue = options.resolveKey(keyValue);
|
|
428
|
+
return {
|
|
429
|
+
[`${dedupeKeyPrefix}${keyValue}`]: resolveValue(v, input)
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function packArray(input, options) {
|
|
434
|
+
const packed = {};
|
|
435
|
+
for (const i of input) {
|
|
436
|
+
const packedObj = packObject(i, options);
|
|
437
|
+
const pKey = Object.keys(packedObj)[0];
|
|
438
|
+
const isDedupeKey = pKey.startsWith(InternalKeySymbol);
|
|
439
|
+
if (!isDedupeKey && packed[pKey]) {
|
|
440
|
+
packed[pKey] = Array.isArray(packed[pKey]) ? packed[pKey] : [packed[pKey]];
|
|
441
|
+
packed[pKey].push(Object.values(packedObj)[0]);
|
|
442
|
+
} else {
|
|
443
|
+
packed[isDedupeKey ? pKey.split("-").slice(1).join("-") || pKey : pKey] = packedObj[pKey];
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return packed;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function unpackToArray(input, options) {
|
|
450
|
+
const unpacked = [];
|
|
451
|
+
const kFn = options.resolveKeyData || ((ctx) => ctx.key);
|
|
452
|
+
const vFn = options.resolveValueData || ((ctx) => ctx.value);
|
|
453
|
+
for (const [k, v] of Object.entries(input)) {
|
|
454
|
+
unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => {
|
|
455
|
+
const ctx = { key: k, value: i };
|
|
456
|
+
const val = vFn(ctx);
|
|
457
|
+
if (typeof val === "object")
|
|
458
|
+
return unpackToArray(val, options);
|
|
459
|
+
if (Array.isArray(val))
|
|
460
|
+
return val;
|
|
461
|
+
return {
|
|
462
|
+
[typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx),
|
|
463
|
+
[typeof options.value === "function" ? options.value(ctx) : options.value]: val
|
|
464
|
+
};
|
|
465
|
+
}).flat());
|
|
466
|
+
}
|
|
467
|
+
return unpacked;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function unpackToString(value, options) {
|
|
471
|
+
return Object.entries(value).map(([key, value2]) => {
|
|
472
|
+
if (typeof value2 === "object")
|
|
473
|
+
value2 = unpackToString(value2, options);
|
|
474
|
+
if (options.resolve) {
|
|
475
|
+
const resolved = options.resolve({ key, value: value2 });
|
|
476
|
+
if (resolved)
|
|
477
|
+
return resolved;
|
|
478
|
+
}
|
|
479
|
+
if (typeof value2 === "number")
|
|
480
|
+
value2 = value2.toString();
|
|
481
|
+
if (typeof value2 === "string" && options.wrapValue) {
|
|
482
|
+
value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`);
|
|
483
|
+
value2 = `${options.wrapValue}${value2}${options.wrapValue}`;
|
|
484
|
+
}
|
|
485
|
+
return `${key}${options.keyValueSeparator || ""}${value2}`;
|
|
486
|
+
}).join(options.entrySeparator || "");
|
|
487
|
+
}
|
|
488
|
+
|
|
394
489
|
const MetaPackingSchema = {
|
|
395
490
|
robots: {
|
|
396
491
|
unpack: {
|
|
@@ -440,13 +535,10 @@ const MetaPackingSchema = {
|
|
|
440
535
|
metaKey: "http-equiv"
|
|
441
536
|
}
|
|
442
537
|
};
|
|
443
|
-
function resolveMetaKeyType(key) {
|
|
444
|
-
return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name";
|
|
445
|
-
}
|
|
446
538
|
|
|
447
539
|
function packMeta(inputs) {
|
|
448
540
|
const mappedPackingSchema = Object.entries(MetaPackingSchema).map(([key, value]) => [key, value.keyValue]);
|
|
449
|
-
return
|
|
541
|
+
return packArray(inputs, {
|
|
450
542
|
key: ["name", "property", "httpEquiv", "http-equiv", "charset"],
|
|
451
543
|
value: ["content", "charset"],
|
|
452
544
|
resolveKey(k) {
|
|
@@ -459,6 +551,32 @@ function packMeta(inputs) {
|
|
|
459
551
|
}
|
|
460
552
|
|
|
461
553
|
const ArrayableInputs = ["Image", "Video", "Audio"];
|
|
554
|
+
const ColonPrefixKeys = /^(og|twitter|fb)/;
|
|
555
|
+
const PropertyPrefixKeys = /^(og|fb)/;
|
|
556
|
+
function resolveMetaKeyType(key) {
|
|
557
|
+
return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name";
|
|
558
|
+
}
|
|
559
|
+
function resolveMetaKeyValue(key) {
|
|
560
|
+
return MetaPackingSchema[key]?.keyValue || fixKeyCase(key);
|
|
561
|
+
}
|
|
562
|
+
function fixKeyCase(key) {
|
|
563
|
+
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
564
|
+
if (ColonPrefixKeys.test(key)) {
|
|
565
|
+
key = key.replace("secure-url", "secure_url").replace(/-/g, ":");
|
|
566
|
+
}
|
|
567
|
+
return key;
|
|
568
|
+
}
|
|
569
|
+
function changeKeyCasingDeep(input) {
|
|
570
|
+
if (Array.isArray(input)) {
|
|
571
|
+
return input.map((entry) => changeKeyCasingDeep(entry));
|
|
572
|
+
}
|
|
573
|
+
if (typeof input !== "object" || Array.isArray(input))
|
|
574
|
+
return input;
|
|
575
|
+
const output = {};
|
|
576
|
+
for (const [key, value] of Object.entries(input))
|
|
577
|
+
output[fixKeyCase(key)] = changeKeyCasingDeep(value);
|
|
578
|
+
return output;
|
|
579
|
+
}
|
|
462
580
|
function unpackMeta(input) {
|
|
463
581
|
const extras = [];
|
|
464
582
|
ArrayableInputs.forEach((key) => {
|
|
@@ -469,7 +587,7 @@ function unpackMeta(input) {
|
|
|
469
587
|
(Array.isArray(val) ? val : [val]).forEach((entry) => {
|
|
470
588
|
if (!entry)
|
|
471
589
|
return;
|
|
472
|
-
const unpackedEntry =
|
|
590
|
+
const unpackedEntry = unpackToArray(entry, {
|
|
473
591
|
key: "property",
|
|
474
592
|
value: "content",
|
|
475
593
|
resolveKeyData({ key: key2 }) {
|
|
@@ -486,7 +604,7 @@ function unpackMeta(input) {
|
|
|
486
604
|
delete input[inputKey];
|
|
487
605
|
}
|
|
488
606
|
});
|
|
489
|
-
const meta =
|
|
607
|
+
const meta = unpackToArray(input, {
|
|
490
608
|
key({ key }) {
|
|
491
609
|
return resolveMetaKeyType(key);
|
|
492
610
|
},
|
|
@@ -494,7 +612,7 @@ function unpackMeta(input) {
|
|
|
494
612
|
return key === "charset" ? "charset" : "content";
|
|
495
613
|
},
|
|
496
614
|
resolveKeyData({ key }) {
|
|
497
|
-
return
|
|
615
|
+
return resolveMetaKeyValue(key);
|
|
498
616
|
},
|
|
499
617
|
resolveValueData({ value, key }) {
|
|
500
618
|
if (value === null)
|
|
@@ -510,7 +628,7 @@ function resolvePackedMetaObjectValue(value, key) {
|
|
|
510
628
|
const definition = MetaPackingSchema[key];
|
|
511
629
|
if (key === "refresh")
|
|
512
630
|
return `${value.seconds};url=${value.url}`;
|
|
513
|
-
return
|
|
631
|
+
return unpackToString(
|
|
514
632
|
changeKeyCasingDeep(value),
|
|
515
633
|
{
|
|
516
634
|
entrySeparator: ", ",
|
|
@@ -609,27 +727,6 @@ async function normaliseEntryTags(e) {
|
|
|
609
727
|
});
|
|
610
728
|
}
|
|
611
729
|
|
|
612
|
-
const PropertyPrefixKeys = /^(og|fb)/;
|
|
613
|
-
const ColonPrefixKeys = /^(og|twitter|fb)/;
|
|
614
|
-
function fixKeyCase(key) {
|
|
615
|
-
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
616
|
-
if (ColonPrefixKeys.test(key)) {
|
|
617
|
-
key = key.replace("secure-url", "secure_url").replace(/-/g, ":");
|
|
618
|
-
}
|
|
619
|
-
return key;
|
|
620
|
-
}
|
|
621
|
-
function changeKeyCasingDeep(input) {
|
|
622
|
-
if (Array.isArray(input)) {
|
|
623
|
-
return input.map((entry) => changeKeyCasingDeep(entry));
|
|
624
|
-
}
|
|
625
|
-
if (typeof input !== "object" || Array.isArray(input))
|
|
626
|
-
return input;
|
|
627
|
-
const output = {};
|
|
628
|
-
for (const [key, value] of Object.entries(input))
|
|
629
|
-
output[fixKeyCase(key)] = changeKeyCasingDeep(value);
|
|
630
|
-
return output;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
730
|
const WhitelistAttributes = {
|
|
634
731
|
htmlAttrs: ["id", "class", "lang", "dir"],
|
|
635
732
|
bodyAttrs: ["id", "class"],
|
|
@@ -757,6 +854,11 @@ function createHead(options = {}) {
|
|
|
757
854
|
setActiveHead(head);
|
|
758
855
|
return head;
|
|
759
856
|
}
|
|
857
|
+
function createServerHead(options = {}) {
|
|
858
|
+
const head = createHeadCore(options);
|
|
859
|
+
setActiveHead(head);
|
|
860
|
+
return head;
|
|
861
|
+
}
|
|
760
862
|
function createHeadCore(options = {}) {
|
|
761
863
|
let entries = [];
|
|
762
864
|
let _sde = {};
|
|
@@ -886,14 +988,11 @@ const unheadComposablesImports = [
|
|
|
886
988
|
}
|
|
887
989
|
];
|
|
888
990
|
|
|
889
|
-
exports.ColonPrefixKeys = ColonPrefixKeys;
|
|
890
991
|
exports.CorePlugins = CorePlugins;
|
|
891
992
|
exports.DOMPlugins = DOMPlugins;
|
|
892
993
|
exports.DedupesTagsPlugin = DedupesTagsPlugin;
|
|
893
994
|
exports.DeprecatedTagAttrPlugin = DeprecatedTagAttrPlugin;
|
|
894
995
|
exports.EventHandlersPlugin = EventHandlersPlugin;
|
|
895
|
-
exports.MetaPackingSchema = MetaPackingSchema;
|
|
896
|
-
exports.PropertyPrefixKeys = PropertyPrefixKeys;
|
|
897
996
|
exports.ProvideTagHashPlugin = ProvideTagHashPlugin;
|
|
898
997
|
exports.SortModifiers = SortModifiers;
|
|
899
998
|
exports.SortTagsPlugin = SortTagsPlugin;
|
|
@@ -901,11 +1000,10 @@ exports.TAG_WEIGHTS = TAG_WEIGHTS;
|
|
|
901
1000
|
exports.TagEntityBits = TagEntityBits;
|
|
902
1001
|
exports.TemplateParamsPlugin = TemplateParamsPlugin;
|
|
903
1002
|
exports.TitleTemplatePlugin = TitleTemplatePlugin;
|
|
904
|
-
exports.changeKeyCasingDeep = changeKeyCasingDeep;
|
|
905
1003
|
exports.composableNames = composableNames;
|
|
906
1004
|
exports.createHead = createHead;
|
|
907
1005
|
exports.createHeadCore = createHeadCore;
|
|
908
|
-
exports.
|
|
1006
|
+
exports.createServerHead = createServerHead;
|
|
909
1007
|
exports.getActiveHead = getActiveHead;
|
|
910
1008
|
exports.normaliseClassProp = normaliseClassProp;
|
|
911
1009
|
exports.normaliseEntryTags = normaliseEntryTags;
|
|
@@ -914,6 +1012,7 @@ exports.normaliseTag = normaliseTag;
|
|
|
914
1012
|
exports.packMeta = packMeta;
|
|
915
1013
|
exports.renderTitleTemplate = renderTitleTemplate;
|
|
916
1014
|
exports.resolveMetaKeyType = resolveMetaKeyType;
|
|
1015
|
+
exports.resolveMetaKeyValue = resolveMetaKeyValue;
|
|
917
1016
|
exports.resolvePackedMetaObjectValue = resolvePackedMetaObjectValue;
|
|
918
1017
|
exports.setActiveHead = setActiveHead;
|
|
919
1018
|
exports.tagWeight = tagWeight;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import * as _unhead_schema from '@unhead/schema';
|
|
|
2
2
|
import { HeadTag, Head, HeadEntryOptions, ActiveHeadEntry, HeadSafe, MetaFlatInput, Title, TitleTemplate, Base, Meta, Link, Script, Style, Noscript, HtmlAttributes, BodyAttributes, Unhead, HeadPlugin, CreateHeadOptions, HeadEntry, MaybeArray } from '@unhead/schema';
|
|
3
3
|
import { Arrayable } from '@unhead/shared';
|
|
4
4
|
export * from '@unhead/shared';
|
|
5
|
-
import { TransformValueOptions } from 'packrup';
|
|
6
5
|
|
|
7
6
|
declare const TAG_WEIGHTS: {
|
|
8
7
|
readonly critical: 2;
|
|
@@ -152,6 +151,7 @@ declare const getActiveHead: () => Unhead<any> | undefined;
|
|
|
152
151
|
declare const CorePlugins: () => HeadPlugin[];
|
|
153
152
|
declare const DOMPlugins: (options?: CreateHeadOptions) => HeadPlugin[];
|
|
154
153
|
declare function createHead<T extends {} = Head>(options?: CreateHeadOptions): Unhead<T>;
|
|
154
|
+
declare function createServerHead<T extends {} = Head>(options?: CreateHeadOptions): Unhead<T>;
|
|
155
155
|
/**
|
|
156
156
|
* Creates a core instance of unhead. Does not provide a global ctx for composables to work
|
|
157
157
|
* and does not register DOM plugins.
|
|
@@ -172,6 +172,8 @@ declare const unheadComposablesImports: {
|
|
|
172
172
|
*/
|
|
173
173
|
declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlatInput;
|
|
174
174
|
|
|
175
|
+
declare function resolveMetaKeyType(key: string): string;
|
|
176
|
+
declare function resolveMetaKeyValue(key: string): string;
|
|
175
177
|
/**
|
|
176
178
|
* Converts a flat meta object into an array of meta entries.
|
|
177
179
|
* @param input
|
|
@@ -179,26 +181,12 @@ declare function packMeta<T extends Required<Head>['meta']>(inputs: T): MetaFlat
|
|
|
179
181
|
declare function unpackMeta<T extends MetaFlatInput>(input: T): Required<Head>['meta'];
|
|
180
182
|
declare function resolvePackedMetaObjectValue(value: string, key: string): string;
|
|
181
183
|
|
|
182
|
-
type ValidMetaType = 'name' | 'http-equiv' | 'property' | 'charset';
|
|
183
|
-
interface PackingDefinition {
|
|
184
|
-
metaKey?: ValidMetaType;
|
|
185
|
-
keyValue?: string;
|
|
186
|
-
unpack?: TransformValueOptions;
|
|
187
|
-
}
|
|
188
|
-
declare const MetaPackingSchema: Record<string, PackingDefinition>;
|
|
189
|
-
declare function resolveMetaKeyType(key: string): ValidMetaType;
|
|
190
|
-
|
|
191
184
|
declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string): Promise<T | T[] | false>;
|
|
192
185
|
declare function normaliseClassProp(v: Required<Required<Head>['htmlAttrs']['class']>): string;
|
|
193
186
|
declare function normaliseProps<T extends HeadTag>(tagName: T['tag'], props: T['props']): Promise<T['props']>;
|
|
194
187
|
declare const TagEntityBits = 10;
|
|
195
188
|
declare function normaliseEntryTags<T extends {} = Head>(e: HeadEntry<T>): Promise<HeadTag[]>;
|
|
196
189
|
|
|
197
|
-
declare const PropertyPrefixKeys: RegExp;
|
|
198
|
-
declare const ColonPrefixKeys: RegExp;
|
|
199
|
-
declare function fixKeyCase(key: string): string;
|
|
200
|
-
declare function changeKeyCasingDeep<T extends any>(input: T): T;
|
|
201
|
-
|
|
202
190
|
declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<string, string>>>): HeadSafe;
|
|
203
191
|
|
|
204
|
-
export {
|
|
192
|
+
export { CorePlugins, DOMPlugins, DedupesTagsPlugin, DedupesTagsPluginOptions, DeprecatedTagAttrPlugin, EventHandlersPlugin, ProvideTagHashPlugin, SortModifiers, SortTagsPlugin, TAG_WEIGHTS, TagEntityBits, TemplateParamsPlugin, TitleTemplatePlugin, UseSeoMetaInput, activeHead, composableNames, createHead, createHeadCore, createServerHead, getActiveHead, normaliseClassProp, normaliseEntryTags, normaliseProps, normaliseTag, packMeta, renderTitleTemplate, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, setActiveHead, tagWeight, unheadComposablesImports, unpackMeta, useBodyAttrs, useHead, useHeadSafe, useHtmlAttrs, useSeoMeta, useServerBodyAttrs, useServerHead, useServerHeadSafe, useServerHtmlAttrs, useServerSeoMeta, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate, whitelistSafeInput };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createHooks } from 'hookable';
|
|
2
2
|
import { PatchDomOnEntryUpdatesPlugin, maybeGetSSRHash } from '@unhead/dom';
|
|
3
|
-
import { defineHeadPlugin, hashTag, HasElementTags, tagDedupeKey, asArray, hashCode, TagConfigKeys, TagsWithInnerContent, ValidHeadTags } from '@unhead/shared';
|
|
3
|
+
import { defineHeadPlugin, hashTag, HasElementTags, tagDedupeKey, asArray as asArray$1, hashCode, TagConfigKeys, TagsWithInnerContent, ValidHeadTags } from '@unhead/shared';
|
|
4
4
|
export * from '@unhead/shared';
|
|
5
|
-
import { packArray, unpackToArray, unpackToString } from 'packrup';
|
|
6
5
|
|
|
7
6
|
const TAG_WEIGHTS = {
|
|
8
7
|
// aliases
|
|
@@ -369,27 +368,123 @@ function useServerSeoMeta(input, options) {
|
|
|
369
368
|
|
|
370
369
|
const useTagTitle = (title) => useHead({ title });
|
|
371
370
|
const useTagBase = (base) => useHead({ base });
|
|
372
|
-
const useTagMeta = (meta) => useHead({ meta: asArray(meta) });
|
|
371
|
+
const useTagMeta = (meta) => useHead({ meta: asArray$1(meta) });
|
|
373
372
|
const useTagMetaFlat = (meta) => useTagMeta(unpackMeta(meta));
|
|
374
|
-
const useTagLink = (link) => useHead({ link: asArray(link) });
|
|
375
|
-
const useTagScript = (script) => useHead({ script: asArray(script) });
|
|
376
|
-
const useTagStyle = (style) => useHead({ style: asArray(style) });
|
|
377
|
-
const useTagNoscript = (noscript) => useHead({ noscript: asArray(noscript) });
|
|
373
|
+
const useTagLink = (link) => useHead({ link: asArray$1(link) });
|
|
374
|
+
const useTagScript = (script) => useHead({ script: asArray$1(script) });
|
|
375
|
+
const useTagStyle = (style) => useHead({ style: asArray$1(style) });
|
|
376
|
+
const useTagNoscript = (noscript) => useHead({ noscript: asArray$1(noscript) });
|
|
378
377
|
const useHtmlAttrs = (attrs) => useHead({ htmlAttrs: attrs });
|
|
379
378
|
const useBodyAttrs = (attrs) => useHead({ bodyAttrs: attrs });
|
|
380
379
|
const useTitleTemplate = (titleTemplate) => useHead({ titleTemplate });
|
|
381
380
|
const useServerTagTitle = (title) => useServerHead({ title });
|
|
382
381
|
const useServerTagBase = (base) => useServerHead({ base });
|
|
383
|
-
const useServerTagMeta = (meta) => useServerHead({ meta: asArray(meta) });
|
|
382
|
+
const useServerTagMeta = (meta) => useServerHead({ meta: asArray$1(meta) });
|
|
384
383
|
const useServerTagMetaFlat = (meta) => useServerTagMeta(unpackMeta(meta));
|
|
385
|
-
const useServerTagLink = (link) => useServerHead({ link: asArray(link) });
|
|
386
|
-
const useServerTagScript = (script) => useServerHead({ script: asArray(script) });
|
|
387
|
-
const useServerTagStyle = (style) => useServerHead({ style: asArray(style) });
|
|
388
|
-
const useServerTagNoscript = (noscript) => useServerHead({ noscript: asArray(noscript) });
|
|
384
|
+
const useServerTagLink = (link) => useServerHead({ link: asArray$1(link) });
|
|
385
|
+
const useServerTagScript = (script) => useServerHead({ script: asArray$1(script) });
|
|
386
|
+
const useServerTagStyle = (style) => useServerHead({ style: asArray$1(style) });
|
|
387
|
+
const useServerTagNoscript = (noscript) => useServerHead({ noscript: asArray$1(noscript) });
|
|
389
388
|
const useServerHtmlAttrs = (attrs) => useServerHead({ htmlAttrs: attrs });
|
|
390
389
|
const useServerBodyAttrs = (attrs) => useServerHead({ bodyAttrs: attrs });
|
|
391
390
|
const useServerTitleTemplate = (titleTemplate) => useServerHead({ titleTemplate });
|
|
392
391
|
|
|
392
|
+
function asArray(input) {
|
|
393
|
+
return Array.isArray(input) ? input : [input];
|
|
394
|
+
}
|
|
395
|
+
const InternalKeySymbol = "_$key";
|
|
396
|
+
function packObject(input, options) {
|
|
397
|
+
const keys = Object.keys(input);
|
|
398
|
+
let [k, v] = keys;
|
|
399
|
+
options = options || {};
|
|
400
|
+
options.key = options.key || k;
|
|
401
|
+
options.value = options.value || v;
|
|
402
|
+
options.resolveKey = options.resolveKey || ((k2) => k2);
|
|
403
|
+
const resolveKey = (index) => {
|
|
404
|
+
const arr = asArray(options?.[index]);
|
|
405
|
+
return arr.find((k2) => {
|
|
406
|
+
if (typeof k2 === "string" && k2.includes(".")) {
|
|
407
|
+
return k2;
|
|
408
|
+
}
|
|
409
|
+
return k2 && keys.includes(k2);
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
const resolveValue = (k2, input2) => {
|
|
413
|
+
if (k2.includes(".")) {
|
|
414
|
+
const paths = k2.split(".");
|
|
415
|
+
let val = input2;
|
|
416
|
+
for (const path of paths)
|
|
417
|
+
val = val[path];
|
|
418
|
+
return val;
|
|
419
|
+
}
|
|
420
|
+
return input2[k2];
|
|
421
|
+
};
|
|
422
|
+
k = resolveKey("key") || k;
|
|
423
|
+
v = resolveKey("value") || v;
|
|
424
|
+
const dedupeKeyPrefix = input.key ? `${InternalKeySymbol}${input.key}-` : "";
|
|
425
|
+
let keyValue = resolveValue(k, input);
|
|
426
|
+
keyValue = options.resolveKey(keyValue);
|
|
427
|
+
return {
|
|
428
|
+
[`${dedupeKeyPrefix}${keyValue}`]: resolveValue(v, input)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function packArray(input, options) {
|
|
433
|
+
const packed = {};
|
|
434
|
+
for (const i of input) {
|
|
435
|
+
const packedObj = packObject(i, options);
|
|
436
|
+
const pKey = Object.keys(packedObj)[0];
|
|
437
|
+
const isDedupeKey = pKey.startsWith(InternalKeySymbol);
|
|
438
|
+
if (!isDedupeKey && packed[pKey]) {
|
|
439
|
+
packed[pKey] = Array.isArray(packed[pKey]) ? packed[pKey] : [packed[pKey]];
|
|
440
|
+
packed[pKey].push(Object.values(packedObj)[0]);
|
|
441
|
+
} else {
|
|
442
|
+
packed[isDedupeKey ? pKey.split("-").slice(1).join("-") || pKey : pKey] = packedObj[pKey];
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return packed;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function unpackToArray(input, options) {
|
|
449
|
+
const unpacked = [];
|
|
450
|
+
const kFn = options.resolveKeyData || ((ctx) => ctx.key);
|
|
451
|
+
const vFn = options.resolveValueData || ((ctx) => ctx.value);
|
|
452
|
+
for (const [k, v] of Object.entries(input)) {
|
|
453
|
+
unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => {
|
|
454
|
+
const ctx = { key: k, value: i };
|
|
455
|
+
const val = vFn(ctx);
|
|
456
|
+
if (typeof val === "object")
|
|
457
|
+
return unpackToArray(val, options);
|
|
458
|
+
if (Array.isArray(val))
|
|
459
|
+
return val;
|
|
460
|
+
return {
|
|
461
|
+
[typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx),
|
|
462
|
+
[typeof options.value === "function" ? options.value(ctx) : options.value]: val
|
|
463
|
+
};
|
|
464
|
+
}).flat());
|
|
465
|
+
}
|
|
466
|
+
return unpacked;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function unpackToString(value, options) {
|
|
470
|
+
return Object.entries(value).map(([key, value2]) => {
|
|
471
|
+
if (typeof value2 === "object")
|
|
472
|
+
value2 = unpackToString(value2, options);
|
|
473
|
+
if (options.resolve) {
|
|
474
|
+
const resolved = options.resolve({ key, value: value2 });
|
|
475
|
+
if (resolved)
|
|
476
|
+
return resolved;
|
|
477
|
+
}
|
|
478
|
+
if (typeof value2 === "number")
|
|
479
|
+
value2 = value2.toString();
|
|
480
|
+
if (typeof value2 === "string" && options.wrapValue) {
|
|
481
|
+
value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`);
|
|
482
|
+
value2 = `${options.wrapValue}${value2}${options.wrapValue}`;
|
|
483
|
+
}
|
|
484
|
+
return `${key}${options.keyValueSeparator || ""}${value2}`;
|
|
485
|
+
}).join(options.entrySeparator || "");
|
|
486
|
+
}
|
|
487
|
+
|
|
393
488
|
const MetaPackingSchema = {
|
|
394
489
|
robots: {
|
|
395
490
|
unpack: {
|
|
@@ -439,9 +534,6 @@ const MetaPackingSchema = {
|
|
|
439
534
|
metaKey: "http-equiv"
|
|
440
535
|
}
|
|
441
536
|
};
|
|
442
|
-
function resolveMetaKeyType(key) {
|
|
443
|
-
return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name";
|
|
444
|
-
}
|
|
445
537
|
|
|
446
538
|
function packMeta(inputs) {
|
|
447
539
|
const mappedPackingSchema = Object.entries(MetaPackingSchema).map(([key, value]) => [key, value.keyValue]);
|
|
@@ -458,6 +550,32 @@ function packMeta(inputs) {
|
|
|
458
550
|
}
|
|
459
551
|
|
|
460
552
|
const ArrayableInputs = ["Image", "Video", "Audio"];
|
|
553
|
+
const ColonPrefixKeys = /^(og|twitter|fb)/;
|
|
554
|
+
const PropertyPrefixKeys = /^(og|fb)/;
|
|
555
|
+
function resolveMetaKeyType(key) {
|
|
556
|
+
return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name";
|
|
557
|
+
}
|
|
558
|
+
function resolveMetaKeyValue(key) {
|
|
559
|
+
return MetaPackingSchema[key]?.keyValue || fixKeyCase(key);
|
|
560
|
+
}
|
|
561
|
+
function fixKeyCase(key) {
|
|
562
|
+
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
563
|
+
if (ColonPrefixKeys.test(key)) {
|
|
564
|
+
key = key.replace("secure-url", "secure_url").replace(/-/g, ":");
|
|
565
|
+
}
|
|
566
|
+
return key;
|
|
567
|
+
}
|
|
568
|
+
function changeKeyCasingDeep(input) {
|
|
569
|
+
if (Array.isArray(input)) {
|
|
570
|
+
return input.map((entry) => changeKeyCasingDeep(entry));
|
|
571
|
+
}
|
|
572
|
+
if (typeof input !== "object" || Array.isArray(input))
|
|
573
|
+
return input;
|
|
574
|
+
const output = {};
|
|
575
|
+
for (const [key, value] of Object.entries(input))
|
|
576
|
+
output[fixKeyCase(key)] = changeKeyCasingDeep(value);
|
|
577
|
+
return output;
|
|
578
|
+
}
|
|
461
579
|
function unpackMeta(input) {
|
|
462
580
|
const extras = [];
|
|
463
581
|
ArrayableInputs.forEach((key) => {
|
|
@@ -493,7 +611,7 @@ function unpackMeta(input) {
|
|
|
493
611
|
return key === "charset" ? "charset" : "content";
|
|
494
612
|
},
|
|
495
613
|
resolveKeyData({ key }) {
|
|
496
|
-
return
|
|
614
|
+
return resolveMetaKeyValue(key);
|
|
497
615
|
},
|
|
498
616
|
resolveValueData({ value, key }) {
|
|
499
617
|
if (value === null)
|
|
@@ -598,7 +716,7 @@ const TagEntityBits = 10;
|
|
|
598
716
|
async function normaliseEntryTags(e) {
|
|
599
717
|
const tagPromises = [];
|
|
600
718
|
Object.entries(e.resolvedInput).filter(([k, v]) => typeof v !== "undefined" && ValidHeadTags.includes(k)).forEach(([k, value]) => {
|
|
601
|
-
const v = asArray(value);
|
|
719
|
+
const v = asArray$1(value);
|
|
602
720
|
tagPromises.push(...v.map((props) => normaliseTag(k, props)).flat());
|
|
603
721
|
});
|
|
604
722
|
return (await Promise.all(tagPromises)).flat().filter(Boolean).map((t, i) => {
|
|
@@ -608,27 +726,6 @@ async function normaliseEntryTags(e) {
|
|
|
608
726
|
});
|
|
609
727
|
}
|
|
610
728
|
|
|
611
|
-
const PropertyPrefixKeys = /^(og|fb)/;
|
|
612
|
-
const ColonPrefixKeys = /^(og|twitter|fb)/;
|
|
613
|
-
function fixKeyCase(key) {
|
|
614
|
-
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
615
|
-
if (ColonPrefixKeys.test(key)) {
|
|
616
|
-
key = key.replace("secure-url", "secure_url").replace(/-/g, ":");
|
|
617
|
-
}
|
|
618
|
-
return key;
|
|
619
|
-
}
|
|
620
|
-
function changeKeyCasingDeep(input) {
|
|
621
|
-
if (Array.isArray(input)) {
|
|
622
|
-
return input.map((entry) => changeKeyCasingDeep(entry));
|
|
623
|
-
}
|
|
624
|
-
if (typeof input !== "object" || Array.isArray(input))
|
|
625
|
-
return input;
|
|
626
|
-
const output = {};
|
|
627
|
-
for (const [key, value] of Object.entries(input))
|
|
628
|
-
output[fixKeyCase(key)] = changeKeyCasingDeep(value);
|
|
629
|
-
return output;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
729
|
const WhitelistAttributes = {
|
|
633
730
|
htmlAttrs: ["id", "class", "lang", "dir"],
|
|
634
731
|
bodyAttrs: ["id", "class"],
|
|
@@ -756,6 +853,11 @@ function createHead(options = {}) {
|
|
|
756
853
|
setActiveHead(head);
|
|
757
854
|
return head;
|
|
758
855
|
}
|
|
856
|
+
function createServerHead(options = {}) {
|
|
857
|
+
const head = createHeadCore(options);
|
|
858
|
+
setActiveHead(head);
|
|
859
|
+
return head;
|
|
860
|
+
}
|
|
759
861
|
function createHeadCore(options = {}) {
|
|
760
862
|
let entries = [];
|
|
761
863
|
let _sde = {};
|
|
@@ -885,4 +987,4 @@ const unheadComposablesImports = [
|
|
|
885
987
|
}
|
|
886
988
|
];
|
|
887
989
|
|
|
888
|
-
export {
|
|
990
|
+
export { CorePlugins, DOMPlugins, DedupesTagsPlugin, DeprecatedTagAttrPlugin, EventHandlersPlugin, ProvideTagHashPlugin, SortModifiers, SortTagsPlugin, TAG_WEIGHTS, TagEntityBits, TemplateParamsPlugin, TitleTemplatePlugin, activeHead, composableNames, createHead, createHeadCore, createServerHead, getActiveHead, normaliseClassProp, normaliseEntryTags, normaliseProps, normaliseTag, packMeta, renderTitleTemplate, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, setActiveHead, tagWeight, unheadComposablesImports, unpackMeta, useBodyAttrs, useHead, useHeadSafe, useHtmlAttrs, useSeoMeta, useServerBodyAttrs, useServerHead, useServerHeadSafe, useServerHtmlAttrs, useServerSeoMeta, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate, whitelistSafeInput };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unhead",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.11",
|
|
5
5
|
"packageManager": "pnpm@7.27.1",
|
|
6
6
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -31,10 +31,12 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"hookable": "^5.4.2",
|
|
34
|
-
"
|
|
35
|
-
"@unhead/
|
|
36
|
-
"@unhead/
|
|
37
|
-
|
|
34
|
+
"@unhead/dom": "1.1.11",
|
|
35
|
+
"@unhead/schema": "1.1.11",
|
|
36
|
+
"@unhead/shared": "1.1.11"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"packrup": "^0.1.0"
|
|
38
40
|
},
|
|
39
41
|
"scripts": {
|
|
40
42
|
"build": "unbuild .",
|