Files
singlechat/client/node_modules/unhead/dist/client.mjs

223 lines
7.1 KiB
JavaScript

import { a as createUnhead } from './shared/unhead.DH45uomy.mjs';
import { H as HasElementTags } from './shared/unhead.yem5I2v_.mjs';
import { h as hashTag, i as isMetaArrayDupeKey, a as normalizeProps, d as dedupeKey } from './shared/unhead.BpRRHAhY.mjs';
import 'hookable';
import './shared/unhead.DZbvapt-.mjs';
async function renderDOMHead(head, options = {}) {
const dom = options.document || head.resolvedOptions.document;
if (!dom || !head.dirty)
return;
const beforeRenderCtx = { shouldRender: true, tags: [] };
await head.hooks.callHook("dom:beforeRender", beforeRenderCtx);
if (!beforeRenderCtx.shouldRender)
return;
if (head._domUpdatePromise) {
return head._domUpdatePromise;
}
head._domUpdatePromise = new Promise(async (resolve) => {
const dupeKeyCounter = /* @__PURE__ */ new Map();
const resolveTagPromise = new Promise((resolve2) => {
head.resolveTags().then((tags2) => {
resolve2(
tags2.map((tag) => {
const count = dupeKeyCounter.get(tag._d) || 0;
const res = {
tag,
id: (count ? `${tag._d}:${count}` : tag._d) || hashTag(tag),
shouldRender: true
};
if (tag._d && isMetaArrayDupeKey(tag._d)) {
dupeKeyCounter.set(tag._d, count + 1);
}
return res;
})
);
});
});
let state = head._dom;
if (!state) {
state = {
title: dom.title,
elMap: (/* @__PURE__ */ new Map()).set("htmlAttrs", dom.documentElement).set("bodyAttrs", dom.body)
};
for (const key of ["body", "head"]) {
const children = dom[key]?.children;
for (const c of children) {
const tag = c.tagName.toLowerCase();
if (!HasElementTags.has(tag)) {
continue;
}
const next = normalizeProps({ tag, props: {} }, {
innerHTML: c.innerHTML,
...c.getAttributeNames().reduce((props, name) => {
props[name] = c.getAttribute(name);
return props;
}, {}) || {}
});
next.key = c.getAttribute("data-hid") || void 0;
next._d = dedupeKey(next) || hashTag(next);
if (state.elMap.has(next._d)) {
let count = 1;
let k = next._d;
while (state.elMap.has(k)) {
k = `${next._d}:${count++}`;
}
state.elMap.set(k, c);
} else {
state.elMap.set(next._d, c);
}
}
}
}
state.pendingSideEffects = { ...state.sideEffects };
state.sideEffects = {};
function track(id, scope, fn) {
const k = `${id}:${scope}`;
state.sideEffects[k] = fn;
delete state.pendingSideEffects[k];
}
function trackCtx({ id, $el, tag }) {
const isAttrTag = tag.tag.endsWith("Attrs");
state.elMap.set(id, $el);
if (!isAttrTag) {
if (tag.textContent && tag.textContent !== $el.textContent) {
$el.textContent = tag.textContent;
}
if (tag.innerHTML && tag.innerHTML !== $el.innerHTML) {
$el.innerHTML = tag.innerHTML;
}
track(id, "el", () => {
$el?.remove();
state.elMap.delete(id);
});
}
for (const k in tag.props) {
if (!Object.prototype.hasOwnProperty.call(tag.props, k))
continue;
const value = tag.props[k];
if (k.startsWith("on") && typeof value === "function") {
const dataset = $el?.dataset;
if (dataset && dataset[`${k}fired`]) {
const ek = k.slice(0, -5);
value.call($el, new Event(ek.substring(2)));
}
if ($el.getAttribute(`data-${k}`) !== "") {
(tag.tag === "bodyAttrs" ? dom.defaultView : $el).addEventListener(
// onload -> load
k.substring(2),
value.bind($el)
);
$el.setAttribute(`data-${k}`, "");
}
continue;
}
const ck = `attr:${k}`;
if (k === "class") {
if (!value) {
continue;
}
for (const c of value) {
isAttrTag && track(id, `${ck}:${c}`, () => $el.classList.remove(c));
!$el.classList.contains(c) && $el.classList.add(c);
}
} else if (k === "style") {
if (!value) {
continue;
}
for (const [k2, v] of value) {
track(id, `${ck}:${k2}`, () => {
$el.style.removeProperty(k2);
});
$el.style.setProperty(k2, v);
}
} else if (value !== false && value !== null) {
$el.getAttribute(k) !== value && $el.setAttribute(k, value === true ? "" : String(value));
isAttrTag && track(id, ck, () => $el.removeAttribute(k));
}
}
}
const pending = [];
const frag = {
bodyClose: void 0,
bodyOpen: void 0,
head: void 0
};
const tags = await resolveTagPromise;
for (const ctx of tags) {
const { tag, shouldRender, id } = ctx;
if (!shouldRender)
continue;
if (tag.tag === "title") {
dom.title = tag.textContent;
track("title", "", () => dom.title = state.title);
continue;
}
ctx.$el = ctx.$el || state.elMap.get(id);
if (ctx.$el) {
trackCtx(ctx);
} else if (HasElementTags.has(tag.tag)) {
pending.push(ctx);
}
}
for (const ctx of pending) {
const pos = ctx.tag.tagPosition || "head";
ctx.$el = dom.createElement(ctx.tag.tag);
trackCtx(ctx);
frag[pos] = frag[pos] || dom.createDocumentFragment();
frag[pos].appendChild(ctx.$el);
}
for (const ctx of tags)
await head.hooks.callHook("dom:renderTag", ctx, dom, track);
frag.head && dom.head.appendChild(frag.head);
frag.bodyOpen && dom.body.insertBefore(frag.bodyOpen, dom.body.firstChild);
frag.bodyClose && dom.body.appendChild(frag.bodyClose);
for (const k in state.pendingSideEffects) {
state.pendingSideEffects[k]();
}
head._dom = state;
await head.hooks.callHook("dom:rendered", { renders: tags });
resolve();
}).finally(() => {
head._domUpdatePromise = void 0;
head.dirty = false;
});
return head._domUpdatePromise;
}
function createHead(options = {}) {
const render = options.domOptions?.render || renderDOMHead;
options.document = options.document || (typeof window !== "undefined" ? document : void 0);
const initialPayload = options.document?.head.querySelector('script[id="unhead:payload"]')?.innerHTML || false;
return createUnhead({
...options,
plugins: [
...options.plugins || [],
{
key: "client",
hooks: {
"entries:updated": render
}
}
],
init: [
initialPayload ? JSON.parse(initialPayload) : false,
...options.init || []
]
});
}
function createDebouncedFn(callee, delayer) {
let ctxId = 0;
return () => {
const delayFnCtxId = ++ctxId;
delayer(() => {
if (ctxId === delayFnCtxId) {
callee();
}
});
};
}
export { createDebouncedFn, createHead, renderDOMHead };