import { Plugin } from "vite"; import * as _$http from "http"; //#region src/shared/types.d.ts /** * Metadata representing a single documentation route. * This information is used to build the client-side router and the sidebar navigation. */ interface RouteMeta { /** The final URL path for the route (e.g., '/docs/guide/start') */ path: string; /** The absolute filesystem path to the source markdown/mdx file */ componentPath: string; /** The title of the page, usually extracted from frontmatter or the filename */ title: string; /** The relative path from the docs directory, used for edit links */ filePath: string; /** Optional description of the page (for SEO/meta tags) */ description?: string; /** Optional explicit position for ordering in the sidebar */ sidebarPosition?: number; /** The group (directory) this route belongs to */ group?: string; /** The display title for the route's group */ groupTitle?: string; /** Optional explicit position for ordering the group itself */ groupPosition?: number; /** Optional icon for the route's group */ groupIcon?: string; /** The sub-route group this route belongs to (from folders starting with _) */ subRouteGroup?: string; /** Extracted markdown headings for search indexing */ headings?: { level: number; text: string; id: string; }[]; /** The locale this route belongs to, if i18n is configured */ locale?: string; /** The version this route belongs to, if versioning is configured */ version?: string; /** Optional badge to display next to the sidebar item (e.g., 'New', 'Experimental') */ badge?: BadgeValue; /** Optional icon to display (Lucide icon name or raw SVG) */ icon?: string; /** The tab this route belongs to, if tabs are configured */ tab?: string; /** The collection this route belongs to (from [name] directories like [blog]) */ collection?: string; /** Tags for blog posts or other taxonomy */ tags?: string[]; /** Author identifier for blog posts */ author?: string; /** Draft flag — excluded from production builds */ draft?: boolean; /** Feature flags required for this page to be visible */ featureFlags?: string[]; /** Short excerpt/summary for list displays */ excerpt?: string; /** Cover image for blog posts */ coverImage?: string; /** The extracted plain-text content of the page for search indexing */ _content?: string; /** The raw markdown content of the page */ _rawContent?: string; /** Extracted SEO and Open Graph metadata from frontmatter */ seo?: Record; /** The publication date */ date?: string | Date; /** The last updated timestamp or date */ lastUpdated?: string | number | Date; /** Optional category for the page */ category?: string; /** Optional explicit order (alternative to sidebarPosition) */ order?: number; /** Optional explicit label for the sidebar */ sidebarLabel?: string; /** Whether the page is hidden from the sidebar */ sidebarHidden?: boolean; /** Raw extensible frontmatter data for custom components and formatters */ frontmatter?: Record; /** Optional recursive child routes for deep sidebar hierarchies */ subRoutes?: RouteMeta[]; /** Clean URL segments stripped of locale/version prefixes */ slugParts?: string[]; } /** * Represents a single social link in the configuration. */ interface BoltdocsSocialLink { icon: 'discord' | 'x' | 'github' | 'bluesky' | string; link: string; } /** * Theme-specific configuration options. */ interface BoltdocsThemeConfig { title?: string | Record; description?: string | Record; logo?: string | { dark: string; light: string; alt?: string; width?: number; height?: number; }; navbar?: Array<{ label: string | Record; href: BoltdocsRoutePathWithFallback; items?: Array<{ label: string | Record; href: BoltdocsRoutePathWithFallback; }>; }>; sidebar?: Record>; sidebarGroups?: Record; icon?: string; }>; socialLinks?: BoltdocsSocialLink[]; editLink?: string; communityHelp?: string; version?: string; githubRepo?: string; favicon?: string; tabs?: Array<{ id: string; text: string | Record; icon?: string; }>; codeTheme?: ShikiTheme | { light: ShikiTheme; dark: ShikiTheme; }; } /** * List of supported syntax highlighting themes. */ type ShikiTheme = 'github-dark' | 'github-light' | 'tokyo-night' | 'dracula' | 'nord' | 'one-dark-pro' | 'one-light'; /** * Configuration for the robots.txt file. */ type BoltdocsRobotsConfig = string | { rules?: Array<{ userAgent: string; allow?: string | string[]; disallow?: string | string[]; }>; sitemaps?: string[]; }; /** * Configuration for a specific locale. */ interface BoltdocsLocaleConfig { label?: string; direction?: 'ltr' | 'rtl'; htmlLang?: string; calendar?: string; } /** * Configuration for internationalization (i18n). */ interface BoltdocsI18nConfig { defaultLocale: string; locales: string[] | Record; localeConfigs?: Record; } /** * Configuration for a specific documentation version. */ interface BoltdocsVersionConfig { label: string; path: string; } /** * Configuration for content collections (e.g. blog posts, changelog) * declared in `boltdocs.config.ts`. Each entry maps a directory name * (e.g. `[blog]`) to its display + ordering settings. */ interface BoltdocsCollectionsConfig { /** * Map of collection id (matches the bracketed directory name) to * its display label. Falls back to the id when a label is missing. */ labels?: Record>; /** * Map of collection id to a numeric position used for sidebar ordering. * Collections with no explicit position are sorted last. */ positions?: Record; /** * Items-per-page for paginated collection routes (e.g. blog indexes). * Falls back to the framework default (10) when omitted. */ postsPerPage?: number; /** * Default collection ID used by collection routing when no collection * is explicitly referenced. Defaults to `'blog'`. */ defaultCollection?: string; /** * Date format string for rendering post dates in listing pages. * Defaults to `'MMMM dd, yyyy'`. */ dateFormat?: string; /** * Field used to sort posts within a collection. * Defaults to `'date'`. */ sortBy?: 'date' | 'title' | 'sidebarPosition'; } /** * Configuration for documentation versioning. */ interface BoltdocsVersionsConfig { defaultVersion: string; prefix?: string; versions: BoltdocsVersionConfig[]; } /** * Shared badge value type used in frontmatter, RouteMeta, and ComponentRoute. */ type BadgeValue = string | { text: string; expires?: string; }; /** * Context provided to plugin lifecycle hooks. */ interface PluginContext { readonly config: BoltdocsConfig; readonly logger: PluginLogger; readonly store: PluginStore; readonly meta: PluginMeta; readonly docsDir: string; readonly rootDir: string; readonly outDir: string; readonly routes: RouteMeta[]; /** Namespaced cache helpers bound to the core's cache machinery. */ readonly caches: PluginCachesAPI; /** Structured diagnostics channel; reports can be drained via `list()`. */ readonly diagnostics: PluginDiagnosticsAPI; /** Helpers for resolving paths inside the workspace safely. */ readonly paths: PluginPathsAPI; /** Declare virtual modules the core should expose to Vite. */ readonly virtualModules: PluginVirtualModulesAPI; /** Register and query transform middleware at runtime. */ readonly middleware: PluginMiddlewareAPI; /** * Hook into dev-server file watching and send custom HMR events * to connected clients. */ readonly hmr: PluginHmrAPI; /** * Register HTTP middleware and server lifecycle hooks without * writing a Vite plugin. */ readonly server: PluginServerAPI; } /** * Functional cache helpers exposed through `PluginContext.caches`. * * Plugin authors do not get a reference to the raw `TransformCache` / * `FileCache` instances — those stay encapsulated in core. The methods * returned here are bound to namespaced keys so two plugins cannot * collide. */ interface PluginCachesAPI { /** Sharded, hash-keyed cache. One namespace per plugin recommended. */ transform(namespace: string): PluginTransformCacheAPI; /** Routes cache wrapper around the parsed-doc cache. */ routes: PluginRoutesCacheAPI; /** In-memory LRU cache keyed by namespace + plugin-supplied key. */ memory(namespace: string, opts?: { max?: number; ttl?: number; }): PluginMemoryCacheAPI; } interface PluginTransformCacheAPI { /** Async read — first call may warm from disk if the entry was evicted. */ get(key: string): Promise; /** Synchronous write that batches a background disk flush. */ set(key: string, value: string): void; /** Force-flush background writes. Call before measuring disk state. */ flush(): Promise; } interface PluginRoutesCacheAPI { /** Read a parsed `RouteMeta` (and its private `_content` blob) by abs file path. */ get(filePath: string): RouteMeta | null; /** Write a parsed route entry. Caller assumptions match `docCache.set`. */ set(filePath: string, route: RouteMeta): void; /** Invalidate one route. Use when content changes. */ invalidate(filePath: string): void; /** Clear every cached route. Use when the directory layout changes. */ invalidateAll(): void; } interface PluginMemoryCacheAPI { get(key: string): V | undefined; set(key: string, value: V): void; has(key: string): boolean; } /** * Plugin diagnostics API. * * Plugins push structured records instead of spamming the logger; downstream * tools (dev-server overlay, CI reporters, IDE plugins) drain the queue via * `list()`. */ interface DiagnosticRecord { readonly id: number; readonly severity: 'info' | 'warn' | 'error'; readonly code: string; readonly message: string; readonly pluginName: string; readonly filePath?: string; readonly routePath?: string; readonly time: Date; } interface PluginDiagnosticsAPI { report(severity: DiagnosticRecord['severity'], code: string, message: string, where?: { filePath?: string; routePath?: string; }): void; list(): readonly DiagnosticRecord[]; clear(): void; } /** * Path-resolution helpers exposed through `PluginContext.paths`. * * Both `resolveDocs` and `resolveAsset` validate the resulting path against * the workspace boundary and reject any segment that resolves outside the * docs / project root directories. */ interface PluginPathsAPI { resolveDocs(...parts: string[]): string; resolveAsset(...parts: string[]): string; /** * Build a `file://` URL for an absolute path inside the workspace. * Useful for `new URL(import.meta.url)` replacements and image srcsets. */ safeFileURL(absFilePath: string): string; } /** * Plugin virtual-modules registration. * * Plugins call `add(id, loader)` to expose a `virtual:/` module * to Vite without having to author a full Vite plugin. The loader returns * the module source code as a string; the core wraps it in the right * `resolveId`/`load` plumbing at Vite build time. */ interface RegisteredVirtualModule { readonly id: string; readonly eager: boolean; readonly loader: () => string | Promise; } interface PluginVirtualModulesAPI { add(id: string, loader: () => string | Promise, opts?: { eager?: boolean; }): void; has(id: string): boolean; list(): readonly RegisteredVirtualModule[]; } /** * Logger interface for plugin logging. */ interface PluginLogger { info(message: string): void; warn(message: string): void; error(message: string | Error): void; debug(message: string): void; } /** * Key-value store interface for plugins. */ interface PluginStore { get(pluginName: string, key: string): T | undefined; set(pluginName: string, key: string, value: unknown): void; has(pluginName: string, key: string): boolean; } /** * Plugin metadata provided in the context. */ interface PluginMeta { name: string; version?: string; boltdocsVersion?: string; } /** * Chain control signal returned by transform hooks. Use with `__signal` in * the return value to influence the middleware chain: * * - `'skip'`: stop processing this hook for the current file (remaining * plugins in the chain still run). * - `'break'`: stop the entire chain immediately — no further plugin's * transform hooks run for this file. * * @example * ```ts * transformMdx: async (_ctx, { code }) => ({ * code: code.replace(/foo/g, 'bar'), * __signal: 'skip', // skip remaining plugins * }) * ``` */ type ChainSignal = 'skip' | 'break'; /** * Returned by a transform hook that wants to signal the chain. The `__signal` * field is optional — most hooks will just return `{ code: string }` and the * chain continues normally. When `__signal` is present, `runChain` reacts: * * - `'skip'` continues with the next plugin, but passes the **original params** * (the output of this hook is discarded). * - `'break'` stops the chain immediately. * * @template T The params shape (e.g. `{ code: string; filePath: string }`). */ type TransformResult = T & { __signal?: ChainSignal; }; /** * Enriched params passed to `transformSource` and `transformMdx`. The `code` * and `filePath` fields are always present. The optional `frontmatter` and * `route` fields are populated when available (they are `undefined` in the * early pipeline where frontmatter hasn't been parsed yet). */ interface TransformSourceParams { /** The raw or compiled code (source before MDX / JS after MDX). */ code: string; /** Absolute file path of the source document. */ filePath: string; /** Parsed frontmatter, if available. `undefined` in very early pipeline. */ frontmatter?: Record; } /** * Enriched params passed to `transformHtml`. The `html` and `path` fields * are always present. The optional `route` carries the generated `RouteMeta` * for richer context (locale, version, collection, etc.). */ interface TransformHtmlParams { /** The rendered HTML string for this page. */ html: string; /** The route path (e.g. `/docs/guides/start`). */ path: string; /** The route metadata for the page, if available. */ route?: RouteMeta; } /** * Plugin transform middleware. Each middleware runs in the transform * pipeline alongside lifecycle hooks. The `name` field is optional — * when omitted, the owning plugin's name is used as context. * Middleware runs in `enforce` order (pre → normal → post) and supports * `__signal: 'skip'` / `__signal: 'break'` for chain control. */ interface PluginTransformMiddleware { /** Optional name. Defaults to the owning plugin's name for diagnostics. */ name?: string; enforce?: 'pre' | 'post'; transformSource?: (ctx: PluginContext, params: TransformSourceParams) => TransformResult<{ code: string; }> | Promise>; transformMdx?: (ctx: PluginContext, params: TransformSourceParams) => TransformResult<{ code: string; }> | Promise>; transformHtml?: (ctx: PluginContext, params: TransformHtmlParams) => TransformResult<{ html: string; }> | Promise>; } /** * Plugin middleware registry API exposed through `PluginContext.middleware`. * Plugins can register named middleware entries from lifecycle hooks. */ interface PluginMiddlewareAPI { add(middleware: PluginTransformMiddleware): void; remove(name: string): void; has(name: string): boolean; list(): readonly PluginTransformMiddleware[]; } /** * HMR event types plugins can listen to. */ type PluginHmrEvent = 'add' | 'change' | 'unlink'; /** * Plugin HMR API — hook into file-watching events and send custom * HMR messages to connected clients. */ interface PluginHmrAPI { /** * Register a callback for file events scoped to the docs directory. * The callback receives the normalized file path and event type. */ onFileEvent(eventType: PluginHmrEvent, handler: (filePath: string) => void | Promise): void; /** Shorthand for `onFileEvent('add', handler)`. */ onFileAdd(handler: (filePath: string) => void | Promise): void; /** Shorthand for `onFileEvent('change', handler)`. */ onFileChange(handler: (filePath: string) => void | Promise): void; /** Shorthand for `onFileEvent('unlink', handler)`. */ onFileUnlink(handler: (filePath: string) => void | Promise): void; /** * Send a custom HMR event to all connected clients. * The client can listen with `import.meta.hot.on('boltdocs:plugin:', ...)`. */ send(event: string, data?: unknown): void; } /** * Plugin Server API — register HTTP middleware and lifecycle hooks * for the dev server and preview server, without writing a Vite plugin. */ interface PluginServerAPI { /** * Register a Connect-style middleware function. * Runs on both dev and preview servers. */ use(middleware: PluginServerMiddleware): void; /** * Register a middleware scoped to a specific path prefix. * Only requests starting with `path` trigger the handler. */ useAt(path: string, handler: PluginServerMiddleware): void; /** Called when the dev/preview server starts (once per process). */ onStart(callback: () => void | Promise): void; /** Called when the server shuts down (cleanup). */ onEnd(callback: () => void | Promise): void; } /** * Connect-style middleware signature. */ type PluginServerMiddleware = (req: _$http.IncomingMessage, res: _$http.ServerResponse, next: (err?: unknown) => void) => void | Promise; /** * Plugin lifecycle hooks with full type safety. */ interface PluginLifecycleHooks { beforeBuild?: (ctx: PluginContext) => Promise | void; afterBuild?: (ctx: PluginContext) => Promise | void; beforeDev?: (ctx: PluginContext) => Promise | void; afterDev?: (ctx: PluginContext) => Promise | void; buildEnd?: (ctx: PluginContext) => Promise | void; transformSource?: (ctx: PluginContext, params: TransformSourceParams) => TransformResult<{ code: string; }> | Promise>; transformMdx?: (ctx: PluginContext, params: TransformSourceParams) => TransformResult<{ code: string; }> | Promise>; transformHtml?: (ctx: PluginContext, params: TransformHtmlParams) => TransformResult<{ html: string; }> | Promise>; } /** * MDX processor configuration. * When `processor` is set to 'satteri', the Sätteri Rust-based compiler is used. */ interface BoltdocsMdxConfig { processor?: 'unified' | 'satteri'; } /** * Defines a Boltdocs plugin. * * Use the `createPlugin()` helper from the node API for full type safety and * access to lifecycle hooks. */ interface BoltdocsPlugin { name: string; enforce?: 'pre' | 'post'; version?: string; boltdocsVersion?: string; remarkPlugins?: unknown[]; rehypePlugins?: unknown[]; vitePlugins?: Plugin[]; components?: Record; /** Optional runtime metadata exposed to client via useConfig().plugins[].metadata */ metadata?: Record; /** Declarative transform middleware entries. */ middleware?: PluginTransformMiddleware[]; /** Lifecycle hooks with full type safety */ hooks?: PluginLifecycleHooks; } /** */ /** */ /** */ interface BoltdocsSecurityConfig { headers?: Record; enableCSP?: boolean; customHeaders?: Record; } interface BoltdocsVerificationConfig { google?: string; bing?: string; yandex?: string; pinterest?: string; facebook?: string; } /** * Configuration for SEO. */ interface BoltdocsSeoConfig { metatags?: Record; indexing?: 'all' | 'public'; thumbnails?: { background?: string; }; verification?: BoltdocsVerificationConfig; } /** * Configuration for Google Analytics 4 (GA4). */ interface BoltdocsGA4Config { measurementId: string; debug?: boolean; anonymizeIp?: boolean; sendPageView?: boolean; cookieFlags?: string; autoTrack?: { pageViews?: boolean; downloads?: boolean; externalLinks?: boolean; search?: boolean; }; } /** * Configuration for Google Tag Manager (GTM). */ interface BoltdocsGTMConfig { tagId: string; dataLayerName?: string; preview?: string; } /** * Configuration for Algolia DocSearch. */ interface BoltdocsAlgoliaConfig { appId: string; apiKey: string; indexName: string; } /** * Configuration for Giscus comments. */ interface BoltdocsGiscusConfig { repo: string; repoId: string; category?: string; categoryId?: string; mapping?: 'pathname' | 'url' | 'title' | 'og:title' | 'specific' | 'number'; strict?: '0' | '1' | boolean; reactionsEnabled?: '0' | '1' | boolean; emitMetadata?: '0' | '1' | boolean; inputPosition?: 'top' | 'bottom'; theme?: string; darkTheme?: string; lang?: string; loading?: 'lazy' | 'eager'; } /** * Configuration for custom feedback system using GitHub Discussions API. */ interface BoltdocsCustomFeedbackConfig { enabled: boolean; owner: string; repo: string; categorySlug?: string; endpoint?: string; } interface BoltdocsVercelConfig { analytics?: boolean; speedInsights?: boolean; } interface BoltdocsPostHogConfig { apiKey: string; host?: string; capturePageview?: boolean; capturePageleave?: boolean; sessionRecording?: boolean; autocapture?: boolean; } interface BoltdocsIntegrationsConfig { analytics?: { ga4?: BoltdocsGA4Config; vercel?: BoltdocsVercelConfig; gtm?: BoltdocsGTMConfig; posthog?: BoltdocsPostHogConfig; }; search?: { algolia?: BoltdocsAlgoliaConfig; }; feedback?: { giscus?: BoltdocsGiscusConfig; custom?: BoltdocsCustomFeedbackConfig; }; } /** * Configuration for drafts visibility control. */ interface BoltdocsDraftsConfig { /** If true, drafts are visible in all environments. Default: false */ visible?: boolean; /** Environments where drafts are visible (e.g. ['development', 'staging']). Default: [] */ environments?: string[]; } /** * The root configuration object for Boltdocs. */ interface BoltdocsConfig { siteUrl?: string; docsDir?: string; base?: string; theme?: BoltdocsThemeConfig; i18n?: BoltdocsI18nConfig; versions?: BoltdocsVersionsConfig; mdx?: BoltdocsMdxConfig; plugins?: BoltdocsPlugin[]; collections?: BoltdocsCollectionsConfig; robots?: BoltdocsRobotsConfig; security?: BoltdocsSecurityConfig; seo?: BoltdocsSeoConfig; integrations?: BoltdocsIntegrationsConfig; drafts?: BoltdocsDraftsConfig; featureFlags?: Record; directoryMeta?: Record; vite?: unknown; } /** * Global namespace for Boltdocs types that can be augmented by generated code. * This allows for strictly typed locales and versions based on the project configuration. */ declare global { namespace Boltdocs { interface Types {} /** * Marker interface augmented by generated code to provide strict route path typing. * When no types have been generated (e.g., before first dev server start), * keyof is never, and BoltdocsRoutePath falls back to string. */ interface RoutePaths {} } } type BoltdocsRoutePath = keyof Boltdocs.RoutePaths; type BoltdocsRoutePathWithFallback = BoltdocsRoutePath extends never ? string : BoltdocsRoutePath; //#endregion //#region src/shared/config-utils.d.ts /** * Type-safe helper for defining Boltdocs configuration. * This is an identity function that provides IntelliSense in both * Node.js (config files) and client-side code (MDX examples). * * @remarks * Intended for use in `boltdocs.config.ts` (Node.js context). This function * is **not** available as a client-side import from `boltdocs/client`. * * @param config - The Boltdocs configuration object */ declare function defineConfig(config: BoltdocsConfig): BoltdocsConfig; //#endregion //#region src/node/config.d.ts /** * Loads user's configuration file (e.g., `boltdocs.config.js` or `boltdocs.config.ts`) if it exists, * merges it with the default configuration, and returns the final `BoltdocsConfig`. * * @param docsDir - The directory containing the documentation files * @param root - The project root directory (defaults to process.cwd()) * @returns The merged configuration object */ declare function resolveConfig(docsDir: string, root?: string): Promise; //#endregion export { BoltdocsThemeConfig as a, PluginLogger as c, PluginTransformMiddleware as d, RouteMeta as f, BoltdocsPlugin as i, PluginMeta as l, defineConfig as n, PluginContext as o, ShikiTheme as p, BoltdocsConfig as r, PluginLifecycleHooks as s, resolveConfig as t, PluginStore as u };