1111
This commit is contained in:
748
.output/server/node_modules/unhead/dist/index.mjs
generated
vendored
Normal file
748
.output/server/node_modules/unhead/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,748 @@
|
||||
import { DomPlugin } from '@unhead/dom';
|
||||
import { defineHeadPlugin, tagDedupeKey, hashTag, tagWeight, HasElementTags, NetworkEvents, hashCode, SortModifiers, processTemplateParams, resolveTitleTemplate, IsBrowser, normaliseEntryTags, composableNames, whitelistSafeInput, ScriptNetworkEvents, unpackMeta } from '@unhead/shared';
|
||||
export { composableNames } from '@unhead/shared';
|
||||
import { createHooks } from 'hookable';
|
||||
|
||||
const UsesMergeStrategy = /* @__PURE__ */ new Set(["templateParams", "htmlAttrs", "bodyAttrs"]);
|
||||
const DedupePlugin = defineHeadPlugin({
|
||||
hooks: {
|
||||
"tag:normalise": ({ tag }) => {
|
||||
if (tag.props.hid) {
|
||||
tag.key = tag.props.hid;
|
||||
delete tag.props.hid;
|
||||
}
|
||||
if (tag.props.vmid) {
|
||||
tag.key = tag.props.vmid;
|
||||
delete tag.props.vmid;
|
||||
}
|
||||
if (tag.props.key) {
|
||||
tag.key = tag.props.key;
|
||||
delete tag.props.key;
|
||||
}
|
||||
const generatedKey = tagDedupeKey(tag);
|
||||
if (generatedKey && !generatedKey.startsWith("meta:og:") && !generatedKey.startsWith("meta:twitter:")) {
|
||||
delete tag.key;
|
||||
}
|
||||
const dedupe = generatedKey || (tag.key ? `${tag.tag}:${tag.key}` : false);
|
||||
if (dedupe)
|
||||
tag._d = dedupe;
|
||||
},
|
||||
"tags:resolve": (ctx) => {
|
||||
const deduping = /* @__PURE__ */ Object.create(null);
|
||||
for (const tag of ctx.tags) {
|
||||
const dedupeKey = (tag.key ? `${tag.tag}:${tag.key}` : tag._d) || hashTag(tag);
|
||||
const dupedTag = deduping[dedupeKey];
|
||||
if (dupedTag) {
|
||||
let strategy = tag?.tagDuplicateStrategy;
|
||||
if (!strategy && UsesMergeStrategy.has(tag.tag))
|
||||
strategy = "merge";
|
||||
if (strategy === "merge") {
|
||||
const oldProps = dupedTag.props;
|
||||
if (oldProps.style && tag.props.style) {
|
||||
if (oldProps.style[oldProps.style.length - 1] !== ";") {
|
||||
oldProps.style += ";";
|
||||
}
|
||||
tag.props.style = `${oldProps.style} ${tag.props.style}`;
|
||||
}
|
||||
if (oldProps.class && tag.props.class) {
|
||||
tag.props.class = `${oldProps.class} ${tag.props.class}`;
|
||||
} else if (oldProps.class) {
|
||||
tag.props.class = oldProps.class;
|
||||
}
|
||||
deduping[dedupeKey].props = {
|
||||
...oldProps,
|
||||
...tag.props
|
||||
};
|
||||
continue;
|
||||
} else if (tag._e === dupedTag._e) {
|
||||
dupedTag._duped = dupedTag._duped || [];
|
||||
tag._d = `${dupedTag._d}:${dupedTag._duped.length + 1}`;
|
||||
dupedTag._duped.push(tag);
|
||||
continue;
|
||||
} else if (tagWeight(tag) > tagWeight(dupedTag)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const hasProps = tag.innerHTML || tag.textContent || Object.keys(tag.props).length !== 0;
|
||||
if (!hasProps && HasElementTags.has(tag.tag)) {
|
||||
delete deduping[dedupeKey];
|
||||
continue;
|
||||
}
|
||||
deduping[dedupeKey] = tag;
|
||||
}
|
||||
const newTags = [];
|
||||
for (const key in deduping) {
|
||||
const tag = deduping[key];
|
||||
const dupes = tag._duped;
|
||||
newTags.push(tag);
|
||||
if (dupes) {
|
||||
delete tag._duped;
|
||||
newTags.push(...dupes);
|
||||
}
|
||||
}
|
||||
ctx.tags = newTags;
|
||||
ctx.tags = ctx.tags.filter((t) => !(t.tag === "meta" && (t.props.name || t.props.property) && !t.props.content));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ValidEventTags = /* @__PURE__ */ new Set(["script", "link", "bodyAttrs"]);
|
||||
const EventHandlersPlugin = defineHeadPlugin((head) => ({
|
||||
hooks: {
|
||||
"tags:resolve": (ctx) => {
|
||||
for (const tag of ctx.tags) {
|
||||
if (!ValidEventTags.has(tag.tag)) {
|
||||
continue;
|
||||
}
|
||||
const props = tag.props;
|
||||
for (const key in props) {
|
||||
if (key[0] !== "o" || key[1] !== "n") {
|
||||
continue;
|
||||
}
|
||||
if (!Object.prototype.hasOwnProperty.call(props, key)) {
|
||||
continue;
|
||||
}
|
||||
const value = props[key];
|
||||
if (typeof value !== "function") {
|
||||
continue;
|
||||
}
|
||||
if (head.ssr && NetworkEvents.has(key)) {
|
||||
props[key] = `this.dataset.${key}fired = true`;
|
||||
} else {
|
||||
delete props[key];
|
||||
}
|
||||
tag._eventHandlers = tag._eventHandlers || {};
|
||||
tag._eventHandlers[key] = value;
|
||||
}
|
||||
if (head.ssr && tag._eventHandlers && (tag.props.src || tag.props.href)) {
|
||||
tag.key = tag.key || hashCode(tag.props.src || tag.props.href);
|
||||
}
|
||||
}
|
||||
},
|
||||
"dom:renderTag": ({ $el, tag }) => {
|
||||
const dataset = $el?.dataset;
|
||||
if (!dataset) {
|
||||
return;
|
||||
}
|
||||
for (const k in dataset) {
|
||||
if (!k.endsWith("fired")) {
|
||||
continue;
|
||||
}
|
||||
const ek = k.slice(0, -5);
|
||||
if (!NetworkEvents.has(ek)) {
|
||||
continue;
|
||||
}
|
||||
tag._eventHandlers?.[ek]?.call($el, new Event(ek.substring(2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const DupeableTags = /* @__PURE__ */ new Set(["link", "style", "script", "noscript"]);
|
||||
const HashKeyedPlugin = defineHeadPlugin({
|
||||
hooks: {
|
||||
"tag:normalise": ({ tag }) => {
|
||||
if (tag.key && DupeableTags.has(tag.tag)) {
|
||||
tag.props["data-hid"] = tag._h = hashCode(tag.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const PayloadPlugin = defineHeadPlugin({
|
||||
mode: "server",
|
||||
hooks: {
|
||||
"tags:beforeResolve": (ctx) => {
|
||||
const payload = {};
|
||||
let hasPayload = false;
|
||||
for (const tag of ctx.tags) {
|
||||
if (tag._m !== "server" || tag.tag !== "titleTemplate" && tag.tag !== "templateParams" && tag.tag !== "title") {
|
||||
continue;
|
||||
}
|
||||
payload[tag.tag] = tag.tag === "title" || tag.tag === "titleTemplate" ? tag.textContent : tag.props;
|
||||
hasPayload = true;
|
||||
}
|
||||
if (hasPayload) {
|
||||
ctx.tags.push({
|
||||
tag: "script",
|
||||
innerHTML: JSON.stringify(payload),
|
||||
props: { id: "unhead:payload", type: "application/json" }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const SortPlugin = defineHeadPlugin({
|
||||
hooks: {
|
||||
"tags:resolve": (ctx) => {
|
||||
for (const tag of ctx.tags) {
|
||||
if (typeof tag.tagPriority !== "string") {
|
||||
continue;
|
||||
}
|
||||
for (const { prefix, offset } of SortModifiers) {
|
||||
if (!tag.tagPriority.startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
const key = tag.tagPriority.substring(prefix.length);
|
||||
const position = ctx.tags.find((tag2) => tag2._d === key)?._p;
|
||||
if (position !== void 0) {
|
||||
tag._p = position + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.tags.sort((a, b) => {
|
||||
const aWeight = tagWeight(a);
|
||||
const bWeight = tagWeight(b);
|
||||
if (aWeight < bWeight) {
|
||||
return -1;
|
||||
} else if (aWeight > bWeight) {
|
||||
return 1;
|
||||
}
|
||||
return a._p - b._p;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const SupportedAttrs = {
|
||||
meta: "content",
|
||||
link: "href",
|
||||
htmlAttrs: "lang"
|
||||
};
|
||||
const contentAttrs = ["innerHTML", "textContent"];
|
||||
const TemplateParamsPlugin = defineHeadPlugin((head) => ({
|
||||
hooks: {
|
||||
"tags:resolve": (ctx) => {
|
||||
const { tags } = ctx;
|
||||
let templateParams;
|
||||
for (let i = 0; i < tags.length; i += 1) {
|
||||
const tag = tags[i];
|
||||
if (tag.tag !== "templateParams") {
|
||||
continue;
|
||||
}
|
||||
templateParams = ctx.tags.splice(i, 1)[0].props;
|
||||
i -= 1;
|
||||
}
|
||||
const params = templateParams || {};
|
||||
const sep = params.separator || "|";
|
||||
delete params.separator;
|
||||
params.pageTitle = processTemplateParams(
|
||||
// find templateParams
|
||||
params.pageTitle || tags.find((tag) => tag.tag === "title")?.textContent || "",
|
||||
params,
|
||||
sep
|
||||
);
|
||||
for (const tag of tags) {
|
||||
if (tag.processTemplateParams === false) {
|
||||
continue;
|
||||
}
|
||||
const v = SupportedAttrs[tag.tag];
|
||||
if (v && typeof tag.props[v] === "string") {
|
||||
tag.props[v] = processTemplateParams(tag.props[v], params, sep);
|
||||
} else if (tag.processTemplateParams || tag.tag === "titleTemplate" || tag.tag === "title") {
|
||||
for (const p of contentAttrs) {
|
||||
if (typeof tag[p] === "string")
|
||||
tag[p] = processTemplateParams(tag[p], params, sep, tag.tag === "script" && tag.props.type.endsWith("json"));
|
||||
}
|
||||
}
|
||||
}
|
||||
head._templateParams = params;
|
||||
head._separator = sep;
|
||||
},
|
||||
"tags:afterResolve": ({ tags }) => {
|
||||
let title;
|
||||
for (let i = 0; i < tags.length; i += 1) {
|
||||
const tag = tags[i];
|
||||
if (tag.tag === "title" && tag.processTemplateParams !== false) {
|
||||
title = tag;
|
||||
}
|
||||
}
|
||||
if (title?.textContent) {
|
||||
title.textContent = processTemplateParams(title.textContent, head._templateParams, head._separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const TitleTemplatePlugin = defineHeadPlugin({
|
||||
hooks: {
|
||||
"tags:resolve": (ctx) => {
|
||||
const { tags } = ctx;
|
||||
let titleTag;
|
||||
let titleTemplateTag;
|
||||
for (let i = 0; i < tags.length; i += 1) {
|
||||
const tag = tags[i];
|
||||
if (tag.tag === "title") {
|
||||
titleTag = tag;
|
||||
} else if (tag.tag === "titleTemplate") {
|
||||
titleTemplateTag = tag;
|
||||
}
|
||||
}
|
||||
if (titleTemplateTag && titleTag) {
|
||||
const newTitle = resolveTitleTemplate(
|
||||
titleTemplateTag.textContent,
|
||||
titleTag.textContent
|
||||
);
|
||||
if (newTitle !== null) {
|
||||
titleTag.textContent = newTitle || titleTag.textContent;
|
||||
} else {
|
||||
ctx.tags.splice(ctx.tags.indexOf(titleTag), 1);
|
||||
}
|
||||
} else if (titleTemplateTag) {
|
||||
const newTitle = resolveTitleTemplate(
|
||||
titleTemplateTag.textContent
|
||||
);
|
||||
if (newTitle !== null) {
|
||||
titleTemplateTag.textContent = newTitle;
|
||||
titleTemplateTag.tag = "title";
|
||||
titleTemplateTag = void 0;
|
||||
}
|
||||
}
|
||||
if (titleTemplateTag) {
|
||||
ctx.tags.splice(ctx.tags.indexOf(titleTemplateTag), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const XSSPlugin = defineHeadPlugin({
|
||||
hooks: {
|
||||
"tags:afterResolve": (ctx) => {
|
||||
for (const tag of ctx.tags) {
|
||||
if (typeof tag.innerHTML === "string") {
|
||||
if (tag.innerHTML && (tag.props.type === "application/ld+json" || tag.props.type === "application/json")) {
|
||||
tag.innerHTML = tag.innerHTML.replace(/</g, "\\u003C");
|
||||
} else {
|
||||
tag.innerHTML = tag.innerHTML.replace(new RegExp(`</${tag.tag}`, "g"), `<\\/${tag.tag}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let activeHead;
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
function createHead(options = {}) {
|
||||
const head = createHeadCore(options);
|
||||
head.use(DomPlugin());
|
||||
return activeHead = head;
|
||||
}
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
function createServerHead(options = {}) {
|
||||
return activeHead = createHeadCore(options);
|
||||
}
|
||||
function filterMode(mode, ssr) {
|
||||
return !mode || mode === "server" && ssr || mode === "client" && !ssr;
|
||||
}
|
||||
function createHeadCore(options = {}) {
|
||||
const hooks = createHooks();
|
||||
hooks.addHooks(options.hooks || {});
|
||||
options.document = options.document || (IsBrowser ? document : void 0);
|
||||
const ssr = !options.document;
|
||||
const updated = () => {
|
||||
head.dirty = true;
|
||||
hooks.callHook("entries:updated", head);
|
||||
};
|
||||
let entryCount = 0;
|
||||
let entries = [];
|
||||
const plugins = [];
|
||||
const head = {
|
||||
plugins,
|
||||
dirty: false,
|
||||
resolvedOptions: options,
|
||||
hooks,
|
||||
headEntries() {
|
||||
return entries;
|
||||
},
|
||||
use(p) {
|
||||
const plugin = typeof p === "function" ? p(head) : p;
|
||||
if (!plugin.key || !plugins.some((p2) => p2.key === plugin.key)) {
|
||||
plugins.push(plugin);
|
||||
filterMode(plugin.mode, ssr) && hooks.addHooks(plugin.hooks || {});
|
||||
}
|
||||
},
|
||||
push(input, entryOptions) {
|
||||
delete entryOptions?.head;
|
||||
const entry = {
|
||||
_i: entryCount++,
|
||||
input,
|
||||
...entryOptions
|
||||
};
|
||||
if (filterMode(entry.mode, ssr)) {
|
||||
entries.push(entry);
|
||||
updated();
|
||||
}
|
||||
return {
|
||||
dispose() {
|
||||
entries = entries.filter((e) => e._i !== entry._i);
|
||||
updated();
|
||||
},
|
||||
// a patch is the same as creating a new entry, just a nice DX
|
||||
patch(input2) {
|
||||
for (const e of entries) {
|
||||
if (e._i === entry._i) {
|
||||
e.input = entry.input = input2;
|
||||
}
|
||||
}
|
||||
updated();
|
||||
}
|
||||
};
|
||||
},
|
||||
async resolveTags() {
|
||||
const resolveCtx = { tags: [], entries: [...entries] };
|
||||
await hooks.callHook("entries:resolve", resolveCtx);
|
||||
for (const entry of resolveCtx.entries) {
|
||||
const resolved = entry.resolvedInput || entry.input;
|
||||
entry.resolvedInput = await (entry.transform ? entry.transform(resolved) : resolved);
|
||||
if (entry.resolvedInput) {
|
||||
for (const tag of await normaliseEntryTags(entry)) {
|
||||
const tagCtx = { tag, entry, resolvedOptions: head.resolvedOptions };
|
||||
await hooks.callHook("tag:normalise", tagCtx);
|
||||
resolveCtx.tags.push(tagCtx.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
await hooks.callHook("tags:beforeResolve", resolveCtx);
|
||||
await hooks.callHook("tags:resolve", resolveCtx);
|
||||
await hooks.callHook("tags:afterResolve", resolveCtx);
|
||||
return resolveCtx.tags;
|
||||
},
|
||||
ssr
|
||||
};
|
||||
[
|
||||
DedupePlugin,
|
||||
PayloadPlugin,
|
||||
EventHandlersPlugin,
|
||||
HashKeyedPlugin,
|
||||
SortPlugin,
|
||||
TemplateParamsPlugin,
|
||||
TitleTemplatePlugin,
|
||||
XSSPlugin,
|
||||
...options?.plugins || []
|
||||
].forEach((p) => head.use(p));
|
||||
head.hooks.callHook("init", head);
|
||||
return head;
|
||||
}
|
||||
|
||||
const unheadComposablesImports = [
|
||||
{
|
||||
from: "unhead",
|
||||
imports: composableNames
|
||||
}
|
||||
];
|
||||
|
||||
function getActiveHead() {
|
||||
return activeHead;
|
||||
}
|
||||
|
||||
function useHead(input, options = {}) {
|
||||
const head = options.head || getActiveHead();
|
||||
return head?.push(input, options);
|
||||
}
|
||||
|
||||
function useHeadSafe(input, options) {
|
||||
return useHead(input, {
|
||||
...options,
|
||||
transform: whitelistSafeInput
|
||||
});
|
||||
}
|
||||
|
||||
const ScriptProxyTarget = Symbol("ScriptProxyTarget");
|
||||
function scriptProxy() {
|
||||
}
|
||||
scriptProxy[ScriptProxyTarget] = true;
|
||||
function resolveScriptKey(input) {
|
||||
return input.key || hashCode(input.src || (typeof input.innerHTML === "string" ? input.innerHTML : ""));
|
||||
}
|
||||
function useScript(_input, _options) {
|
||||
const input = typeof _input === "string" ? { src: _input } : _input;
|
||||
const options = _options || {};
|
||||
const head = options.head || getActiveHead();
|
||||
if (!head)
|
||||
throw new Error("Missing Unhead context.");
|
||||
const id = resolveScriptKey(input);
|
||||
const prevScript = head._scripts?.[id];
|
||||
if (prevScript) {
|
||||
prevScript.setupTriggerHandler(options.trigger);
|
||||
return prevScript;
|
||||
}
|
||||
options.beforeInit?.();
|
||||
const syncStatus = (s) => {
|
||||
script.status = s;
|
||||
head.hooks.callHook(`script:updated`, hookCtx);
|
||||
};
|
||||
ScriptNetworkEvents.forEach((fn) => {
|
||||
const _fn = typeof input[fn] === "function" ? input[fn].bind(options.eventContext) : null;
|
||||
input[fn] = (e) => {
|
||||
syncStatus(fn === "onload" ? "loaded" : fn === "onerror" ? "error" : "loading");
|
||||
_fn?.(e);
|
||||
};
|
||||
});
|
||||
const _cbs = { loaded: [], error: [] };
|
||||
const _registerCb = (key, cb) => {
|
||||
if (_cbs[key]) {
|
||||
const i = _cbs[key].push(cb);
|
||||
return () => _cbs[key]?.splice(i - 1, 1);
|
||||
}
|
||||
cb(script.instance);
|
||||
return () => {
|
||||
};
|
||||
};
|
||||
const loadPromise = new Promise((resolve) => {
|
||||
if (head.ssr)
|
||||
return;
|
||||
const emit = (api) => requestAnimationFrame(() => resolve(api));
|
||||
const _ = head.hooks.hook("script:updated", ({ script: script2 }) => {
|
||||
const status = script2.status;
|
||||
if (script2.id === id && (status === "loaded" || status === "error")) {
|
||||
if (status === "loaded") {
|
||||
if (typeof options.use === "function") {
|
||||
const api = options.use();
|
||||
if (api) {
|
||||
emit(api);
|
||||
}
|
||||
} else {
|
||||
emit({});
|
||||
}
|
||||
} else if (status === "error") {
|
||||
resolve(false);
|
||||
}
|
||||
_();
|
||||
}
|
||||
});
|
||||
});
|
||||
const script = Object.assign(loadPromise, {
|
||||
instance: !head.ssr && options?.use?.() || null,
|
||||
proxy: null,
|
||||
id,
|
||||
status: "awaitingLoad",
|
||||
remove() {
|
||||
script._triggerAbortController?.abort();
|
||||
script._triggerPromises = [];
|
||||
if (script.entry) {
|
||||
script.entry.dispose();
|
||||
script.entry = void 0;
|
||||
syncStatus("removed");
|
||||
delete head._scripts?.[id];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
load(cb) {
|
||||
script._triggerAbortController?.abort();
|
||||
script._triggerPromises = [];
|
||||
if (!script.entry) {
|
||||
syncStatus("loading");
|
||||
const defaults = {
|
||||
defer: true,
|
||||
fetchpriority: "low"
|
||||
};
|
||||
if (input.src && (input.src.startsWith("http") || input.src.startsWith("//"))) {
|
||||
defaults.crossorigin = "anonymous";
|
||||
defaults.referrerpolicy = "no-referrer";
|
||||
}
|
||||
script.entry = head.push({
|
||||
script: [{ ...defaults, ...input, key: `script.${id}` }]
|
||||
}, options);
|
||||
}
|
||||
if (cb)
|
||||
_registerCb("loaded", cb);
|
||||
return loadPromise;
|
||||
},
|
||||
onLoaded(cb) {
|
||||
return _registerCb("loaded", cb);
|
||||
},
|
||||
onError(cb) {
|
||||
return _registerCb("error", cb);
|
||||
},
|
||||
setupTriggerHandler(trigger) {
|
||||
if (script.status !== "awaitingLoad") {
|
||||
return;
|
||||
}
|
||||
if ((typeof trigger === "undefined" || trigger === "client") && !head.ssr || trigger === "server") {
|
||||
script.load();
|
||||
} else if (trigger instanceof Promise) {
|
||||
if (head.ssr) {
|
||||
return;
|
||||
}
|
||||
if (!script._triggerAbortController) {
|
||||
script._triggerAbortController = new AbortController();
|
||||
script._triggerAbortPromise = new Promise((resolve) => {
|
||||
script._triggerAbortController.signal.addEventListener("abort", () => {
|
||||
script._triggerAbortController = null;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
script._triggerPromises = script._triggerPromises || [];
|
||||
const idx = script._triggerPromises.push(Promise.race([
|
||||
trigger.then((v) => typeof v === "undefined" || v ? script.load : void 0),
|
||||
script._triggerAbortPromise
|
||||
]).catch(() => {
|
||||
}).then((res2) => {
|
||||
res2?.();
|
||||
}).finally(() => {
|
||||
script._triggerPromises?.splice(idx, 1);
|
||||
}));
|
||||
} else if (typeof trigger === "function") {
|
||||
trigger(script.load);
|
||||
}
|
||||
},
|
||||
_cbs
|
||||
});
|
||||
loadPromise.then((api) => {
|
||||
if (api !== false) {
|
||||
script.instance = api;
|
||||
_cbs.loaded?.forEach((cb) => cb(api));
|
||||
_cbs.loaded = null;
|
||||
} else {
|
||||
_cbs.error?.forEach((cb) => cb());
|
||||
_cbs.error = null;
|
||||
}
|
||||
});
|
||||
const hookCtx = { script };
|
||||
script.setupTriggerHandler(options.trigger);
|
||||
script.$script = script;
|
||||
const proxyChain = (instance, accessor, accessors) => {
|
||||
return new Proxy((!accessor ? instance : instance?.[accessor]) || scriptProxy, {
|
||||
get(_, k, r) {
|
||||
head.hooks.callHook("script:instance-fn", { script, fn: k, exists: k in _ });
|
||||
if (!accessor) {
|
||||
const stub = options.stub?.({ script, fn: k });
|
||||
if (stub)
|
||||
return stub;
|
||||
}
|
||||
if (_ && k in _ && typeof _[k] !== "undefined") {
|
||||
return Reflect.get(_, k, r);
|
||||
}
|
||||
if (k === Symbol.iterator) {
|
||||
return [][Symbol.iterator];
|
||||
}
|
||||
return proxyChain(accessor ? instance?.[accessor] : instance, k, accessors || [k]);
|
||||
},
|
||||
async apply(_, _this, args) {
|
||||
if (head.ssr && _[ScriptProxyTarget])
|
||||
return;
|
||||
let instance2;
|
||||
const access = (fn2) => {
|
||||
instance2 = fn2 || instance2;
|
||||
for (let i = 0; i < (accessors || []).length; i++) {
|
||||
const k = (accessors || [])[i];
|
||||
fn2 = fn2?.[k];
|
||||
}
|
||||
return fn2;
|
||||
};
|
||||
let fn = access(script.instance);
|
||||
if (!fn) {
|
||||
fn = await new Promise((resolve) => {
|
||||
script.onLoaded((api) => {
|
||||
resolve(access(api));
|
||||
});
|
||||
});
|
||||
}
|
||||
return typeof fn === "function" ? Reflect.apply(fn, instance2, args) : fn;
|
||||
}
|
||||
});
|
||||
};
|
||||
script.proxy = proxyChain(script.instance);
|
||||
const res = new Proxy(script, {
|
||||
get(_, k) {
|
||||
const target = k in script || String(k)[0] === "_" ? script : script.proxy;
|
||||
if (k === "then" || k === "catch") {
|
||||
return script[k].bind(script);
|
||||
}
|
||||
return Reflect.get(target, k, target);
|
||||
}
|
||||
});
|
||||
head._scripts = Object.assign(head._scripts || {}, { [id]: res });
|
||||
return res;
|
||||
}
|
||||
|
||||
function useSeoMeta(input, options) {
|
||||
const { title, titleTemplate, ...meta } = input;
|
||||
return useHead({
|
||||
title,
|
||||
titleTemplate,
|
||||
// we need to input the meta so the reactivity will be resolved
|
||||
// @ts-expect-error runtime type
|
||||
_flatMeta: meta
|
||||
}, {
|
||||
...options,
|
||||
transform(t) {
|
||||
const meta2 = unpackMeta({ ...t._flatMeta });
|
||||
delete t._flatMeta;
|
||||
return {
|
||||
// @ts-expect-error runtime type
|
||||
...t,
|
||||
meta: meta2
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function useServerHead(input, options = {}) {
|
||||
return useHead(input, { ...options, mode: "server" });
|
||||
}
|
||||
|
||||
function useServerHeadSafe(input, options = {}) {
|
||||
return useHeadSafe(input, { ...options, mode: "server" });
|
||||
}
|
||||
|
||||
function useServerSeoMeta(input, options) {
|
||||
return useSeoMeta(input, {
|
||||
...options,
|
||||
mode: "server"
|
||||
});
|
||||
}
|
||||
|
||||
const importRe = /@import/;
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
function CapoPlugin(options) {
|
||||
return defineHeadPlugin({
|
||||
hooks: {
|
||||
"tags:beforeResolve": ({ tags }) => {
|
||||
for (const tag of tags) {
|
||||
if (tag.tagPosition && tag.tagPosition !== "head")
|
||||
continue;
|
||||
tag.tagPriority = tag.tagPriority || tagWeight(tag);
|
||||
if (tag.tagPriority !== 100)
|
||||
continue;
|
||||
const isTruthy = (val) => val === "" || val === true;
|
||||
const isScript = tag.tag === "script";
|
||||
const isLink = tag.tag === "link";
|
||||
if (isScript && isTruthy(tag.props.async)) {
|
||||
tag.tagPriority = 30;
|
||||
} else if (tag.tag === "style" && tag.innerHTML && importRe.test(tag.innerHTML)) {
|
||||
tag.tagPriority = 40;
|
||||
} else if (isScript && tag.props.src && !isTruthy(tag.props.defer) && !isTruthy(tag.props.async) && tag.props.type !== "module" && !tag.props.type?.endsWith("json")) {
|
||||
tag.tagPriority = 50;
|
||||
} else if (isLink && tag.props.rel === "stylesheet" || tag.tag === "style") {
|
||||
tag.tagPriority = 60;
|
||||
} else if (isLink && (tag.props.rel === "preload" || tag.props.rel === "modulepreload")) {
|
||||
tag.tagPriority = 70;
|
||||
} else if (isScript && isTruthy(tag.props.defer) && tag.props.src && !isTruthy(tag.props.async)) {
|
||||
tag.tagPriority = 80;
|
||||
} else if (isLink && (tag.props.rel === "prefetch" || tag.props.rel === "dns-prefetch" || tag.props.rel === "prerender")) {
|
||||
tag.tagPriority = 90;
|
||||
}
|
||||
}
|
||||
options?.track && tags.push({
|
||||
tag: "htmlAttrs",
|
||||
props: {
|
||||
"data-capo": ""
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
function HashHydrationPlugin() {
|
||||
return defineHeadPlugin({});
|
||||
}
|
||||
|
||||
export { CapoPlugin, HashHydrationPlugin, createHead, createHeadCore, createServerHead, getActiveHead, resolveScriptKey, unheadComposablesImports, useHead, useHeadSafe, useScript, useSeoMeta, useServerHead, useServerHeadSafe, useServerSeoMeta };
|
||||
49
.output/server/node_modules/unhead/package.json
generated
vendored
Normal file
49
.output/server/node_modules/unhead/package.json
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "unhead",
|
||||
"type": "module",
|
||||
"version": "1.11.19",
|
||||
"author": {
|
||||
"name": "Harlan Wilton",
|
||||
"email": "harlan@harlanzw.com",
|
||||
"url": "https://harlanzw.com/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/harlan-zw",
|
||||
"homepage": "https://unhead.unjs.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/unjs/unhead.git",
|
||||
"directory": "packages/unhead"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/unjs/unhead/issues"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
},
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.mjs",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"hookable": "^5.5.3",
|
||||
"@unhead/schema": "1.11.19",
|
||||
"@unhead/shared": "1.11.19",
|
||||
"@unhead/dom": "1.11.19"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "unbuild .",
|
||||
"stub": "unbuild . --stub",
|
||||
"export:sizes": "npx export-size . -r"
|
||||
},
|
||||
"__npminstall_done": true,
|
||||
"_from": "unhead@1.11.19",
|
||||
"_resolved": "https://registry.npmmirror.com/unhead/-/unhead-1.11.19.tgz"
|
||||
}
|
||||
Reference in New Issue
Block a user