/**
* Head manager for SSR.
*
* Collects `
`, ``, `` and inline ``;
}
return html;
};
const reset: HeadManager['reset'] = () => {
state.title = null;
state.titleTemplate = null;
state.meta = [];
state.link = [];
state.script = [];
};
return {
add,
state: () =>
({
...state,
meta: [...state.meta],
link: [...state.link],
script: [...state.script],
}) as SSRHeadState,
render,
reset,
};
};
/* ---------------------------------------------------------------------------
* Asset manifest
* ------------------------------------------------------------------------- */
/** Asset preload entry. */
export interface SSRAsset {
href: string;
rel: 'preload' | 'modulepreload' | 'stylesheet';
as?: string;
type?: string;
crossorigin?: string;
integrity?: string;
}
/** Public asset manager handle. */
export interface AssetManager {
/** Add a generic preload (``). */
preload(href: string, opts?: Omit): void;
/** Add a JS module preload (``). */
module(href: string, opts?: Omit): void;
/** Add a stylesheet link (``). */
style(href: string, opts?: Omit): void;
/** Returns the current asset list snapshot. */
list(): SSRAsset[];
/** Renders all assets to a series of `` tags. */
render(options?: { nonce?: string }): string;
/** Resets the manifest. */
reset(): void;
}
export const createAssetManager = (): AssetManager => {
const assets: SSRAsset[] = [];
return {
preload(href, opts = {}) {
assets.push({ href, rel: 'preload', ...opts });
},
module(href, opts = {}) {
assets.push({ href, rel: 'modulepreload', ...opts });
},
style(href, opts = {}) {
assets.push({ href, rel: 'stylesheet', ...opts });
},
list: () => [...assets],
render(renderOpts = {}) {
let html = '';
for (const a of assets) {
let attrs = ` rel="${escapeAttr(a.rel)}" href="${escapeAttr(a.href)}"`;
if (a.as) attrs += ` as="${escapeAttr(a.as)}"`;
if (a.type) attrs += ` type="${escapeAttr(a.type)}"`;
if (a.crossorigin) attrs += ` crossorigin="${escapeAttr(a.crossorigin)}"`;
if (a.integrity) attrs += ` integrity="${escapeAttr(a.integrity)}"`;
if (renderOpts.nonce) attrs += ` nonce="${escapeAttr(renderOpts.nonce)}"`;
html += ``;
}
return html;
},
reset() {
assets.length = 0;
},
};
};