import type { AstroConfig, ViteUserConfig } from 'astro'; import { resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { StarlightConfig } from '../utils/user-config'; function resolveVirtualModuleId(id: T): `\0${T}` { return `\0${id}`; } /** Vite plugin that exposes Starlight user config and project context via virtual modules. */ export function vitePluginStarlightUserConfig( opts: StarlightConfig, { build, root, srcDir, trailingSlash, }: Pick & { build: Pick; } ): NonNullable[number] { const resolveId = (id: string) => JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(root), id) : id); const virtualComponentModules = Object.fromEntries( Object.entries(opts.components).map(([name, path]) => [ `virtual:starlight/components/${name}`, `export { default } from ${resolveId(path)};`, ]) ); /** Map of virtual module names to their code contents as strings. */ const modules = { 'virtual:starlight/user-config': `export default ${JSON.stringify(opts)}`, 'virtual:starlight/project-context': `export default ${JSON.stringify({ build: { format: build.format }, root, srcDir, trailingSlash, })}`, 'virtual:starlight/user-css': opts.customCss.map((id) => `import ${resolveId(id)};`).join(''), 'virtual:starlight/user-images': opts.logo ? 'src' in opts.logo ? `import src from ${resolveId( opts.logo.src )}; export const logos = { dark: src, light: src };` : `import dark from ${resolveId(opts.logo.dark)}; import light from ${resolveId( opts.logo.light )}; export const logos = { dark, light };` : 'export const logos = {};', 'virtual:starlight/collection-config': `let userCollections; try { userCollections = (await import('/src/content/config.ts')).collections; } catch {} export const collections = userCollections;`, ...virtualComponentModules, } satisfies Record; /** Mapping names prefixed with `\0` to their original form. */ const resolutionMap = Object.fromEntries( (Object.keys(modules) as (keyof typeof modules)[]).map((key) => [ resolveVirtualModuleId(key), key, ]) ); return { name: 'vite-plugin-starlight-user-config', resolveId(id): string | void { if (id in modules) return resolveVirtualModuleId(id); }, load(id): string | void { const resolution = resolutionMap[id]; if (resolution) return modules[resolution]; }, }; }