import { a as createUnhead } from './shared/unhead.CXyUfY4l.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.ytfIU1HR.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 };