unhead 0.4.5 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -229,9 +229,26 @@ const sortTags = (aTag, bTag) => {
229
229
  return tagWeight(aTag) - tagWeight(bTag);
230
230
  };
231
231
 
232
+ const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
233
+ const ArrayMetaProperties = [
234
+ "og:image",
235
+ "og:video",
236
+ "og:audio",
237
+ "og:locale:alternate",
238
+ "video:actor",
239
+ "video:director",
240
+ "video:writer",
241
+ "video:tag",
242
+ "article:author",
243
+ "article:tag",
244
+ "book:tag",
245
+ "book:author",
246
+ "music:album",
247
+ "music:musician"
248
+ ];
232
249
  function tagDedupeKey(tag) {
233
250
  const { props, tag: tagName } = tag;
234
- if (["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"].includes(tagName))
251
+ if (UniqueTags.includes(tagName))
235
252
  return tagName;
236
253
  if (tagName === "link" && props.rel === "canonical")
237
254
  return "canonical";
@@ -242,7 +259,10 @@ function tagDedupeKey(tag) {
242
259
  name.push(...["name", "property", "http-equiv"]);
243
260
  for (const n of name) {
244
261
  if (typeof props[n] !== "undefined") {
245
- return `${tagName}:${n}:${props[n]}`;
262
+ const val = String(props[n]);
263
+ if (ArrayMetaProperties.findIndex((p) => val.startsWith(p)) !== -1)
264
+ return false;
265
+ return `${tagName}:${n}:${val}`;
246
266
  }
247
267
  }
248
268
  return false;
@@ -324,13 +344,9 @@ const DedupesTagsPlugin = (options) => {
324
344
  return;
325
345
  } else if (tag._e === dupedTag._e) {
326
346
  dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
327
- if (dupedTag._s && typeof dupedTag.props[dupedTag._s] !== "undefined") {
328
- delete tag.props[dupedTag._s];
329
- tag._s = `${dupedTag._s}${tag._p}`;
330
- tag.props[tag._s] = "";
331
- }
332
347
  }
333
- if (Object.keys(tag.props).length === 0 && !tag.children) {
348
+ const propCount = Object.keys(tag.props).length;
349
+ if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
334
350
  delete deduping[dedupeKey];
335
351
  return;
336
352
  }
@@ -392,23 +408,16 @@ const DeprecatedTagAttrPlugin = () => {
392
408
 
393
409
  const IsBrowser = typeof window !== "undefined";
394
410
 
395
- function hashCode(s) {
396
- let h = 9;
397
- for (let i = 0; i < s.length; )
398
- h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
399
- return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 7).toLowerCase();
400
- }
401
- const HydrateStateFromSSRPlugin = () => {
411
+ const ProvideTagHashPlugin = () => {
402
412
  return defineHeadPlugin({
403
413
  hooks: {
404
414
  "tag:normalise": (ctx) => {
405
415
  const { tag, entry } = ctx;
406
- if (!HasElementTags.includes(tag.tag) || typeof tag._d === "undefined")
416
+ if (!HasElementTags.includes(tag.tag))
407
417
  return;
408
- tag._s = `data-h-${hashCode(tag._d)}`;
409
418
  const isBrowser = IsBrowser || getActiveHead()?.resolvedOptions?.document;
410
- if (!isBrowser && (entry._m === "server" || tag.key))
411
- tag.props[tag._s] = "";
419
+ if (!isBrowser && entry._m === "server" && tag.key)
420
+ tag.props["data-h-key"] = tag._d;
412
421
  }
413
422
  }
414
423
  });
@@ -445,7 +454,7 @@ const EventHandlersPlugin = () => {
445
454
  };
446
455
  return defineHeadPlugin({
447
456
  hooks: {
448
- "ssr:beforeRender": function(ctx) {
457
+ "ssr:render": function(ctx) {
449
458
  ctx.tags = ctx.tags.map((tag) => {
450
459
  tag.props = stripEventHandlers(tag).props;
451
460
  return tag;
@@ -463,7 +472,7 @@ const EventHandlersPlugin = () => {
463
472
  if (!ctx.tag._eventHandlers || !$el)
464
473
  return;
465
474
  Object.entries(ctx.tag._eventHandlers).forEach(([k, value]) => {
466
- const sdeKey = `${ctx.tag._s || ctx.tag._p}:${k}`;
475
+ const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
467
476
  const eventName = k.slice(2).toLowerCase();
468
477
  const handler = value;
469
478
  $el?.addEventListener(eventName, handler);
@@ -587,8 +596,9 @@ function createHead(options = {}) {
587
596
  DedupesTagsPlugin(),
588
597
  SortTagsPlugin(),
589
598
  TitleTemplatePlugin(),
590
- PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
591
599
  EventHandlersPlugin(),
600
+ ProvideTagHashPlugin(),
601
+ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
592
602
  ...options?.plugins || []
593
603
  ];
594
604
  options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
@@ -668,15 +678,14 @@ function defineHeadPlugin(plugin) {
668
678
  exports.DedupesTagsPlugin = DedupesTagsPlugin;
669
679
  exports.DeprecatedTagAttrPlugin = DeprecatedTagAttrPlugin;
670
680
  exports.EventHandlersPlugin = EventHandlersPlugin;
671
- exports.HydrateStateFromSSRPlugin = HydrateStateFromSSRPlugin;
672
681
  exports.PatchDomOnEntryUpdatesPlugin = PatchDomOnEntryUpdatesPlugin;
682
+ exports.ProvideTagHashPlugin = ProvideTagHashPlugin;
673
683
  exports.SortTagsPlugin = SortTagsPlugin;
674
684
  exports.TitleTemplatePlugin = TitleTemplatePlugin;
675
685
  exports.asArray = asArray;
676
686
  exports.createHead = createHead;
677
687
  exports.defineHeadPlugin = defineHeadPlugin;
678
688
  exports.getActiveHead = getActiveHead;
679
- exports.hashCode = hashCode;
680
689
  exports.normaliseEntryTags = normaliseEntryTags;
681
690
  exports.setActiveHead = setActiveHead;
682
691
  exports.useBodyAttrs = useBodyAttrs;
package/dist/index.d.ts CHANGED
@@ -13,8 +13,7 @@ declare const TitleTemplatePlugin: () => _unhead_schema.HeadPlugin;
13
13
 
14
14
  declare const DeprecatedTagAttrPlugin: () => _unhead_schema.HeadPlugin;
15
15
 
16
- declare function hashCode(s: string): string;
17
- declare const HydrateStateFromSSRPlugin: () => _unhead_schema.HeadPlugin;
16
+ declare const ProvideTagHashPlugin: () => _unhead_schema.HeadPlugin;
18
17
 
19
18
  interface TriggerDomPatchingOnUpdatesPluginOptions extends RenderDomHeadOptions {
20
19
  delayFn?: (fn: () => void) => void;
@@ -67,4 +66,4 @@ declare function defineHeadPlugin(plugin: HeadPlugin): HeadPlugin;
67
66
 
68
67
  declare function normaliseEntryTags<T extends {} = Head>(e: HeadEntry<T>): HeadTag[];
69
68
 
70
- export { Arrayable, DedupesTagsPlugin, DedupesTagsPluginOptions, DeprecatedTagAttrPlugin, EventHandlersPlugin, HydrateStateFromSSRPlugin, PatchDomOnEntryUpdatesPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, createHead, defineHeadPlugin, getActiveHead, hashCode, normaliseEntryTags, setActiveHead, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
69
+ export { Arrayable, DedupesTagsPlugin, DedupesTagsPluginOptions, DeprecatedTagAttrPlugin, EventHandlersPlugin, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, createHead, defineHeadPlugin, getActiveHead, normaliseEntryTags, setActiveHead, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
package/dist/index.mjs CHANGED
@@ -227,9 +227,26 @@ const sortTags = (aTag, bTag) => {
227
227
  return tagWeight(aTag) - tagWeight(bTag);
228
228
  };
229
229
 
230
+ const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
231
+ const ArrayMetaProperties = [
232
+ "og:image",
233
+ "og:video",
234
+ "og:audio",
235
+ "og:locale:alternate",
236
+ "video:actor",
237
+ "video:director",
238
+ "video:writer",
239
+ "video:tag",
240
+ "article:author",
241
+ "article:tag",
242
+ "book:tag",
243
+ "book:author",
244
+ "music:album",
245
+ "music:musician"
246
+ ];
230
247
  function tagDedupeKey(tag) {
231
248
  const { props, tag: tagName } = tag;
232
- if (["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"].includes(tagName))
249
+ if (UniqueTags.includes(tagName))
233
250
  return tagName;
234
251
  if (tagName === "link" && props.rel === "canonical")
235
252
  return "canonical";
@@ -240,7 +257,10 @@ function tagDedupeKey(tag) {
240
257
  name.push(...["name", "property", "http-equiv"]);
241
258
  for (const n of name) {
242
259
  if (typeof props[n] !== "undefined") {
243
- return `${tagName}:${n}:${props[n]}`;
260
+ const val = String(props[n]);
261
+ if (ArrayMetaProperties.findIndex((p) => val.startsWith(p)) !== -1)
262
+ return false;
263
+ return `${tagName}:${n}:${val}`;
244
264
  }
245
265
  }
246
266
  return false;
@@ -322,13 +342,9 @@ const DedupesTagsPlugin = (options) => {
322
342
  return;
323
343
  } else if (tag._e === dupedTag._e) {
324
344
  dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
325
- if (dupedTag._s && typeof dupedTag.props[dupedTag._s] !== "undefined") {
326
- delete tag.props[dupedTag._s];
327
- tag._s = `${dupedTag._s}${tag._p}`;
328
- tag.props[tag._s] = "";
329
- }
330
345
  }
331
- if (Object.keys(tag.props).length === 0 && !tag.children) {
346
+ const propCount = Object.keys(tag.props).length;
347
+ if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
332
348
  delete deduping[dedupeKey];
333
349
  return;
334
350
  }
@@ -390,23 +406,16 @@ const DeprecatedTagAttrPlugin = () => {
390
406
 
391
407
  const IsBrowser = typeof window !== "undefined";
392
408
 
393
- function hashCode(s) {
394
- let h = 9;
395
- for (let i = 0; i < s.length; )
396
- h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
397
- return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 7).toLowerCase();
398
- }
399
- const HydrateStateFromSSRPlugin = () => {
409
+ const ProvideTagHashPlugin = () => {
400
410
  return defineHeadPlugin({
401
411
  hooks: {
402
412
  "tag:normalise": (ctx) => {
403
413
  const { tag, entry } = ctx;
404
- if (!HasElementTags.includes(tag.tag) || typeof tag._d === "undefined")
414
+ if (!HasElementTags.includes(tag.tag))
405
415
  return;
406
- tag._s = `data-h-${hashCode(tag._d)}`;
407
416
  const isBrowser = IsBrowser || getActiveHead()?.resolvedOptions?.document;
408
- if (!isBrowser && (entry._m === "server" || tag.key))
409
- tag.props[tag._s] = "";
417
+ if (!isBrowser && entry._m === "server" && tag.key)
418
+ tag.props["data-h-key"] = tag._d;
410
419
  }
411
420
  }
412
421
  });
@@ -443,7 +452,7 @@ const EventHandlersPlugin = () => {
443
452
  };
444
453
  return defineHeadPlugin({
445
454
  hooks: {
446
- "ssr:beforeRender": function(ctx) {
455
+ "ssr:render": function(ctx) {
447
456
  ctx.tags = ctx.tags.map((tag) => {
448
457
  tag.props = stripEventHandlers(tag).props;
449
458
  return tag;
@@ -461,7 +470,7 @@ const EventHandlersPlugin = () => {
461
470
  if (!ctx.tag._eventHandlers || !$el)
462
471
  return;
463
472
  Object.entries(ctx.tag._eventHandlers).forEach(([k, value]) => {
464
- const sdeKey = `${ctx.tag._s || ctx.tag._p}:${k}`;
473
+ const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
465
474
  const eventName = k.slice(2).toLowerCase();
466
475
  const handler = value;
467
476
  $el?.addEventListener(eventName, handler);
@@ -585,8 +594,9 @@ function createHead(options = {}) {
585
594
  DedupesTagsPlugin(),
586
595
  SortTagsPlugin(),
587
596
  TitleTemplatePlugin(),
588
- PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
589
597
  EventHandlersPlugin(),
598
+ ProvideTagHashPlugin(),
599
+ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
590
600
  ...options?.plugins || []
591
601
  ];
592
602
  options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
@@ -663,4 +673,4 @@ function defineHeadPlugin(plugin) {
663
673
  return plugin;
664
674
  }
665
675
 
666
- export { DedupesTagsPlugin, DeprecatedTagAttrPlugin, EventHandlersPlugin, HydrateStateFromSSRPlugin, PatchDomOnEntryUpdatesPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, createHead, defineHeadPlugin, getActiveHead, hashCode, normaliseEntryTags, setActiveHead, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
676
+ export { DedupesTagsPlugin, DeprecatedTagAttrPlugin, EventHandlersPlugin, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, createHead, defineHeadPlugin, getActiveHead, normaliseEntryTags, setActiveHead, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unhead",
3
3
  "type": "module",
4
- "version": "0.4.5",
4
+ "version": "0.4.7",
5
5
  "packageManager": "pnpm@7.14.0",
6
6
  "author": "Harlan Wilton <harlan@harlanzw.com>",
7
7
  "license": "MIT",
@@ -30,12 +30,12 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "@unhead/dom": "0.4.5",
34
- "@unhead/schema": "0.4.5",
33
+ "@unhead/dom": "0.4.7",
34
+ "@unhead/schema": "0.4.7",
35
35
  "hookable": "^5.4.1"
36
36
  },
37
37
  "devDependencies": {
38
- "zhead": "1.0.0-beta.11"
38
+ "zhead": "1.0.0-beta.13"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "unbuild .",