unhead 0.6.5 → 0.6.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
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const hookable = require('hookable');
4
+ const dom = require('@unhead/dom');
4
5
 
5
6
  const ValidHeadTags = [
6
7
  "title",
@@ -408,7 +409,7 @@ const ProvideTagHashPlugin = () => {
408
409
  const isDynamic = typeof tag.props._dynamic !== "undefined";
409
410
  if (!HasElementTags.includes(tag.tag) || !tag.key)
410
411
  return;
411
- tag._hash = hashCode(JSON.stringify({ tag: tag.tag, key: tag.key }));
412
+ tag._hash = dom.hashCode(JSON.stringify({ tag: tag.tag, key: tag.key }));
412
413
  if (IsBrowser || getActiveHead()?.resolvedOptions?.document)
413
414
  return;
414
415
  if (entry._m === "server" || isDynamic) {
@@ -484,16 +485,18 @@ const EventHandlersPlugin = () => {
484
485
  const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
485
486
  const eventName = k.slice(2).toLowerCase();
486
487
  const eventDedupeKey = `data-h-${eventName}`;
487
- delete ctx.queuedSideEffects[sdeKey];
488
+ delete ctx.staleSideEffects[sdeKey];
488
489
  if ($el.hasAttribute(eventDedupeKey))
489
490
  return;
490
491
  const handler = value;
491
492
  $el.setAttribute(eventDedupeKey, "");
492
493
  $eventListenerTarget.addEventListener(eventName, handler);
493
- ctx.entry._sde[sdeKey] = () => {
494
- $eventListenerTarget.removeEventListener(eventName, handler);
495
- $el.removeAttribute(eventDedupeKey);
496
- };
494
+ if (ctx.entry) {
495
+ ctx.entry._sde[sdeKey] = () => {
496
+ $eventListenerTarget.removeEventListener(eventName, handler);
497
+ $el.removeAttribute(eventDedupeKey);
498
+ };
499
+ }
497
500
  });
498
501
  if (ctx.tag._delayedSrc) {
499
502
  $el.setAttribute("src", ctx.tag._delayedSrc);
@@ -506,12 +509,6 @@ const EventHandlersPlugin = () => {
506
509
  function asArray(value) {
507
510
  return Array.isArray(value) ? value : [value];
508
511
  }
509
- function hashCode(s) {
510
- let h = 9;
511
- for (let i = 0; i < s.length; )
512
- h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
513
- return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
514
- }
515
512
  const HasElementTags = [
516
513
  "base",
517
514
  "meta",
@@ -527,15 +524,18 @@ const getActiveHead = () => exports.activeHead;
527
524
 
528
525
  function useHead(input, options = {}) {
529
526
  const head = getActiveHead();
530
- const isBrowser = IsBrowser || head.resolvedOptions?.document;
531
- if (options.mode === "server" && isBrowser || options.mode === "client" && !isBrowser)
532
- return;
533
- return head.push(input, options);
527
+ if (head) {
528
+ const isBrowser = IsBrowser || head.resolvedOptions?.document;
529
+ if (options.mode === "server" && isBrowser || options.mode === "client" && !isBrowser)
530
+ return;
531
+ return head.push(input, options);
532
+ }
534
533
  }
535
534
  const useTagTitle = (title) => useHead({ title });
536
535
  const useTagBase = (base) => useHead({ base });
537
536
  const useTagMeta = (meta) => useHead({ meta: asArray(meta) });
538
537
  const useTagMetaFlat = (meta) => useTagMeta(unpackMeta(meta));
538
+ const useSeoMeta = useTagMetaFlat;
539
539
  const useTagLink = (link) => useHead({ link: asArray(link) });
540
540
  const useTagScript = (script) => useHead({ script: asArray(script) });
541
541
  const useTagStyle = (style) => useHead({ style: asArray(style) });
@@ -571,7 +571,26 @@ function normaliseEntryTags(e) {
571
571
  });
572
572
  }
573
573
 
574
+ const CorePlugins = () => [
575
+ DedupesTagsPlugin(),
576
+ SortTagsPlugin(),
577
+ TitleTemplatePlugin(),
578
+ ProvideTagHashPlugin(),
579
+ EventHandlersPlugin(),
580
+ DeprecatedTagAttrPlugin()
581
+ ];
582
+ const DOMPlugins = (options = {}) => [
583
+ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn })
584
+ ];
574
585
  function createHead(options = {}) {
586
+ const head = createHeadCore({
587
+ ...options,
588
+ plugins: [...DOMPlugins(options), ...options?.plugins || []]
589
+ });
590
+ setActiveHead(head);
591
+ return head;
592
+ }
593
+ function createHeadCore(options = {}) {
575
594
  let entries = [];
576
595
  let _sde = {};
577
596
  let _eid = 0;
@@ -579,17 +598,11 @@ function createHead(options = {}) {
579
598
  if (options?.hooks)
580
599
  hooks.addHooks(options.hooks);
581
600
  options.plugins = [
582
- DeprecatedTagAttrPlugin(),
583
- DedupesTagsPlugin(),
584
- SortTagsPlugin(),
585
- TitleTemplatePlugin(),
586
- EventHandlersPlugin(),
587
- ProvideTagHashPlugin(),
588
- PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
601
+ ...CorePlugins(),
589
602
  ...options?.plugins || []
590
603
  ];
591
604
  options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
592
- const triggerUpdateHook = () => hooks.callHook("entries:updated", head);
605
+ const updated = () => hooks.callHook("entries:updated", head);
593
606
  const head = {
594
607
  resolvedOptions: options,
595
608
  headEntries() {
@@ -607,27 +620,23 @@ function createHead(options = {}) {
607
620
  if (options2?.mode)
608
621
  activeEntry._m = options2?.mode;
609
622
  entries.push(activeEntry);
610
- triggerUpdateHook();
611
- const queueSideEffects = (e) => {
612
- _sde = { ..._sde, ...e._sde || {} };
613
- e._sde = {};
614
- triggerUpdateHook();
615
- };
623
+ updated();
616
624
  return {
617
625
  dispose() {
618
626
  entries = entries.filter((e) => {
619
627
  if (e._i !== activeEntry._i)
620
628
  return true;
621
- queueSideEffects(e);
629
+ _sde = { ..._sde, ...e._sde || {} };
630
+ e._sde = {};
631
+ updated();
622
632
  return false;
623
633
  });
624
634
  },
625
635
  patch(input2) {
626
636
  entries = entries.map((e) => {
627
637
  if (e._i === activeEntry._i) {
628
- queueSideEffects(e);
629
638
  activeEntry.input = e.input = input2;
630
- activeEntry._i = e._i = _eid++;
639
+ updated();
631
640
  }
632
641
  return e;
633
642
  });
@@ -655,7 +664,6 @@ function createHead(options = {}) {
655
664
  }
656
665
  };
657
666
  head.hooks.callHook("init", head);
658
- setActiveHead(head);
659
667
  return head;
660
668
  }
661
669
 
@@ -672,6 +680,7 @@ const composableNames = [
672
680
  "useTagBase",
673
681
  "useTagMeta",
674
682
  "useTagMetaFlat",
683
+ "useSeoMeta",
675
684
  "useTagLink",
676
685
  "useTagScript",
677
686
  "useTagStyle",
@@ -699,6 +708,8 @@ const unheadComposablesImports = [
699
708
  }
700
709
  ];
701
710
 
711
+ exports.CorePlugins = CorePlugins;
712
+ exports.DOMPlugins = DOMPlugins;
702
713
  exports.DedupesTagsPlugin = DedupesTagsPlugin;
703
714
  exports.DeprecatedTagAttrPlugin = DeprecatedTagAttrPlugin;
704
715
  exports.EventHandlersPlugin = EventHandlersPlugin;
@@ -710,15 +721,16 @@ exports.TitleTemplatePlugin = TitleTemplatePlugin;
710
721
  exports.asArray = asArray;
711
722
  exports.composableNames = composableNames;
712
723
  exports.createHead = createHead;
724
+ exports.createHeadCore = createHeadCore;
713
725
  exports.defineHeadPlugin = defineHeadPlugin;
714
726
  exports.getActiveHead = getActiveHead;
715
- exports.hashCode = hashCode;
716
727
  exports.normaliseEntryTags = normaliseEntryTags;
717
728
  exports.setActiveHead = setActiveHead;
718
729
  exports.unheadComposablesImports = unheadComposablesImports;
719
730
  exports.useBodyAttrs = useBodyAttrs;
720
731
  exports.useHead = useHead;
721
732
  exports.useHtmlAttrs = useHtmlAttrs;
733
+ exports.useSeoMeta = useSeoMeta;
722
734
  exports.useServerBodyAttrs = useServerBodyAttrs;
723
735
  exports.useServerHead = useServerHead;
724
736
  exports.useServerHtmlAttrs = useServerHtmlAttrs;
package/dist/index.d.ts CHANGED
@@ -29,7 +29,6 @@ declare const EventHandlersPlugin: () => _unhead_schema.HeadPlugin;
29
29
 
30
30
  declare type Arrayable<T> = T | Array<T>;
31
31
  declare function asArray<T>(value: Arrayable<T>): T[];
32
- declare function hashCode(s: string): string;
33
32
  declare const HasElementTags: string[];
34
33
 
35
34
  declare function useHead<T extends Head>(input: T, options?: HeadEntryOptions): ActiveHeadEntry<T> | void;
@@ -37,6 +36,7 @@ declare const useTagTitle: (title: Title) => ActiveHeadEntry<any> | void;
37
36
  declare const useTagBase: (base: Base) => ActiveHeadEntry<any> | void;
38
37
  declare const useTagMeta: (meta: Arrayable<Meta>) => ActiveHeadEntry<any> | void;
39
38
  declare const useTagMetaFlat: (meta: MetaFlatInput) => ActiveHeadEntry<any> | void;
39
+ declare const useSeoMeta: (meta: MetaFlatInput) => ActiveHeadEntry<any> | void;
40
40
  declare const useTagLink: (link: Arrayable<Link>) => ActiveHeadEntry<any> | void;
41
41
  declare const useTagScript: (script: Arrayable<Script>) => ActiveHeadEntry<any> | void;
42
42
  declare const useTagStyle: (style: Arrayable<Style>) => ActiveHeadEntry<any> | void;
@@ -59,10 +59,19 @@ declare const useServerBodyAttrs: (attrs: BodyAttributes) => ActiveHeadEntry<any
59
59
  declare const useServerTitleTemplate: (titleTemplate: TitleTemplate) => ActiveHeadEntry<any> | void;
60
60
 
61
61
  declare let activeHead: Unhead<any> | undefined;
62
- declare const setActiveHead: <T extends Unhead<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>>(head: T | undefined) => T | undefined;
63
- declare const getActiveHead: <T extends Unhead<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>>() => T;
62
+ declare const setActiveHead: (head: Unhead<any> | undefined) => Unhead<any> | undefined;
63
+ declare const getActiveHead: () => Unhead<any> | undefined;
64
64
 
65
+ declare const CorePlugins: () => _unhead_schema.HeadPlugin[];
66
+ declare const DOMPlugins: (options?: CreateHeadOptions) => _unhead_schema.HeadPlugin[];
65
67
  declare function createHead<T extends {} = Head>(options?: CreateHeadOptions): Unhead<T>;
68
+ /**
69
+ * Creates a core instance of unhead. Does not provide a global ctx for composables to work
70
+ * and does not register DOM plugins.
71
+ *
72
+ * @param options
73
+ */
74
+ declare function createHeadCore<T extends {} = Head>(options?: CreateHeadOptions): Unhead<T>;
66
75
 
67
76
  declare function defineHeadPlugin(plugin: HeadPlugin): HeadPlugin;
68
77
 
@@ -74,4 +83,4 @@ declare const unheadComposablesImports: {
74
83
  imports: string[];
75
84
  }[];
76
85
 
77
- export { Arrayable, DedupesTagsPlugin, DedupesTagsPluginOptions, DeprecatedTagAttrPlugin, EventHandlersPlugin, HasElementTags, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, composableNames, createHead, defineHeadPlugin, getActiveHead, hashCode, normaliseEntryTags, setActiveHead, unheadComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
86
+ export { Arrayable, CorePlugins, DOMPlugins, DedupesTagsPlugin, DedupesTagsPluginOptions, DeprecatedTagAttrPlugin, EventHandlersPlugin, HasElementTags, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, composableNames, createHead, createHeadCore, defineHeadPlugin, getActiveHead, normaliseEntryTags, setActiveHead, unheadComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useSeoMeta, 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
@@ -1,4 +1,5 @@
1
1
  import { createHooks } from 'hookable';
2
+ import { hashCode } from '@unhead/dom';
2
3
 
3
4
  const ValidHeadTags = [
4
5
  "title",
@@ -482,16 +483,18 @@ const EventHandlersPlugin = () => {
482
483
  const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
483
484
  const eventName = k.slice(2).toLowerCase();
484
485
  const eventDedupeKey = `data-h-${eventName}`;
485
- delete ctx.queuedSideEffects[sdeKey];
486
+ delete ctx.staleSideEffects[sdeKey];
486
487
  if ($el.hasAttribute(eventDedupeKey))
487
488
  return;
488
489
  const handler = value;
489
490
  $el.setAttribute(eventDedupeKey, "");
490
491
  $eventListenerTarget.addEventListener(eventName, handler);
491
- ctx.entry._sde[sdeKey] = () => {
492
- $eventListenerTarget.removeEventListener(eventName, handler);
493
- $el.removeAttribute(eventDedupeKey);
494
- };
492
+ if (ctx.entry) {
493
+ ctx.entry._sde[sdeKey] = () => {
494
+ $eventListenerTarget.removeEventListener(eventName, handler);
495
+ $el.removeAttribute(eventDedupeKey);
496
+ };
497
+ }
495
498
  });
496
499
  if (ctx.tag._delayedSrc) {
497
500
  $el.setAttribute("src", ctx.tag._delayedSrc);
@@ -504,12 +507,6 @@ const EventHandlersPlugin = () => {
504
507
  function asArray(value) {
505
508
  return Array.isArray(value) ? value : [value];
506
509
  }
507
- function hashCode(s) {
508
- let h = 9;
509
- for (let i = 0; i < s.length; )
510
- h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
511
- return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
512
- }
513
510
  const HasElementTags = [
514
511
  "base",
515
512
  "meta",
@@ -525,15 +522,18 @@ const getActiveHead = () => activeHead;
525
522
 
526
523
  function useHead(input, options = {}) {
527
524
  const head = getActiveHead();
528
- const isBrowser = IsBrowser || head.resolvedOptions?.document;
529
- if (options.mode === "server" && isBrowser || options.mode === "client" && !isBrowser)
530
- return;
531
- return head.push(input, options);
525
+ if (head) {
526
+ const isBrowser = IsBrowser || head.resolvedOptions?.document;
527
+ if (options.mode === "server" && isBrowser || options.mode === "client" && !isBrowser)
528
+ return;
529
+ return head.push(input, options);
530
+ }
532
531
  }
533
532
  const useTagTitle = (title) => useHead({ title });
534
533
  const useTagBase = (base) => useHead({ base });
535
534
  const useTagMeta = (meta) => useHead({ meta: asArray(meta) });
536
535
  const useTagMetaFlat = (meta) => useTagMeta(unpackMeta(meta));
536
+ const useSeoMeta = useTagMetaFlat;
537
537
  const useTagLink = (link) => useHead({ link: asArray(link) });
538
538
  const useTagScript = (script) => useHead({ script: asArray(script) });
539
539
  const useTagStyle = (style) => useHead({ style: asArray(style) });
@@ -569,7 +569,26 @@ function normaliseEntryTags(e) {
569
569
  });
570
570
  }
571
571
 
572
+ const CorePlugins = () => [
573
+ DedupesTagsPlugin(),
574
+ SortTagsPlugin(),
575
+ TitleTemplatePlugin(),
576
+ ProvideTagHashPlugin(),
577
+ EventHandlersPlugin(),
578
+ DeprecatedTagAttrPlugin()
579
+ ];
580
+ const DOMPlugins = (options = {}) => [
581
+ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn })
582
+ ];
572
583
  function createHead(options = {}) {
584
+ const head = createHeadCore({
585
+ ...options,
586
+ plugins: [...DOMPlugins(options), ...options?.plugins || []]
587
+ });
588
+ setActiveHead(head);
589
+ return head;
590
+ }
591
+ function createHeadCore(options = {}) {
573
592
  let entries = [];
574
593
  let _sde = {};
575
594
  let _eid = 0;
@@ -577,17 +596,11 @@ function createHead(options = {}) {
577
596
  if (options?.hooks)
578
597
  hooks.addHooks(options.hooks);
579
598
  options.plugins = [
580
- DeprecatedTagAttrPlugin(),
581
- DedupesTagsPlugin(),
582
- SortTagsPlugin(),
583
- TitleTemplatePlugin(),
584
- EventHandlersPlugin(),
585
- ProvideTagHashPlugin(),
586
- PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
599
+ ...CorePlugins(),
587
600
  ...options?.plugins || []
588
601
  ];
589
602
  options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
590
- const triggerUpdateHook = () => hooks.callHook("entries:updated", head);
603
+ const updated = () => hooks.callHook("entries:updated", head);
591
604
  const head = {
592
605
  resolvedOptions: options,
593
606
  headEntries() {
@@ -605,27 +618,23 @@ function createHead(options = {}) {
605
618
  if (options2?.mode)
606
619
  activeEntry._m = options2?.mode;
607
620
  entries.push(activeEntry);
608
- triggerUpdateHook();
609
- const queueSideEffects = (e) => {
610
- _sde = { ..._sde, ...e._sde || {} };
611
- e._sde = {};
612
- triggerUpdateHook();
613
- };
621
+ updated();
614
622
  return {
615
623
  dispose() {
616
624
  entries = entries.filter((e) => {
617
625
  if (e._i !== activeEntry._i)
618
626
  return true;
619
- queueSideEffects(e);
627
+ _sde = { ..._sde, ...e._sde || {} };
628
+ e._sde = {};
629
+ updated();
620
630
  return false;
621
631
  });
622
632
  },
623
633
  patch(input2) {
624
634
  entries = entries.map((e) => {
625
635
  if (e._i === activeEntry._i) {
626
- queueSideEffects(e);
627
636
  activeEntry.input = e.input = input2;
628
- activeEntry._i = e._i = _eid++;
637
+ updated();
629
638
  }
630
639
  return e;
631
640
  });
@@ -653,7 +662,6 @@ function createHead(options = {}) {
653
662
  }
654
663
  };
655
664
  head.hooks.callHook("init", head);
656
- setActiveHead(head);
657
665
  return head;
658
666
  }
659
667
 
@@ -670,6 +678,7 @@ const composableNames = [
670
678
  "useTagBase",
671
679
  "useTagMeta",
672
680
  "useTagMetaFlat",
681
+ "useSeoMeta",
673
682
  "useTagLink",
674
683
  "useTagScript",
675
684
  "useTagStyle",
@@ -697,4 +706,4 @@ const unheadComposablesImports = [
697
706
  }
698
707
  ];
699
708
 
700
- export { DedupesTagsPlugin, DeprecatedTagAttrPlugin, EventHandlersPlugin, HasElementTags, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, composableNames, createHead, defineHeadPlugin, getActiveHead, hashCode, normaliseEntryTags, setActiveHead, unheadComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
709
+ export { CorePlugins, DOMPlugins, DedupesTagsPlugin, DeprecatedTagAttrPlugin, EventHandlersPlugin, HasElementTags, PatchDomOnEntryUpdatesPlugin, ProvideTagHashPlugin, SortTagsPlugin, TitleTemplatePlugin, activeHead, asArray, composableNames, createHead, createHeadCore, defineHeadPlugin, getActiveHead, normaliseEntryTags, setActiveHead, unheadComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useSeoMeta, 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.6.5",
4
+ "version": "0.6.7",
5
5
  "packageManager": "pnpm@7.14.0",
6
6
  "author": "Harlan Wilton <harlan@harlanzw.com>",
7
7
  "license": "MIT",
@@ -30,8 +30,8 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "@unhead/dom": "0.6.5",
34
- "@unhead/schema": "0.6.5",
33
+ "@unhead/dom": "0.6.7",
34
+ "@unhead/schema": "0.6.7",
35
35
  "hookable": "^5.4.1"
36
36
  },
37
37
  "devDependencies": {