@unhead/vue 0.6.2 → 0.6.4

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,24 +1,541 @@
1
1
  'use strict';
2
2
 
3
- const shared = require('@vueuse/shared');
4
3
  const vue = require('vue');
5
- const unhead = require('unhead');
6
- const dom = require('@unhead/dom');
4
+ const hookable = require('hookable');
7
5
 
8
- function resolveUnrefHeadInput(ref) {
9
- const root = shared.resolveUnref(ref);
6
+ const ValidHeadTags = [
7
+ "title",
8
+ "titleTemplate",
9
+ "base",
10
+ "htmlAttrs",
11
+ "bodyAttrs",
12
+ "meta",
13
+ "link",
14
+ "style",
15
+ "script",
16
+ "noscript"
17
+ ];
18
+ const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"];
19
+
20
+ function normaliseTag(tagName, input) {
21
+ const tag = { tag: tagName, props: {} };
22
+ if (tagName === "title" || tagName === "titleTemplate") {
23
+ tag.children = input;
24
+ return tag;
25
+ }
26
+ tag.props = normaliseProps({ ...input });
27
+ ["children", "innerHtml", "innerHTML"].forEach((key) => {
28
+ if (typeof tag.props[key] !== "undefined") {
29
+ tag.children = tag.props[key];
30
+ delete tag.props[key];
31
+ }
32
+ });
33
+ Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => {
34
+ tag[k] = tag.props[k];
35
+ delete tag.props[k];
36
+ });
37
+ if (typeof tag.props.class === "object" && !Array.isArray(tag.props.class)) {
38
+ tag.props.class = Object.keys(tag.props.class).filter((k) => tag.props.class[k]);
39
+ }
40
+ if (Array.isArray(tag.props.class))
41
+ tag.props.class = tag.props.class.join(" ");
42
+ if (tag.props.content && Array.isArray(tag.props.content)) {
43
+ return tag.props.content.map((v, i) => {
44
+ const newTag = { ...tag, props: { ...tag.props } };
45
+ newTag.props.content = v;
46
+ newTag.key = `${tag.props.name || tag.props.property}:${i}`;
47
+ return newTag;
48
+ });
49
+ }
50
+ return tag;
51
+ }
52
+ function normaliseProps(props) {
53
+ for (const k in props) {
54
+ if (String(props[k]) === "true") {
55
+ props[k] = "";
56
+ } else if (String(props[k]) === "false") {
57
+ delete props[k];
58
+ }
59
+ }
60
+ return props;
61
+ }
62
+
63
+ const tagWeight = (tag) => {
64
+ if (typeof tag.tagPriority === "number")
65
+ return tag.tagPriority;
66
+ switch (tag.tag) {
67
+ case "base":
68
+ return -1;
69
+ case "title":
70
+ return 1;
71
+ case "meta":
72
+ if (tag.props.charset)
73
+ return -2;
74
+ if (tag.props["http-equiv"] === "content-security-policy")
75
+ return 0;
76
+ return 10;
77
+ default:
78
+ return 10;
79
+ }
80
+ };
81
+ const sortTags = (aTag, bTag) => {
82
+ return tagWeight(aTag) - tagWeight(bTag);
83
+ };
84
+
85
+ const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
86
+ const ArrayMetaProperties = [
87
+ "og:image",
88
+ "og:video",
89
+ "og:audio",
90
+ "og:locale:alternate",
91
+ "video:actor",
92
+ "video:director",
93
+ "video:writer",
94
+ "video:tag",
95
+ "article:author",
96
+ "article:tag",
97
+ "book:tag",
98
+ "book:author",
99
+ "music:album",
100
+ "music:musician"
101
+ ];
102
+ function tagDedupeKey(tag) {
103
+ const { props, tag: tagName } = tag;
104
+ if (UniqueTags.includes(tagName))
105
+ return tagName;
106
+ if (tagName === "link" && props.rel === "canonical")
107
+ return "canonical";
108
+ if (props.charset)
109
+ return "charset";
110
+ const name = ["id"];
111
+ if (tagName === "meta")
112
+ name.push(...["name", "property", "http-equiv"]);
113
+ for (const n of name) {
114
+ if (typeof props[n] !== "undefined") {
115
+ const val = String(props[n]);
116
+ if (ArrayMetaProperties.findIndex((p) => val.startsWith(p)) !== -1)
117
+ return false;
118
+ return `${tagName}:${n}:${val}`;
119
+ }
120
+ }
121
+ return false;
122
+ }
123
+
124
+ const renderTitleTemplate = (template, title) => {
125
+ if (template == null)
126
+ return title || null;
127
+ if (typeof template === "function")
128
+ return template(title);
129
+ return template.replace("%s", title ?? "");
130
+ };
131
+ function resolveTitleTemplateFromTags(tags) {
132
+ const titleTemplateIdx = tags.findIndex((i) => i.tag === "titleTemplate");
133
+ const titleIdx = tags.findIndex((i) => i.tag === "title");
134
+ if (titleIdx !== -1 && titleTemplateIdx !== -1) {
135
+ const newTitle = renderTitleTemplate(
136
+ tags[titleTemplateIdx].children,
137
+ tags[titleIdx].children
138
+ );
139
+ if (newTitle !== null) {
140
+ tags[titleIdx].children = newTitle || tags[titleIdx].children;
141
+ } else {
142
+ delete tags[titleIdx];
143
+ }
144
+ } else if (titleTemplateIdx !== -1) {
145
+ const newTitle = renderTitleTemplate(
146
+ tags[titleTemplateIdx].children
147
+ );
148
+ if (newTitle !== null) {
149
+ tags[titleTemplateIdx].children = newTitle;
150
+ tags[titleTemplateIdx].tag = "title";
151
+ }
152
+ }
153
+ if (titleTemplateIdx !== -1) {
154
+ delete tags[titleTemplateIdx];
155
+ }
156
+ return tags.filter(Boolean);
157
+ }
158
+
159
+ const DedupesTagsPlugin = (options) => {
160
+ options = options || {};
161
+ const dedupeKeys = options.dedupeKeys || ["hid", "vmid", "key"];
162
+ return defineHeadPlugin({
163
+ hooks: {
164
+ "tag:normalise": function({ tag }) {
165
+ dedupeKeys.forEach((key) => {
166
+ if (tag.props[key]) {
167
+ tag.key = tag.props[key];
168
+ delete tag.props[key];
169
+ }
170
+ });
171
+ const dedupe = tag.key ? `${tag.tag}:${tag.key}` : tagDedupeKey(tag);
172
+ if (dedupe)
173
+ tag._d = dedupe;
174
+ },
175
+ "tags:resolve": function(ctx) {
176
+ const deduping = {};
177
+ ctx.tags.forEach((tag) => {
178
+ let dedupeKey = tag._d || tag._p;
179
+ const dupedTag = deduping[dedupeKey];
180
+ if (dupedTag) {
181
+ let strategy = tag?.tagDuplicateStrategy;
182
+ if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"))
183
+ strategy = "merge";
184
+ if (strategy === "merge") {
185
+ const oldProps = dupedTag.props;
186
+ ["class", "style"].forEach((key) => {
187
+ if (tag.props[key] && oldProps[key]) {
188
+ if (key === "style" && !oldProps[key].endsWith(";"))
189
+ oldProps[key] += ";";
190
+ tag.props[key] = `${oldProps[key]} ${tag.props[key]}`;
191
+ }
192
+ });
193
+ deduping[dedupeKey].props = {
194
+ ...oldProps,
195
+ ...tag.props
196
+ };
197
+ return;
198
+ } else if (tag._e === dupedTag._e) {
199
+ dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
200
+ }
201
+ const propCount = Object.keys(tag.props).length;
202
+ if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
203
+ delete deduping[dedupeKey];
204
+ return;
205
+ }
206
+ }
207
+ deduping[dedupeKey] = tag;
208
+ });
209
+ ctx.tags = Object.values(deduping);
210
+ }
211
+ }
212
+ });
213
+ };
214
+
215
+ const SortTagsPlugin = () => {
216
+ return defineHeadPlugin({
217
+ hooks: {
218
+ "tags:resolve": (ctx) => {
219
+ const tagIndexForKey = (key) => ctx.tags.find((tag) => tag._d === key)?._p;
220
+ for (const tag of ctx.tags) {
221
+ if (!tag.tagPriority || typeof tag.tagPriority === "number")
222
+ continue;
223
+ const modifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }];
224
+ for (const { prefix, offset } of modifiers) {
225
+ if (tag.tagPriority.startsWith(prefix)) {
226
+ const key = tag.tagPriority.replace(prefix, "");
227
+ const index = tagIndexForKey(key);
228
+ if (typeof index !== "undefined")
229
+ tag._p = index + offset;
230
+ }
231
+ }
232
+ }
233
+ ctx.tags.sort((a, b) => a._p - b._p).sort(sortTags);
234
+ }
235
+ }
236
+ });
237
+ };
238
+
239
+ const TitleTemplatePlugin = () => {
240
+ return defineHeadPlugin({
241
+ hooks: {
242
+ "tags:resolve": (ctx) => {
243
+ ctx.tags = resolveTitleTemplateFromTags(ctx.tags);
244
+ }
245
+ }
246
+ });
247
+ };
248
+
249
+ const DeprecatedTagAttrPlugin = () => {
250
+ return defineHeadPlugin({
251
+ hooks: {
252
+ "tag:normalise": function({ tag }) {
253
+ if (typeof tag.props.body !== "undefined") {
254
+ tag.tagPosition = "bodyClose";
255
+ delete tag.props.body;
256
+ }
257
+ }
258
+ }
259
+ });
260
+ };
261
+
262
+ const IsBrowser$1 = typeof window !== "undefined";
263
+
264
+ const ProvideTagHashPlugin = () => {
265
+ return defineHeadPlugin({
266
+ hooks: {
267
+ "tag:normalise": (ctx) => {
268
+ const { tag, entry } = ctx;
269
+ const isDynamic = typeof tag.props._dynamic !== "undefined";
270
+ if (!HasElementTags.includes(tag.tag) || !tag.key)
271
+ return;
272
+ tag._hash = hashCode(JSON.stringify({ tag: tag.tag, key: tag.key }));
273
+ if (IsBrowser$1 || getActiveHead()?.resolvedOptions?.document)
274
+ return;
275
+ if (entry._m === "server" || isDynamic) {
276
+ tag.props[`data-h-${tag._hash}`] = "";
277
+ }
278
+ },
279
+ "tags:resolve": (ctx) => {
280
+ ctx.tags = ctx.tags.map((t) => {
281
+ delete t.props._dynamic;
282
+ return t;
283
+ });
284
+ }
285
+ }
286
+ });
287
+ };
288
+
289
+ const PatchDomOnEntryUpdatesPlugin = (options) => {
290
+ return defineHeadPlugin({
291
+ hooks: {
292
+ "entries:updated": function(head) {
293
+ if (typeof options?.document === "undefined" && typeof window === "undefined")
294
+ return;
295
+ let delayFn = options?.delayFn;
296
+ if (!delayFn && typeof requestAnimationFrame !== "undefined")
297
+ delayFn = requestAnimationFrame;
298
+ import('./chunks/index.cjs').then(({ debouncedRenderDOMHead }) => {
299
+ debouncedRenderDOMHead(head, { document: options?.document || window.document, delayFn });
300
+ });
301
+ }
302
+ }
303
+ });
304
+ };
305
+
306
+ const EventHandlersPlugin = () => {
307
+ const stripEventHandlers = (mode, tag) => {
308
+ const props = {};
309
+ const eventHandlers = {};
310
+ Object.entries(tag.props).forEach(([key, value]) => {
311
+ if (key.startsWith("on") && typeof value === "function")
312
+ eventHandlers[key] = value;
313
+ else
314
+ props[key] = value;
315
+ });
316
+ let delayedSrc;
317
+ if (mode === "dom" && tag.tag === "script" && typeof props.src === "string" && typeof eventHandlers.onload !== "undefined") {
318
+ delayedSrc = props.src;
319
+ delete props.src;
320
+ }
321
+ return { props, eventHandlers, delayedSrc };
322
+ };
323
+ return defineHeadPlugin({
324
+ hooks: {
325
+ "ssr:render": function(ctx) {
326
+ ctx.tags = ctx.tags.map((tag) => {
327
+ tag.props = stripEventHandlers("ssr", tag).props;
328
+ return tag;
329
+ });
330
+ },
331
+ "dom:beforeRenderTag": function(ctx) {
332
+ const { props, eventHandlers, delayedSrc } = stripEventHandlers("dom", ctx.tag);
333
+ if (!Object.keys(eventHandlers).length)
334
+ return;
335
+ ctx.tag.props = props;
336
+ ctx.tag._eventHandlers = eventHandlers;
337
+ ctx.tag._delayedSrc = delayedSrc;
338
+ },
339
+ "dom:renderTag": function(ctx) {
340
+ const $el = ctx.$el;
341
+ if (!ctx.tag._eventHandlers || !$el)
342
+ return;
343
+ const $eventListenerTarget = ctx.tag.tag === "bodyAttrs" && typeof window !== "undefined" ? window : $el;
344
+ Object.entries(ctx.tag._eventHandlers).forEach(([k, value]) => {
345
+ const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`;
346
+ const eventName = k.slice(2).toLowerCase();
347
+ const eventDedupeKey = `data-h-${eventName}`;
348
+ delete ctx.queuedSideEffects[sdeKey];
349
+ if ($el.hasAttribute(eventDedupeKey))
350
+ return;
351
+ const handler = value;
352
+ $el.setAttribute(eventDedupeKey, "");
353
+ $eventListenerTarget.addEventListener(eventName, handler);
354
+ ctx.entry._sde[sdeKey] = () => {
355
+ $eventListenerTarget.removeEventListener(eventName, handler);
356
+ $el.removeAttribute(eventDedupeKey);
357
+ };
358
+ });
359
+ if (ctx.tag._delayedSrc) {
360
+ $el.setAttribute("src", ctx.tag._delayedSrc);
361
+ }
362
+ }
363
+ }
364
+ });
365
+ };
366
+
367
+ function asArray$1(value) {
368
+ return Array.isArray(value) ? value : [value];
369
+ }
370
+ function hashCode(s) {
371
+ let h = 9;
372
+ for (let i = 0; i < s.length; )
373
+ h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
374
+ return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
375
+ }
376
+ const HasElementTags = [
377
+ "base",
378
+ "meta",
379
+ "link",
380
+ "style",
381
+ "script",
382
+ "noscript"
383
+ ];
384
+
385
+ let activeHead;
386
+ const setActiveHead = (head) => activeHead = head;
387
+ const getActiveHead = () => activeHead;
388
+
389
+ const TagEntityBits = 10;
390
+
391
+ function normaliseEntryTags(e) {
392
+ return Object.entries(e.input).filter(([k, v]) => typeof v !== "undefined" && ValidHeadTags.includes(k)).map(
393
+ ([k, value]) => asArray$1(value).map((props) => asArray$1(normaliseTag(k, props)))
394
+ ).flat(3).map((t, i) => {
395
+ t._e = e._i;
396
+ t._p = (e._i << TagEntityBits) + i;
397
+ return t;
398
+ });
399
+ }
400
+
401
+ function createHead$1(options = {}) {
402
+ let entries = [];
403
+ let _sde = {};
404
+ let _eid = 0;
405
+ const hooks = hookable.createHooks();
406
+ if (options?.hooks)
407
+ hooks.addHooks(options.hooks);
408
+ options.plugins = [
409
+ DeprecatedTagAttrPlugin(),
410
+ DedupesTagsPlugin(),
411
+ SortTagsPlugin(),
412
+ TitleTemplatePlugin(),
413
+ EventHandlersPlugin(),
414
+ ProvideTagHashPlugin(),
415
+ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }),
416
+ ...options?.plugins || []
417
+ ];
418
+ options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks));
419
+ const triggerUpdateHook = () => hooks.callHook("entries:updated", head);
420
+ const head = {
421
+ resolvedOptions: options,
422
+ headEntries() {
423
+ return entries;
424
+ },
425
+ get hooks() {
426
+ return hooks;
427
+ },
428
+ push(input, options2) {
429
+ const activeEntry = {
430
+ _i: _eid++,
431
+ input,
432
+ _sde: {}
433
+ };
434
+ if (options2?.mode)
435
+ activeEntry._m = options2?.mode;
436
+ entries.push(activeEntry);
437
+ triggerUpdateHook();
438
+ const queueSideEffects = (e) => {
439
+ _sde = { ..._sde, ...e._sde || {} };
440
+ e._sde = {};
441
+ triggerUpdateHook();
442
+ };
443
+ return {
444
+ dispose() {
445
+ entries = entries.filter((e) => {
446
+ if (e._i !== activeEntry._i)
447
+ return true;
448
+ queueSideEffects(e);
449
+ return false;
450
+ });
451
+ },
452
+ patch(input2) {
453
+ entries = entries.map((e) => {
454
+ if (e._i === activeEntry._i) {
455
+ queueSideEffects(e);
456
+ activeEntry.input = e.input = input2;
457
+ activeEntry._i = e._i = _eid++;
458
+ }
459
+ return e;
460
+ });
461
+ }
462
+ };
463
+ },
464
+ async resolveTags() {
465
+ const resolveCtx = { tags: [], entries: [...entries] };
466
+ await hooks.callHook("entries:resolve", resolveCtx);
467
+ for (const entry of resolveCtx.entries) {
468
+ for (const tag of normaliseEntryTags(entry)) {
469
+ const tagCtx = { tag, entry };
470
+ await hooks.callHook("tag:normalise", tagCtx);
471
+ resolveCtx.tags.push(tagCtx.tag);
472
+ }
473
+ }
474
+ await hooks.callHook("tags:resolve", resolveCtx);
475
+ return resolveCtx.tags;
476
+ },
477
+ _elMap: {},
478
+ _popSideEffectQueue() {
479
+ const sde = { ..._sde };
480
+ _sde = {};
481
+ return sde;
482
+ }
483
+ };
484
+ head.hooks.callHook("init", head);
485
+ setActiveHead(head);
486
+ return head;
487
+ }
488
+
489
+ function defineHeadPlugin(plugin) {
490
+ return plugin;
491
+ }
492
+ const composableNames = [
493
+ "useHead",
494
+ "useTagTitle",
495
+ "useTagBase",
496
+ "useTagMeta",
497
+ "useTagMetaFlat",
498
+ "useTagLink",
499
+ "useTagScript",
500
+ "useTagStyle",
501
+ "useTagNoscript",
502
+ "useHtmlAttrs",
503
+ "useBodyAttrs",
504
+ "useTitleTemplate",
505
+ "useServerHead",
506
+ "useServerTagTitle",
507
+ "useServerTagBase",
508
+ "useServerTagMeta",
509
+ "useServerTagMetaFlat",
510
+ "useServerTagLink",
511
+ "useServerTagScript",
512
+ "useServerTagStyle",
513
+ "useServerTagNoscript",
514
+ "useServerHtmlAttrs",
515
+ "useServerBodyAttrs",
516
+ "useServerTitleTemplate"
517
+ ];
518
+
519
+ function resolveUnref(r) {
520
+ return typeof r === "function" ? r() : vue.unref(r);
521
+ }
522
+ function resolveUnrefHeadInput(ref, lastKey = "") {
523
+ const root = resolveUnref(ref);
10
524
  if (!ref || !root)
11
525
  return root;
12
526
  if (Array.isArray(root))
13
- return root.map(resolveUnrefHeadInput);
527
+ return root.map((r) => resolveUnrefHeadInput(r, lastKey));
14
528
  if (typeof root === "object") {
15
- return Object.fromEntries(
529
+ const unrefdObj = Object.fromEntries(
16
530
  Object.entries(root).map(([key, value]) => {
17
531
  if (key === "titleTemplate" || key.startsWith("on"))
18
532
  return [key, vue.unref(value)];
19
- return [key, resolveUnrefHeadInput(value)];
533
+ return [key, resolveUnrefHeadInput(value, key)];
20
534
  })
21
535
  );
536
+ if (HasElementTags.includes(String(lastKey)) && JSON.stringify(unrefdObj) !== JSON.stringify(root))
537
+ unrefdObj._dynamic = true;
538
+ return unrefdObj;
22
539
  }
23
540
  return root;
24
541
  }
@@ -31,14 +548,14 @@ const IsBrowser = typeof window !== "undefined";
31
548
 
32
549
  const headSymbol = "usehead";
33
550
  function injectHead() {
34
- return vue.getCurrentInstance() && vue.inject(headSymbol) || unhead.getActiveHead();
551
+ return vue.getCurrentInstance() && vue.inject(headSymbol) || getActiveHead();
35
552
  }
36
553
  function createHead(options = {}) {
37
554
  const plugins = [
38
555
  VueReactiveUseHeadPlugin(),
39
556
  ...options?.plugins || []
40
557
  ];
41
- const head = unhead.createHead({
558
+ const head = createHead$1({
42
559
  ...options,
43
560
  domDelayFn: (fn) => setTimeout(() => vue.nextTick(() => fn()), 10),
44
561
  plugins
@@ -69,7 +586,7 @@ const VueHeadMixin = {
69
586
  };
70
587
 
71
588
  const VueReactiveUseHeadPlugin = () => {
72
- return unhead.defineHeadPlugin({
589
+ return defineHeadPlugin({
73
590
  hooks: {
74
591
  "entries:resolve": function(ctx) {
75
592
  for (const entry of ctx.entries)
@@ -313,7 +830,7 @@ const coreComposableNames = [
313
830
  const unheadVueComposablesImports = [
314
831
  {
315
832
  from: "@unhead/vue",
316
- imports: [...coreComposableNames, ...unhead.composableNames]
833
+ imports: [...coreComposableNames, ...composableNames]
317
834
  }
318
835
  ];
319
836
 
@@ -350,6 +867,3 @@ exports.useTagScript = useTagScript;
350
867
  exports.useTagStyle = useTagStyle;
351
868
  exports.useTagTitle = useTagTitle;
352
869
  exports.useTitleTemplate = useTitleTemplate;
353
- for (const k in dom) {
354
- if (k !== 'default' && !exports.hasOwnProperty(k)) exports[k] = dom[k];
355
- }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,10 @@
1
- import { MaybeComputedRef, MaybeRef } from '@vueuse/shared';
2
- export { MaybeComputedRef } from '@vueuse/shared';
3
1
  import * as _unhead_schema from '@unhead/schema';
4
2
  import { Title as Title$1, TitleTemplate as TitleTemplate$1, EntryAugmentation, Base as Base$1, Link as Link$1, Meta as Meta$1, Style as Style$1, Script as Script$1, Noscript as Noscript$1, DataKeys, SchemaAugmentations, DefinedValueOrEmptyObject, MergeHead, BaseHtmlAttr, MaybeArray, BaseBodyAttr, Unhead, CreateHeadOptions, HeadEntryOptions, MetaFlatInput, ActiveHeadEntry } from '@unhead/schema';
5
3
  export { ActiveHeadEntry, Head, HeadEntryOptions, HeadTag, MergeHead, Unhead } from '@unhead/schema';
6
- import { Plugin } from 'vue';
7
- export * from '@unhead/dom';
4
+ import { ComputedRef, Ref, Plugin } from 'vue';
8
5
 
6
+ declare type MaybeReadonlyRef<T> = (() => T) | ComputedRef<T>;
7
+ declare type MaybeComputedRef<T> = T | MaybeReadonlyRef<T> | Ref<T>;
9
8
  declare type MaybeComputedRefEntries<T> = MaybeComputedRef<T> | {
10
9
  [key in keyof T]?: MaybeComputedRef<T[key]>;
11
10
  };
@@ -28,7 +27,7 @@ interface BodyAttr extends Omit<BaseBodyAttr, 'class'> {
28
27
  class?: MaybeArray<MaybeComputedRef<string>> | Record<string, MaybeComputedRef<boolean>>;
29
28
  }
30
29
  declare type Title = MaybeComputedRef<Title$1>;
31
- declare type TitleTemplate = MaybeRef<TitleTemplate$1> | ((title?: string) => TitleTemplate$1);
30
+ declare type TitleTemplate = TitleTemplate$1 | Ref<TitleTemplate$1> | ((title?: string) => TitleTemplate$1);
32
31
  declare type Base<E extends EntryAugmentation = {}> = MaybeComputedRef<MaybeComputedRefEntries<Base$1<E>>>;
33
32
  declare type Link<E extends EntryAugmentation = {}> = MaybeComputedRefEntries<Link$1<E>>;
34
33
  declare type Meta<E extends EntryAugmentation = {}> = MaybeComputedRefEntries<Meta$1<E>>;
@@ -105,7 +104,7 @@ interface ReactiveHead<E extends MergeHead = MergeHead> {
105
104
  }
106
105
  declare type UseHeadInput<T extends MergeHead = {}> = MaybeComputedRef<ReactiveHead<T>>;
107
106
 
108
- declare function resolveUnrefHeadInput(ref: any): any;
107
+ declare function resolveUnrefHeadInput(ref: any, lastKey?: string | number): any;
109
108
  declare function asArray<T>(value: Arrayable<T>): T[];
110
109
 
111
110
  declare type VueHeadClient<T extends MergeHead> = Unhead<MaybeComputedRef<ReactiveHead<T>>> & Plugin;
@@ -152,4 +151,4 @@ declare const unheadVueComposablesImports: {
152
151
  imports: string[];
153
152
  }[];
154
153
 
155
- export { Arrayable, Base, BodyAttributes, HtmlAttributes, Link, MaybeComputedRefEntries, Meta, Noscript, ReactiveHead, Script, Style, Title, TitleTemplate, UseHeadInput, Vue2ProvideUnheadPlugin, VueHeadClient, VueHeadMixin, VueReactiveUseHeadPlugin, asArray, createHead, headSymbol, injectHead, resolveUnrefHeadInput, unheadVueComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };
154
+ export { Arrayable, Base, BodyAttributes, HtmlAttributes, Link, MaybeComputedRef, MaybeComputedRefEntries, MaybeReadonlyRef, Meta, Noscript, ReactiveHead, Script, Style, Title, TitleTemplate, UseHeadInput, Vue2ProvideUnheadPlugin, VueHeadClient, VueHeadMixin, VueReactiveUseHeadPlugin, asArray, createHead, headSymbol, injectHead, resolveUnrefHeadInput, unheadVueComposablesImports, useBodyAttrs, useHead, useHtmlAttrs, useServerBodyAttrs, useServerHead, useServerHtmlAttrs, useServerTagBase, useServerTagLink, useServerTagMeta, useServerTagMetaFlat, useServerTagNoscript, useServerTagScript, useServerTagStyle, useServerTagTitle, useServerTitleTemplate, useTagBase, useTagLink, useTagMeta, useTagMetaFlat, useTagNoscript, useTagScript, useTagStyle, useTagTitle, useTitleTemplate };