import { HookableCore } from 'hookable'; import { t as GenericScript, aO as ScriptHttpEvents, D as DataKeys, a3 as MaybeEventFnHandlers, z as HttpEventAttributes, aL as SchemaAugmentations, H as HeadTag, R as ResolvableHead, b2 as TagPosition, b3 as TagPriority, at as ProcessesTemplateParams, aK as ResolvesDuplicates, b5 as TemplateParams } from './unhead.DC0v7nqS.js'; type UseScriptStatus = 'awaitingLoad' | 'loading' | 'loaded' | 'error' | 'removed'; type UseScriptContext> = ScriptInstance; /** * Either a string source for the script or full script properties. */ type UseScriptInputBase = Omit & DataKeys & MaybeEventFnHandlers & SchemaAugmentations['script']; type UseScriptResolvedInput = UseScriptInputBase & { src: string; }; type BaseScriptApi = Record; /** A keyed client-side resource loaded without a DOM script tag. */ interface UseScriptLoaderInput { key: string; loader: UseScriptLoader; crossorigin?: never; referrerpolicy?: never; src?: never; innerHTML?: never; onerror?: never; onload?: never; textContent?: never; } type HasDiscriminatedParameters = T extends { (first: infer A, ...rest1: any[]): any; (first: infer B, ...rest2: any[]): any; } ? A extends B ? B extends A ? false : true : true : false; type HasDifferentParameterCounts = T extends { (...args: infer A): any; } & { (...args: infer B): any; } ? A['length'] extends B['length'] ? B['length'] extends A['length'] ? false : true : true : false; type IsOverloadedFunction = HasDiscriminatedParameters extends true ? true : HasDifferentParameterCounts extends true ? true : false; type AsVoidFunctions = { [K in keyof T]: T[K] extends any[] ? T[K] : T[K] extends (...args: infer A) => any ? IsOverloadedFunction extends true ? T[K] : (...args: A) => void : T[K] extends Record ? AsVoidFunctions : never; }; type UseScriptInput = string | UseScriptResolvedInput; type UseFunctionType = T extends { resolve: infer V; } ? V extends (...args: any) => any ? NonNullable>> : U : T extends { use: infer V; } ? V extends (...args: any) => any ? NonNullable>> : U : U; type WarmupStrategy = false | 'preload' | 'preconnect' | 'dns-prefetch'; type UseScriptWaitForSetup = (resolve: (value: T | PromiseLike) => void, reject: (reason?: unknown) => void) => void | (() => void); interface UseScriptWaitForResolve { (value: V): V; (value: PromiseLike): PromiseLike; (value: T | PromiseLike): T | PromiseLike; } type UseScriptWaitForInferredResult = [T] extends [void | (() => void)] ? unknown : NonNullable>; interface UseScriptWaitFor { /** * With an explicit result type, setup may use callback-style registration and * return cleanup. Without one, `waitFor(resolve => resolve(value))` infers it. */ (setup: (resolve: UseScriptWaitForResolve<[T] extends [never] ? unknown : T>, reject: (reason?: unknown) => void) => R): Promise<[T] extends [never] ? UseScriptWaitForInferredResult : T>; } interface UseScriptContextOptions { /** * Aborted when the script is removed or fails to load. */ signal: AbortSignal; /** * Wait for an SDK-specific readiness callback. Abort rejection and returned * cleanup are tied to the script lifecycle. */ waitFor: UseScriptWaitFor; } type UseScriptResolver = (ctx: UseScriptContextOptions) => T | PromiseLike | undefined | null; /** * Register a script load trigger. A returned function is treated as cleanup; * other return values are ignored for backwards compatibility. */ type UseScriptTrigger = (load: () => void) => any; type UseScriptLoader = (ctx: UseScriptContextOptions) => T | PromiseLike; /** * A consumer-owned view of a shared script. Disposing it only releases the * callbacks and triggers registered through this scope. */ interface ScriptScope extends ScriptInstance { readonly script: ScriptInstance; /** * Aborted when this consumer is disposed or the shared script fails or is removed. */ readonly signal: AbortSignal; dispose: () => void; /** * Remove the shared script for every consumer. Use `dispose()` to release * only the registrations and resources owned by this scope. */ remove: () => boolean; } interface ScriptInstance { proxy: AsVoidFunctions; instance?: T; id: string; /** * Aborted when the script is removed or fails to load. */ signal: AbortSignal; status: Readonly; entry?: ActiveHeadEntry; load: () => Promise; warmup: (rel: WarmupStrategy) => ActiveHeadEntry; remove: () => boolean; setupTriggerHandler: (trigger: UseScriptOptions['trigger']) => () => void; onLoaded: (fn: (instance: T) => void | Promise, options?: EventHandlerOptions) => () => void; onError: (fn: (err?: Error) => void | Promise, options?: EventHandlerOptions) => () => void; /** * @internal */ _warmupStrategy?: string; /** * @internal */ _loadPromise: Promise; /** * @internal */ _warmupEl: any; /** * @internal */ _triggerAbortController?: AbortController | null; /** * @internal */ _triggerAbortControllers?: Set; /** * @internal */ _triggerPromises?: Promise[]; /** * @internal */ _setupTriggerHandler: (trigger: UseScriptOptions['trigger'], removeOnError?: boolean) => () => void; /** * @internal */ _cbs: { loaded: null | ((instance: T) => void | Promise)[]; error: null | ((err?: Error) => void | Promise)[]; }; } interface EventHandlerOptions { /** * Used to dedupe the event, allowing you to have an event run only a single time. */ key?: string; } type RecordingEntry = { type: 'get'; key: string | symbol; args?: any[]; value?: any; } | { type: 'apply'; key: string | symbol; args: any[]; }; interface UseScriptOptions> extends HeadEntryOptions { /** * Create a consumer-owned handle without changing the shared script lifecycle. * Existing callers receive the cached shared script unless this is enabled. */ scope?: boolean; /** * Resolve the script instance from the window. This legacy callback is always * called without arguments. It may return the API asynchronously. */ use?: () => T | PromiseLike | undefined | null; /** * Resolve the script API with lifecycle helpers. Prefer this over `use` when * readiness needs an abort signal or `waitFor()` callback bridge. */ resolve?: UseScriptResolver; /** * The trigger to load the script: * - `undefined` | `client` - (Default) Load the script on the client when this js is loaded. * - `manual` - Load the script manually by calling `$script.load()`, exists only on the client. * - `Promise` - Load the script when the promise resolves, exists only on the client. * - `Function` - Register a callback function to load the script, exists only on the client. It may return a cleanup function. * - `server` - Have the script injected on the server. */ trigger?: 'client' | 'server' | 'manual' | Promise | UseScriptTrigger | null; /** * Add a preload or preconnect link tag before the script is loaded. */ warmupStrategy?: WarmupStrategy; /** * Context to run events with. This is useful in Vue to attach the current instance context before * calling the event, allowing the event to be reactive. */ eventContext?: any; /** * Called before the script is initialized. Will not be triggered when the script is already loaded. This means * this is guaranteed to be called only once, unless the script is removed and re-added. */ beforeInit?: () => void; } /** Options for a keyed, client-only resource that does not render a script tag. */ type UseScriptLoaderOptions = Omit, 'resolve' | 'use' | 'warmupStrategy'> & { resolve?: never; use?: never; warmupStrategy?: never; }; type UseScriptReturn> = ScriptInstance, T>>; type UseScriptScopeReturn> = ScriptScope, T>>; type HookResult = Promise | void; type SyncHookResult = void; interface SSRHeadPayload { headTags: string; bodyTags: string; bodyTagsOpen: string; htmlAttrs: string; bodyAttrs: string; } interface RenderSSRHeadOptions { omitLineBreaks?: boolean; resolvedTags?: HeadTag[]; tagWeight?: (tag: HeadTag) => number; } interface EntryResolveCtx { tags: HeadTag[]; entries: HeadEntry[]; } interface DomBeforeRenderCtx extends ShouldRenderContext { tags: HeadTag[]; } interface ShouldRenderContext { shouldRender: boolean; } interface DomRenderTagContext { tag: HeadTag; id: string; $el?: Element; shouldRender: boolean; } interface SSRRenderContext { tags: HeadTag[]; html: SSRHeadPayload; } interface TagResolveContext { tagMap: Map; tags: HeadTag[]; } interface CoreHeadHooks { 'entries:updated': (ctx: Unhead) => HookResult; 'entries:resolve': (ctx: EntryResolveCtx) => SyncHookResult; 'entries:normalize': (ctx: { tags: HeadTag[]; entry: HeadEntry; }) => SyncHookResult; 'tag:normalise': (ctx: { tag: HeadTag; entry: HeadEntry; resolvedOptions: CreateClientHeadOptions; }) => SyncHookResult; 'tags:beforeResolve': (ctx: TagResolveContext) => SyncHookResult; 'tags:resolve': (ctx: TagResolveContext) => SyncHookResult; 'tags:afterResolve': (ctx: TagResolveContext) => SyncHookResult; 'script:updated': (ctx: { script: ScriptInstance; }) => void | Promise; } interface DOMHeadHooks { 'dom:beforeRender': (ctx: DomBeforeRenderCtx) => SyncHookResult; /** @deprecated Not called internally. Will be removed in v4. */ 'dom:renderTag': (ctx: DomRenderTagContext, document: Document, track: (id: string, scope: string, fn: () => void) => void) => HookResult; /** @deprecated Will be removed in v4. DOM rendering is synchronous; run post-render logic after calling `renderDOMHead()` directly. */ 'dom:rendered': (ctx: { renders: DomRenderTagContext[]; }) => HookResult; } interface SSRHeadHooks { /** * Fired by `renderSSRHeadSuspenseChunk` with normalized tags from entries * pending after the shell. It runs before streamed body tags are split out. * It also runs before the remaining patch is serialized and entries clear. * * The chunk renderer normally serializes entry input without normalizing * tags. This hook supplies normalized copies for inspection. The rendered * patch does not use these tags. Plugin-owned shapes (`_flatMeta`, the legacy * `body` prop) are left for the listener to resolve. * * Synchronous: the renderer does not wait for promises before it serializes * the patch and clears entries. */ 'ssr:streamChunk': (ctx: { tags: HeadTag[]; }) => SyncHookResult; 'ssr:beforeRender': (ctx: ShouldRenderContext) => HookResult; 'ssr:render': (ctx: { tags: HeadTag[]; options: RenderSSRHeadOptions; }) => HookResult; 'ssr:rendered': (ctx: SSRRenderContext) => HookResult; } type ClientHeadHooks = CoreHeadHooks & DOMHeadHooks; type ServerHeadHooks = CoreHeadHooks & SSRHeadHooks; type HeadHooks = CoreHeadHooks & DOMHeadHooks & SSRHeadHooks; /** * Side effects are mapped with a key and their cleanup function. * * For example, `meta:data-h-4h46h465`: () => { document.querySelector('meta[data-h-4h46h465]').remove() } */ type SideEffectsRecord = Record void>; interface HeadEntry { /** * User provided input for the entry. */ input: Input; options?: Omit; /** * Head entry index * * @internal */ _i: number; /** * Resolved tags * * @internal */ _tags?: HeadTag[]; /** * Precomputed normalized tags shared across head instances (SSR default init * entry). Only used when no entry hooks, tag weight overrides or entry * options could observe or alter normalization, see `resolveTags`. * * @internal */ _precomputedTags?: HeadTag[]; /** * Pending patch to apply on next render (client-only) * @internal */ _pending?: Input; /** * @internal */ _o?: Input; } interface HeadPluginOptions extends CreateHeadOptions { hooks?: Record any>; } type HeadPluginInput = (HeadPluginOptions & { key: string; }) | (((head: Unhead) => HeadPluginOptions & { key: string; }) & { key?: string; }); type HeadPlugin = HeadPluginOptions & { key: string; }; /** * An active head entry provides an API to manipulate it. */ interface ActiveHeadEntry { /** * Updates the entry with new input. * * Will first clear any side effects for previous input. */ patch: (input: Input) => void; /** * Dispose the entry, removing it from the active head. * * Will queue side effects for removal. */ dispose: () => void; /** * @internal */ _i: number; } type PropResolver = ((key?: string, value?: any, tag?: HeadTag) => any) & { /** * Marks the resolver as the identity function for plain non-reactive JSON * values (strings/numbers/booleans/plain objects/arrays). When every * configured resolver is static, the SSR default init entry can use the * precomputed fast path (see `server/createHead.ts`). * * @internal */ _static?: boolean; }; interface CreateHeadOptions { document?: Document; /** * Initial head input that should be added. * * Any tags here are added with low priority. */ init?: (ResolvableHead | undefined | false)[]; /** * Prop resolvers for tags. */ propResolvers?: PropResolver[]; /** * @experimental * Key used for window attachment during streaming SSR. * Allows multiple Unhead instances on the same page. * @default '__unhead__' */ experimentalStreamKey?: string; /** * @internal */ _tagWeight?: (tag: HeadTag) => number; } interface CreateServerHeadOptions extends CreateHeadOptions { plugins?: HeadPluginInput[]; hooks?: Partial; /** * Custom tag weight function for controlling `` tag ordering. * * By default, tags are sorted using CAPO weights optimised for the browser preload scanner. * Override this to change the ordering — for example, to prioritise SEO meta tags for bot requests. * * @example * ```ts * import { capoTagWeight } from 'unhead/server' * * createHead({ * tagWeight(tag) { * // Promote SEO meta above styles for bots * if (isBot && tag.tag === 'meta' && tag.props.property?.startsWith('og:')) * return 55 // just above styles (60) * return capoTagWeight(tag) * } * }) * ``` */ tagWeight?: (tag: HeadTag) => number; /** * Should default important tags be skipped. * * Adds the following tags with low priority: * - * - * - */ disableDefaults?: boolean; /** * Omit line breaks between rendered tags, producing a single line of output. * * Only removes the separators *between* tags; newlines inside inline * `