'use strict'; const hookable = require('hookable'); const vue = require('vue'); const TagsWithInnerContent = ["script", "style", "noscript"]; const HasElementTags$1 = [ "base", "meta", "link", "style", "script", "noscript" ]; const UniqueTags$1 = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"]; function tagDedupeKey$1(tag, fn) { const { props, tag: tagName } = tag; if (UniqueTags$1.includes(tagName)) return tagName; if (tagName === "link" && props.rel === "canonical") return "canonical"; if (props.charset) return "charset"; const name = ["id"]; if (tagName === "meta") name.push(...["name", "property", "http-equiv"]); for (const n of name) { if (typeof props[n] !== "undefined") { const val = String(props[n]); if (fn && !fn(val)) return false; return `${tagName}:${n}:${val}`; } } return false; } const setAttrs = (ctx, markSideEffect) => { const { tag, $el } = ctx; if (!$el) return; Object.entries(tag.props).forEach(([k, value]) => { value = String(value); const attrSdeKey = `attr:${k}`; if (k === "class") { if (!value) return; for (const c of value.split(" ")) { const classSdeKey = `${attrSdeKey}:${c}`; if (markSideEffect) markSideEffect(ctx, classSdeKey, () => $el.classList.remove(c)); if (!$el.classList.contains(c)) $el.classList.add(c); } return; } if (markSideEffect && !k.startsWith("data-h-")) markSideEffect(ctx, attrSdeKey, () => $el.removeAttribute(k)); if ($el.getAttribute(k) !== value) $el.setAttribute(k, value); }); if (TagsWithInnerContent.includes(tag.tag) && $el.innerHTML !== (tag.children || "")) $el.innerHTML = tag.children || ""; }; function hashCode(s) { let h = 9; for (let i = 0; i < s.length; ) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9); return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase(); } async function renderDOMHead(head, options = {}) { const ctx = { shouldRender: true }; await head.hooks.callHook("dom:beforeRender", ctx); if (!ctx.shouldRender) return; const dom = options.document || window.document; const staleSideEffects = head._popSideEffectQueue(); head.headEntries().map((entry) => entry._sde).forEach((sde) => { Object.entries(sde).forEach(([key, fn]) => { staleSideEffects[key] = fn; }); }); const preRenderTag = async (tag) => { const entry = head.headEntries().find((e) => e._i === tag._e); const renderCtx = { renderId: tag._d || hashCode(JSON.stringify({ ...tag, _e: void 0, _p: void 0 })), $el: null, shouldRender: true, tag, entry, staleSideEffects }; await head.hooks.callHook("dom:beforeRenderTag", renderCtx); return renderCtx; }; const renders = []; const pendingRenders = { body: [], head: [] }; const markSideEffect = (ctx2, key, fn) => { key = `${ctx2.renderId}:${key}`; if (ctx2.entry) ctx2.entry._sde[key] = fn; delete staleSideEffects[key]; }; const markEl = (ctx2) => { head._elMap[ctx2.renderId] = ctx2.$el; renders.push(ctx2); markSideEffect(ctx2, "el", () => { ctx2.$el?.remove(); delete head._elMap[ctx2.renderId]; }); }; for (const t of await head.resolveTags()) { const ctx2 = await preRenderTag(t); if (!ctx2.shouldRender) continue; const { tag } = ctx2; if (tag.tag === "title") { dom.title = tag.children || ""; renders.push(ctx2); continue; } if (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs") { ctx2.$el = dom[tag.tag === "htmlAttrs" ? "documentElement" : "body"]; setAttrs(ctx2, markSideEffect); renders.push(ctx2); continue; } ctx2.$el = head._elMap[ctx2.renderId]; if (!ctx2.$el && tag._hash) { ctx2.$el = dom.querySelector(`${tag.tagPosition?.startsWith("body") ? "body" : "head"} > ${tag.tag}[data-h-${tag._hash}]`); } if (ctx2.$el) { if (ctx2.tag._d) setAttrs(ctx2); markEl(ctx2); continue; } ctx2.$el = dom.createElement(tag.tag); setAttrs(ctx2); pendingRenders[tag.tagPosition?.startsWith("body") ? "body" : "head"].push(ctx2); } Object.entries(pendingRenders).forEach(([pos, queue]) => { if (!queue.length) return; for (const $el of [...dom[pos].children].reverse()) { const elTag = $el.tagName.toLowerCase(); if (!HasElementTags$1.includes(elTag)) continue; const dedupeKey = tagDedupeKey$1({ tag: elTag, props: $el.getAttributeNames().reduce((props, name) => ({ ...props, [name]: $el.getAttribute(name) }), {}) }); const matchIdx = queue.findIndex((ctx2) => ctx2 && (ctx2.tag._d === dedupeKey || $el.isEqualNode(ctx2.$el))); if (matchIdx !== -1) { const ctx2 = queue[matchIdx]; ctx2.$el = $el; setAttrs(ctx2); markEl(ctx2); delete queue[matchIdx]; } } queue.forEach((ctx2) => { if (!ctx2.$el) return; switch (ctx2.tag.tagPosition) { case "bodyClose": dom.body.appendChild(ctx2.$el); break; case "bodyOpen": dom.body.insertBefore(ctx2.$el, dom.body.firstChild); break; case "head": default: dom.head.appendChild(ctx2.$el); break; } markEl(ctx2); }); }); for (const ctx2 of renders) await head.hooks.callHook("dom:renderTag", ctx2); Object.values(staleSideEffects).forEach((fn) => fn()); } let domUpdatePromise = null; async function debouncedRenderDOMHead(head, options = {}) { function doDomUpdate() { domUpdatePromise = null; return renderDOMHead(head, options); } const delayFn = options.delayFn || ((fn) => setTimeout(fn, 10)); return domUpdatePromise = domUpdatePromise || new Promise((resolve) => delayFn(() => resolve(doDomUpdate()))); } const index = { __proto__: null, debouncedRenderDOMHead: debouncedRenderDOMHead, get domUpdatePromise () { return domUpdatePromise; }, hashCode: hashCode, renderDOMHead: renderDOMHead }; const ValidHeadTags = [ "title", "titleTemplate", "base", "htmlAttrs", "bodyAttrs", "meta", "link", "style", "script", "noscript" ]; const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"]; async function normaliseTag(tagName, input) { const tag = { tag: tagName, props: {} }; if (tagName === "title" || tagName === "titleTemplate") { tag.children = input instanceof Promise ? await input : input; return tag; } tag.props = await normaliseProps({ ...input }); ["children", "innerHtml", "innerHTML"].forEach((key) => { if (typeof tag.props[key] !== "undefined") { tag.children = tag.props[key]; if (typeof tag.children === "object") tag.children = JSON.stringify(tag.children); delete tag.props[key]; } }); Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => { tag[k] = tag.props[k]; delete tag.props[k]; }); if (typeof tag.props.class === "object" && !Array.isArray(tag.props.class)) { tag.props.class = Object.keys(tag.props.class).filter((k) => tag.props.class[k]); } if (Array.isArray(tag.props.class)) tag.props.class = tag.props.class.join(" "); if (tag.props.content && Array.isArray(tag.props.content)) { return tag.props.content.map((v, i) => { const newTag = { ...tag, props: { ...tag.props } }; newTag.props.content = v; newTag.key = `${tag.props.name || tag.props.property}:${i}`; return newTag; }); } return tag; } async function normaliseProps(props) { for (const k of Object.keys(props)) { if (props[k] instanceof Promise) { props[k] = await props[k]; } if (String(props[k]) === "true") { props[k] = ""; } else if (String(props[k]) === "false") { delete props[k]; } } return props; } const tagWeight = (tag) => { if (typeof tag.tagPriority === "number") return tag.tagPriority; switch (tag.tagPriority) { case "critical": return 2; case "high": return 9; case "low": return 12; } switch (tag.tag) { case "base": return -1; case "title": return 1; case "meta": if (tag.props.charset) return -2; if (tag.props["http-equiv"] === "content-security-policy") return 0; return 10; default: return 10; } }; const sortTags = (aTag, bTag) => { return tagWeight(aTag) - tagWeight(bTag); }; const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"]; function tagDedupeKey(tag, fn) { const { props, tag: tagName } = tag; if (UniqueTags.includes(tagName)) return tagName; if (tagName === "link" && props.rel === "canonical") return "canonical"; if (props.charset) return "charset"; const name = ["id"]; if (tagName === "meta") name.push(...["name", "property", "http-equiv"]); for (const n of name) { if (typeof props[n] !== "undefined") { const val = String(props[n]); if (fn && !fn(val)) return false; return `${tagName}:${n}:${val}`; } } return false; } const renderTitleTemplate = (template, title) => { if (template == null) return title || null; if (typeof template === "function") return template(title); return template.replace("%s", title ?? ""); }; function resolveTitleTemplateFromTags(tags) { let titleTemplateIdx = tags.findIndex((i) => i.tag === "titleTemplate"); const titleIdx = tags.findIndex((i) => i.tag === "title"); if (titleIdx !== -1 && titleTemplateIdx !== -1) { const newTitle = renderTitleTemplate( tags[titleTemplateIdx].children, tags[titleIdx].children ); if (newTitle !== null) { tags[titleIdx].children = newTitle || tags[titleIdx].children; } else { delete tags[titleIdx]; } } else if (titleTemplateIdx !== -1) { const newTitle = renderTitleTemplate( tags[titleTemplateIdx].children ); if (newTitle !== null) { tags[titleTemplateIdx].children = newTitle; tags[titleTemplateIdx].tag = "title"; titleTemplateIdx = -1; } } if (titleTemplateIdx !== -1) { delete tags[titleTemplateIdx]; } return tags.filter(Boolean); } const DedupesTagsPlugin = (options) => { options = options || {}; const dedupeKeys = options.dedupeKeys || ["hid", "vmid", "key"]; return defineHeadPlugin({ hooks: { "tag:normalise": function({ tag }) { dedupeKeys.forEach((key) => { if (tag.props[key]) { tag.key = tag.props[key]; delete tag.props[key]; } }); const dedupe = tag.key ? `${tag.tag}:${tag.key}` : tagDedupeKey(tag); if (dedupe) tag._d = dedupe; }, "tags:resolve": function(ctx) { const deduping = {}; ctx.tags.forEach((tag) => { let dedupeKey = tag._d || tag._p; const dupedTag = deduping[dedupeKey]; if (dupedTag) { let strategy = tag?.tagDuplicateStrategy; if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs")) strategy = "merge"; if (strategy === "merge") { const oldProps = dupedTag.props; ["class", "style"].forEach((key) => { if (tag.props[key] && oldProps[key]) { if (key === "style" && !oldProps[key].endsWith(";")) oldProps[key] += ";"; tag.props[key] = `${oldProps[key]} ${tag.props[key]}`; } }); deduping[dedupeKey].props = { ...oldProps, ...tag.props }; return; } else if (tag._e === dupedTag._e) { dedupeKey = tag._d = `${dedupeKey}:${tag._p}`; } const propCount = Object.keys(tag.props).length; if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) { delete deduping[dedupeKey]; return; } } deduping[dedupeKey] = tag; }); ctx.tags = Object.values(deduping); } } }); }; const SortTagsPlugin = () => { return defineHeadPlugin({ hooks: { "tags:resolve": (ctx) => { const tagIndexForKey = (key) => ctx.tags.find((tag) => tag._d === key)?._p; for (const tag of ctx.tags) { if (!tag.tagPriority || typeof tag.tagPriority === "number") continue; const modifiers = [{ prefix: "before:", offset: -1 }, { prefix: "after:", offset: 1 }]; for (const { prefix, offset } of modifiers) { if (tag.tagPriority.startsWith(prefix)) { const key = tag.tagPriority.replace(prefix, ""); const index = tagIndexForKey(key); if (typeof index !== "undefined") tag._p = index + offset; } } } ctx.tags.sort((a, b) => a._p - b._p).sort(sortTags); } } }); }; const TitleTemplatePlugin = () => { return defineHeadPlugin({ hooks: { "tags:resolve": (ctx) => { ctx.tags = resolveTitleTemplateFromTags(ctx.tags); } } }); }; const DeprecatedTagAttrPlugin = () => { return defineHeadPlugin({ hooks: { "tag:normalise": function({ tag }) { if (typeof tag.props.body !== "undefined") { tag.tagPosition = "bodyClose"; delete tag.props.body; } } } }); }; const IsBrowser$1 = typeof window !== "undefined"; const ProvideTagHashPlugin = () => { return defineHeadPlugin({ hooks: { "tag:normalise": (ctx) => { const { tag, entry } = ctx; const isDynamic = typeof tag.props._dynamic !== "undefined"; if (!HasElementTags.includes(tag.tag) || !tag.key) return; tag._hash = hashCode(JSON.stringify({ tag: tag.tag, key: tag.key })); if (IsBrowser$1 || getActiveHead()?.resolvedOptions?.document) return; if (entry._m === "server" || isDynamic) { tag.props[`data-h-${tag._hash}`] = ""; } }, "tags:resolve": (ctx) => { ctx.tags = ctx.tags.map((t) => { delete t.props._dynamic; return t; }); } } }); }; const PatchDomOnEntryUpdatesPlugin = (options) => { return defineHeadPlugin({ hooks: { "entries:updated": function(head) { if (typeof options?.document === "undefined" && typeof window === "undefined") return; let delayFn = options?.delayFn; if (!delayFn && typeof requestAnimationFrame !== "undefined") delayFn = requestAnimationFrame; Promise.resolve().then(function () { return index; }).then(({ debouncedRenderDOMHead }) => { debouncedRenderDOMHead(head, { document: options?.document || window.document, delayFn }); }); } } }); }; const EventHandlersPlugin = () => { const stripEventHandlers = (mode, tag) => { const props = {}; const eventHandlers = {}; Object.entries(tag.props).forEach(([key, value]) => { if (key.startsWith("on") && typeof value === "function") eventHandlers[key] = value; else props[key] = value; }); let delayedSrc; if (mode === "dom" && tag.tag === "script" && typeof props.src === "string" && typeof eventHandlers.onload !== "undefined") { delayedSrc = props.src; delete props.src; } return { props, eventHandlers, delayedSrc }; }; return defineHeadPlugin({ hooks: { "ssr:render": function(ctx) { ctx.tags = ctx.tags.map((tag) => { tag.props = stripEventHandlers("ssr", tag).props; return tag; }); }, "dom:beforeRenderTag": function(ctx) { const { props, eventHandlers, delayedSrc } = stripEventHandlers("dom", ctx.tag); if (!Object.keys(eventHandlers).length) return; ctx.tag.props = props; ctx.tag._eventHandlers = eventHandlers; ctx.tag._delayedSrc = delayedSrc; }, "dom:renderTag": function(ctx) { const $el = ctx.$el; if (!ctx.tag._eventHandlers || !$el) return; const $eventListenerTarget = ctx.tag.tag === "bodyAttrs" && typeof window !== "undefined" ? window : $el; Object.entries(ctx.tag._eventHandlers).forEach(([k, value]) => { const sdeKey = `${ctx.tag._d || ctx.tag._p}:${k}`; const eventName = k.slice(2).toLowerCase(); const eventDedupeKey = `data-h-${eventName}`; delete ctx.staleSideEffects[sdeKey]; if ($el.hasAttribute(eventDedupeKey)) return; const handler = value; $el.setAttribute(eventDedupeKey, ""); $eventListenerTarget.addEventListener(eventName, handler); if (ctx.entry) { ctx.entry._sde[sdeKey] = () => { $eventListenerTarget.removeEventListener(eventName, handler); $el.removeAttribute(eventDedupeKey); }; } }); if (ctx.tag._delayedSrc) { $el.setAttribute("src", ctx.tag._delayedSrc); } } } }); }; function asArray$1(value) { return Array.isArray(value) ? value : [value]; } const HasElementTags = [ "base", "meta", "link", "style", "script", "noscript" ]; let activeHead; const setActiveHead = (head) => activeHead = head; const getActiveHead = () => activeHead; const TagEntityBits = 10; async function normaliseEntryTags(e) { const tagPromises = []; Object.entries(e.resolvedInput || e.input).filter(([k, v]) => typeof v !== "undefined" && ValidHeadTags.includes(k)).forEach(([k, value]) => { const v = asArray$1(value); tagPromises.push(...v.map((props) => normaliseTag(k, props)).flat()); }); return (await Promise.all(tagPromises)).flat().map((t, i) => { t._e = e._i; t._p = (e._i << TagEntityBits) + i; return t; }); } const CorePlugins = () => [ DedupesTagsPlugin(), SortTagsPlugin(), TitleTemplatePlugin(), ProvideTagHashPlugin(), EventHandlersPlugin(), DeprecatedTagAttrPlugin() ]; const DOMPlugins = (options = {}) => [ PatchDomOnEntryUpdatesPlugin({ document: options?.document, delayFn: options?.domDelayFn }) ]; function createHead$1(options = {}) { const head = createHeadCore({ ...options, plugins: [...DOMPlugins(options), ...options?.plugins || []] }); setActiveHead(head); return head; } function createHeadCore(options = {}) { let entries = []; let _sde = {}; let _eid = 0; const hooks = hookable.createHooks(); if (options?.hooks) hooks.addHooks(options.hooks); options.plugins = [ ...CorePlugins(), ...options?.plugins || [] ]; options.plugins.forEach((p) => p.hooks && hooks.addHooks(p.hooks)); const updated = () => hooks.callHook("entries:updated", head); const head = { resolvedOptions: options, headEntries() { return entries; }, get hooks() { return hooks; }, use(plugin) { if (plugin.hooks) hooks.addHooks(plugin.hooks); }, push(input, options2) { const activeEntry = { _i: _eid++, input, _sde: {} }; if (options2?.mode) activeEntry._m = options2?.mode; entries.push(activeEntry); updated(); return { dispose() { entries = entries.filter((e) => { if (e._i !== activeEntry._i) return true; _sde = { ..._sde, ...e._sde || {} }; e._sde = {}; updated(); return false; }); }, patch(input2) { entries = entries.map((e) => { if (e._i === activeEntry._i) { activeEntry.input = e.input = input2; updated(); } return e; }); } }; }, async resolveTags() { const resolveCtx = { tags: [], entries: [...entries] }; await hooks.callHook("entries:resolve", resolveCtx); for (const entry of resolveCtx.entries) { for (const tag of await normaliseEntryTags(entry)) { const tagCtx = { tag, entry }; await hooks.callHook("tag:normalise", tagCtx); resolveCtx.tags.push(tagCtx.tag); } } await hooks.callHook("tags:resolve", resolveCtx); return resolveCtx.tags; }, _elMap: {}, _popSideEffectQueue() { const sde = { ..._sde }; _sde = {}; return sde; } }; head.hooks.callHook("init", head); return head; } function defineHeadPlugin(plugin) { return plugin; } const composableNames = [ "useHead", "useTagTitle", "useTagBase", "useTagMeta", "useTagMetaFlat", "useSeoMeta", "useTagLink", "useTagScript", "useTagStyle", "useTagNoscript", "useHtmlAttrs", "useBodyAttrs", "useTitleTemplate", "useServerHead", "useServerTagTitle", "useServerTagBase", "useServerTagMeta", "useServerTagMetaFlat", "useServerTagLink", "useServerTagScript", "useServerTagStyle", "useServerTagNoscript", "useServerHtmlAttrs", "useServerBodyAttrs", "useServerTitleTemplate" ]; function resolveUnref(r) { return typeof r === "function" ? r() : vue.unref(r); } function resolveUnrefHeadInput(ref, lastKey = "") { if (ref instanceof Promise) return ref; const root = resolveUnref(ref); if (!ref || !root) return root; if (Array.isArray(root)) return root.map((r) => resolveUnrefHeadInput(r, lastKey)); if (typeof root === "object") { let dynamic = false; const unrefdObj = Object.fromEntries( Object.entries(root).map(([k, v]) => { if (k === "titleTemplate" || k.startsWith("on")) return [k, vue.unref(v)]; if (typeof v === "function" || vue.isRef(v)) dynamic = true; return [k, resolveUnrefHeadInput(v, k)]; }) ); if (dynamic && HasElementTags.includes(String(lastKey))) unrefdObj._dynamic = true; return unrefdObj; } return root; } function asArray(value) { return Array.isArray(value) ? value : [value]; } const Vue3 = vue.version.startsWith("3"); const IsBrowser = typeof window !== "undefined"; const headSymbol = "usehead"; function injectHead() { return vue.getCurrentInstance() && vue.inject(headSymbol) || getActiveHead(); } function createHead(options = {}) { const head = createHead$1({ ...options, domDelayFn: (fn) => setTimeout(() => vue.nextTick(() => fn()), 10), plugins: [ VueReactiveUseHeadPlugin(), ...options?.plugins || [] ] }); const vuePlugin = { install(app) { if (Vue3) { app.config.globalProperties.$unhead = head; app.provide(headSymbol, head); } } }; head.install = vuePlugin.install; return head; } const VueHeadMixin = { created() { const instance = vue.getCurrentInstance(); if (!instance) return; const options = instance.type; if (!options || !("head" in options)) return; const source = typeof options.head === "function" ? () => options.head.call(instance.proxy) : options.head; useHead(source); } }; const VueReactiveUseHeadPlugin = () => { return defineHeadPlugin({ hooks: { "entries:resolve": function(ctx) { for (const entry of ctx.entries) entry.resolvedInput = resolveUnrefHeadInput(entry.input); } } }); }; const Vue2ProvideUnheadPlugin = function(_Vue, head) { _Vue.mixin({ beforeCreate() { const options = this.$options; const origProvide = options.provide; options.provide = function() { let origProvideResult; if (typeof origProvide === "function") origProvideResult = origProvide.call(this); else origProvideResult = origProvide || {}; return { ...origProvideResult, [headSymbol]: head }; }; } }); }; function unpackToArray(input, options) { const unpacked = []; const kFn = options.resolveKeyData || ((ctx) => ctx.key); const vFn = options.resolveValueData || ((ctx) => ctx.value); for (const [k, v] of Object.entries(input)) { unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => { const ctx = { key: k, value: i }; const val = vFn(ctx); if (typeof val === "object") return unpackToArray(val, options); if (Array.isArray(val)) return val; return { [typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx), [typeof options.value === "function" ? options.value(ctx) : options.value]: val }; }).flat()); } return unpacked; } function unpackToString(value, options) { return Object.entries(value).map(([key, value2]) => { if (typeof value2 === "object") value2 = unpackToString(value2, options); if (options.resolve) { const resolved = options.resolve({ key, value: value2 }); if (resolved) return resolved; } if (typeof value2 === "number") value2 = value2.toString(); if (typeof value2 === "string" && options.wrapValue) { value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`); value2 = `${options.wrapValue}${value2}${options.wrapValue}`; } return `${key}${options.keyValueSeparator || ""}${value2}`; }).join(options.entrySeparator || ""); } const MetaPackingSchema = { robots: { unpack: { keyValueSeparator: ":" } }, contentSecurityPolicy: { unpack: { keyValueSeparator: " ", entrySeparator: "; " }, metaKey: "http-equiv" }, fbAppId: { keyValue: "fb:app_id", metaKey: "property" }, msapplicationTileImage: { keyValue: "msapplication-TileImage" }, msapplicationTileColor: { keyValue: "msapplication-TileColor" }, msapplicationConfig: { keyValue: "msapplication-Config" }, charset: { metaKey: "charset" }, contentType: { metaKey: "http-equiv" }, defaultStyle: { metaKey: "http-equiv" }, xUaCompatible: { metaKey: "http-equiv" }, refresh: { metaKey: "http-equiv" } }; function resolveMetaKeyType(key) { return PropertyPrefixKeys.test(key) ? "property" : MetaPackingSchema[key]?.metaKey || "name"; } function unpackMeta(input) { const meta = unpackToArray(input, { key({ key }) { return resolveMetaKeyType(key); }, value({ key }) { return key === "charset" ? "charset" : "content"; }, resolveKeyData({ key }) { return MetaPackingSchema[key]?.keyValue || fixKeyCase(key); }, resolveValueData({ value, key }) { if (value === null) return "_null"; if (typeof value === "object") { const definition = MetaPackingSchema[key]; if (key === "refresh") return `${value.seconds};url=${value.url}`; return unpackToString( changeKeyCasingDeep(value), { entrySeparator: ", ", keyValueSeparator: "=", resolve({ value: value2, key: key2 }) { if (value2 === null) return ""; if (typeof value2 === "boolean") return `${key2}`; }, ...definition?.unpack } ); } return typeof value === "number" ? value.toString() : value; } }); return meta.filter((v) => typeof v.content === "undefined" || v.content !== "_null"); } const PropertyPrefixKeys = /^(og|twitter|fb)/; function fixKeyCase(key) { key = key.replace(/([A-Z])/g, "-$1").toLowerCase(); if (PropertyPrefixKeys.test(key)) { key = key.replace("secure-url", "secure_url").replace(/-/g, ":"); } return key; } function changeKeyCasingDeep(input) { if (Array.isArray(input)) { return input.map((entry) => changeKeyCasingDeep(entry)); } if (typeof input !== "object" || Array.isArray(input)) return input; const output = {}; for (const [key, value] of Object.entries(input)) output[fixKeyCase(key)] = changeKeyCasingDeep(value); return output; } function clientUseHead(input, options = {}) { const head = injectHead(); const resolvedInput = vue.ref({}); vue.watchEffect(() => { resolvedInput.value = resolveUnrefHeadInput(input); }); const entry = head.push(resolvedInput.value, options); vue.watch(resolvedInput, (e) => entry.patch(e)); const vm = vue.getCurrentInstance(); if (vm) { vue.onBeforeUnmount(() => { entry.dispose(); }); } return entry; } function serverUseHead(input, options = {}) { const head = injectHead(); return head.push(input, options); } function useServerHead(input, options = {}) { return useHead(input, { ...options, mode: "server" }); } const useServerTagTitle = (title) => useServerHead({ title }); const useServerTitleTemplate = (titleTemplate) => useServerHead({ titleTemplate }); const useServerTagMeta = (meta) => useServerHead({ meta: asArray(meta) }); const useServerTagMetaFlat = (meta) => { const input = vue.ref({}); vue.watchEffect(() => { input.value = unpackMeta(resolveUnrefHeadInput(meta)); }); return useServerHead({ meta: input }); }; const useServerTagLink = (link) => useServerHead({ link: asArray(link) }); const useServerTagScript = (script) => useServerHead({ script: asArray(script) }); const useServerTagStyle = (style) => useServerHead({ style: asArray(style) }); const useServerTagNoscript = (noscript) => useServerHead({ noscript: asArray(noscript) }); const useServerTagBase = (base) => useServerHead({ base }); const useServerHtmlAttrs = (attrs) => useServerHead({ htmlAttrs: attrs }); const useServerBodyAttrs = (attrs) => useHead({ bodyAttrs: attrs }); function useHead(input, options = {}) { const head = injectHead(); if (head) { const isBrowser = IsBrowser || !!head.resolvedOptions?.document; if (options.mode === "server" && isBrowser || options.mode === "client" && !isBrowser) return; return isBrowser ? clientUseHead(input, options) : serverUseHead(input, options); } } const useTagTitle = (title) => useHead({ title }); const useTitleTemplate = (titleTemplate) => useHead({ titleTemplate }); const useTagMeta = (meta) => useHead({ meta: asArray(meta) }); const useTagMetaFlat = (meta) => { const input = vue.ref({}); vue.watchEffect(() => { input.value = unpackMeta(resolveUnrefHeadInput(meta)); }); return useHead({ meta: input }); }; const useSeoMeta = useTagMetaFlat; const useTagLink = (link) => useHead({ link: asArray(link) }); const useTagScript = (script) => useHead({ script: asArray(script) }); const useTagStyle = (style) => useHead({ style: asArray(style) }); const useTagNoscript = (noscript) => useHead({ noscript: asArray(noscript) }); const useTagBase = (base) => useHead({ base }); const useHtmlAttrs = (attrs) => useHead({ htmlAttrs: attrs }); const useBodyAttrs = (attrs) => useHead({ bodyAttrs: attrs }); const coreComposableNames = [ "injectHead" ]; const unheadVueComposablesImports = [ { from: "@unhead/vue", imports: [...coreComposableNames, ...composableNames] } ]; exports.Vue2ProvideUnheadPlugin = Vue2ProvideUnheadPlugin; exports.VueHeadMixin = VueHeadMixin; exports.VueReactiveUseHeadPlugin = VueReactiveUseHeadPlugin; exports.asArray = asArray; exports.createHead = createHead; exports.createHeadCore = createHeadCore; exports.headSymbol = headSymbol; exports.injectHead = injectHead; exports.resolveUnrefHeadInput = resolveUnrefHeadInput; exports.unheadVueComposablesImports = unheadVueComposablesImports; exports.useBodyAttrs = useBodyAttrs; exports.useHead = useHead; exports.useHtmlAttrs = useHtmlAttrs; exports.useSeoMeta = useSeoMeta; exports.useServerBodyAttrs = useServerBodyAttrs; exports.useServerHead = useServerHead; exports.useServerHtmlAttrs = useServerHtmlAttrs; exports.useServerTagBase = useServerTagBase; exports.useServerTagLink = useServerTagLink; exports.useServerTagMeta = useServerTagMeta; exports.useServerTagMetaFlat = useServerTagMetaFlat; exports.useServerTagNoscript = useServerTagNoscript; exports.useServerTagScript = useServerTagScript; exports.useServerTagStyle = useServerTagStyle; exports.useServerTagTitle = useServerTagTitle; exports.useServerTitleTemplate = useServerTitleTemplate; exports.useTagBase = useTagBase; exports.useTagLink = useTagLink; exports.useTagMeta = useTagMeta; exports.useTagMetaFlat = useTagMetaFlat; exports.useTagNoscript = useTagNoscript; exports.useTagScript = useTagScript; exports.useTagStyle = useTagStyle; exports.useTagTitle = useTagTitle; exports.useTitleTemplate = useTitleTemplate;