import { hashedAssetPath } from "../assets/assets.js"; import type { ScalarUiOptions } from "../options/options.js"; /** * Minimal HTML escape — replaces the five characters that have special * meaning in HTML attribute / text contexts. Used to safely embed * caller-supplied title / theme / endpoint strings into the rendered * shell. */ export function escapeHtml(input: string): string { return input .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } /** Inputs threaded into the rendered shell beyond the parsed options. */ export interface RenderShellInput { readonly options: ScalarUiOptions; /** Document URL the Scalar shell points at (may carry query string). */ readonly openapiUrl: string; /** Resolved Scalar runtime URL (CDN or bundled asset path). */ readonly runtimeUrl: string; /** Optional per-request CSP nonce embedded on inline JSON config. */ readonly nonce?: string; } /** * Render the Scalar HTML shell. * * The shell embeds the configured `openapiUrl` into a * `" // is unsafe — JSON syntax doesn't otherwise collide with HTML. We // replace every "<" with its unicode escape so even string values // like `"foo"` cannot terminate the block. const configJson = JSON.stringify(config).replace(/` : ""; return ` ${title} ${linkBlock}
${title}

initialising…

`; }