@ox-content/vite-plugin 3.0.0-alpha.13 → 3.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +200 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -15
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +199 -20
- package/dist/index.mjs.map +1 -1
- package/dist/markdown-tables.cjs.map +1 -1
- package/dist/markdown-tables.mjs.map +1 -1
- package/dist/styles/core.css +16 -16
- package/dist/styles/markdown-tables.css +3 -1
- package/dist/styles/social.css +68 -15
- package/dist/styles/tabs.css +15 -15
- package/dist/styles/twitter-full.css +71 -0
- package/dist/theme-tokens.cjs +95 -0
- package/dist/theme-tokens.cjs.map +1 -0
- package/dist/theme-tokens.d.cts +75 -0
- package/dist/theme-tokens.d.cts.map +1 -0
- package/dist/theme-tokens.d.mts +75 -0
- package/dist/theme-tokens.d.mts.map +1 -0
- package/dist/theme-tokens.mjs +91 -0
- package/dist/theme-tokens.mjs.map +1 -0
- package/dist/vitepress.cjs +2 -31
- package/dist/vitepress.cjs.map +1 -1
- package/dist/vitepress.mjs +2 -31
- package/dist/vitepress.mjs.map +1 -1
- package/package.json +13 -3
package/dist/vitepress.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitepress.cjs","names":["createRequire","join","stat","readFile","isAbsolute","resolve","existsSync","readdir","mkdir","createHash","writeFile","join","mkdir","writeFile","join","existsSync","createRequire","readFile","join","mkdir","writeFile","readFile"],"sources":["../src/napi.ts","../src/theme-fonts-acquire.ts","../src/theme-fonts.ts","../src/icons-css.ts","../src/icons.ts","../src/header-chrome.ts","../src/theme-tokens.ts","../src/theme.ts","../src/vitepress.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\ntype NapiModule = typeof import(\"@ox-content/napi\");\nconst requireNapi = createRequire(import.meta.url);\n\nfunction getDefaultExport(value: unknown): object | undefined {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return undefined;\n }\n\n const defaultExport = value.default;\n return defaultExport && typeof defaultExport === \"object\" ? defaultExport : undefined;\n}\n\nfunction normalizeNapiModule(mod: NapiModule): NapiModule {\n const defaultExport = getDefaultExport(mod);\n return defaultExport\n ? ({\n ...defaultExport,\n ...mod,\n } as NapiModule)\n : mod;\n}\n\nexport async function importNapiModule(): Promise<NapiModule> {\n return normalizeNapiModule((await import(\"@ox-content/napi\")) as NapiModule);\n}\n\nlet syncNapiModule: NapiModule | null | undefined;\n\nexport function importNapiModuleSync(): NapiModule {\n if (syncNapiModule) {\n return syncNapiModule;\n }\n\n if (syncNapiModule === null) {\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n\n try {\n const mod = requireNapi(\"@ox-content/napi\") as NapiModule;\n syncNapiModule = normalizeNapiModule(mod);\n return syncNapiModule;\n } catch {\n syncNapiModule = null;\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n}\n","/**\n * Resolve self-hosted faces from a local file / `@fontsource` directory or\n * Google Fonts. Downloads are cached; tests inject `fetch` so CI never hits\n * the network.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport type { PlannedSelfHostFace, WriteThemeFontsOptions } from \"./theme-fonts\";\n\nexport type FontFetch = (input: string, init?: RequestInit) => Promise<Response>;\n\nconst GOOGLE_CSS = \"https://fonts.googleapis.com/css2\";\nconst GOOGLE_UA =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\";\nconst ALLOWED_HOSTS = new Set([\"fonts.googleapis.com\", \"fonts.gstatic.com\"]);\n\nexport interface AcquiredSelfHostFace extends PlannedSelfHostFace {\n bytes: Uint8Array;\n}\n\nexport function fontMime(fileName: string): string {\n if (fileName.endsWith(\".woff\")) {\n return \"font/woff\";\n }\n if (fileName.endsWith(\".ttf\")) {\n return \"font/ttf\";\n }\n if (fileName.endsWith(\".otf\")) {\n return \"font/otf\";\n }\n return \"font/woff2\";\n}\n\nexport function renderFontFaceCss(faces: AcquiredSelfHostFace[]): string {\n return faces\n .map((face) => {\n const range = face.unicodeRange ? `\\n unicode-range: ${face.unicodeRange};` : \"\";\n const fileName = face.fileName;\n const format = fileName.endsWith(\".woff\")\n ? \"woff\"\n : fileName.endsWith(\".ttf\")\n ? \"truetype\"\n : fileName.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n const family = /^[a-zA-Z_-][\\w-]*$/.test(face.family)\n ? face.family\n : `\"${face.family.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n return `@font-face {\n font-family: ${family};\n font-style: ${face.style};\n font-weight: ${face.weight};\n font-display: ${face.display};\n src: url(./${fileName}) format(\"${format}\");${range}\n}`;\n })\n .join(\"\\n\\n\");\n}\n\nexport function resolveFontCacheDir(root: string, cacheDir?: string): string {\n return cacheDir ?? join(root, \"node_modules\", \".cache\", \"ox-content\", \"fonts\");\n}\n\nexport async function acquireSelfHostedFaces(\n faces: PlannedSelfHostFace[],\n options: WriteThemeFontsOptions,\n): Promise<AcquiredSelfHostFace[]> {\n const cacheDir = resolveFontCacheDir(options.root, options.cacheDir);\n const acquired: AcquiredSelfHostFace[] = [];\n for (const face of faces) {\n acquired.push(\n face.provider === \"local\"\n ? await acquireLocalFace(face, options.root)\n : await acquireGoogleFace(face, cacheDir, options.fetch ?? fetch),\n );\n }\n return acquired;\n}\n\nasync function acquireLocalFace(\n face: PlannedSelfHostFace,\n root: string,\n): Promise<AcquiredSelfHostFace> {\n if (!face.path) {\n throw new Error(`Theme font \"${face.family}\" uses provider \"local\" but has no path.`);\n }\n if (face.path.includes(\"\\0\")) {\n throw new Error(`Theme font \"${face.family}\" path must not contain NUL.`);\n }\n const resolved = resolveLocalPath(root, face.path);\n const info = await stat(resolved).catch(() => undefined);\n if (!info) {\n throw new Error(`Theme font \"${face.family}\" was not found at ${resolved}.`);\n }\n const file = info.isDirectory() ? await findDirectoryFont(resolved, face) : resolved;\n return { ...face, bytes: await readFile(file) };\n}\n\nfunction resolveLocalPath(root: string, spec: string): string {\n if (isAbsolute(spec)) {\n return spec;\n }\n if (spec.startsWith(\"@\") || !spec.startsWith(\".\")) {\n return resolve(root, \"node_modules\", spec);\n }\n return resolve(root, spec);\n}\n\nasync function findDirectoryFont(dir: string, face: PlannedSelfHostFace): Promise<string> {\n const filesDir = existsSync(join(dir, \"files\")) ? join(dir, \"files\") : dir;\n const names = (await readdir(filesDir)).filter((name) => /\\.(woff2|woff|ttf|otf)$/i.test(name));\n const weight = String(face.weight);\n const wantItalic = face.style === \"italic\";\n const match = names.find((name) => {\n const lower = name.toLowerCase();\n const hasWeight = lower.includes(weight);\n const italic = lower.includes(\"italic\");\n const subset = face.subset === \"all\" || lower.includes(face.subset.toLowerCase());\n return hasWeight && subset && italic === wantItalic;\n });\n const fallback = names[0];\n const chosen = match ?? (names.length === 1 ? fallback : undefined);\n if (!chosen) {\n throw new Error(\n `Theme font \"${face.family}\" has no ${face.weight} ${face.style} ${face.subset} file in ${filesDir}.`,\n );\n }\n return join(filesDir, chosen);\n}\n\nasync function acquireGoogleFace(\n face: PlannedSelfHostFace,\n cacheDir: string,\n fetchFn: FontFetch,\n): Promise<AcquiredSelfHostFace> {\n const css = await cachedText(googleCssUrl(face), cacheDir, fetchFn, \".css\");\n const parsed = parseGoogleCss(css).find(\n (entry) =>\n entry.weight === face.weight &&\n entry.style === face.style &&\n (entry.subset === face.subset || !entry.subset),\n );\n if (!parsed) {\n throw new Error(\n `Google Fonts CSS for \"${face.family}\" has no ${face.weight} ${face.style} ${face.subset} face.`,\n );\n }\n const bytes = await cachedBytes(parsed.url, cacheDir, fetchFn, \".woff2\");\n return { ...face, bytes, unicodeRange: face.unicodeRange ?? parsed.unicodeRange };\n}\n\nexport function googleCssUrl(face: PlannedSelfHostFace): string {\n const italic = face.style === \"italic\";\n const axis = italic ? \"ital,wght\" : \"wght\";\n const spec = italic ? `1,${face.weight}` : `${face.weight}`;\n const family = `${face.family.replace(/ /g, \"+\")}:${axis}@${spec}`;\n return `${GOOGLE_CSS}?family=${family}&display=${encodeURIComponent(face.display)}`;\n}\n\ninterface ParsedGoogleFace {\n subset: string;\n weight: number;\n style: \"normal\" | \"italic\";\n url: string;\n unicodeRange?: string;\n}\n\nexport function parseGoogleCss(css: string): ParsedGoogleFace[] {\n const faces: ParsedGoogleFace[] = [];\n const blocks = css.matchAll(/\\/\\*\\s*([a-z0-9-]+)\\s*\\*\\/\\s*@font-face\\s*\\{([^}]+)\\}/gi);\n for (const match of blocks) {\n const parsed = parseGoogleBlock(match[2] ?? \"\", match[1]?.toLowerCase() ?? \"\");\n if (parsed) {\n faces.push(parsed);\n }\n }\n if (faces.length === 0) {\n for (const match of css.matchAll(/@font-face\\s*\\{([^}]+)\\}/gi)) {\n const parsed = parseGoogleBlock(match[1] ?? \"\", \"\");\n if (parsed) {\n faces.push(parsed);\n }\n }\n }\n return faces;\n}\n\nfunction parseGoogleBlock(body: string, subset: string): ParsedGoogleFace | undefined {\n const url = body.match(/url\\((['\"]?)(https?:\\/\\/[^'\")]+)\\1\\)/)?.[2];\n if (!url || !isAllowedFontUrl(url)) {\n return undefined;\n }\n const weight = Number(body.match(/font-weight:\\s*(\\d+)/i)?.[1] ?? 400);\n const style = /font-style:\\s*italic/i.test(body) ? \"italic\" : \"normal\";\n return {\n subset,\n weight,\n style,\n url,\n unicodeRange: body.match(/unicode-range:\\s*([^;]+)/i)?.[1]?.trim(),\n };\n}\n\nfunction isAllowedFontUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"https:\" && ALLOWED_HOSTS.has(parsed.hostname);\n } catch {\n return false;\n }\n}\n\nasync function cachedText(\n url: string,\n cacheDir: string,\n fetchFn: FontFetch,\n ext: string,\n): Promise<string> {\n const bytes = await cachedBytes(url, cacheDir, fetchFn, ext);\n return new TextDecoder().decode(bytes);\n}\n\nasync function cachedBytes(\n url: string,\n cacheDir: string,\n fetchFn: FontFetch,\n ext: string,\n): Promise<Uint8Array> {\n if (!isAllowedFontUrl(url)) {\n throw new Error(`Refusing to download font from ${url}.`);\n }\n await mkdir(cacheDir, { recursive: true });\n const dest = join(\n cacheDir,\n `${createHash(\"sha256\").update(url).digest(\"hex\").slice(0, 16)}${ext}`,\n );\n if (existsSync(dest)) {\n return readFile(dest);\n }\n const response = await fetchFn(url, { headers: { \"User-Agent\": GOOGLE_UA } });\n if (!response.ok) {\n throw new Error(`Failed to download ${url}: ${response.status}`);\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n await writeFile(dest, bytes);\n return bytes;\n}\n","/**\n * Opt-in web-font objects for `theme.fonts`, plus SSG self-host emission.\n *\n * NAPI still receives flattened CSS stacks (`JsThemeFonts`). File acquisition\n * and `@font-face` generation stay in TypeScript so other PRs can keep landing\n * NAPI theme-type changes independently.\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n acquireSelfHostedFaces,\n fontMime,\n renderFontFaceCss,\n type FontFetch,\n} from \"./theme-fonts-acquire\";\n\nexport const FONT_ASSET_DIR = \"__ox_fonts__\";\nexport const FONT_CSS_NAME = \"fonts.css\";\n\nexport type ThemeFontProvider = \"google\" | \"local\";\nexport type ThemeFontStyle = \"normal\" | \"italic\";\nexport type ThemeFontDisplay = \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n\n/** UnoCSS-inspired family descriptor. The string stack form remains valid. */\nexport interface ThemeWebFont {\n /** Family name, e.g. `\"Inter\"` or `\"DM Mono\"`. */\n family: string;\n /** Defaults to `\"local\"` when `path` is set, otherwise `\"google\"`. */\n provider?: ThemeFontProvider;\n /** File, directory, or `@fontsource/*` package. Required for `local`. */\n path?: string;\n weights?: number[];\n styles?: ThemeFontStyle[];\n subsets?: string[];\n display?: ThemeFontDisplay;\n /** Copy files into the SSG output and emit `@font-face`. */\n selfHost?: boolean;\n /** Extra families after `family` in the emitted CSS stack. */\n fallbacks?: string[];\n /** Preload every self-hosted face, or only these weights. */\n preload?: boolean | number[];\n /** Optional `unicode-range` for local faces. */\n unicodeRange?: string;\n}\n\nexport type ThemeFontValue = string | ThemeWebFont;\n\nexport interface ThemeFontsLike {\n sans?: ThemeFontValue;\n mono?: ThemeFontValue;\n named?: Record<string, ThemeFontValue>;\n}\n\nexport interface WriteThemeFontsOptions {\n fonts: ThemeFontsLike;\n outDir: string;\n root: string;\n cacheDir?: string;\n fetch?: FontFetch;\n}\n\nconst NAMED_FONT_PATTERN = /^[a-z][a-z0-9-]*$/;\nconst GENERIC_FOR = { sans: \"sans-serif\", mono: \"monospace\", named: \"sans-serif\" } as const;\n\nexport function isThemeWebFont(value: ThemeFontValue | undefined): value is ThemeWebFont {\n return typeof value === \"object\" && value !== null && typeof value.family === \"string\";\n}\n\n/** CSS `font-family` identifier; quotes names that are not a single ident. */\nexport function cssFamilyName(family: string): string {\n const trimmed = family.trim();\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed;\n }\n if (/^[a-zA-Z_-][\\w-]*$/.test(trimmed)) {\n return trimmed;\n }\n return `\"${trimmed.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nexport function flattenThemeFont(\n value: ThemeFontValue | undefined,\n generic: string,\n): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value === \"string\") {\n return value;\n }\n const fallbacks = value.fallbacks?.length ? value.fallbacks.join(\", \") : generic;\n return `${cssFamilyName(value.family)}, ${fallbacks}`;\n}\n\n/** Flatten object fonts so `JsThemeFonts` stays `{ sans?: string; mono?: string }`. */\nexport function flattenThemeFonts(\n fonts: ThemeFontsLike,\n): { sans?: string; mono?: string } | undefined {\n const sans = flattenThemeFont(fonts.sans, GENERIC_FOR.sans);\n const mono = flattenThemeFont(fonts.mono, GENERIC_FOR.mono);\n if (!sans && !mono) {\n return undefined;\n }\n return { sans, mono };\n}\n\nexport function namedFontToken(name: string): string {\n if (!NAMED_FONT_PATTERN.test(name)) {\n throw new Error(\n `Invalid theme font name: ${JSON.stringify(name)}. ` +\n `Named fonts are lowercase kebab-case (e.g. \"code\").`,\n );\n }\n return name;\n}\n\n/** Extra `--octc-font-*` variables for `fonts.named`. Roles stay in Rust theme CSS. */\nexport function namedFontVarsCss(fonts: ThemeFontsLike): string {\n const entries = Object.entries(fonts.named ?? {});\n if (entries.length === 0) {\n return \"\";\n }\n const lines = entries.map(([name, value]) => {\n const stack = flattenThemeFont(value, GENERIC_FOR.named);\n return ` --octc-font-${namedFontToken(name)}: ${stack};`;\n });\n return `:root {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\nexport function normalizeBasePath(base: string | undefined): string {\n if (!base || base === \"/\") {\n return \"/\";\n }\n return base.endsWith(\"/\") ? base : `${base}/`;\n}\n\nexport function plannedFontFileName(\n family: string,\n weight: number,\n style: ThemeFontStyle,\n subset: string,\n extension: string,\n): string {\n const ext = extension.startsWith(\".\") ? extension : `.${extension}`;\n return `${slugify(family)}-${weight}-${style}-${slugify(subset)}${ext}`;\n}\n\nexport function plannedFontExtension(font: ThemeWebFont): string {\n if (\n font.provider === \"local\" &&\n font.path &&\n /\\.\\w+$/.test(font.path) &&\n !font.path.endsWith(\"/\")\n ) {\n const match = font.path.match(/(\\.\\w+)$/);\n return match?.[1] ?? \".woff2\";\n }\n return \".woff2\";\n}\n\nexport interface PlannedSelfHostFace {\n family: string;\n weight: number;\n style: ThemeFontStyle;\n subset: string;\n display: ThemeFontDisplay;\n preload: boolean;\n provider: ThemeFontProvider;\n path?: string;\n fileName: string;\n unicodeRange?: string;\n}\n\nexport function planSelfHostedFaces(fonts: ThemeFontsLike): PlannedSelfHostFace[] {\n const faces: PlannedSelfHostFace[] = [];\n for (const value of themeFontValues(fonts)) {\n if (!isThemeWebFont(value) || !value.selfHost) {\n continue;\n }\n const font = normalizeWebFont(value);\n const extension = plannedFontExtension(font);\n for (const weight of font.weights) {\n for (const style of font.styles) {\n for (const subset of font.subsets) {\n faces.push({\n family: font.family,\n weight,\n style,\n subset,\n display: font.display,\n preload: shouldPreload(font.preload, weight),\n provider: font.provider,\n path: font.path,\n fileName: plannedFontFileName(font.family, weight, style, subset, extension),\n unicodeRange: font.unicodeRange,\n });\n }\n }\n }\n }\n const unique = new Map<string, PlannedSelfHostFace>();\n for (const face of faces) {\n const existing = unique.get(face.fileName);\n if (existing) {\n existing.preload ||= face.preload;\n } else {\n unique.set(face.fileName, face);\n }\n }\n return [...unique.values()];\n}\n\nexport function themeFontHeadHtml(fonts: ThemeFontsLike, base?: string): string {\n const faces = planSelfHostedFaces(fonts);\n if (faces.length === 0) {\n return \"\";\n }\n const root = normalizeBasePath(base);\n const tags = [`<link rel=\"stylesheet\" href=\"${root}${FONT_ASSET_DIR}/${FONT_CSS_NAME}\">`];\n for (const face of faces) {\n if (!face.preload) {\n continue;\n }\n tags.push(\n `<link rel=\"preload\" href=\"${root}${FONT_ASSET_DIR}/${face.fileName}\" as=\"font\" type=\"${fontMime(face.fileName)}\" crossorigin>`,\n );\n }\n return tags.join(\"\\n\");\n}\n\nexport function withSelfHostedFontHead<T extends { head?: string }>(\n embed: T,\n fonts: ThemeFontsLike,\n base?: string,\n): T | undefined {\n const extra = themeFontHeadHtml(fonts, base);\n const keys = Object.keys(embed);\n if (!extra && keys.length === 0) {\n return undefined;\n }\n if (!extra) {\n return embed;\n }\n return { ...embed, head: embed.head ? `${extra}\\n${embed.head}` : extra };\n}\n\n/** Copy self-hosted faces into `outDir` and write `@font-face` CSS. */\nexport async function writeSelfHostedThemeFonts(\n options: WriteThemeFontsOptions,\n): Promise<string[]> {\n const faces = planSelfHostedFaces(options.fonts);\n if (faces.length === 0) {\n return [];\n }\n const acquired = await acquireSelfHostedFaces(faces, options);\n const destDir = join(options.outDir, FONT_ASSET_DIR);\n await mkdir(destDir, { recursive: true });\n const written: string[] = [];\n for (const face of acquired) {\n const dest = join(destDir, face.fileName);\n await writeFile(dest, face.bytes);\n written.push(dest);\n }\n const cssPath = join(destDir, FONT_CSS_NAME);\n await writeFile(cssPath, renderFontFaceCss(acquired), \"utf8\");\n written.push(cssPath);\n return written;\n}\n\nfunction themeFontValues(fonts: ThemeFontsLike): ThemeFontValue[] {\n return [fonts.sans, fonts.mono, ...Object.values(fonts.named ?? {})].filter(\n (value): value is ThemeFontValue => value !== undefined,\n );\n}\n\nfunction normalizeWebFont(\n font: ThemeWebFont,\n): Required<\n Pick<ThemeWebFont, \"family\" | \"provider\" | \"weights\" | \"styles\" | \"subsets\" | \"display\">\n> &\n ThemeWebFont {\n const provider = font.provider ?? (font.path ? \"local\" : \"google\");\n if (provider === \"local\" && !font.path) {\n throw new Error(`Theme font \"${font.family}\" uses provider \"local\" but has no path.`);\n }\n return {\n ...font,\n family: font.family.trim(),\n provider,\n weights: font.weights?.length ? font.weights : [400],\n styles: font.styles?.length ? font.styles : [\"normal\"],\n subsets: font.subsets?.length ? font.subsets : [\"latin\"],\n display: font.display ?? \"swap\",\n };\n}\n\nfunction shouldPreload(preload: ThemeWebFont[\"preload\"], weight: number): boolean {\n if (preload === true) {\n return true;\n }\n return Array.isArray(preload) && preload.includes(weight);\n}\n\nfunction slugify(value: string): string {\n const slug = value\n .trim()\n .toLowerCase()\n .replace(/['\"]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n return slug || \"font\";\n}\n","/**\n * Resolve Iconify JSON collections and emit CSS-mask rules.\n *\n * Collections come from installed `@iconify-json/*` or `@iconify/json`.\n * Tests supply fixture JSON under the project `root` — no network.\n */\n\nimport { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface IconifyIcon {\n body: string;\n width?: number;\n height?: number;\n}\n\nexport interface IconifyJSON {\n prefix?: string;\n width?: number;\n height?: number;\n icons: Record<string, IconifyIcon>;\n aliases?: Record<string, { parent: string; width?: number; height?: number }>;\n}\n\nexport interface ResolvedIcon {\n prefix: string;\n name: string;\n body: string;\n width: number;\n height: number;\n multicolor: boolean;\n}\n\nexport function iconClassName(prefix: string, name: string): string {\n return `icon-[${prefix}--${name}]`;\n}\n\nexport function iconCssSelector(prefix: string, name: string): string {\n return `.icon-\\\\[${prefix}--${name}\\\\]`;\n}\n\nexport function resolveIconCollectionPath(prefix: string, root: string): string | undefined {\n const files = [\n join(root, \"node_modules\", \"@iconify-json\", prefix, \"icons.json\"),\n join(root, \"node_modules\", \"@iconify\", \"json\", \"json\", `${prefix}.json`),\n ];\n for (const file of files) {\n if (existsSync(file)) {\n return file;\n }\n }\n return resolveViaNode(prefix, root);\n}\n\nfunction resolveViaNode(prefix: string, root: string): string | undefined {\n try {\n return createRequire(join(root, \"package.json\")).resolve(`@iconify-json/${prefix}/icons.json`);\n } catch {\n try {\n return createRequire(join(root, \"package.json\")).resolve(`@iconify/json/json/${prefix}.json`);\n } catch {\n return undefined;\n }\n }\n}\n\nexport async function loadIconCollection(\n prefix: string,\n root: string,\n): Promise<IconifyJSON | undefined> {\n const path = resolveIconCollectionPath(prefix, root);\n if (!path) {\n return undefined;\n }\n const raw = await readFile(path, \"utf8\");\n return JSON.parse(raw) as IconifyJSON;\n}\n\nexport function lookupIcon(\n collection: IconifyJSON,\n name: string,\n): { body: string; width: number; height: number } | undefined {\n const fallback = collection.width ?? 16;\n const fallbackH = collection.height ?? fallback;\n const direct = collection.icons[name];\n if (direct) {\n return {\n body: direct.body,\n width: direct.width ?? fallback,\n height: direct.height ?? fallbackH,\n };\n }\n const alias = collection.aliases?.[name];\n if (!alias) {\n return undefined;\n }\n const parent = collection.icons[alias.parent];\n if (!parent) {\n return undefined;\n }\n return {\n body: parent.body,\n width: alias.width ?? parent.width ?? fallback,\n height: alias.height ?? parent.height ?? fallbackH,\n };\n}\n\nexport function isMulticolorIcon(body: string): boolean {\n return /(?:fill|stroke)=[\"'](?!currentColor|none)[^\"']+[\"']/i.test(body);\n}\n\nexport function renderIconsCss(icons: ResolvedIcon[]): string {\n const rules = icons.map(renderOneIconCss);\n return `/* ox-content self-hosted Iconify icons */\\n${rules.join(\"\\n\")}\\n`;\n}\n\nfunction renderOneIconCss(icon: ResolvedIcon): string {\n const selector = iconCssSelector(icon.prefix, icon.name);\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${icon.width} ${icon.height}\">${maskBody(icon)}</svg>`;\n const url = svgToDataUrl(svg);\n if (icon.multicolor) {\n return `${selector}{display:inline-block;width:1em;height:1em;background-color:transparent;background-image:${url};background-repeat:no-repeat;background-size:100% 100%}`;\n }\n return `${selector}{display:inline-block;width:1em;height:1em;background-color:currentColor;-webkit-mask-image:${url};mask-image:${url};-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%}`;\n}\n\nfunction maskBody(icon: ResolvedIcon): string {\n return icon.multicolor ? icon.body : icon.body.replace(/currentColor/g, \"black\");\n}\n\nfunction svgToDataUrl(svg: string): string {\n const encoded = svg\n .replace(/\"/g, \"'\")\n .replace(/%/g, \"%25\")\n .replace(/#/g, \"%23\")\n .replace(/</g, \"%3C\")\n .replace(/>/g, \"%3E\")\n .replace(/\\s+/g, \" \");\n return `url(\"data:image/svg+xml,${encoded}\")`;\n}\n","/**\n * Opt-in self-hosted Iconify CSS for used and safelisted icons.\n *\n * Collection lookup stays on disk (`@iconify-json/*` / `@iconify/json`).\n * Theme embed injection composes with self-hosted font `<link>` tags.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { IconsOptions, ResolvedIconsOptions } from \"./types\";\nimport { normalizeBasePath } from \"./theme-fonts\";\nimport {\n iconClassName,\n isMulticolorIcon,\n loadIconCollection,\n lookupIcon,\n renderIconsCss,\n type ResolvedIcon,\n} from \"./icons-css\";\n\nexport const ICON_ASSET_DIR = \"__ox_icons__\";\nexport const ICON_CSS_NAME = \"icons.css\";\n\nconst URL_SCHEMES = new Set([\n \"http\",\n \"https\",\n \"data\",\n \"mailto\",\n \"file\",\n \"javascript\",\n \"vscode\",\n \"tel\",\n \"blob\",\n]);\n\nconst COLON_ICON = /(?<![A-Za-z0-9_-])([a-z][a-z0-9-]*):([a-z0-9][a-z0-9-]*)/gi;\nconst CLASS_ICON = /icon-\\[([a-z][a-z0-9-]*)--([a-z0-9][a-z0-9-]*)\\]/gi;\nconst ICON_FIELD = /(?:^|[\\s,{])icon\\s*:\\s*[\"']([^\"']+)[\"']/g;\n\nexport function resolveIconsOptions(\n value: boolean | IconsOptions | undefined,\n): ResolvedIconsOptions {\n if (!value) {\n return { enabled: false, mode: \"css-mask\", syntax: \"unocss\", include: [], safelist: [] };\n }\n if (value === true) {\n return { enabled: true, mode: \"css-mask\", syntax: \"unocss\", include: [], safelist: [] };\n }\n return {\n enabled: true,\n mode: value.mode ?? \"css-mask\",\n syntax: value.syntax ?? \"unocss\",\n include: value.include ?? [],\n safelist: value.safelist ?? [],\n };\n}\n\nexport interface ParsedIconName {\n prefix: string;\n name: string;\n}\n\nexport function parseIconName(value: string): ParsedIconName | undefined {\n const trimmed = value.trim();\n const classMatch = /^icon-\\[(.+)\\]$/.exec(trimmed);\n if (classMatch?.[1]) {\n const inner = classMatch[1];\n const sep = inner.indexOf(\"--\");\n if (sep <= 0) {\n return undefined;\n }\n return tokenPair(inner.slice(0, sep), inner.slice(sep + 2));\n }\n const sep = trimmed.indexOf(\":\");\n if (sep <= 0) {\n return undefined;\n }\n return tokenPair(trimmed.slice(0, sep), trimmed.slice(sep + 1));\n}\n\nexport function normalizeIconName(value: string): string {\n const parsed = parseIconName(value);\n return parsed ? `${parsed.prefix}:${parsed.name}` : value;\n}\n\nfunction tokenPair(prefix: string, name: string): ParsedIconName | undefined {\n if (!/^[a-z][a-z0-9-]*$/i.test(prefix) || !/^[a-z0-9][a-z0-9-]*$/i.test(name)) {\n return undefined;\n }\n if (URL_SCHEMES.has(prefix.toLowerCase())) {\n return undefined;\n }\n return { prefix, name };\n}\n\nexport function collectIconNamesFromText(text: string, into: Set<string> = new Set()): Set<string> {\n COLON_ICON.lastIndex = 0;\n for (const match of text.matchAll(COLON_ICON)) {\n addParsed(into, match[1], match[2]);\n }\n CLASS_ICON.lastIndex = 0;\n for (const match of text.matchAll(CLASS_ICON)) {\n addParsed(into, match[1], match[2]);\n }\n return into;\n}\n\nexport function collectIconFieldNames(text: string, into: Set<string> = new Set()): Set<string> {\n ICON_FIELD.lastIndex = 0;\n for (const match of text.matchAll(ICON_FIELD)) {\n const parsed = match[1] ? parseIconName(match[1]) : undefined;\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n }\n return into;\n}\n\nexport function collectThemeIconNames(socialLinks: unknown): string[] {\n if (!Array.isArray(socialLinks)) {\n return [];\n }\n const names: string[] = [];\n for (const link of socialLinks) {\n if (!link || typeof link !== \"object\") {\n continue;\n }\n const icon = (link as { icon?: unknown }).icon;\n if (typeof icon === \"string\" && parseIconName(icon)) {\n names.push(normalizeIconName(icon));\n }\n }\n return names;\n}\n\nfunction addParsed(into: Set<string>, prefix: string | undefined, name: string | undefined): void {\n if (!prefix || !name) {\n return;\n }\n const parsed = tokenPair(prefix, name);\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n}\n\nexport function iconStylesheetHref(base?: string): string {\n return `${normalizeBasePath(base)}${ICON_ASSET_DIR}/${ICON_CSS_NAME}`;\n}\n\nexport function iconStylesheetLink(base?: string): string {\n return `<link rel=\"stylesheet\" href=\"${iconStylesheetHref(base)}\">`;\n}\n\nexport function withSelfHostedIconHead<T extends { head?: string }>(\n embed: T | undefined,\n enabled: boolean,\n base?: string,\n): T | { head: string } | undefined {\n if (!enabled) {\n return embed;\n }\n const extra = iconStylesheetLink(base);\n if (!embed) {\n return { head: extra };\n }\n return { ...embed, head: embed.head ? `${extra}\\n${embed.head}` : extra };\n}\n\nexport interface WriteSelfHostedIconsOptions {\n options: ResolvedIconsOptions;\n outDir: string;\n root: string;\n srcDir?: string;\n socialLinks?: unknown;\n}\n\nexport interface WriteSelfHostedIconsResult {\n files: string[];\n errors: string[];\n names: string[];\n}\n\n/** Copy resolved icon CSS into `outDir`. Missing collections or names become errors. */\nexport async function writeSelfHostedIcons(\n input: WriteSelfHostedIconsOptions,\n): Promise<WriteSelfHostedIconsResult> {\n if (!input.options.enabled) {\n return { files: [], errors: [], names: [] };\n }\n const names = await collectResolvedIconNames(input);\n const { icons, errors } = await resolveIconBodies(names, input.root);\n const destDir = join(input.outDir, ICON_ASSET_DIR);\n await mkdir(destDir, { recursive: true });\n const cssPath = join(destDir, ICON_CSS_NAME);\n await writeFile(cssPath, renderIconsCss(icons), \"utf8\");\n return { files: [cssPath], errors, names };\n}\n\nexport { iconClassName };\n\nasync function collectResolvedIconNames(input: WriteSelfHostedIconsOptions): Promise<string[]> {\n const names = new Set<string>();\n for (const item of input.options.safelist) {\n addName(names, item);\n }\n for (const item of collectThemeIconNames(input.socialLinks)) {\n names.add(item);\n }\n const { names: includeNames, globs } = partitionInclude(input.options.include);\n for (const item of includeNames) {\n names.add(item);\n }\n for (const pattern of globs) {\n const files = await glob(pattern, {\n cwd: input.root,\n nodir: true,\n absolute: true,\n ignore: [\"**/node_modules/**\"],\n });\n for (const file of files) {\n collectIconNamesFromText(await readFile(file, \"utf8\"), names);\n }\n }\n if (input.srcDir) {\n const files = await glob(\"**/*.{md,mdx,markdown}\", {\n cwd: input.srcDir,\n nodir: true,\n absolute: true,\n ignore: [\"**/node_modules/**\"],\n });\n for (const file of files) {\n collectIconFieldNames(await readFile(file, \"utf8\"), names);\n }\n }\n return [...names].sort();\n}\n\nfunction partitionInclude(include: string[]): { names: string[]; globs: string[] } {\n const names: string[] = [];\n const globs: string[] = [];\n for (const entry of include) {\n if (parseIconName(entry)) {\n names.push(normalizeIconName(entry));\n } else {\n globs.push(entry);\n }\n }\n return { names, globs };\n}\n\nfunction addName(into: Set<string>, value: string): void {\n const parsed = parseIconName(value);\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n}\n\nasync function resolveIconBodies(\n names: string[],\n root: string,\n): Promise<{ icons: ResolvedIcon[]; errors: string[] }> {\n const icons: ResolvedIcon[] = [];\n const errors: string[] = [];\n const collections = new Map<string, Awaited<ReturnType<typeof loadIconCollection>>>();\n for (const id of names) {\n const parsed = parseIconName(id);\n if (!parsed) {\n continue;\n }\n if (!collections.has(parsed.prefix)) {\n collections.set(parsed.prefix, await loadIconCollection(parsed.prefix, root));\n }\n const collection = collections.get(parsed.prefix);\n if (!collection) {\n errors.push(\n `[ox-content] icons: missing Iconify collection \"${parsed.prefix}\". Install @iconify-json/${parsed.prefix} or @iconify/json.`,\n );\n continue;\n }\n const found = lookupIcon(collection, parsed.name);\n if (!found) {\n errors.push(\n `[ox-content] icons: missing icon \"${parsed.prefix}:${parsed.name}\" in collection \"${parsed.prefix}\".`,\n );\n continue;\n }\n icons.push({\n prefix: parsed.prefix,\n name: parsed.name,\n body: found.body,\n width: found.width,\n height: found.height,\n multicolor: isMulticolorIcon(found.body),\n });\n }\n return { icons, errors };\n}\n","/**\n * Opt-in header nav, announcement, and per-page chrome helpers.\n */\n\n/** Plain label or locale map (`{ en: \"Guide\", ja: \"ガイド\" }`). */\nexport type LocaleLabel = string | Record<string, string>;\n\n/** Header nav link or dropdown. */\nexport interface HeaderNavItem {\n text: LocaleLabel;\n link?: string;\n items?: HeaderNavItem[];\n}\n\n/** Announcement bar. Text is escaped; no raw HTML slot. */\nexport interface ThemeAnnouncement {\n text: string;\n /** https or same-origin only. */\n link?: string;\n /** Best-effort localStorage key for dismiss. */\n dismissKey?: string;\n}\n\n/** Per-page frontmatter chrome flags. `false` hides that region. */\nexport interface PageChromeFlags {\n sidebar?: boolean;\n outline?: boolean;\n aside?: boolean;\n footer?: boolean;\n navbar?: boolean;\n lastUpdated?: boolean;\n editLink?: boolean;\n}\n\n/** `false` or omitted stays off. `true` or `{}` enables default flag reading. */\nexport function resolvePageChromeOption(\n value: boolean | Record<string, unknown> | undefined,\n): boolean {\n return value === true || (typeof value === \"object\" && value !== null);\n}\n\n/** Reads hide flags from frontmatter. Non-boolean values are ignored. */\nexport function parsePageChromeFlags(frontmatter: Record<string, unknown>): PageChromeFlags {\n return {\n sidebar: readBool(frontmatter.sidebar),\n outline: readBool(frontmatter.outline),\n aside: readBool(frontmatter.aside),\n footer: readBool(frontmatter.footer),\n navbar: readBool(frontmatter.navbar),\n lastUpdated: readBool(frontmatter.lastUpdated),\n editLink: readBool(frontmatter.editLink),\n };\n}\n\nfunction readBool(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\n/**\n * Picks the exact locale, its language, the default locale, then the first\n * non-empty own string in declaration order.\n */\nexport function resolveLocaleLabel(\n text: LocaleLabel,\n locale?: string,\n defaultLocale?: string,\n): string {\n if (typeof text === \"string\") {\n return text;\n }\n const candidates = [locale, locale?.split(\"-\")[0], defaultLocale, defaultLocale?.split(\"-\")[0]];\n for (const candidate of candidates) {\n if (!candidate || !Object.hasOwn(text, candidate)) {\n continue;\n }\n const value = text[candidate];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n for (const value of Object.values(text)) {\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n return \"\";\n}\n\n/** Nav item after locale maps are flattened to strings. */\nexport interface ResolvedHeaderNavItem {\n text: string;\n link?: string;\n items?: ResolvedHeaderNavItem[];\n}\n\n/** Resolves locale maps so NAPI always receives string labels. */\nexport function resolveHeaderNavItems(\n items: HeaderNavItem[] | undefined,\n locale?: string,\n defaultLocale?: string,\n): ResolvedHeaderNavItem[] | undefined {\n if (!items?.length) {\n return undefined;\n }\n return items.map((item) => ({\n text: resolveLocaleLabel(item.text, locale, defaultLocale),\n link: item.link,\n items: resolveHeaderNavItems(item.items, locale, defaultLocale),\n }));\n}\n","/**\n * Free-form `--octc-*` custom properties for themes that need more than the\n * typed `colors` / `fonts` / `layout` fields.\n *\n * Keys are written **without** the `--octc-` prefix, so `\"surface-glass\"`\n * becomes `--octc-surface-glass`. This is the seam that keeps the two theme\n * axes independent: a color package can restyle code-block line markers, brand\n * accents, and surface textures purely through tokens, while a skin package\n * lays out geometry against those same tokens without knowing any color.\n */\nexport type ThemeTokens = Record<string, string>;\n\nconst TOKEN_PREFIX = \"--octc-\";\nconst TOKEN_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Renders light and dark token records as the three selectors the SSG runtime\n * switches between: an explicit `[data-theme=\"dark\"]` opt-in, the OS\n * `prefers-color-scheme` fallback, and the `:root` base.\n *\n * Emitted after the typed color variables and before the theme's own `css`, so\n * a token can override a typed color and raw `css` can override a token.\n */\nexport function tokensToCss(light: ThemeTokens, dark: ThemeTokens): string {\n const lightBody = declarations(light, \" \");\n const darkBody = declarations(dark, \" \");\n const blocks: string[] = [];\n\n if (lightBody) {\n blocks.push(`:root {\\n${lightBody}\\n}`);\n }\n if (darkBody) {\n blocks.push(`[data-theme=\"dark\"] {\\n${darkBody}\\n}`);\n blocks.push(\n `@media (prefers-color-scheme: dark) {\\n :root:not([data-theme=\"light\"]) {\\n${declarations(dark, \" \")}\\n }\\n}`,\n );\n }\n\n return blocks.join(\"\\n\");\n}\n\nfunction declarations(tokens: ThemeTokens, indent: string): string {\n return Object.entries(tokens)\n .filter(([, value]) => value !== undefined && value !== \"\")\n .map(([name, value]) => `${indent}${TOKEN_PREFIX}${assertTokenName(name)}: ${value};`)\n .join(\"\\n\");\n}\n\nfunction assertTokenName(name: string): string {\n // Token names land verbatim inside a declaration block, so a stray `:` or `}`\n // would silently break every rule after it. Fail the build with the offending\n // key instead of shipping a corrupt stylesheet.\n if (!TOKEN_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid theme token name: ${JSON.stringify(name)}. ` +\n `Token names are lowercase kebab-case without the \"${TOKEN_PREFIX}\" prefix (e.g. \"surface-glass\").`,\n );\n }\n return name;\n}\n","/**\n * Theme API for ox-content SSG\n *\n * Provides VitePress-like theming with default theme + customization.\n */\n\nimport type {\n HeaderNavItem,\n LocaleLabel,\n ResolvedHeaderNavItem,\n ThemeAnnouncement,\n} from \"./header-chrome\";\nimport { resolveHeaderNavItems } from \"./header-chrome\";\nimport {\n flattenThemeFonts,\n namedFontVarsCss,\n withSelfHostedFontHead,\n type ThemeFontValue,\n} from \"./theme-fonts\";\nimport { tokensToCss, type ThemeTokens } from \"./theme-tokens\";\nimport { withSelfHostedIconHead } from \"./icons\";\n\nexport type { HeaderNavItem, LocaleLabel, ThemeAnnouncement } from \"./header-chrome\";\n\nexport type { ThemeFontValue, ThemeWebFont } from \"./theme-fonts\";\nexport type { ThemeTokens } from \"./theme-tokens\";\n\n/**\n * Theme color configuration.\n */\nexport interface ThemeColors {\n /** Primary accent color */\n primary?: string;\n /** Primary color on hover */\n primaryHover?: string;\n /** Background color */\n background?: string;\n /** Alternative background color (sidebar, code blocks) */\n backgroundAlt?: string;\n /** Main text color */\n text?: string;\n /** Muted/secondary text color */\n textMuted?: string;\n /** Border color */\n border?: string;\n /** Code block background color */\n codeBackground?: string;\n /** Code block gradient color at the top; defaults to `codeBackground` when customized */\n codeBackgroundTop?: string;\n /** Code block text color */\n codeText?: string;\n}\n\n/**\n * Theme layout configuration.\n */\nexport interface ThemeLayout {\n /** Sidebar width (CSS value, e.g., \"260px\") */\n sidebarWidth?: string;\n /** Header height (CSS value, e.g., \"60px\") */\n headerHeight?: string;\n /** Maximum content width (CSS value, e.g., \"960px\") */\n maxContentWidth?: string;\n}\n\n/**\n * Theme font configuration.\n *\n * `sans` and `mono` accept a CSS stack string or a web-font object. Named\n * families are extra stacks exposed as `--octc-font-<name>`.\n */\nexport interface ThemeFonts {\n /** Sans-serif font stack or self-hosted family */\n sans?: ThemeFontValue;\n /** Monospace font stack or self-hosted family */\n mono?: ThemeFontValue;\n /** Additional families, exposed as `--octc-font-<name>` */\n named?: Record<string, ThemeFontValue>;\n}\n\n/**\n * Entry page theme configuration.\n */\nexport interface ThemeEntryPage {\n /** Landing page presentation mode */\n mode?: \"default\" | \"subtle\";\n}\n\n/**\n * Theme header configuration.\n */\nexport interface ThemeHeader {\n /** Logo image URL */\n logo?: string;\n /** Light mode logo image URL */\n logoLight?: string;\n /** Dark mode logo image URL */\n logoDark?: string;\n /** Whether to render the site name text next to the logo */\n showSiteNameText?: boolean;\n /** Logo width in pixels */\n logoWidth?: number;\n /** Logo height in pixels */\n logoHeight?: number;\n}\n\n/**\n * Theme footer configuration.\n */\nexport interface ThemeFooter {\n /** Footer message (supports HTML) */\n message?: string;\n /** Copyright text (supports HTML) */\n copyright?: string;\n}\n\n/** Custom social link icon. */\nexport type SocialLinkIcon = string | { svg: string };\n\n/** Custom social link. */\nexport interface SocialLink {\n icon: SocialLinkIcon;\n link: string;\n ariaLabel?: string;\n}\n\n/** Legacy social links configuration. */\nexport interface LegacySocialLinks {\n /** GitHub URL */\n github?: string;\n /** Twitter/X URL */\n twitter?: string;\n /** Discord URL */\n discord?: string;\n}\n\n/** Social links configuration. */\nexport type SocialLinks = LegacySocialLinks | SocialLink[];\n\n/**\n * Embedded HTML content for specific positions in the page layout.\n */\nexport interface ThemeEmbed {\n /** Content to embed into <head> */\n head?: string;\n /** Content before header */\n headerBefore?: string;\n /** Content after header */\n headerAfter?: string;\n /** Content before sidebar navigation */\n sidebarBefore?: string;\n /** Content after sidebar navigation */\n sidebarAfter?: string;\n /** Content before main content */\n contentBefore?: string;\n /** Content after main content */\n contentAfter?: string;\n /** Content before footer */\n footerBefore?: string;\n /** Custom footer content (replaces default footer) */\n footer?: string;\n}\n\n/** Sidebar group or link, including recursively nested localized labels. */\nexport interface SidebarItem {\n /** Plain label or locale map (`{ en: \"Guide\", ja: \"ガイド\" }`). */\n text?: LocaleLabel;\n link?: string;\n items?: SidebarItem[];\n collapsed?: boolean;\n stickyCollapsed?: boolean;\n}\n\n/**\n * Complete theme configuration.\n */\nexport interface ThemeConfig {\n /** Theme name for identification */\n name?: string;\n /** Base theme to extend */\n extends?: ThemeConfig;\n /**\n * Preserve the current surface during same-origin MPA navigation with the\n * browser's cross-document View Transition API.\n *\n * Unsupported browsers use normal navigation. Reduced-motion preferences\n * never enable the transition. Set `false` to opt out.\n *\n * @default true\n */\n viewTransitions?: boolean;\n /**\n * Show the right-hand \"On this page\" outline.\n *\n * Default `false`. When `true`, the outline is rendered only on pages\n * that have TOC entries, using the existing `<aside class=\"toc\">` markup.\n */\n aside?: boolean;\n /**\n * Show a breadcrumb trail from the site root through sidebar ancestors.\n *\n * Default `false`. `true` or an object enables the trail. Frontmatter\n * `breadcrumbs: false` still hides it on that page.\n */\n breadcrumbs?: boolean | Record<string, unknown>;\n /**\n * Heading permalink visibility. CSS only — the renderer HTML stays\n * `<a class=\"header-anchor\" href=\"#id\">`.\n *\n * `\"hover\"` (default) reveals the `#` on hover / focus-visible, and\n * stays visible on touch. `\"always\"` keeps it visible.\n */\n headingPermalink?: \"hover\" | \"always\";\n /** Light mode colors (maps to CSS variables) */\n colors?: ThemeColors;\n /** Dark mode colors (maps to CSS variables) */\n darkColors?: ThemeColors;\n /** Font configuration (maps to CSS variables) */\n fonts?: ThemeFonts;\n /** Entry page configuration */\n entryPage?: ThemeEntryPage;\n /** Layout configuration (maps to CSS variables) */\n layout?: ThemeLayout;\n /** Header configuration */\n header?: ThemeHeader;\n /**\n * Opt-in header nav. Each item is `{ text, link }` or a dropdown\n * `{ text, items }`. Labels are escaped. `javascript:`, `data:`,\n * `vbscript:`, and protocol-relative `//` links are omitted.\n */\n nav?: HeaderNavItem[];\n /**\n * Opt-in announcement bar above the header. Text is escaped.\n * Optional `link` must be https or same-origin.\n */\n announcement?: ThemeAnnouncement;\n /** Footer configuration */\n footer?: ThemeFooter;\n /** Social links configuration */\n socialLinks?: SocialLinks;\n sidebar?: SidebarItem[];\n /** Embedded HTML content at specific positions */\n embed?: ThemeEmbed;\n /**\n * Extra `--octc-*` custom properties for light mode, keyed without the\n * prefix. Merged key-by-key across composed layers, so a later layer can\n * restyle one token without redeclaring the rest.\n */\n tokens?: ThemeTokens;\n /** Extra `--octc-*` custom properties for dark mode. */\n darkTokens?: ThemeTokens;\n /**\n * Additional custom CSS. Composed layers **concatenate** this rather than\n * overwrite, so stacking a skin and a color scheme keeps both stylesheets.\n */\n css?: string;\n /** Additional custom JavaScript. Concatenated across composed layers. */\n js?: string;\n}\n\n/**\n * Resolved theme configuration (after merging with defaults).\n */\nexport interface ResolvedThemeConfig {\n name: string;\n viewTransitions: boolean;\n aside: boolean;\n breadcrumbs: boolean;\n headingPermalink: \"hover\" | \"always\";\n colors: ThemeColors;\n darkColors: ThemeColors;\n fonts: ThemeFonts;\n entryPage: ThemeEntryPage;\n layout: ThemeLayout;\n header: ThemeHeader;\n nav?: HeaderNavItem[];\n announcement?: ThemeAnnouncement;\n footer: ThemeFooter;\n socialLinks: SocialLinks;\n sidebar: SidebarItem[];\n embed: ThemeEmbed;\n tokens: ThemeTokens;\n darkTokens: ThemeTokens;\n css: string;\n js: string;\n}\n\n/**\n * Default theme configuration.\n * Based on the current ox-content SSG styles.\n */\nexport const defaultTheme: ThemeConfig = {\n name: \"default\",\n viewTransitions: true,\n aside: false,\n breadcrumbs: false,\n headingPermalink: \"hover\",\n colors: {\n primary: \"#4f6fae\",\n primaryHover: \"#425f96\",\n background: \"#ffffff\",\n backgroundAlt: \"#f5f7fb\",\n text: \"#131a30\",\n textMuted: \"#4f607b\",\n border: \"#d2dbea\",\n codeBackground: \"#101a31\",\n codeBackgroundTop: \"#18264a\",\n codeText: \"#edf3ff\",\n },\n darkColors: {\n primary: \"#86a4da\",\n primaryHover: \"#a3bbe8\",\n background: \"#060816\",\n backgroundAlt: \"#0d1528\",\n text: \"#ebf2ff\",\n textMuted: \"#8ea0bf\",\n border: \"#223252\",\n codeBackground: \"#0a1020\",\n codeBackgroundTop: \"#0a1020\",\n codeText: \"#e7f0ff\",\n },\n fonts: {\n sans: '\"IBM Plex Sans\", \"Avenir Next\", \"Segoe UI Variable\", \"Segoe UI\", sans-serif',\n mono: '\"IBM Plex Mono\", \"SFMono-Regular\", Consolas, monospace',\n },\n entryPage: {\n mode: \"default\",\n },\n layout: {\n sidebarWidth: \"260px\",\n headerHeight: \"60px\",\n maxContentWidth: \"960px\",\n },\n header: {\n logo: undefined,\n logoLight: undefined,\n logoDark: undefined,\n showSiteNameText: true,\n logoWidth: 28,\n logoHeight: 28,\n },\n footer: {\n message: undefined,\n copyright: undefined,\n },\n socialLinks: {},\n embed: {},\n tokens: {},\n darkTokens: {},\n css: \"\",\n js: \"\",\n};\n\n/**\n * Deep merge two objects.\n */\nfunction deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue !== undefined &&\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === \"object\" &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n ) as T[keyof T];\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Defines a theme configuration with type checking.\n *\n * @example\n * ```ts\n * const myTheme = defineTheme({\n * extends: defaultTheme,\n * colors: {\n * primary: '#3498db',\n * },\n * footer: {\n * copyright: '2025 My Company',\n * },\n * });\n * ```\n */\nexport function defineTheme(config: ThemeConfig): ThemeConfig {\n return config;\n}\n\n/**\n * Merges multiple theme configurations.\n * Later themes override earlier ones.\n *\n * Object fields (`colors`, `tokens`, `layout`, …) merge key-by-key, but `css`\n * and `js` **concatenate** in layer order — overwriting them would throw away\n * one half of a `[skin, colorScheme]` stack. Identical fragments are joined\n * once, so a layer reached through both an array and an `extends` chain does\n * not emit its stylesheet twice.\n *\n * @example\n * ```ts\n * const merged = mergeThemes(defaultTheme, pixelSkin, tokyoNight, overrides);\n * ```\n */\nexport function mergeThemes(...themes: (ThemeConfig | ThemeConfig[])[]): ThemeConfig {\n const layers = themes.flat();\n if (layers.length === 0) {\n return { ...defaultTheme };\n }\n\n let result: ThemeConfig = {};\n\n for (const theme of layers) {\n const { css, js, ...rest } = theme;\n result = deepMerge(\n result as Record<string, unknown>,\n rest as Record<string, unknown>,\n ) as ThemeConfig;\n\n const mergedCss = appendSource(result.css, css);\n if (mergedCss) {\n result.css = mergedCss;\n }\n const mergedJs = appendSource(result.js, js);\n if (mergedJs) {\n result.js = mergedJs;\n }\n }\n\n return result;\n}\n\nfunction appendSource(existing: string | undefined, addition: string | undefined): string {\n const next = addition?.trim() ?? \"\";\n const current = existing ?? \"\";\n if (!next || current.includes(next)) {\n return current;\n }\n return current ? `${current}\\n${next}` : next;\n}\n\n/**\n * Resolves a theme configuration by merging with its extends chain and defaults.\n *\n * An array composes independent layers left to right, which is how a skin\n * package and a color package are stacked:\n *\n * ```ts\n * resolveTheme([pixelSkin, tokyoNight, { footer: { copyright: \"2026\" } }]);\n * ```\n */\nexport function resolveTheme(config?: ThemeConfig | ThemeConfig[]): ResolvedThemeConfig {\n const layers = config === undefined ? [defaultTheme] : Array.isArray(config) ? config : [config];\n const chain = layers.flatMap(expandExtendsChain);\n\n // Always start with default theme\n if (chain.length === 0) {\n chain.push(defaultTheme);\n }\n if (chain[0] !== defaultTheme && chain[0]?.name !== \"default\") {\n chain.unshift(defaultTheme);\n }\n\n // Merge all themes in the chain\n const merged = mergeThemes(...chain.map(withDerivedCodeBackgroundTop));\n\n // Return resolved config with all required fields\n return {\n name: merged.name ?? \"custom\",\n viewTransitions: merged.viewTransitions ?? defaultTheme.viewTransitions ?? true,\n aside: merged.aside ?? defaultTheme.aside ?? false,\n breadcrumbs: resolveThemeFlag(merged.breadcrumbs),\n headingPermalink: merged.headingPermalink === \"always\" ? \"always\" : \"hover\",\n colors: merged.colors ?? defaultTheme.colors!,\n darkColors: merged.darkColors ?? defaultTheme.darkColors!,\n fonts: merged.fonts ?? defaultTheme.fonts!,\n entryPage: merged.entryPage ?? defaultTheme.entryPage!,\n layout: merged.layout ?? defaultTheme.layout!,\n header: merged.header ?? defaultTheme.header!,\n nav: merged.nav,\n announcement: merged.announcement,\n footer: merged.footer ?? defaultTheme.footer!,\n socialLinks: merged.socialLinks ?? defaultTheme.socialLinks!,\n sidebar: merged.sidebar ?? [],\n embed: merged.embed ?? {},\n tokens: merged.tokens ?? {},\n darkTokens: merged.darkTokens ?? {},\n css: merged.css ?? \"\",\n js: merged.js ?? \"\",\n };\n}\n\n/**\n * Flattens one layer's `extends` chain into base-first order.\n *\n * The `seen` guard keeps a theme that accidentally extends itself (or forms a\n * cycle through two packages) from hanging the build.\n */\nfunction expandExtendsChain(config: ThemeConfig): ThemeConfig[] {\n const chain: ThemeConfig[] = [];\n const seen = new Set<ThemeConfig>();\n let current: ThemeConfig | undefined = config;\n\n while (current && !seen.has(current)) {\n seen.add(current);\n chain.unshift(current);\n current = current.extends;\n }\n\n return chain;\n}\n\nfunction withDerivedCodeBackgroundTop(theme: ThemeConfig): ThemeConfig {\n const derive = (colors: ThemeColors | undefined): ThemeColors | undefined => {\n if (colors?.codeBackground !== undefined && colors.codeBackgroundTop === undefined) {\n return { ...colors, codeBackgroundTop: colors.codeBackground };\n }\n return colors;\n };\n\n return {\n ...theme,\n colors: derive(theme.colors),\n darkColors: derive(theme.darkColors),\n };\n}\n\n/**\n * Converts resolved theme to the format expected by Rust NAPI.\n */\nexport function themeToNapi(\n theme: ResolvedThemeConfig,\n locale?: string,\n base?: string,\n iconsEnabled = false,\n): NapiThemeConfig {\n const socialLinks = socialLinksToNapi(theme.socialLinks);\n\n return {\n viewTransitions: theme.viewTransitions,\n aside: theme.aside,\n breadcrumbs: theme.breadcrumbs,\n headingPermalink: theme.headingPermalink,\n colors: theme.colors.primary\n ? {\n primary: theme.colors.primary,\n primaryHover: theme.colors.primaryHover,\n background: theme.colors.background,\n backgroundAlt: theme.colors.backgroundAlt,\n text: theme.colors.text,\n textMuted: theme.colors.textMuted,\n border: theme.colors.border,\n codeBackground: theme.colors.codeBackground,\n codeBackgroundTop: theme.colors.codeBackgroundTop,\n codeText: theme.colors.codeText,\n }\n : undefined,\n darkColors: theme.darkColors.primary\n ? {\n primary: theme.darkColors.primary,\n primaryHover: theme.darkColors.primaryHover,\n background: theme.darkColors.background,\n backgroundAlt: theme.darkColors.backgroundAlt,\n text: theme.darkColors.text,\n textMuted: theme.darkColors.textMuted,\n border: theme.darkColors.border,\n codeBackground: theme.darkColors.codeBackground,\n codeBackgroundTop: theme.darkColors.codeBackgroundTop,\n codeText: theme.darkColors.codeText,\n }\n : undefined,\n fonts: flattenThemeFonts(theme.fonts),\n entryPage: theme.entryPage.mode\n ? {\n mode: theme.entryPage.mode,\n }\n : undefined,\n layout: theme.layout.sidebarWidth\n ? {\n sidebarWidth: theme.layout.sidebarWidth,\n headerHeight: theme.layout.headerHeight,\n maxContentWidth: theme.layout.maxContentWidth,\n }\n : undefined,\n header:\n theme.header.logo || theme.header.logoLight || theme.header.logoDark\n ? {\n logo: theme.header.logo,\n logoLight: theme.header.logoLight,\n logoDark: theme.header.logoDark,\n showSiteNameText: theme.header.showSiteNameText,\n logoWidth: theme.header.logoWidth,\n logoHeight: theme.header.logoHeight,\n }\n : undefined,\n nav: resolveHeaderNavItems(theme.nav, locale),\n announcement: theme.announcement?.text ? theme.announcement : undefined,\n footer:\n theme.footer.message || theme.footer.copyright\n ? {\n message: theme.footer.message,\n copyright: theme.footer.copyright,\n }\n : undefined,\n socialLinks,\n embed: withSelfHostedIconHead(\n withSelfHostedFontHead(theme.embed, theme.fonts, base),\n iconsEnabled,\n base,\n ),\n css: themeCss(theme) || undefined,\n js: theme.js || undefined,\n };\n}\n\n/**\n * Token blocks come first so a theme's own `css` stays the final word, and both\n * land after the typed color variables the Rust renderer emits.\n */\nfunction themeCss(theme: ResolvedThemeConfig): string {\n const tokenCss = tokensToCss(theme.tokens, theme.darkTokens);\n const namedCss = namedFontVarsCss(theme.fonts);\n const prefix = [tokenCss, namedCss].filter(Boolean).join(\"\\n\");\n if (!prefix) {\n return theme.css;\n }\n return theme.css ? `${prefix}\\n${theme.css}` : prefix;\n}\n\nfunction socialLinksToNapi(links: SocialLinks): NapiSocialLinks | undefined {\n if (Array.isArray(links)) {\n const items = links.map((item) => {\n const icon = typeof item.icon === \"string\" ? item.icon : undefined;\n const iconSvg = typeof item.icon === \"object\" ? item.icon.svg : undefined;\n return { icon, iconSvg, link: item.link, ariaLabel: item.ariaLabel };\n });\n return items.length > 0 ? { links: items } : undefined;\n }\n\n return links.github || links.twitter || links.discord\n ? { github: links.github, twitter: links.twitter, discord: links.discord }\n : undefined;\n}\n\n/**\n * NAPI-compatible theme colors type.\n */\nexport interface NapiThemeColors {\n primary?: string;\n primaryHover?: string;\n background?: string;\n backgroundAlt?: string;\n text?: string;\n textMuted?: string;\n border?: string;\n codeBackground?: string;\n codeBackgroundTop?: string;\n codeText?: string;\n}\n\n/**\n * NAPI-compatible theme fonts type.\n */\nexport interface NapiThemeFonts {\n sans?: string;\n mono?: string;\n}\n\n/**\n * NAPI-compatible entry page theme type.\n */\nexport interface NapiThemeEntryPage {\n mode?: \"default\" | \"subtle\";\n}\n\n/**\n * NAPI-compatible theme layout type.\n */\nexport interface NapiThemeLayout {\n sidebarWidth?: string;\n headerHeight?: string;\n maxContentWidth?: string;\n}\n\n/**\n * NAPI-compatible theme header type.\n */\nexport interface NapiThemeHeader {\n logo?: string;\n logoLight?: string;\n logoDark?: string;\n showSiteNameText?: boolean;\n logoWidth?: number;\n logoHeight?: number;\n}\n\n/**\n * NAPI-compatible theme footer type.\n */\nexport interface NapiThemeFooter {\n message?: string;\n copyright?: string;\n}\n\n/**\n * NAPI-compatible social links type.\n */\nexport interface NapiSocialLinks {\n github?: string;\n twitter?: string;\n discord?: string;\n links?: NapiSocialLink[];\n}\n\nexport interface NapiSocialLink {\n icon?: string;\n iconSvg?: string;\n link: string;\n ariaLabel?: string;\n}\n\n/**\n * NAPI-compatible theme embed type.\n */\nexport interface NapiThemeEmbed {\n head?: string;\n headerBefore?: string;\n headerAfter?: string;\n sidebarBefore?: string;\n sidebarAfter?: string;\n contentBefore?: string;\n contentAfter?: string;\n footerBefore?: string;\n footer?: string;\n}\n\nfunction resolveThemeFlag(value: boolean | Record<string, unknown> | undefined): boolean {\n return value === true || (typeof value === \"object\" && value !== null);\n}\n\n/**\n * NAPI-compatible theme configuration type.\n */\nexport interface NapiThemeConfig {\n /** Progressive cross-document transitions for same-origin MPA navigation. */\n viewTransitions?: boolean;\n /** Right-hand \"On this page\" outline. */\n aside?: boolean;\n /** Breadcrumb trail from the site root through sidebar ancestors. */\n breadcrumbs?: boolean;\n /** Heading permalink visibility. CSS only. */\n headingPermalink?: \"hover\" | \"always\";\n nav?: ResolvedHeaderNavItem[];\n announcement?: ThemeAnnouncement;\n colors?: NapiThemeColors;\n darkColors?: NapiThemeColors;\n fonts?: NapiThemeFonts;\n entryPage?: NapiThemeEntryPage;\n layout?: NapiThemeLayout;\n header?: NapiThemeHeader;\n footer?: NapiThemeFooter;\n socialLinks?: NapiSocialLinks;\n embed?: NapiThemeEmbed;\n css?: string;\n js?: string;\n}\n","import { importNapiModuleSync } from \"./napi\";\nimport { defineTheme, mergeThemes, type ThemeConfig } from \"./theme\";\nimport type { OxContentOptions, SsgNavigationGroup, SsgNavigationItem } from \"./types\";\n\nexport interface VitePressLogo {\n light?: string;\n dark?: string;\n src?: string;\n alt?: string;\n}\n\nexport interface VitePressSocialLink {\n icon: string;\n link: string;\n ariaLabel?: string;\n}\n\nexport interface VitePressFooter {\n message?: string;\n copyright?: string;\n}\n\nexport interface VitePressSidebarItem {\n text?: string;\n link?: string;\n items?: VitePressSidebarItem[];\n collapsed?: boolean;\n}\n\nexport type VitePressSidebar = VitePressSidebarItem[] | Record<string, VitePressSidebarItem[]>;\n\nexport interface VitePressNavItem {\n text?: string;\n link?: string;\n items?: VitePressNavItem[];\n activeMatch?: string;\n}\n\nexport interface VitePressThemeConfig {\n siteTitle?: string | false;\n logo?: string | VitePressLogo;\n nav?: VitePressNavItem[];\n sidebar?: VitePressSidebar;\n socialLinks?: VitePressSocialLink[];\n footer?: VitePressFooter;\n search?: {\n placeholder?: string;\n };\n}\n\nexport interface VitePressConfig {\n title?: string;\n description?: string;\n base?: string;\n themeConfig?: VitePressThemeConfig;\n}\n\nexport interface GenerateVitePressMigrationConfigOptions {\n importSource?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isExternalLink(value: string): boolean {\n return /^[a-z][a-z0-9+.-]*:/i.test(value) || value.startsWith(\"//\");\n}\n\nfunction splitLink(value: string): { pathname: string; suffix: string } {\n const match = /^([^?#]*)([?#].*)?$/.exec(value);\n return {\n pathname: match?.[1] ?? value,\n suffix: match?.[2] ?? \"\",\n };\n}\n\nfunction normalizeInternalPath(value: string): string {\n const { pathname } = splitLink(value.trim());\n let normalized = pathname || \"/\";\n\n if (!normalized.startsWith(\"/\")) {\n normalized = `/${normalized}`;\n }\n\n normalized = normalized\n .replace(/\\/index(?:\\.(?:html?|md|markdown))?$/i, \"/\")\n .replace(/\\.(?:html?|md|markdown)$/i, \"\");\n\n if (normalized !== \"/\") {\n normalized = normalized.replace(/\\/+$/, \"\");\n }\n\n return normalized || \"/\";\n}\n\nfunction formatTitle(value: string): string {\n return value\n .replace(/[-_]([a-z])/g, (_, char: string) => ` ${char.toUpperCase()}`)\n .replace(/^[a-z]/, (char) => char.toUpperCase());\n}\n\nfunction titleFromPath(value: string): string {\n const normalized = normalizeInternalPath(value);\n if (normalized === \"/\") {\n return \"Home\";\n }\n\n const segment = normalized.split(\"/\").filter(Boolean).pop() ?? \"Page\";\n return formatTitle(segment);\n}\n\nfunction titleFromSidebarKey(value: string): string {\n const segment = value\n .replace(/^\\/+|\\/+$/g, \"\")\n .split(\"/\")\n .filter(Boolean)\n .pop();\n return formatTitle(segment ?? \"guide\");\n}\n\nfunction toNavigationItem(text: string | undefined, link: string): SsgNavigationItem {\n const title = text?.trim() || titleFromPath(link);\n\n if (isExternalLink(link) || link.startsWith(\"#\")) {\n return { title, href: link };\n }\n\n const { suffix } = splitLink(link);\n const path = normalizeInternalPath(link);\n\n return suffix ? { title, path, href: `${path}${suffix}` } : { title, path };\n}\n\nfunction dedupeNavigationItems(items: SsgNavigationItem[]): SsgNavigationItem[] {\n const seen = new Set<string>();\n const next: SsgNavigationItem[] = [];\n\n for (const item of items) {\n const key = `${item.title}::${item.path ?? \"\"}::${item.href ?? \"\"}`;\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n next.push(item);\n }\n\n return next;\n}\n\nfunction dedupeNavigationGroups(groups: SsgNavigationGroup[]): SsgNavigationGroup[] {\n const merged = new Map<string, SsgNavigationItem[]>();\n const orderedTitles: string[] = [];\n\n for (const group of groups) {\n if (group.items.length === 0) {\n continue;\n }\n\n if (!merged.has(group.title)) {\n merged.set(group.title, []);\n orderedTitles.push(group.title);\n }\n\n merged.get(group.title)!.push(...group.items);\n }\n\n return orderedTitles.map((title) => ({\n title,\n items: dedupeNavigationItems(merged.get(title) ?? []),\n }));\n}\n\nfunction collectSidebarLinks(items: VitePressSidebarItem[]): SsgNavigationItem[] {\n const links: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n links.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n links.push(...collectSidebarLinks(item.items));\n }\n }\n\n return dedupeNavigationItems(links);\n}\n\nfunction sidebarArrayToGroups(\n items: VitePressSidebarItem[],\n fallbackTitle: string,\n): SsgNavigationGroup[] {\n const groups: SsgNavigationGroup[] = [];\n const rootItems: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n rootItems.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n const children = collectSidebarLinks(item.items);\n if (children.length > 0) {\n groups.push({\n title: item.text?.trim() || fallbackTitle,\n items: children,\n });\n }\n }\n }\n\n if (rootItems.length > 0) {\n groups.unshift({\n title: fallbackTitle,\n items: dedupeNavigationItems(rootItems),\n });\n }\n\n return groups;\n}\n\nfunction collectNavLinks(items: VitePressNavItem[]): SsgNavigationItem[] {\n const links: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n links.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n links.push(...collectNavLinks(item.items));\n }\n }\n\n return dedupeNavigationItems(links);\n}\n\nfunction resolveLogoSrc(logo: string | VitePressLogo | undefined): string | undefined {\n if (!logo) {\n return undefined;\n }\n\n if (typeof logo === \"string\") {\n return logo;\n }\n\n return logo.light ?? logo.dark ?? logo.src;\n}\n\nfunction normalizeSocialIcon(icon: string): \"github\" | \"twitter\" | \"discord\" | undefined {\n const normalized = icon.trim().toLowerCase();\n\n if (normalized === \"github\") return \"github\";\n if (normalized === \"discord\") return \"discord\";\n if (normalized === \"twitter\" || normalized === \"x\" || normalized === \"x-twitter\") {\n return \"twitter\";\n }\n\n return undefined;\n}\n\nfunction toThemeConfig(themeConfig: VitePressThemeConfig | undefined): ThemeConfig | undefined {\n if (!themeConfig) {\n return undefined;\n }\n\n const logo = resolveLogoSrc(themeConfig.logo);\n const socialLinks = Object.fromEntries(\n (themeConfig.socialLinks ?? [])\n .map((link) => {\n const key = normalizeSocialIcon(link.icon);\n return key ? [key, link.link] : null;\n })\n .filter((entry): entry is [string, string] => entry !== null),\n );\n\n const theme: ThemeConfig = {\n ...(logo\n ? {\n header: {\n logo,\n },\n }\n : {}),\n ...(themeConfig.footer?.message || themeConfig.footer?.copyright\n ? {\n footer: {\n message: themeConfig.footer.message,\n copyright: themeConfig.footer.copyright,\n },\n }\n : {}),\n ...(Object.keys(socialLinks).length > 0\n ? {\n socialLinks,\n }\n : {}),\n };\n\n return logo || Object.keys(socialLinks).length > 0 || themeConfig.footer\n ? defineTheme(theme)\n : undefined;\n}\n\nfunction resolveSiteName(config: VitePressConfig): string | undefined {\n const siteTitle = config.themeConfig?.siteTitle;\n if (typeof siteTitle === \"string\" && siteTitle.trim()) {\n return siteTitle;\n }\n\n return config.title;\n}\n\nfunction mergeOxContentOptions(\n baseOptions: OxContentOptions,\n overrides: OxContentOptions,\n): OxContentOptions {\n const mergedSsg =\n overrides.ssg === false\n ? false\n : {\n ...(typeof baseOptions.ssg === \"object\" ? baseOptions.ssg : {}),\n ...(typeof overrides.ssg === \"object\" ? overrides.ssg : {}),\n theme:\n typeof baseOptions.ssg === \"object\" &&\n typeof overrides.ssg === \"object\" &&\n baseOptions.ssg.theme &&\n overrides.ssg.theme\n ? defineTheme(mergeThemes(baseOptions.ssg.theme, overrides.ssg.theme))\n : typeof overrides.ssg === \"object\" && overrides.ssg.theme\n ? overrides.ssg.theme\n : typeof baseOptions.ssg === \"object\"\n ? baseOptions.ssg.theme\n : undefined,\n };\n\n const mergedSearch =\n overrides.search === false\n ? false\n : typeof overrides.search === \"object\"\n ? {\n ...(typeof baseOptions.search === \"object\" ? baseOptions.search : {}),\n ...overrides.search,\n }\n : baseOptions.search;\n\n return {\n ...baseOptions,\n ...overrides,\n ssg: mergedSsg,\n search: mergedSearch,\n };\n}\n\n/**\n * Converts a VitePress sidebar config into ox-content navigation groups.\n * Nested VitePress items are flattened into the nearest ox-content group.\n */\nexport function convertVitePressSidebar(sidebar: VitePressSidebar): SsgNavigationGroup[] {\n if (Array.isArray(sidebar)) {\n return dedupeNavigationGroups(sidebarArrayToGroups(sidebar, \"Guide\"));\n }\n\n const groups = Object.entries(sidebar).flatMap(([key, items]) =>\n sidebarArrayToGroups(items, titleFromSidebarKey(key)),\n );\n\n return dedupeNavigationGroups(groups);\n}\n\n/**\n * Converts VitePress top navigation into ox-content sidebar groups.\n * This is used as a fallback when no explicit sidebar is defined.\n */\nexport function convertVitePressNav(nav: VitePressNavItem[]): SsgNavigationGroup[] {\n const groups: SsgNavigationGroup[] = [];\n const rootItems: SsgNavigationItem[] = [];\n\n for (const item of nav) {\n if (item.link) {\n rootItems.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n const children = collectNavLinks(item.items);\n if (children.length > 0) {\n groups.push({\n title: item.text?.trim() || \"Navigation\",\n items: children,\n });\n }\n }\n }\n\n if (rootItems.length > 0) {\n groups.unshift({\n title: \"Navigation\",\n items: dedupeNavigationItems(rootItems),\n });\n }\n\n return dedupeNavigationGroups(groups);\n}\n\n/**\n * Creates ox-content plugin options from an existing VitePress config.\n */\nexport function fromVitePressConfig(\n config: VitePressConfig,\n overrides: OxContentOptions = {},\n): OxContentOptions {\n const theme = toThemeConfig(config.themeConfig);\n const navigation = config.themeConfig?.sidebar\n ? convertVitePressSidebar(config.themeConfig.sidebar)\n : config.themeConfig?.nav\n ? convertVitePressNav(config.themeConfig.nav)\n : undefined;\n\n const migrated: OxContentOptions = {\n ...(config.base ? { base: config.base } : {}),\n ...(config.themeConfig?.search?.placeholder\n ? {\n search: {\n placeholder: config.themeConfig.search.placeholder,\n },\n }\n : {}),\n ssg: {\n ...(resolveSiteName(config) ? { siteName: resolveSiteName(config) } : {}),\n ...(theme ? { theme } : {}),\n ...(navigation ? { navigation } : {}),\n },\n };\n\n return mergeOxContentOptions(migrated, overrides);\n}\n\n/**\n * Generates a TypeScript module exporting migrated ox-content options.\n *\n * This is used by the migration CLI so users can inspect and edit the resulting\n * object instead of keeping a runtime dependency on their VitePress config.\n */\nexport function generateVitePressMigrationConfig(\n config: VitePressConfig,\n overrides: OxContentOptions = {},\n options: GenerateVitePressMigrationConfigOptions = {},\n): string {\n const importSource = options.importSource ?? \"@ox-content/vite-plugin\";\n const migrated = fromVitePressConfig(config, overrides);\n\n return `import type { OxContentOptions } from ${JSON.stringify(importSource)};\n\nconst config = ${formatTsValue(migrated)} satisfies OxContentOptions;\n\nexport default config;\n`;\n}\n\nfunction formatTsValue(value: unknown, depth = 0): string {\n if (value === undefined) {\n return \"undefined\";\n }\n\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\") {\n return JSON.stringify(value);\n }\n\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return \"[]\";\n }\n\n const indent = \" \".repeat(depth + 1);\n const closingIndent = \" \".repeat(depth);\n return `[\\n${value.map((item) => `${indent}${formatTsValue(item, depth + 1)},`).join(\"\\n\")}\\n${closingIndent}]`;\n }\n\n if (isRecord(value)) {\n const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== undefined);\n if (entries.length === 0) {\n return \"{}\";\n }\n\n const indent = \" \".repeat(depth + 1);\n const closingIndent = \" \".repeat(depth);\n return `{\\n${entries\n .map(\n ([key, entryValue]) =>\n `${indent}${formatObjectKey(key)}: ${formatTsValue(entryValue, depth + 1)},`,\n )\n .join(\"\\n\")}\\n${closingIndent}}`;\n }\n\n return \"undefined\";\n}\n\nfunction formatObjectKey(key: string): string {\n return /^[A-Za-z_$][\\w$]*$/.test(key) ? key : JSON.stringify(key);\n}\n\n/**\n * Normalizes VitePress-specific frontmatter into ox-content's entry-page shape.\n */\nexport function normalizeVitePressFrontmatter(\n frontmatter: Record<string, unknown>,\n): Record<string, unknown> {\n return importNapiModuleSync().normalizeVitePressFrontmatter(frontmatter);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vitepress.cjs","names":["createRequire","join","stat","readFile","isAbsolute","resolve","existsSync","readdir","mkdir","createHash","writeFile","join","mkdir","writeFile","join","existsSync","createRequire","readFile","join","mkdir","writeFile","readFile","renderThemeTokenCss"],"sources":["../src/napi.ts","../src/theme-fonts-acquire.ts","../src/theme-fonts.ts","../src/icons-css.ts","../src/icons.ts","../src/header-chrome.ts","../src/theme.ts","../src/vitepress.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\ntype NapiModule = typeof import(\"@ox-content/napi\");\nconst requireNapi = createRequire(import.meta.url);\n\nfunction getDefaultExport(value: unknown): object | undefined {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return undefined;\n }\n\n const defaultExport = value.default;\n return defaultExport && typeof defaultExport === \"object\" ? defaultExport : undefined;\n}\n\nfunction normalizeNapiModule(mod: NapiModule): NapiModule {\n const defaultExport = getDefaultExport(mod);\n return defaultExport\n ? ({\n ...defaultExport,\n ...mod,\n } as NapiModule)\n : mod;\n}\n\nexport async function importNapiModule(): Promise<NapiModule> {\n return normalizeNapiModule((await import(\"@ox-content/napi\")) as NapiModule);\n}\n\nlet syncNapiModule: NapiModule | null | undefined;\n\nexport function importNapiModuleSync(): NapiModule {\n if (syncNapiModule) {\n return syncNapiModule;\n }\n\n if (syncNapiModule === null) {\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n\n try {\n const mod = requireNapi(\"@ox-content/napi\") as NapiModule;\n syncNapiModule = normalizeNapiModule(mod);\n return syncNapiModule;\n } catch {\n syncNapiModule = null;\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n}\n","/**\n * Resolve self-hosted faces from a local file / `@fontsource` directory or\n * Google Fonts. Downloads are cached; tests inject `fetch` so CI never hits\n * the network.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport type { PlannedSelfHostFace, WriteThemeFontsOptions } from \"./theme-fonts\";\n\nexport type FontFetch = (input: string, init?: RequestInit) => Promise<Response>;\n\nconst GOOGLE_CSS = \"https://fonts.googleapis.com/css2\";\nconst GOOGLE_UA =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\";\nconst ALLOWED_HOSTS = new Set([\"fonts.googleapis.com\", \"fonts.gstatic.com\"]);\n\nexport interface AcquiredSelfHostFace extends PlannedSelfHostFace {\n bytes: Uint8Array;\n}\n\nexport function fontMime(fileName: string): string {\n if (fileName.endsWith(\".woff\")) {\n return \"font/woff\";\n }\n if (fileName.endsWith(\".ttf\")) {\n return \"font/ttf\";\n }\n if (fileName.endsWith(\".otf\")) {\n return \"font/otf\";\n }\n return \"font/woff2\";\n}\n\nexport function renderFontFaceCss(faces: AcquiredSelfHostFace[]): string {\n return faces\n .map((face) => {\n const range = face.unicodeRange ? `\\n unicode-range: ${face.unicodeRange};` : \"\";\n const fileName = face.fileName;\n const format = fileName.endsWith(\".woff\")\n ? \"woff\"\n : fileName.endsWith(\".ttf\")\n ? \"truetype\"\n : fileName.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n const family = /^[a-zA-Z_-][\\w-]*$/.test(face.family)\n ? face.family\n : `\"${face.family.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n return `@font-face {\n font-family: ${family};\n font-style: ${face.style};\n font-weight: ${face.weight};\n font-display: ${face.display};\n src: url(./${fileName}) format(\"${format}\");${range}\n}`;\n })\n .join(\"\\n\\n\");\n}\n\nexport function resolveFontCacheDir(root: string, cacheDir?: string): string {\n return cacheDir ?? join(root, \"node_modules\", \".cache\", \"ox-content\", \"fonts\");\n}\n\nexport async function acquireSelfHostedFaces(\n faces: PlannedSelfHostFace[],\n options: WriteThemeFontsOptions,\n): Promise<AcquiredSelfHostFace[]> {\n const cacheDir = resolveFontCacheDir(options.root, options.cacheDir);\n const acquired: AcquiredSelfHostFace[] = [];\n for (const face of faces) {\n acquired.push(\n face.provider === \"local\"\n ? await acquireLocalFace(face, options.root)\n : await acquireGoogleFace(face, cacheDir, options.fetch ?? fetch),\n );\n }\n return acquired;\n}\n\nasync function acquireLocalFace(\n face: PlannedSelfHostFace,\n root: string,\n): Promise<AcquiredSelfHostFace> {\n if (!face.path) {\n throw new Error(`Theme font \"${face.family}\" uses provider \"local\" but has no path.`);\n }\n if (face.path.includes(\"\\0\")) {\n throw new Error(`Theme font \"${face.family}\" path must not contain NUL.`);\n }\n const resolved = resolveLocalPath(root, face.path);\n const info = await stat(resolved).catch(() => undefined);\n if (!info) {\n throw new Error(`Theme font \"${face.family}\" was not found at ${resolved}.`);\n }\n const file = info.isDirectory() ? await findDirectoryFont(resolved, face) : resolved;\n return { ...face, bytes: await readFile(file) };\n}\n\nfunction resolveLocalPath(root: string, spec: string): string {\n if (isAbsolute(spec)) {\n return spec;\n }\n if (spec.startsWith(\"@\") || !spec.startsWith(\".\")) {\n return resolve(root, \"node_modules\", spec);\n }\n return resolve(root, spec);\n}\n\nasync function findDirectoryFont(dir: string, face: PlannedSelfHostFace): Promise<string> {\n const filesDir = existsSync(join(dir, \"files\")) ? join(dir, \"files\") : dir;\n const names = (await readdir(filesDir)).filter((name) => /\\.(woff2|woff|ttf|otf)$/i.test(name));\n const weight = String(face.weight);\n const wantItalic = face.style === \"italic\";\n const match = names.find((name) => {\n const lower = name.toLowerCase();\n const hasWeight = lower.includes(weight);\n const italic = lower.includes(\"italic\");\n const subset = face.subset === \"all\" || lower.includes(face.subset.toLowerCase());\n return hasWeight && subset && italic === wantItalic;\n });\n const fallback = names[0];\n const chosen = match ?? (names.length === 1 ? fallback : undefined);\n if (!chosen) {\n throw new Error(\n `Theme font \"${face.family}\" has no ${face.weight} ${face.style} ${face.subset} file in ${filesDir}.`,\n );\n }\n return join(filesDir, chosen);\n}\n\nasync function acquireGoogleFace(\n face: PlannedSelfHostFace,\n cacheDir: string,\n fetchFn: FontFetch,\n): Promise<AcquiredSelfHostFace> {\n const css = await cachedText(googleCssUrl(face), cacheDir, fetchFn, \".css\");\n const parsed = parseGoogleCss(css).find(\n (entry) =>\n entry.weight === face.weight &&\n entry.style === face.style &&\n (entry.subset === face.subset || !entry.subset),\n );\n if (!parsed) {\n throw new Error(\n `Google Fonts CSS for \"${face.family}\" has no ${face.weight} ${face.style} ${face.subset} face.`,\n );\n }\n const bytes = await cachedBytes(parsed.url, cacheDir, fetchFn, \".woff2\");\n return { ...face, bytes, unicodeRange: face.unicodeRange ?? parsed.unicodeRange };\n}\n\nexport function googleCssUrl(face: PlannedSelfHostFace): string {\n const italic = face.style === \"italic\";\n const axis = italic ? \"ital,wght\" : \"wght\";\n const spec = italic ? `1,${face.weight}` : `${face.weight}`;\n const family = `${face.family.replace(/ /g, \"+\")}:${axis}@${spec}`;\n return `${GOOGLE_CSS}?family=${family}&display=${encodeURIComponent(face.display)}`;\n}\n\ninterface ParsedGoogleFace {\n subset: string;\n weight: number;\n style: \"normal\" | \"italic\";\n url: string;\n unicodeRange?: string;\n}\n\nexport function parseGoogleCss(css: string): ParsedGoogleFace[] {\n const faces: ParsedGoogleFace[] = [];\n const blocks = css.matchAll(/\\/\\*\\s*([a-z0-9-]+)\\s*\\*\\/\\s*@font-face\\s*\\{([^}]+)\\}/gi);\n for (const match of blocks) {\n const parsed = parseGoogleBlock(match[2] ?? \"\", match[1]?.toLowerCase() ?? \"\");\n if (parsed) {\n faces.push(parsed);\n }\n }\n if (faces.length === 0) {\n for (const match of css.matchAll(/@font-face\\s*\\{([^}]+)\\}/gi)) {\n const parsed = parseGoogleBlock(match[1] ?? \"\", \"\");\n if (parsed) {\n faces.push(parsed);\n }\n }\n }\n return faces;\n}\n\nfunction parseGoogleBlock(body: string, subset: string): ParsedGoogleFace | undefined {\n const url = body.match(/url\\((['\"]?)(https?:\\/\\/[^'\")]+)\\1\\)/)?.[2];\n if (!url || !isAllowedFontUrl(url)) {\n return undefined;\n }\n const weight = Number(body.match(/font-weight:\\s*(\\d+)/i)?.[1] ?? 400);\n const style = /font-style:\\s*italic/i.test(body) ? \"italic\" : \"normal\";\n return {\n subset,\n weight,\n style,\n url,\n unicodeRange: body.match(/unicode-range:\\s*([^;]+)/i)?.[1]?.trim(),\n };\n}\n\nfunction isAllowedFontUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"https:\" && ALLOWED_HOSTS.has(parsed.hostname);\n } catch {\n return false;\n }\n}\n\nasync function cachedText(\n url: string,\n cacheDir: string,\n fetchFn: FontFetch,\n ext: string,\n): Promise<string> {\n const bytes = await cachedBytes(url, cacheDir, fetchFn, ext);\n return new TextDecoder().decode(bytes);\n}\n\nasync function cachedBytes(\n url: string,\n cacheDir: string,\n fetchFn: FontFetch,\n ext: string,\n): Promise<Uint8Array> {\n if (!isAllowedFontUrl(url)) {\n throw new Error(`Refusing to download font from ${url}.`);\n }\n await mkdir(cacheDir, { recursive: true });\n const dest = join(\n cacheDir,\n `${createHash(\"sha256\").update(url).digest(\"hex\").slice(0, 16)}${ext}`,\n );\n if (existsSync(dest)) {\n return readFile(dest);\n }\n const response = await fetchFn(url, { headers: { \"User-Agent\": GOOGLE_UA } });\n if (!response.ok) {\n throw new Error(`Failed to download ${url}: ${response.status}`);\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n await writeFile(dest, bytes);\n return bytes;\n}\n","/**\n * Opt-in web-font objects for `theme.fonts`, plus SSG self-host emission.\n *\n * NAPI still receives flattened CSS stacks (`JsThemeFonts`). File acquisition\n * and `@font-face` generation stay in TypeScript so other PRs can keep landing\n * NAPI theme-type changes independently.\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n acquireSelfHostedFaces,\n fontMime,\n renderFontFaceCss,\n type FontFetch,\n} from \"./theme-fonts-acquire\";\n\nexport const FONT_ASSET_DIR = \"__ox_fonts__\";\nexport const FONT_CSS_NAME = \"fonts.css\";\n\nexport type ThemeFontProvider = \"google\" | \"local\";\nexport type ThemeFontStyle = \"normal\" | \"italic\";\nexport type ThemeFontDisplay = \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n\n/** UnoCSS-inspired family descriptor. The string stack form remains valid. */\nexport interface ThemeWebFont {\n /** Family name, e.g. `\"Inter\"` or `\"DM Mono\"`. */\n family: string;\n /** Defaults to `\"local\"` when `path` is set, otherwise `\"google\"`. */\n provider?: ThemeFontProvider;\n /** File, directory, or `@fontsource/*` package. Required for `local`. */\n path?: string;\n weights?: number[];\n styles?: ThemeFontStyle[];\n subsets?: string[];\n display?: ThemeFontDisplay;\n /** Copy files into the SSG output and emit `@font-face`. */\n selfHost?: boolean;\n /** Extra families after `family` in the emitted CSS stack. */\n fallbacks?: string[];\n /** Preload every self-hosted face, or only these weights. */\n preload?: boolean | number[];\n /** Optional `unicode-range` for local faces. */\n unicodeRange?: string;\n}\n\nexport type ThemeFontValue = string | ThemeWebFont;\n\nexport interface ThemeFontsLike {\n sans?: ThemeFontValue;\n mono?: ThemeFontValue;\n named?: Record<string, ThemeFontValue>;\n}\n\nexport interface WriteThemeFontsOptions {\n fonts: ThemeFontsLike;\n outDir: string;\n root: string;\n cacheDir?: string;\n fetch?: FontFetch;\n}\n\nconst NAMED_FONT_PATTERN = /^[a-z][a-z0-9-]*$/;\nconst GENERIC_FOR = { sans: \"sans-serif\", mono: \"monospace\", named: \"sans-serif\" } as const;\n\nexport function isThemeWebFont(value: ThemeFontValue | undefined): value is ThemeWebFont {\n return typeof value === \"object\" && value !== null && typeof value.family === \"string\";\n}\n\n/** CSS `font-family` identifier; quotes names that are not a single ident. */\nexport function cssFamilyName(family: string): string {\n const trimmed = family.trim();\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed;\n }\n if (/^[a-zA-Z_-][\\w-]*$/.test(trimmed)) {\n return trimmed;\n }\n return `\"${trimmed.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nexport function flattenThemeFont(\n value: ThemeFontValue | undefined,\n generic: string,\n): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value === \"string\") {\n return value;\n }\n const fallbacks = value.fallbacks?.length ? value.fallbacks.join(\", \") : generic;\n return `${cssFamilyName(value.family)}, ${fallbacks}`;\n}\n\n/** Flatten object fonts so `JsThemeFonts` stays `{ sans?: string; mono?: string }`. */\nexport function flattenThemeFonts(\n fonts: ThemeFontsLike,\n): { sans?: string; mono?: string } | undefined {\n const sans = flattenThemeFont(fonts.sans, GENERIC_FOR.sans);\n const mono = flattenThemeFont(fonts.mono, GENERIC_FOR.mono);\n if (!sans && !mono) {\n return undefined;\n }\n return { sans, mono };\n}\n\nexport function namedFontToken(name: string): string {\n if (!NAMED_FONT_PATTERN.test(name)) {\n throw new Error(\n `Invalid theme font name: ${JSON.stringify(name)}. ` +\n `Named fonts are lowercase kebab-case (e.g. \"code\").`,\n );\n }\n return name;\n}\n\n/** Extra `--octc-font-*` variables for `fonts.named`. Roles stay in Rust theme CSS. */\nexport function namedFontVarsCss(fonts: ThemeFontsLike): string {\n const entries = Object.entries(fonts.named ?? {});\n if (entries.length === 0) {\n return \"\";\n }\n const lines = entries.map(([name, value]) => {\n const stack = flattenThemeFont(value, GENERIC_FOR.named);\n return ` --octc-font-${namedFontToken(name)}: ${stack};`;\n });\n return `:root {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\nexport function normalizeBasePath(base: string | undefined): string {\n if (!base || base === \"/\") {\n return \"/\";\n }\n return base.endsWith(\"/\") ? base : `${base}/`;\n}\n\nexport function plannedFontFileName(\n family: string,\n weight: number,\n style: ThemeFontStyle,\n subset: string,\n extension: string,\n): string {\n const ext = extension.startsWith(\".\") ? extension : `.${extension}`;\n return `${slugify(family)}-${weight}-${style}-${slugify(subset)}${ext}`;\n}\n\nexport function plannedFontExtension(font: ThemeWebFont): string {\n if (\n font.provider === \"local\" &&\n font.path &&\n /\\.\\w+$/.test(font.path) &&\n !font.path.endsWith(\"/\")\n ) {\n const match = font.path.match(/(\\.\\w+)$/);\n return match?.[1] ?? \".woff2\";\n }\n return \".woff2\";\n}\n\nexport interface PlannedSelfHostFace {\n family: string;\n weight: number;\n style: ThemeFontStyle;\n subset: string;\n display: ThemeFontDisplay;\n preload: boolean;\n provider: ThemeFontProvider;\n path?: string;\n fileName: string;\n unicodeRange?: string;\n}\n\nexport function planSelfHostedFaces(fonts: ThemeFontsLike): PlannedSelfHostFace[] {\n const faces: PlannedSelfHostFace[] = [];\n for (const value of themeFontValues(fonts)) {\n if (!isThemeWebFont(value) || !value.selfHost) {\n continue;\n }\n const font = normalizeWebFont(value);\n const extension = plannedFontExtension(font);\n for (const weight of font.weights) {\n for (const style of font.styles) {\n for (const subset of font.subsets) {\n faces.push({\n family: font.family,\n weight,\n style,\n subset,\n display: font.display,\n preload: shouldPreload(font.preload, weight),\n provider: font.provider,\n path: font.path,\n fileName: plannedFontFileName(font.family, weight, style, subset, extension),\n unicodeRange: font.unicodeRange,\n });\n }\n }\n }\n }\n const unique = new Map<string, PlannedSelfHostFace>();\n for (const face of faces) {\n const existing = unique.get(face.fileName);\n if (existing) {\n existing.preload ||= face.preload;\n } else {\n unique.set(face.fileName, face);\n }\n }\n return [...unique.values()];\n}\n\nexport function themeFontHeadHtml(fonts: ThemeFontsLike, base?: string): string {\n const faces = planSelfHostedFaces(fonts);\n if (faces.length === 0) {\n return \"\";\n }\n const root = normalizeBasePath(base);\n const tags = [`<link rel=\"stylesheet\" href=\"${root}${FONT_ASSET_DIR}/${FONT_CSS_NAME}\">`];\n for (const face of faces) {\n if (!face.preload) {\n continue;\n }\n tags.push(\n `<link rel=\"preload\" href=\"${root}${FONT_ASSET_DIR}/${face.fileName}\" as=\"font\" type=\"${fontMime(face.fileName)}\" crossorigin>`,\n );\n }\n return tags.join(\"\\n\");\n}\n\nexport function withSelfHostedFontHead<T extends { head?: string }>(\n embed: T,\n fonts: ThemeFontsLike,\n base?: string,\n): T | undefined {\n const extra = themeFontHeadHtml(fonts, base);\n const keys = Object.keys(embed);\n if (!extra && keys.length === 0) {\n return undefined;\n }\n if (!extra) {\n return embed;\n }\n return { ...embed, head: embed.head ? `${extra}\\n${embed.head}` : extra };\n}\n\n/** Copy self-hosted faces into `outDir` and write `@font-face` CSS. */\nexport async function writeSelfHostedThemeFonts(\n options: WriteThemeFontsOptions,\n): Promise<string[]> {\n const faces = planSelfHostedFaces(options.fonts);\n if (faces.length === 0) {\n return [];\n }\n const acquired = await acquireSelfHostedFaces(faces, options);\n const destDir = join(options.outDir, FONT_ASSET_DIR);\n await mkdir(destDir, { recursive: true });\n const written: string[] = [];\n for (const face of acquired) {\n const dest = join(destDir, face.fileName);\n await writeFile(dest, face.bytes);\n written.push(dest);\n }\n const cssPath = join(destDir, FONT_CSS_NAME);\n await writeFile(cssPath, renderFontFaceCss(acquired), \"utf8\");\n written.push(cssPath);\n return written;\n}\n\nfunction themeFontValues(fonts: ThemeFontsLike): ThemeFontValue[] {\n return [fonts.sans, fonts.mono, ...Object.values(fonts.named ?? {})].filter(\n (value): value is ThemeFontValue => value !== undefined,\n );\n}\n\nfunction normalizeWebFont(\n font: ThemeWebFont,\n): Required<\n Pick<ThemeWebFont, \"family\" | \"provider\" | \"weights\" | \"styles\" | \"subsets\" | \"display\">\n> &\n ThemeWebFont {\n const provider = font.provider ?? (font.path ? \"local\" : \"google\");\n if (provider === \"local\" && !font.path) {\n throw new Error(`Theme font \"${font.family}\" uses provider \"local\" but has no path.`);\n }\n return {\n ...font,\n family: font.family.trim(),\n provider,\n weights: font.weights?.length ? font.weights : [400],\n styles: font.styles?.length ? font.styles : [\"normal\"],\n subsets: font.subsets?.length ? font.subsets : [\"latin\"],\n display: font.display ?? \"swap\",\n };\n}\n\nfunction shouldPreload(preload: ThemeWebFont[\"preload\"], weight: number): boolean {\n if (preload === true) {\n return true;\n }\n return Array.isArray(preload) && preload.includes(weight);\n}\n\nfunction slugify(value: string): string {\n const slug = value\n .trim()\n .toLowerCase()\n .replace(/['\"]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n return slug || \"font\";\n}\n","/**\n * Resolve Iconify JSON collections and emit CSS-mask rules.\n *\n * Collections come from installed `@iconify-json/*` or `@iconify/json`.\n * Tests supply fixture JSON under the project `root` — no network.\n */\n\nimport { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface IconifyIcon {\n body: string;\n width?: number;\n height?: number;\n}\n\nexport interface IconifyJSON {\n prefix?: string;\n width?: number;\n height?: number;\n icons: Record<string, IconifyIcon>;\n aliases?: Record<string, { parent: string; width?: number; height?: number }>;\n}\n\nexport interface ResolvedIcon {\n prefix: string;\n name: string;\n body: string;\n width: number;\n height: number;\n multicolor: boolean;\n}\n\nexport function iconClassName(prefix: string, name: string): string {\n return `icon-[${prefix}--${name}]`;\n}\n\nexport function iconCssSelector(prefix: string, name: string): string {\n return `.icon-\\\\[${prefix}--${name}\\\\]`;\n}\n\nexport function resolveIconCollectionPath(prefix: string, root: string): string | undefined {\n const files = [\n join(root, \"node_modules\", \"@iconify-json\", prefix, \"icons.json\"),\n join(root, \"node_modules\", \"@iconify\", \"json\", \"json\", `${prefix}.json`),\n ];\n for (const file of files) {\n if (existsSync(file)) {\n return file;\n }\n }\n return resolveViaNode(prefix, root);\n}\n\nfunction resolveViaNode(prefix: string, root: string): string | undefined {\n try {\n return createRequire(join(root, \"package.json\")).resolve(`@iconify-json/${prefix}/icons.json`);\n } catch {\n try {\n return createRequire(join(root, \"package.json\")).resolve(`@iconify/json/json/${prefix}.json`);\n } catch {\n return undefined;\n }\n }\n}\n\nexport async function loadIconCollection(\n prefix: string,\n root: string,\n): Promise<IconifyJSON | undefined> {\n const path = resolveIconCollectionPath(prefix, root);\n if (!path) {\n return undefined;\n }\n const raw = await readFile(path, \"utf8\");\n return JSON.parse(raw) as IconifyJSON;\n}\n\nexport function lookupIcon(\n collection: IconifyJSON,\n name: string,\n): { body: string; width: number; height: number } | undefined {\n const fallback = collection.width ?? 16;\n const fallbackH = collection.height ?? fallback;\n const direct = collection.icons[name];\n if (direct) {\n return {\n body: direct.body,\n width: direct.width ?? fallback,\n height: direct.height ?? fallbackH,\n };\n }\n const alias = collection.aliases?.[name];\n if (!alias) {\n return undefined;\n }\n const parent = collection.icons[alias.parent];\n if (!parent) {\n return undefined;\n }\n return {\n body: parent.body,\n width: alias.width ?? parent.width ?? fallback,\n height: alias.height ?? parent.height ?? fallbackH,\n };\n}\n\nexport function isMulticolorIcon(body: string): boolean {\n return /(?:fill|stroke)=[\"'](?!currentColor|none)[^\"']+[\"']/i.test(body);\n}\n\nexport function renderIconsCss(icons: ResolvedIcon[]): string {\n const rules = icons.map(renderOneIconCss);\n return `/* ox-content self-hosted Iconify icons */\\n${rules.join(\"\\n\")}\\n`;\n}\n\nfunction renderOneIconCss(icon: ResolvedIcon): string {\n const selector = iconCssSelector(icon.prefix, icon.name);\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${icon.width} ${icon.height}\">${maskBody(icon)}</svg>`;\n const url = svgToDataUrl(svg);\n if (icon.multicolor) {\n return `${selector}{display:inline-block;width:1em;height:1em;background-color:transparent;background-image:${url};background-repeat:no-repeat;background-size:100% 100%}`;\n }\n return `${selector}{display:inline-block;width:1em;height:1em;background-color:currentColor;-webkit-mask-image:${url};mask-image:${url};-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%}`;\n}\n\nfunction maskBody(icon: ResolvedIcon): string {\n return icon.multicolor ? icon.body : icon.body.replace(/currentColor/g, \"black\");\n}\n\nfunction svgToDataUrl(svg: string): string {\n const encoded = svg\n .replace(/\"/g, \"'\")\n .replace(/%/g, \"%25\")\n .replace(/#/g, \"%23\")\n .replace(/</g, \"%3C\")\n .replace(/>/g, \"%3E\")\n .replace(/\\s+/g, \" \");\n return `url(\"data:image/svg+xml,${encoded}\")`;\n}\n","/**\n * Opt-in self-hosted Iconify CSS for used and safelisted icons.\n *\n * Collection lookup stays on disk (`@iconify-json/*` / `@iconify/json`).\n * Theme embed injection composes with self-hosted font `<link>` tags.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { IconsOptions, ResolvedIconsOptions } from \"./types\";\nimport { normalizeBasePath } from \"./theme-fonts\";\nimport {\n iconClassName,\n isMulticolorIcon,\n loadIconCollection,\n lookupIcon,\n renderIconsCss,\n type ResolvedIcon,\n} from \"./icons-css\";\n\nexport const ICON_ASSET_DIR = \"__ox_icons__\";\nexport const ICON_CSS_NAME = \"icons.css\";\n\nconst URL_SCHEMES = new Set([\n \"http\",\n \"https\",\n \"data\",\n \"mailto\",\n \"file\",\n \"javascript\",\n \"vscode\",\n \"tel\",\n \"blob\",\n]);\n\nconst COLON_ICON = /(?<![A-Za-z0-9_-])([a-z][a-z0-9-]*):([a-z0-9][a-z0-9-]*)/gi;\nconst CLASS_ICON = /icon-\\[([a-z][a-z0-9-]*)--([a-z0-9][a-z0-9-]*)\\]/gi;\nconst ICON_FIELD = /(?:^|[\\s,{])icon\\s*:\\s*[\"']([^\"']+)[\"']/g;\n\nexport function resolveIconsOptions(\n value: boolean | IconsOptions | undefined,\n): ResolvedIconsOptions {\n if (!value) {\n return { enabled: false, mode: \"css-mask\", syntax: \"unocss\", include: [], safelist: [] };\n }\n if (value === true) {\n return { enabled: true, mode: \"css-mask\", syntax: \"unocss\", include: [], safelist: [] };\n }\n return {\n enabled: true,\n mode: value.mode ?? \"css-mask\",\n syntax: value.syntax ?? \"unocss\",\n include: value.include ?? [],\n safelist: value.safelist ?? [],\n };\n}\n\nexport interface ParsedIconName {\n prefix: string;\n name: string;\n}\n\nexport function parseIconName(value: string): ParsedIconName | undefined {\n const trimmed = value.trim();\n const classMatch = /^icon-\\[(.+)\\]$/.exec(trimmed);\n if (classMatch?.[1]) {\n const inner = classMatch[1];\n const sep = inner.indexOf(\"--\");\n if (sep <= 0) {\n return undefined;\n }\n return tokenPair(inner.slice(0, sep), inner.slice(sep + 2));\n }\n const sep = trimmed.indexOf(\":\");\n if (sep <= 0) {\n return undefined;\n }\n return tokenPair(trimmed.slice(0, sep), trimmed.slice(sep + 1));\n}\n\nexport function normalizeIconName(value: string): string {\n const parsed = parseIconName(value);\n return parsed ? `${parsed.prefix}:${parsed.name}` : value;\n}\n\nfunction tokenPair(prefix: string, name: string): ParsedIconName | undefined {\n if (!/^[a-z][a-z0-9-]*$/i.test(prefix) || !/^[a-z0-9][a-z0-9-]*$/i.test(name)) {\n return undefined;\n }\n if (URL_SCHEMES.has(prefix.toLowerCase())) {\n return undefined;\n }\n return { prefix, name };\n}\n\nexport function collectIconNamesFromText(text: string, into: Set<string> = new Set()): Set<string> {\n COLON_ICON.lastIndex = 0;\n for (const match of text.matchAll(COLON_ICON)) {\n addParsed(into, match[1], match[2]);\n }\n CLASS_ICON.lastIndex = 0;\n for (const match of text.matchAll(CLASS_ICON)) {\n addParsed(into, match[1], match[2]);\n }\n return into;\n}\n\nexport function collectIconFieldNames(text: string, into: Set<string> = new Set()): Set<string> {\n ICON_FIELD.lastIndex = 0;\n for (const match of text.matchAll(ICON_FIELD)) {\n const parsed = match[1] ? parseIconName(match[1]) : undefined;\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n }\n return into;\n}\n\nexport function collectThemeIconNames(socialLinks: unknown): string[] {\n if (!Array.isArray(socialLinks)) {\n return [];\n }\n const names: string[] = [];\n for (const link of socialLinks) {\n if (!link || typeof link !== \"object\") {\n continue;\n }\n const icon = (link as { icon?: unknown }).icon;\n if (typeof icon === \"string\" && parseIconName(icon)) {\n names.push(normalizeIconName(icon));\n }\n }\n return names;\n}\n\nfunction addParsed(into: Set<string>, prefix: string | undefined, name: string | undefined): void {\n if (!prefix || !name) {\n return;\n }\n const parsed = tokenPair(prefix, name);\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n}\n\nexport function iconStylesheetHref(base?: string): string {\n return `${normalizeBasePath(base)}${ICON_ASSET_DIR}/${ICON_CSS_NAME}`;\n}\n\nexport function iconStylesheetLink(base?: string): string {\n return `<link rel=\"stylesheet\" href=\"${iconStylesheetHref(base)}\">`;\n}\n\nexport function withSelfHostedIconHead<T extends { head?: string }>(\n embed: T | undefined,\n enabled: boolean,\n base?: string,\n): T | { head: string } | undefined {\n if (!enabled) {\n return embed;\n }\n const extra = iconStylesheetLink(base);\n if (!embed) {\n return { head: extra };\n }\n return { ...embed, head: embed.head ? `${extra}\\n${embed.head}` : extra };\n}\n\nexport interface WriteSelfHostedIconsOptions {\n options: ResolvedIconsOptions;\n outDir: string;\n root: string;\n srcDir?: string;\n socialLinks?: unknown;\n}\n\nexport interface WriteSelfHostedIconsResult {\n files: string[];\n errors: string[];\n names: string[];\n}\n\n/** Copy resolved icon CSS into `outDir`. Missing collections or names become errors. */\nexport async function writeSelfHostedIcons(\n input: WriteSelfHostedIconsOptions,\n): Promise<WriteSelfHostedIconsResult> {\n if (!input.options.enabled) {\n return { files: [], errors: [], names: [] };\n }\n const names = await collectResolvedIconNames(input);\n const { icons, errors } = await resolveIconBodies(names, input.root);\n const destDir = join(input.outDir, ICON_ASSET_DIR);\n await mkdir(destDir, { recursive: true });\n const cssPath = join(destDir, ICON_CSS_NAME);\n await writeFile(cssPath, renderIconsCss(icons), \"utf8\");\n return { files: [cssPath], errors, names };\n}\n\nexport { iconClassName };\n\nasync function collectResolvedIconNames(input: WriteSelfHostedIconsOptions): Promise<string[]> {\n const names = new Set<string>();\n for (const item of input.options.safelist) {\n addName(names, item);\n }\n for (const item of collectThemeIconNames(input.socialLinks)) {\n names.add(item);\n }\n const { names: includeNames, globs } = partitionInclude(input.options.include);\n for (const item of includeNames) {\n names.add(item);\n }\n for (const pattern of globs) {\n const files = await glob(pattern, {\n cwd: input.root,\n nodir: true,\n absolute: true,\n ignore: [\"**/node_modules/**\"],\n });\n for (const file of files) {\n collectIconNamesFromText(await readFile(file, \"utf8\"), names);\n }\n }\n if (input.srcDir) {\n const files = await glob(\"**/*.{md,mdx,markdown}\", {\n cwd: input.srcDir,\n nodir: true,\n absolute: true,\n ignore: [\"**/node_modules/**\"],\n });\n for (const file of files) {\n collectIconFieldNames(await readFile(file, \"utf8\"), names);\n }\n }\n return [...names].sort();\n}\n\nfunction partitionInclude(include: string[]): { names: string[]; globs: string[] } {\n const names: string[] = [];\n const globs: string[] = [];\n for (const entry of include) {\n if (parseIconName(entry)) {\n names.push(normalizeIconName(entry));\n } else {\n globs.push(entry);\n }\n }\n return { names, globs };\n}\n\nfunction addName(into: Set<string>, value: string): void {\n const parsed = parseIconName(value);\n if (parsed) {\n into.add(`${parsed.prefix}:${parsed.name}`);\n }\n}\n\nasync function resolveIconBodies(\n names: string[],\n root: string,\n): Promise<{ icons: ResolvedIcon[]; errors: string[] }> {\n const icons: ResolvedIcon[] = [];\n const errors: string[] = [];\n const collections = new Map<string, Awaited<ReturnType<typeof loadIconCollection>>>();\n for (const id of names) {\n const parsed = parseIconName(id);\n if (!parsed) {\n continue;\n }\n if (!collections.has(parsed.prefix)) {\n collections.set(parsed.prefix, await loadIconCollection(parsed.prefix, root));\n }\n const collection = collections.get(parsed.prefix);\n if (!collection) {\n errors.push(\n `[ox-content] icons: missing Iconify collection \"${parsed.prefix}\". Install @iconify-json/${parsed.prefix} or @iconify/json.`,\n );\n continue;\n }\n const found = lookupIcon(collection, parsed.name);\n if (!found) {\n errors.push(\n `[ox-content] icons: missing icon \"${parsed.prefix}:${parsed.name}\" in collection \"${parsed.prefix}\".`,\n );\n continue;\n }\n icons.push({\n prefix: parsed.prefix,\n name: parsed.name,\n body: found.body,\n width: found.width,\n height: found.height,\n multicolor: isMulticolorIcon(found.body),\n });\n }\n return { icons, errors };\n}\n","/**\n * Opt-in header nav, announcement, and per-page chrome helpers.\n */\n\n/** Plain label or locale map (`{ en: \"Guide\", ja: \"ガイド\" }`). */\nexport type LocaleLabel = string | Record<string, string>;\n\n/** Header nav link or dropdown. */\nexport interface HeaderNavItem {\n text: LocaleLabel;\n link?: string;\n items?: HeaderNavItem[];\n}\n\n/** Announcement bar. Text is escaped; no raw HTML slot. */\nexport interface ThemeAnnouncement {\n text: string;\n /** https or same-origin only. */\n link?: string;\n /** Best-effort localStorage key for dismiss. */\n dismissKey?: string;\n}\n\n/** Per-page frontmatter chrome flags. `false` hides that region. */\nexport interface PageChromeFlags {\n sidebar?: boolean;\n outline?: boolean;\n aside?: boolean;\n footer?: boolean;\n navbar?: boolean;\n lastUpdated?: boolean;\n editLink?: boolean;\n}\n\n/** `false` or omitted stays off. `true` or `{}` enables default flag reading. */\nexport function resolvePageChromeOption(\n value: boolean | Record<string, unknown> | undefined,\n): boolean {\n return value === true || (typeof value === \"object\" && value !== null);\n}\n\n/** Reads hide flags from frontmatter. Non-boolean values are ignored. */\nexport function parsePageChromeFlags(frontmatter: Record<string, unknown>): PageChromeFlags {\n return {\n sidebar: readBool(frontmatter.sidebar),\n outline: readBool(frontmatter.outline),\n aside: readBool(frontmatter.aside),\n footer: readBool(frontmatter.footer),\n navbar: readBool(frontmatter.navbar),\n lastUpdated: readBool(frontmatter.lastUpdated),\n editLink: readBool(frontmatter.editLink),\n };\n}\n\nfunction readBool(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\n/**\n * Picks the exact locale, its language, the default locale, then the first\n * non-empty own string in declaration order.\n */\nexport function resolveLocaleLabel(\n text: LocaleLabel,\n locale?: string,\n defaultLocale?: string,\n): string {\n if (typeof text === \"string\") {\n return text;\n }\n const candidates = [locale, locale?.split(\"-\")[0], defaultLocale, defaultLocale?.split(\"-\")[0]];\n for (const candidate of candidates) {\n if (!candidate || !Object.hasOwn(text, candidate)) {\n continue;\n }\n const value = text[candidate];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n for (const value of Object.values(text)) {\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n return \"\";\n}\n\n/** Nav item after locale maps are flattened to strings. */\nexport interface ResolvedHeaderNavItem {\n text: string;\n link?: string;\n items?: ResolvedHeaderNavItem[];\n}\n\n/** Resolves locale maps so NAPI always receives string labels. */\nexport function resolveHeaderNavItems(\n items: HeaderNavItem[] | undefined,\n locale?: string,\n defaultLocale?: string,\n): ResolvedHeaderNavItem[] | undefined {\n if (!items?.length) {\n return undefined;\n }\n return items.map((item) => ({\n text: resolveLocaleLabel(item.text, locale, defaultLocale),\n link: item.link,\n items: resolveHeaderNavItems(item.items, locale, defaultLocale),\n }));\n}\n","/**\n * Theme API for ox-content SSG\n *\n * Provides VitePress-like theming with default theme + customization.\n */\n\nimport type {\n HeaderNavItem,\n LocaleLabel,\n ResolvedHeaderNavItem,\n ThemeAnnouncement,\n} from \"./header-chrome\";\nimport { resolveHeaderNavItems } from \"./header-chrome\";\nimport {\n flattenThemeFonts,\n namedFontVarsCss,\n withSelfHostedFontHead,\n type ThemeFontValue,\n} from \"./theme-fonts\";\nimport { renderThemeTokenCss, type ThemeTokens } from \"./theme-tokens\";\nimport { withSelfHostedIconHead } from \"./icons\";\n\nexport type { HeaderNavItem, LocaleLabel, ThemeAnnouncement } from \"./header-chrome\";\n\nexport type { ThemeFontValue, ThemeWebFont } from \"./theme-fonts\";\nexport type { ThemeTokens, ThemeTokenSource } from \"./theme-tokens\";\n\n/**\n * Theme color configuration.\n */\nexport interface ThemeColors {\n /** Primary accent color */\n primary?: string;\n /** Primary color on hover */\n primaryHover?: string;\n /** Background color */\n background?: string;\n /** Alternative background color (sidebar, code blocks) */\n backgroundAlt?: string;\n /** Main text color */\n text?: string;\n /** Muted/secondary text color */\n textMuted?: string;\n /** Border color */\n border?: string;\n /** Code block background color */\n codeBackground?: string;\n /** Code block gradient color at the top; defaults to `codeBackground` when customized */\n codeBackgroundTop?: string;\n /** Code block text color */\n codeText?: string;\n}\n\n/**\n * Theme layout configuration.\n */\nexport interface ThemeLayout {\n /** Sidebar width (CSS value, e.g., \"260px\") */\n sidebarWidth?: string;\n /** Header height (CSS value, e.g., \"60px\") */\n headerHeight?: string;\n /** Maximum content width (CSS value, e.g., \"960px\") */\n maxContentWidth?: string;\n}\n\n/**\n * Theme font configuration.\n *\n * `sans` and `mono` accept a CSS stack string or a web-font object. Named\n * families are extra stacks exposed as `--octc-font-<name>`.\n */\nexport interface ThemeFonts {\n /** Sans-serif font stack or self-hosted family */\n sans?: ThemeFontValue;\n /** Monospace font stack or self-hosted family */\n mono?: ThemeFontValue;\n /** Additional families, exposed as `--octc-font-<name>` */\n named?: Record<string, ThemeFontValue>;\n}\n\n/**\n * Entry page theme configuration.\n */\nexport interface ThemeEntryPage {\n /** Landing page presentation mode */\n mode?: \"default\" | \"subtle\";\n}\n\n/**\n * Theme header configuration.\n */\nexport interface ThemeHeader {\n /** Logo image URL */\n logo?: string;\n /** Light mode logo image URL */\n logoLight?: string;\n /** Dark mode logo image URL */\n logoDark?: string;\n /** Whether to render the site name text next to the logo */\n showSiteNameText?: boolean;\n /** Logo width in pixels */\n logoWidth?: number;\n /** Logo height in pixels */\n logoHeight?: number;\n}\n\n/**\n * Theme footer configuration.\n */\nexport interface ThemeFooter {\n /** Footer message (supports HTML) */\n message?: string;\n /** Copyright text (supports HTML) */\n copyright?: string;\n}\n\n/** Custom social link icon. */\nexport type SocialLinkIcon = string | { svg: string };\n\n/** Custom social link. */\nexport interface SocialLink {\n icon: SocialLinkIcon;\n link: string;\n ariaLabel?: string;\n}\n\n/** Legacy social links configuration. */\nexport interface LegacySocialLinks {\n /** GitHub URL */\n github?: string;\n /** Twitter/X URL */\n twitter?: string;\n /** Discord URL */\n discord?: string;\n}\n\n/** Social links configuration. */\nexport type SocialLinks = LegacySocialLinks | SocialLink[];\n\n/**\n * Embedded HTML content for specific positions in the page layout.\n */\nexport interface ThemeEmbed {\n /** Content to embed into <head> */\n head?: string;\n /** Content before header */\n headerBefore?: string;\n /** Content after header */\n headerAfter?: string;\n /** Content before sidebar navigation */\n sidebarBefore?: string;\n /** Content after sidebar navigation */\n sidebarAfter?: string;\n /** Content before main content */\n contentBefore?: string;\n /** Content after main content */\n contentAfter?: string;\n /** Content before footer */\n footerBefore?: string;\n /** Custom footer content (replaces default footer) */\n footer?: string;\n}\n\n/** Sidebar group or link, including recursively nested localized labels. */\nexport interface SidebarItem {\n /** Plain label or locale map (`{ en: \"Guide\", ja: \"ガイド\" }`). */\n text?: LocaleLabel;\n link?: string;\n items?: SidebarItem[];\n collapsed?: boolean;\n stickyCollapsed?: boolean;\n}\n\n/**\n * Complete theme configuration.\n */\nexport interface ThemeConfig {\n /** Theme name for identification */\n name?: string;\n /** Base theme to extend */\n extends?: ThemeConfig;\n /**\n * Preserve the current surface during same-origin MPA navigation with the\n * browser's cross-document View Transition API.\n *\n * Unsupported browsers use normal navigation. Reduced-motion preferences\n * never enable the transition. Set `false` to opt out.\n *\n * @default true\n */\n viewTransitions?: boolean;\n /**\n * Show the right-hand \"On this page\" outline.\n *\n * Default `false`. When `true`, the outline is rendered only on pages\n * that have TOC entries, using the existing `<aside class=\"toc\">` markup.\n */\n aside?: boolean;\n /**\n * Show a breadcrumb trail from the site root through sidebar ancestors.\n *\n * Default `false`. `true` or an object enables the trail. Frontmatter\n * `breadcrumbs: false` still hides it on that page.\n */\n breadcrumbs?: boolean | Record<string, unknown>;\n /**\n * Heading permalink visibility. CSS only — the renderer HTML stays\n * `<a class=\"header-anchor\" href=\"#id\">`.\n *\n * `\"hover\"` (default) reveals the `#` on hover / focus-visible, and\n * stays visible on touch. `\"always\"` keeps it visible.\n */\n headingPermalink?: \"hover\" | \"always\";\n /** Light mode colors (maps to CSS variables) */\n colors?: ThemeColors;\n /** Dark mode colors (maps to CSS variables) */\n darkColors?: ThemeColors;\n /** Font configuration (maps to CSS variables) */\n fonts?: ThemeFonts;\n /** Entry page configuration */\n entryPage?: ThemeEntryPage;\n /** Layout configuration (maps to CSS variables) */\n layout?: ThemeLayout;\n /** Header configuration */\n header?: ThemeHeader;\n /**\n * Opt-in header nav. Each item is `{ text, link }` or a dropdown\n * `{ text, items }`. Labels are escaped. `javascript:`, `data:`,\n * `vbscript:`, and protocol-relative `//` links are omitted.\n */\n nav?: HeaderNavItem[];\n /**\n * Opt-in announcement bar above the header. Text is escaped.\n * Optional `link` must be https or same-origin.\n */\n announcement?: ThemeAnnouncement;\n /** Footer configuration */\n footer?: ThemeFooter;\n /** Social links configuration */\n socialLinks?: SocialLinks;\n sidebar?: SidebarItem[];\n /** Embedded HTML content at specific positions */\n embed?: ThemeEmbed;\n /**\n * Extra `--octc-*` custom properties for light mode, keyed without the\n * prefix. Merged key-by-key across composed layers, so a later layer can\n * restyle one token without redeclaring the rest.\n */\n tokens?: ThemeTokens;\n /** Extra `--octc-*` custom properties for dark mode. */\n darkTokens?: ThemeTokens;\n /**\n * Additional custom CSS. Composed layers **concatenate** this rather than\n * overwrite, so stacking a skin and a color scheme keeps both stylesheets.\n */\n css?: string;\n /** Additional custom JavaScript. Concatenated across composed layers. */\n js?: string;\n}\n\n/**\n * Resolved theme configuration (after merging with defaults).\n */\nexport interface ResolvedThemeConfig {\n name: string;\n viewTransitions: boolean;\n aside: boolean;\n breadcrumbs: boolean;\n headingPermalink: \"hover\" | \"always\";\n colors: ThemeColors;\n darkColors: ThemeColors;\n fonts: ThemeFonts;\n entryPage: ThemeEntryPage;\n layout: ThemeLayout;\n header: ThemeHeader;\n nav?: HeaderNavItem[];\n announcement?: ThemeAnnouncement;\n footer: ThemeFooter;\n socialLinks: SocialLinks;\n sidebar: SidebarItem[];\n embed: ThemeEmbed;\n tokens: ThemeTokens;\n darkTokens: ThemeTokens;\n css: string;\n js: string;\n}\n\n/**\n * Default theme configuration.\n * Based on the current ox-content SSG styles.\n */\nexport const defaultTheme: ThemeConfig = {\n name: \"default\",\n viewTransitions: true,\n aside: false,\n breadcrumbs: false,\n headingPermalink: \"hover\",\n colors: {\n primary: \"#4f6fae\",\n primaryHover: \"#425f96\",\n background: \"#ffffff\",\n backgroundAlt: \"#f5f7fb\",\n text: \"#131a30\",\n textMuted: \"#4f607b\",\n border: \"#d2dbea\",\n codeBackground: \"#101a31\",\n codeBackgroundTop: \"#18264a\",\n codeText: \"#edf3ff\",\n },\n darkColors: {\n primary: \"#86a4da\",\n primaryHover: \"#a3bbe8\",\n background: \"#060816\",\n backgroundAlt: \"#0d1528\",\n text: \"#ebf2ff\",\n textMuted: \"#8ea0bf\",\n border: \"#223252\",\n codeBackground: \"#0a1020\",\n codeBackgroundTop: \"#0a1020\",\n codeText: \"#e7f0ff\",\n },\n fonts: {\n sans: '\"IBM Plex Sans\", \"Avenir Next\", \"Segoe UI Variable\", \"Segoe UI\", sans-serif',\n mono: '\"IBM Plex Mono\", \"SFMono-Regular\", Consolas, monospace',\n },\n entryPage: {\n mode: \"default\",\n },\n layout: {\n sidebarWidth: \"260px\",\n headerHeight: \"60px\",\n maxContentWidth: \"960px\",\n },\n header: {\n logo: undefined,\n logoLight: undefined,\n logoDark: undefined,\n showSiteNameText: true,\n logoWidth: 28,\n logoHeight: 28,\n },\n footer: {\n message: undefined,\n copyright: undefined,\n },\n socialLinks: {},\n embed: {},\n tokens: {},\n darkTokens: {},\n css: \"\",\n js: \"\",\n};\n\n/**\n * Deep merge two objects.\n */\nfunction deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue !== undefined &&\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === \"object\" &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n ) as T[keyof T];\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Defines a theme configuration with type checking.\n *\n * @example\n * ```ts\n * const myTheme = defineTheme({\n * extends: defaultTheme,\n * colors: {\n * primary: '#3498db',\n * },\n * footer: {\n * copyright: '2025 My Company',\n * },\n * });\n * ```\n */\nexport function defineTheme(config: ThemeConfig): ThemeConfig {\n return config;\n}\n\n/**\n * Merges multiple theme configurations.\n * Later themes override earlier ones.\n *\n * Object fields (`colors`, `tokens`, `layout`, …) merge key-by-key, but `css`\n * and `js` **concatenate** in layer order — overwriting them would throw away\n * one half of a `[skin, colorScheme]` stack. Identical fragments are joined\n * once, so a layer reached through both an array and an `extends` chain does\n * not emit its stylesheet twice.\n *\n * @example\n * ```ts\n * const merged = mergeThemes(defaultTheme, pixelSkin, tokyoNight, overrides);\n * ```\n */\nexport function mergeThemes(...themes: (ThemeConfig | ThemeConfig[])[]): ThemeConfig {\n const layers = themes.flat();\n if (layers.length === 0) {\n return { ...defaultTheme };\n }\n\n let result: ThemeConfig = {};\n\n for (const theme of layers) {\n const { css, js, ...rest } = theme;\n result = deepMerge(\n result as Record<string, unknown>,\n rest as Record<string, unknown>,\n ) as ThemeConfig;\n\n const mergedCss = appendSource(result.css, css);\n if (mergedCss) {\n result.css = mergedCss;\n }\n const mergedJs = appendSource(result.js, js);\n if (mergedJs) {\n result.js = mergedJs;\n }\n }\n\n return result;\n}\n\nfunction appendSource(existing: string | undefined, addition: string | undefined): string {\n const next = addition?.trim() ?? \"\";\n const current = existing ?? \"\";\n if (!next || current.includes(next)) {\n return current;\n }\n return current ? `${current}\\n${next}` : next;\n}\n\n/**\n * Resolves a theme configuration by merging with its extends chain and defaults.\n *\n * An array composes independent layers left to right, which is how a skin\n * package and a color package are stacked:\n *\n * ```ts\n * resolveTheme([pixelSkin, tokyoNight, { footer: { copyright: \"2026\" } }]);\n * ```\n */\nexport function resolveTheme(config?: ThemeConfig | ThemeConfig[]): ResolvedThemeConfig {\n const layers = config === undefined ? [defaultTheme] : Array.isArray(config) ? config : [config];\n const chain = layers.flatMap(expandExtendsChain);\n\n // Always start with default theme\n if (chain.length === 0) {\n chain.push(defaultTheme);\n }\n if (chain[0] !== defaultTheme && chain[0]?.name !== \"default\") {\n chain.unshift(defaultTheme);\n }\n\n // Merge all themes in the chain\n const merged = mergeThemes(...chain.map(withDerivedCodeBackgroundTop));\n\n // Return resolved config with all required fields\n return {\n name: merged.name ?? \"custom\",\n viewTransitions: merged.viewTransitions ?? defaultTheme.viewTransitions ?? true,\n aside: merged.aside ?? defaultTheme.aside ?? false,\n breadcrumbs: resolveThemeFlag(merged.breadcrumbs),\n headingPermalink: merged.headingPermalink === \"always\" ? \"always\" : \"hover\",\n colors: merged.colors ?? defaultTheme.colors!,\n darkColors: merged.darkColors ?? defaultTheme.darkColors!,\n fonts: merged.fonts ?? defaultTheme.fonts!,\n entryPage: merged.entryPage ?? defaultTheme.entryPage!,\n layout: merged.layout ?? defaultTheme.layout!,\n header: merged.header ?? defaultTheme.header!,\n nav: merged.nav,\n announcement: merged.announcement,\n footer: merged.footer ?? defaultTheme.footer!,\n socialLinks: merged.socialLinks ?? defaultTheme.socialLinks!,\n sidebar: merged.sidebar ?? [],\n embed: merged.embed ?? {},\n tokens: merged.tokens ?? {},\n darkTokens: merged.darkTokens ?? {},\n css: merged.css ?? \"\",\n js: merged.js ?? \"\",\n };\n}\n\n/**\n * Flattens one layer's `extends` chain into base-first order.\n *\n * The `seen` guard keeps a theme that accidentally extends itself (or forms a\n * cycle through two packages) from hanging the build.\n */\nfunction expandExtendsChain(config: ThemeConfig): ThemeConfig[] {\n const chain: ThemeConfig[] = [];\n const seen = new Set<ThemeConfig>();\n let current: ThemeConfig | undefined = config;\n\n while (current && !seen.has(current)) {\n seen.add(current);\n chain.unshift(current);\n current = current.extends;\n }\n\n return chain;\n}\n\nfunction withDerivedCodeBackgroundTop(theme: ThemeConfig): ThemeConfig {\n const derive = (colors: ThemeColors | undefined): ThemeColors | undefined => {\n if (colors?.codeBackground !== undefined && colors.codeBackgroundTop === undefined) {\n return { ...colors, codeBackgroundTop: colors.codeBackground };\n }\n return colors;\n };\n\n return {\n ...theme,\n colors: derive(theme.colors),\n darkColors: derive(theme.darkColors),\n };\n}\n\n/**\n * Converts resolved theme to the format expected by Rust NAPI.\n */\nexport function themeToNapi(\n theme: ResolvedThemeConfig,\n locale?: string,\n base?: string,\n iconsEnabled = false,\n): NapiThemeConfig {\n const socialLinks = socialLinksToNapi(theme.socialLinks);\n\n return {\n viewTransitions: theme.viewTransitions,\n aside: theme.aside,\n breadcrumbs: theme.breadcrumbs,\n headingPermalink: theme.headingPermalink,\n colors: theme.colors.primary\n ? {\n primary: theme.colors.primary,\n primaryHover: theme.colors.primaryHover,\n background: theme.colors.background,\n backgroundAlt: theme.colors.backgroundAlt,\n text: theme.colors.text,\n textMuted: theme.colors.textMuted,\n border: theme.colors.border,\n codeBackground: theme.colors.codeBackground,\n codeBackgroundTop: theme.colors.codeBackgroundTop,\n codeText: theme.colors.codeText,\n }\n : undefined,\n darkColors: theme.darkColors.primary\n ? {\n primary: theme.darkColors.primary,\n primaryHover: theme.darkColors.primaryHover,\n background: theme.darkColors.background,\n backgroundAlt: theme.darkColors.backgroundAlt,\n text: theme.darkColors.text,\n textMuted: theme.darkColors.textMuted,\n border: theme.darkColors.border,\n codeBackground: theme.darkColors.codeBackground,\n codeBackgroundTop: theme.darkColors.codeBackgroundTop,\n codeText: theme.darkColors.codeText,\n }\n : undefined,\n fonts: flattenThemeFonts(theme.fonts),\n entryPage: theme.entryPage.mode\n ? {\n mode: theme.entryPage.mode,\n }\n : undefined,\n layout: theme.layout.sidebarWidth\n ? {\n sidebarWidth: theme.layout.sidebarWidth,\n headerHeight: theme.layout.headerHeight,\n maxContentWidth: theme.layout.maxContentWidth,\n }\n : undefined,\n header:\n theme.header.logo || theme.header.logoLight || theme.header.logoDark\n ? {\n logo: theme.header.logo,\n logoLight: theme.header.logoLight,\n logoDark: theme.header.logoDark,\n showSiteNameText: theme.header.showSiteNameText,\n logoWidth: theme.header.logoWidth,\n logoHeight: theme.header.logoHeight,\n }\n : undefined,\n nav: resolveHeaderNavItems(theme.nav, locale),\n announcement: theme.announcement?.text ? theme.announcement : undefined,\n footer:\n theme.footer.message || theme.footer.copyright\n ? {\n message: theme.footer.message,\n copyright: theme.footer.copyright,\n }\n : undefined,\n socialLinks,\n embed: withSelfHostedIconHead(\n withSelfHostedFontHead(theme.embed, theme.fonts, base),\n iconsEnabled,\n base,\n ),\n css: themeCss(theme) || undefined,\n js: theme.js || undefined,\n };\n}\n\n/**\n * Token blocks come first so a theme's own `css` stays the final word, and both\n * land after the typed color variables the Rust renderer emits.\n */\nfunction themeCss(theme: ResolvedThemeConfig): string {\n const tokenCss = renderThemeTokenCss(theme);\n const namedCss = namedFontVarsCss(theme.fonts);\n const prefix = [tokenCss, namedCss].filter(Boolean).join(\"\\n\");\n if (!prefix) {\n return theme.css;\n }\n return theme.css ? `${prefix}\\n${theme.css}` : prefix;\n}\n\nfunction socialLinksToNapi(links: SocialLinks): NapiSocialLinks | undefined {\n if (Array.isArray(links)) {\n const items = links.map((item) => {\n const icon = typeof item.icon === \"string\" ? item.icon : undefined;\n const iconSvg = typeof item.icon === \"object\" ? item.icon.svg : undefined;\n return { icon, iconSvg, link: item.link, ariaLabel: item.ariaLabel };\n });\n return items.length > 0 ? { links: items } : undefined;\n }\n\n return links.github || links.twitter || links.discord\n ? { github: links.github, twitter: links.twitter, discord: links.discord }\n : undefined;\n}\n\n/**\n * NAPI-compatible theme colors type.\n */\nexport interface NapiThemeColors {\n primary?: string;\n primaryHover?: string;\n background?: string;\n backgroundAlt?: string;\n text?: string;\n textMuted?: string;\n border?: string;\n codeBackground?: string;\n codeBackgroundTop?: string;\n codeText?: string;\n}\n\n/**\n * NAPI-compatible theme fonts type.\n */\nexport interface NapiThemeFonts {\n sans?: string;\n mono?: string;\n}\n\n/**\n * NAPI-compatible entry page theme type.\n */\nexport interface NapiThemeEntryPage {\n mode?: \"default\" | \"subtle\";\n}\n\n/**\n * NAPI-compatible theme layout type.\n */\nexport interface NapiThemeLayout {\n sidebarWidth?: string;\n headerHeight?: string;\n maxContentWidth?: string;\n}\n\n/**\n * NAPI-compatible theme header type.\n */\nexport interface NapiThemeHeader {\n logo?: string;\n logoLight?: string;\n logoDark?: string;\n showSiteNameText?: boolean;\n logoWidth?: number;\n logoHeight?: number;\n}\n\n/**\n * NAPI-compatible theme footer type.\n */\nexport interface NapiThemeFooter {\n message?: string;\n copyright?: string;\n}\n\n/**\n * NAPI-compatible social links type.\n */\nexport interface NapiSocialLinks {\n github?: string;\n twitter?: string;\n discord?: string;\n links?: NapiSocialLink[];\n}\n\nexport interface NapiSocialLink {\n icon?: string;\n iconSvg?: string;\n link: string;\n ariaLabel?: string;\n}\n\n/**\n * NAPI-compatible theme embed type.\n */\nexport interface NapiThemeEmbed {\n head?: string;\n headerBefore?: string;\n headerAfter?: string;\n sidebarBefore?: string;\n sidebarAfter?: string;\n contentBefore?: string;\n contentAfter?: string;\n footerBefore?: string;\n footer?: string;\n}\n\nfunction resolveThemeFlag(value: boolean | Record<string, unknown> | undefined): boolean {\n return value === true || (typeof value === \"object\" && value !== null);\n}\n\n/**\n * NAPI-compatible theme configuration type.\n */\nexport interface NapiThemeConfig {\n /** Progressive cross-document transitions for same-origin MPA navigation. */\n viewTransitions?: boolean;\n /** Right-hand \"On this page\" outline. */\n aside?: boolean;\n /** Breadcrumb trail from the site root through sidebar ancestors. */\n breadcrumbs?: boolean;\n /** Heading permalink visibility. CSS only. */\n headingPermalink?: \"hover\" | \"always\";\n nav?: ResolvedHeaderNavItem[];\n announcement?: ThemeAnnouncement;\n colors?: NapiThemeColors;\n darkColors?: NapiThemeColors;\n fonts?: NapiThemeFonts;\n entryPage?: NapiThemeEntryPage;\n layout?: NapiThemeLayout;\n header?: NapiThemeHeader;\n footer?: NapiThemeFooter;\n socialLinks?: NapiSocialLinks;\n embed?: NapiThemeEmbed;\n css?: string;\n js?: string;\n}\n","import { importNapiModuleSync } from \"./napi\";\nimport { defineTheme, mergeThemes, type ThemeConfig } from \"./theme\";\nimport type { OxContentOptions, SsgNavigationGroup, SsgNavigationItem } from \"./types\";\n\nexport interface VitePressLogo {\n light?: string;\n dark?: string;\n src?: string;\n alt?: string;\n}\n\nexport interface VitePressSocialLink {\n icon: string;\n link: string;\n ariaLabel?: string;\n}\n\nexport interface VitePressFooter {\n message?: string;\n copyright?: string;\n}\n\nexport interface VitePressSidebarItem {\n text?: string;\n link?: string;\n items?: VitePressSidebarItem[];\n collapsed?: boolean;\n}\n\nexport type VitePressSidebar = VitePressSidebarItem[] | Record<string, VitePressSidebarItem[]>;\n\nexport interface VitePressNavItem {\n text?: string;\n link?: string;\n items?: VitePressNavItem[];\n activeMatch?: string;\n}\n\nexport interface VitePressThemeConfig {\n siteTitle?: string | false;\n logo?: string | VitePressLogo;\n nav?: VitePressNavItem[];\n sidebar?: VitePressSidebar;\n socialLinks?: VitePressSocialLink[];\n footer?: VitePressFooter;\n search?: {\n placeholder?: string;\n };\n}\n\nexport interface VitePressConfig {\n title?: string;\n description?: string;\n base?: string;\n themeConfig?: VitePressThemeConfig;\n}\n\nexport interface GenerateVitePressMigrationConfigOptions {\n importSource?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isExternalLink(value: string): boolean {\n return /^[a-z][a-z0-9+.-]*:/i.test(value) || value.startsWith(\"//\");\n}\n\nfunction splitLink(value: string): { pathname: string; suffix: string } {\n const match = /^([^?#]*)([?#].*)?$/.exec(value);\n return {\n pathname: match?.[1] ?? value,\n suffix: match?.[2] ?? \"\",\n };\n}\n\nfunction normalizeInternalPath(value: string): string {\n const { pathname } = splitLink(value.trim());\n let normalized = pathname || \"/\";\n\n if (!normalized.startsWith(\"/\")) {\n normalized = `/${normalized}`;\n }\n\n normalized = normalized\n .replace(/\\/index(?:\\.(?:html?|md|markdown))?$/i, \"/\")\n .replace(/\\.(?:html?|md|markdown)$/i, \"\");\n\n if (normalized !== \"/\") {\n normalized = normalized.replace(/\\/+$/, \"\");\n }\n\n return normalized || \"/\";\n}\n\nfunction formatTitle(value: string): string {\n return value\n .replace(/[-_]([a-z])/g, (_, char: string) => ` ${char.toUpperCase()}`)\n .replace(/^[a-z]/, (char) => char.toUpperCase());\n}\n\nfunction titleFromPath(value: string): string {\n const normalized = normalizeInternalPath(value);\n if (normalized === \"/\") {\n return \"Home\";\n }\n\n const segment = normalized.split(\"/\").filter(Boolean).pop() ?? \"Page\";\n return formatTitle(segment);\n}\n\nfunction titleFromSidebarKey(value: string): string {\n const segment = value\n .replace(/^\\/+|\\/+$/g, \"\")\n .split(\"/\")\n .filter(Boolean)\n .pop();\n return formatTitle(segment ?? \"guide\");\n}\n\nfunction toNavigationItem(text: string | undefined, link: string): SsgNavigationItem {\n const title = text?.trim() || titleFromPath(link);\n\n if (isExternalLink(link) || link.startsWith(\"#\")) {\n return { title, href: link };\n }\n\n const { suffix } = splitLink(link);\n const path = normalizeInternalPath(link);\n\n return suffix ? { title, path, href: `${path}${suffix}` } : { title, path };\n}\n\nfunction dedupeNavigationItems(items: SsgNavigationItem[]): SsgNavigationItem[] {\n const seen = new Set<string>();\n const next: SsgNavigationItem[] = [];\n\n for (const item of items) {\n const key = `${item.title}::${item.path ?? \"\"}::${item.href ?? \"\"}`;\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n next.push(item);\n }\n\n return next;\n}\n\nfunction dedupeNavigationGroups(groups: SsgNavigationGroup[]): SsgNavigationGroup[] {\n const merged = new Map<string, SsgNavigationItem[]>();\n const orderedTitles: string[] = [];\n\n for (const group of groups) {\n if (group.items.length === 0) {\n continue;\n }\n\n if (!merged.has(group.title)) {\n merged.set(group.title, []);\n orderedTitles.push(group.title);\n }\n\n merged.get(group.title)!.push(...group.items);\n }\n\n return orderedTitles.map((title) => ({\n title,\n items: dedupeNavigationItems(merged.get(title) ?? []),\n }));\n}\n\nfunction collectSidebarLinks(items: VitePressSidebarItem[]): SsgNavigationItem[] {\n const links: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n links.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n links.push(...collectSidebarLinks(item.items));\n }\n }\n\n return dedupeNavigationItems(links);\n}\n\nfunction sidebarArrayToGroups(\n items: VitePressSidebarItem[],\n fallbackTitle: string,\n): SsgNavigationGroup[] {\n const groups: SsgNavigationGroup[] = [];\n const rootItems: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n rootItems.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n const children = collectSidebarLinks(item.items);\n if (children.length > 0) {\n groups.push({\n title: item.text?.trim() || fallbackTitle,\n items: children,\n });\n }\n }\n }\n\n if (rootItems.length > 0) {\n groups.unshift({\n title: fallbackTitle,\n items: dedupeNavigationItems(rootItems),\n });\n }\n\n return groups;\n}\n\nfunction collectNavLinks(items: VitePressNavItem[]): SsgNavigationItem[] {\n const links: SsgNavigationItem[] = [];\n\n for (const item of items) {\n if (item.link) {\n links.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n links.push(...collectNavLinks(item.items));\n }\n }\n\n return dedupeNavigationItems(links);\n}\n\nfunction resolveLogoSrc(logo: string | VitePressLogo | undefined): string | undefined {\n if (!logo) {\n return undefined;\n }\n\n if (typeof logo === \"string\") {\n return logo;\n }\n\n return logo.light ?? logo.dark ?? logo.src;\n}\n\nfunction normalizeSocialIcon(icon: string): \"github\" | \"twitter\" | \"discord\" | undefined {\n const normalized = icon.trim().toLowerCase();\n\n if (normalized === \"github\") return \"github\";\n if (normalized === \"discord\") return \"discord\";\n if (normalized === \"twitter\" || normalized === \"x\" || normalized === \"x-twitter\") {\n return \"twitter\";\n }\n\n return undefined;\n}\n\nfunction toThemeConfig(themeConfig: VitePressThemeConfig | undefined): ThemeConfig | undefined {\n if (!themeConfig) {\n return undefined;\n }\n\n const logo = resolveLogoSrc(themeConfig.logo);\n const socialLinks = Object.fromEntries(\n (themeConfig.socialLinks ?? [])\n .map((link) => {\n const key = normalizeSocialIcon(link.icon);\n return key ? [key, link.link] : null;\n })\n .filter((entry): entry is [string, string] => entry !== null),\n );\n\n const theme: ThemeConfig = {\n ...(logo\n ? {\n header: {\n logo,\n },\n }\n : {}),\n ...(themeConfig.footer?.message || themeConfig.footer?.copyright\n ? {\n footer: {\n message: themeConfig.footer.message,\n copyright: themeConfig.footer.copyright,\n },\n }\n : {}),\n ...(Object.keys(socialLinks).length > 0\n ? {\n socialLinks,\n }\n : {}),\n };\n\n return logo || Object.keys(socialLinks).length > 0 || themeConfig.footer\n ? defineTheme(theme)\n : undefined;\n}\n\nfunction resolveSiteName(config: VitePressConfig): string | undefined {\n const siteTitle = config.themeConfig?.siteTitle;\n if (typeof siteTitle === \"string\" && siteTitle.trim()) {\n return siteTitle;\n }\n\n return config.title;\n}\n\nfunction mergeOxContentOptions(\n baseOptions: OxContentOptions,\n overrides: OxContentOptions,\n): OxContentOptions {\n const mergedSsg =\n overrides.ssg === false\n ? false\n : {\n ...(typeof baseOptions.ssg === \"object\" ? baseOptions.ssg : {}),\n ...(typeof overrides.ssg === \"object\" ? overrides.ssg : {}),\n theme:\n typeof baseOptions.ssg === \"object\" &&\n typeof overrides.ssg === \"object\" &&\n baseOptions.ssg.theme &&\n overrides.ssg.theme\n ? defineTheme(mergeThemes(baseOptions.ssg.theme, overrides.ssg.theme))\n : typeof overrides.ssg === \"object\" && overrides.ssg.theme\n ? overrides.ssg.theme\n : typeof baseOptions.ssg === \"object\"\n ? baseOptions.ssg.theme\n : undefined,\n };\n\n const mergedSearch =\n overrides.search === false\n ? false\n : typeof overrides.search === \"object\"\n ? {\n ...(typeof baseOptions.search === \"object\" ? baseOptions.search : {}),\n ...overrides.search,\n }\n : baseOptions.search;\n\n return {\n ...baseOptions,\n ...overrides,\n ssg: mergedSsg,\n search: mergedSearch,\n };\n}\n\n/**\n * Converts a VitePress sidebar config into ox-content navigation groups.\n * Nested VitePress items are flattened into the nearest ox-content group.\n */\nexport function convertVitePressSidebar(sidebar: VitePressSidebar): SsgNavigationGroup[] {\n if (Array.isArray(sidebar)) {\n return dedupeNavigationGroups(sidebarArrayToGroups(sidebar, \"Guide\"));\n }\n\n const groups = Object.entries(sidebar).flatMap(([key, items]) =>\n sidebarArrayToGroups(items, titleFromSidebarKey(key)),\n );\n\n return dedupeNavigationGroups(groups);\n}\n\n/**\n * Converts VitePress top navigation into ox-content sidebar groups.\n * This is used as a fallback when no explicit sidebar is defined.\n */\nexport function convertVitePressNav(nav: VitePressNavItem[]): SsgNavigationGroup[] {\n const groups: SsgNavigationGroup[] = [];\n const rootItems: SsgNavigationItem[] = [];\n\n for (const item of nav) {\n if (item.link) {\n rootItems.push(toNavigationItem(item.text, item.link));\n }\n\n if (item.items?.length) {\n const children = collectNavLinks(item.items);\n if (children.length > 0) {\n groups.push({\n title: item.text?.trim() || \"Navigation\",\n items: children,\n });\n }\n }\n }\n\n if (rootItems.length > 0) {\n groups.unshift({\n title: \"Navigation\",\n items: dedupeNavigationItems(rootItems),\n });\n }\n\n return dedupeNavigationGroups(groups);\n}\n\n/**\n * Creates ox-content plugin options from an existing VitePress config.\n */\nexport function fromVitePressConfig(\n config: VitePressConfig,\n overrides: OxContentOptions = {},\n): OxContentOptions {\n const theme = toThemeConfig(config.themeConfig);\n const navigation = config.themeConfig?.sidebar\n ? convertVitePressSidebar(config.themeConfig.sidebar)\n : config.themeConfig?.nav\n ? convertVitePressNav(config.themeConfig.nav)\n : undefined;\n\n const migrated: OxContentOptions = {\n ...(config.base ? { base: config.base } : {}),\n ...(config.themeConfig?.search?.placeholder\n ? {\n search: {\n placeholder: config.themeConfig.search.placeholder,\n },\n }\n : {}),\n ssg: {\n ...(resolveSiteName(config) ? { siteName: resolveSiteName(config) } : {}),\n ...(theme ? { theme } : {}),\n ...(navigation ? { navigation } : {}),\n },\n };\n\n return mergeOxContentOptions(migrated, overrides);\n}\n\n/**\n * Generates a TypeScript module exporting migrated ox-content options.\n *\n * This is used by the migration CLI so users can inspect and edit the resulting\n * object instead of keeping a runtime dependency on their VitePress config.\n */\nexport function generateVitePressMigrationConfig(\n config: VitePressConfig,\n overrides: OxContentOptions = {},\n options: GenerateVitePressMigrationConfigOptions = {},\n): string {\n const importSource = options.importSource ?? \"@ox-content/vite-plugin\";\n const migrated = fromVitePressConfig(config, overrides);\n\n return `import type { OxContentOptions } from ${JSON.stringify(importSource)};\n\nconst config = ${formatTsValue(migrated)} satisfies OxContentOptions;\n\nexport default config;\n`;\n}\n\nfunction formatTsValue(value: unknown, depth = 0): string {\n if (value === undefined) {\n return \"undefined\";\n }\n\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\") {\n return JSON.stringify(value);\n }\n\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return \"[]\";\n }\n\n const indent = \" \".repeat(depth + 1);\n const closingIndent = \" \".repeat(depth);\n return `[\\n${value.map((item) => `${indent}${formatTsValue(item, depth + 1)},`).join(\"\\n\")}\\n${closingIndent}]`;\n }\n\n if (isRecord(value)) {\n const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== undefined);\n if (entries.length === 0) {\n return \"{}\";\n }\n\n const indent = \" \".repeat(depth + 1);\n const closingIndent = \" \".repeat(depth);\n return `{\\n${entries\n .map(\n ([key, entryValue]) =>\n `${indent}${formatObjectKey(key)}: ${formatTsValue(entryValue, depth + 1)},`,\n )\n .join(\"\\n\")}\\n${closingIndent}}`;\n }\n\n return \"undefined\";\n}\n\nfunction formatObjectKey(key: string): string {\n return /^[A-Za-z_$][\\w$]*$/.test(key) ? key : JSON.stringify(key);\n}\n\n/**\n * Normalizes VitePress-specific frontmatter into ox-content's entry-page shape.\n */\nexport function normalizeVitePressFrontmatter(\n frontmatter: Record<string, unknown>,\n): Record<string, unknown> {\n return importNapiModuleSync().normalizeVitePressFrontmatter(frontmatter);\n}\n"],"mappings":"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"}
|
package/dist/vitepress.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderThemeTokenCss } from "./theme-tokens.mjs";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import { isAbsolute, join, resolve } from "node:path";
|
|
@@ -660,36 +661,6 @@ function resolveHeaderNavItems(items, locale, defaultLocale) {
|
|
|
660
661
|
}));
|
|
661
662
|
}
|
|
662
663
|
//#endregion
|
|
663
|
-
//#region src/theme-tokens.ts
|
|
664
|
-
const TOKEN_PREFIX = "--octc-";
|
|
665
|
-
const TOKEN_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
666
|
-
/**
|
|
667
|
-
* Renders light and dark token records as the three selectors the SSG runtime
|
|
668
|
-
* switches between: an explicit `[data-theme="dark"]` opt-in, the OS
|
|
669
|
-
* `prefers-color-scheme` fallback, and the `:root` base.
|
|
670
|
-
*
|
|
671
|
-
* Emitted after the typed color variables and before the theme's own `css`, so
|
|
672
|
-
* a token can override a typed color and raw `css` can override a token.
|
|
673
|
-
*/
|
|
674
|
-
function tokensToCss(light, dark) {
|
|
675
|
-
const lightBody = declarations(light, " ");
|
|
676
|
-
const darkBody = declarations(dark, " ");
|
|
677
|
-
const blocks = [];
|
|
678
|
-
if (lightBody) blocks.push(`:root {\n${lightBody}\n}`);
|
|
679
|
-
if (darkBody) {
|
|
680
|
-
blocks.push(`[data-theme="dark"] {\n${darkBody}\n}`);
|
|
681
|
-
blocks.push(`@media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n${declarations(dark, " ")}\n }\n}`);
|
|
682
|
-
}
|
|
683
|
-
return blocks.join("\n");
|
|
684
|
-
}
|
|
685
|
-
function declarations(tokens, indent) {
|
|
686
|
-
return Object.entries(tokens).filter(([, value]) => value !== void 0 && value !== "").map(([name, value]) => `${indent}${TOKEN_PREFIX}${assertTokenName(name)}: ${value};`).join("\n");
|
|
687
|
-
}
|
|
688
|
-
function assertTokenName(name) {
|
|
689
|
-
if (!TOKEN_NAME_PATTERN.test(name)) throw new Error(`Invalid theme token name: ${JSON.stringify(name)}. Token names are lowercase kebab-case without the "${TOKEN_PREFIX}" prefix (e.g. "surface-glass").`);
|
|
690
|
-
return name;
|
|
691
|
-
}
|
|
692
|
-
//#endregion
|
|
693
664
|
//#region src/theme.ts
|
|
694
665
|
/**
|
|
695
666
|
* Default theme configuration.
|
|
@@ -957,7 +928,7 @@ function themeToNapi(theme, locale, base, iconsEnabled = false) {
|
|
|
957
928
|
* land after the typed color variables the Rust renderer emits.
|
|
958
929
|
*/
|
|
959
930
|
function themeCss(theme) {
|
|
960
|
-
const prefix = [
|
|
931
|
+
const prefix = [renderThemeTokenCss(theme), namedFontVarsCss(theme.fonts)].filter(Boolean).join("\n");
|
|
961
932
|
if (!prefix) return theme.css;
|
|
962
933
|
return theme.css ? `${prefix}\n${theme.css}` : prefix;
|
|
963
934
|
}
|