PC-mj/.output/server/node_modules/unhead/dist/shared/unhead.B52g_5xR.mjs

171 lines
6.4 KiB
JavaScript
Raw Normal View History

2025-03-11 05:57:38 +00:00
import { createHooks } from 'hookable';
import { n as normalizeEntryToTags, d as dedupeKey, i as isMetaArrayDupeKey } from './unhead.BaPU1zLf.mjs';
import { t as tagWeight, s as sortTags } from './unhead.DZbvapt-.mjs';
import { c as UsesMergeStrategy, V as ValidHeadTags } from './unhead.yem5I2v_.mjs';
function registerPlugin(head, p) {
const plugin = typeof p === "function" ? p(head) : p;
const key = plugin.key || String(head.plugins.size + 1);
const exists = head.plugins.get(key);
if (!exists) {
head.plugins.set(key, plugin);
head.hooks.addHooks(plugin.hooks || {});
}
}
function createHeadCore(resolvedOptions = {}) {
return createUnhead(resolvedOptions);
}
function createUnhead(resolvedOptions = {}) {
const hooks = createHooks();
hooks.addHooks(resolvedOptions.hooks || {});
const ssr = !resolvedOptions.document;
const entries = /* @__PURE__ */ new Map();
const plugins = /* @__PURE__ */ new Map();
const normalizeQueue = [];
const head = {
_entryCount: 1,
// 0 is reserved for internal use
plugins,
dirty: false,
resolvedOptions,
hooks,
ssr,
entries,
headEntries() {
return [...entries.values()];
},
use: (p) => registerPlugin(head, p),
push(input, _options) {
const options = { ..._options || {} };
delete options.head;
const _i = options._index ?? head._entryCount++;
const inst = { _i, input, options };
const _ = {
_poll(rm = false) {
head.dirty = true;
!rm && normalizeQueue.push(_i);
hooks.callHook("entries:updated", head);
},
dispose() {
if (entries.delete(_i)) {
_._poll(true);
}
},
// a patch is the same as creating a new entry, just a nice DX
patch(input2) {
if (!options.mode || options.mode === "server" && ssr || options.mode === "client" && !ssr) {
inst.input = input2;
entries.set(_i, inst);
_._poll();
}
}
};
_.patch(input);
return _;
},
async resolveTags() {
const ctx = {
tagMap: /* @__PURE__ */ new Map(),
tags: [],
entries: [...head.entries.values()]
};
await hooks.callHook("entries:resolve", ctx);
while (normalizeQueue.length) {
const i = normalizeQueue.shift();
const e = entries.get(i);
if (e) {
const normalizeCtx = {
tags: normalizeEntryToTags(e.input, resolvedOptions.propResolvers || []).map((t) => Object.assign(t, e.options)),
entry: e
};
await hooks.callHook("entries:normalize", normalizeCtx);
e._tags = normalizeCtx.tags.map((t, i2) => {
t._w = tagWeight(head, t);
t._p = (e._i << 10) + i2;
t._d = dedupeKey(t);
return t;
});
}
}
let hasFlatMeta = false;
ctx.entries.flatMap((e) => (e._tags || []).map((t) => ({ ...t, props: { ...t.props } }))).sort(sortTags).reduce((acc, next) => {
const k = String(next._d || next._p);
if (!acc.has(k))
return acc.set(k, next);
const prev = acc.get(k);
const strategy = next?.tagDuplicateStrategy || (UsesMergeStrategy.has(next.tag) ? "merge" : null) || (next.key && next.key === prev.key ? "merge" : null);
if (strategy === "merge") {
const newProps = { ...prev.props };
Object.entries(next.props).forEach(([p, v]) => (
// @ts-expect-error untyped
newProps[p] = p === "style" ? new Map([...prev.props.style || /* @__PURE__ */ new Map(), ...v]) : p === "class" ? /* @__PURE__ */ new Set([...prev.props.class || /* @__PURE__ */ new Set(), ...v]) : v
));
acc.set(k, { ...next, props: newProps });
} else if (next._p >> 10 === prev._p >> 10 && isMetaArrayDupeKey(next._d)) {
acc.set(k, Object.assign([...Array.isArray(prev) ? prev : [prev], next], next));
hasFlatMeta = true;
} else if (next._w === prev._w ? next._p > prev._p : next?._w < prev?._w) {
acc.set(k, next);
}
return acc;
}, ctx.tagMap);
const title = ctx.tagMap.get("title");
const titleTemplate = ctx.tagMap.get("titleTemplate");
head._title = title?.textContent;
if (titleTemplate) {
const titleTemplateFn = titleTemplate?.textContent;
head._titleTemplate = typeof titleTemplateFn === "string" ? titleTemplateFn : void 0;
if (titleTemplateFn) {
let newTitle = typeof titleTemplateFn === "function" ? titleTemplateFn(title?.textContent) : titleTemplateFn;
if (typeof newTitle === "string" && !head.plugins.has("template-params")) {
newTitle = newTitle.replace("%s", title?.textContent || "");
}
if (title) {
newTitle === null ? ctx.tagMap.delete("title") : ctx.tagMap.set("title", { ...title, textContent: newTitle });
} else {
titleTemplate.tag = "title";
titleTemplate.textContent = newTitle;
}
}
}
ctx.tags = Array.from(ctx.tagMap.values());
if (hasFlatMeta) {
ctx.tags = ctx.tags.flat().sort(sortTags);
}
await hooks.callHook("tags:beforeResolve", ctx);
await hooks.callHook("tags:resolve", ctx);
await hooks.callHook("tags:afterResolve", ctx);
const finalTags = [];
for (const t of ctx.tags) {
const { innerHTML, tag, props } = t;
if (!ValidHeadTags.has(tag)) {
continue;
}
if (Object.keys(props).length === 0 && !t.innerHTML && !t.textContent) {
continue;
}
if (tag === "meta" && !props.content && !props["http-equiv"] && !props.charset) {
continue;
}
if (tag === "script" && innerHTML) {
if (props.type?.endsWith("json")) {
const v = typeof innerHTML === "string" ? innerHTML : JSON.stringify(innerHTML);
t.innerHTML = v.replace(/</g, "\\u003C");
} else if (typeof innerHTML === "string") {
t.innerHTML = innerHTML.replace(new RegExp(`</${tag}`, "g"), `<\\/${tag}`);
}
t._d = dedupeKey(t);
}
finalTags.push(t);
}
return finalTags;
}
};
(resolvedOptions?.plugins || []).forEach((p) => registerPlugin(head, p));
head.hooks.callHook("init", head);
resolvedOptions.init?.forEach((e) => e && head.push(e));
return head;
}
export { createUnhead as a, createHeadCore as c };