import fs from "node:fs"; import http from "node:http"; import { Writr } from "writr"; //#region src/console.d.ts declare class DoculaConsole { quiet: boolean; log(message: string): void; error(message: string): void; warn(message: string): void; success(message: string): void; info(message: string): void; step(message: string): void; fileBuilt(filePath: string): void; fileCopied(filePath: string): void; serverLog(method: string, url: string, statusCode: number, durationMs?: number): void; banner(message: string): void; printHelp(): void; parseProcessArgv(argv: string[]): DoculaConsoleProcess; getCommand(argv: string[]): string | undefined; getArguments(argv: string[]): DoculaConsoleArguments; } type DoculaConsoleProcess = { argv: string[]; command: string | undefined; args: DoculaConsoleArguments; }; type DoculaConsoleArguments = { sitePath: string | undefined; templatePath: string | undefined; template: string | undefined; output: string | undefined; watch: boolean; clean: boolean; build: boolean; port: number | undefined; typescript: boolean; javascript: boolean; overwrite: boolean; downloadTarget: string; }; //#endregion //#region src/github.d.ts type GithubData = { releases: Record; contributors: Record; }; //#endregion //#region src/api-parser.d.ts type ApiSchemaProperty = { name: string; type: string; required: boolean; description: string; enumValues?: string[]; }; type ApiOperationParameter = { name: string; in: string; required: boolean; type: string; description: string; }; type ApiRequestBody = { contentType: string; schemaProperties: ApiSchemaProperty[]; example: string; }; type ApiResponse = { statusCode: string; statusClass: string; description: string; contentType: string; schemaProperties: ApiSchemaProperty[]; example: string; }; type ApiCodeExamples = { curl: string; javascript: string; python: string; }; type ApiOperation = { id: string; method: string; methodUpper: string; path: string; summary: string; description: string; parameters: ApiOperationParameter[]; requestBody?: ApiRequestBody; responses: ApiResponse[]; codeExamples: ApiCodeExamples; }; type ApiGroup = { name: string; description: string; id: string; operations: ApiOperation[]; }; type ApiOAuth2Flow = { authorizationUrl?: string; tokenUrl?: string; refreshUrl?: string; scopes: Record; }; type ApiSecurityScheme = { key: string; type: string; scheme?: string; bearerFormat?: string; name?: string; in?: string; description: string; flows?: { authorizationCode?: ApiOAuth2Flow; implicit?: ApiOAuth2Flow; clientCredentials?: ApiOAuth2Flow; password?: ApiOAuth2Flow; }; }; type ApiSpecData = { info: { title: string; description: string; version: string; }; servers: Array<{ url: string; description: string; }>; groups: ApiGroup[]; securitySchemes: ApiSecurityScheme[]; }; //#endregion //#region src/types.d.ts type DoculaOpenApiSpecEntry = { name: string; url: string; order?: number; apiSpec?: ApiSpecData; }; type DoculaChangelogEntry = { title: string; date: string; formattedDate: string; tag?: string; tagClass?: string; slug: string; content: string; generatedHtml: string; preview: string; draft?: boolean; previewImage?: string; urlPath: string; lastModified: string; description?: string; keywords?: string[]; ogTitle?: string; ogDescription?: string; }; type DoculaData = { siteUrl: string; siteTitle: string; siteDescription: string; sitePath: string; templatePath: string; output: string; githubPath?: string; github?: GithubData; templates?: DoculaTemplates; hasDocuments?: boolean; hasChangelog?: boolean; sections?: DoculaSection[]; documents?: DoculaDocument[]; sidebarItems?: DoculaSection[]; announcement?: string; hasApi?: boolean; apiSpec?: ApiSpecData; openApiSpecs?: DoculaOpenApiSpecEntry[]; changelogEntries?: DoculaChangelogEntry[]; hasReadme?: boolean; readmeContent?: string; readmeMetadata?: { description?: string; keywords?: string[]; ogTitle?: string; ogDescription?: string; }; themeMode?: string; cookieAuth?: { loginUrl: string; logoutUrl?: string; authCheckUrl?: string; authCheckMethod?: string; authCheckUserPath?: string; }; headerLinks?: Array<{ label: string; url: string; icon?: string; }>; googleTagManager?: string; isGtag?: boolean; enableLlmsTxt?: boolean; hasFeed?: boolean; lastModified?: string; homeUrl?: string; baseUrl: string; docsPath: string; apiPath: string; changelogPath: string; docsUrl: string; apiUrl: string; changelogUrl: string; editPageUrl?: string; openGraph?: DoculaOpenGraph; }; type DoculaTemplates = { home: string; docPage?: string; api?: string; changelog?: string; changelogEntry?: string; }; type DoculaSection = { name: string; order?: number; path: string; children?: DoculaSection[]; }; type DoculaDocument = { title: string; navTitle: string; description: string; order?: number; section?: string; keywords: string[]; content: string; markdown: string; generatedHtml: string; documentPath: string; urlPath: string; isRoot: boolean; lastModified: string; ogTitle?: string; ogDescription?: string; ogImage?: string; }; //#endregion //#region src/options.d.ts type DoculaCookieAuth = { loginUrl: string; logoutUrl?: string; authCheckUrl?: string; authCheckMethod?: string; authCheckUserPath?: string; }; type DoculaHeaderLink = { label: string; url: string; icon?: string; }; type DoculaOpenApiSpec = { name: string; url: string; order?: number; }; type DoculaOpenGraph = { title?: string; description?: string; image?: string; url?: string; type?: string; siteName?: string; twitterCard?: string; }; type DoculaCacheOptions = { github: { ttl: number; }; }; type DoculaAIOptions = { provider: string; model?: string; apiKey?: string; }; declare class DoculaOptions { /** * Name of the built-in template to use (e.g., "modern", "classic") */ template: string; /** * Path to the template directory. When set, overrides the `template` option. */ templatePath: string; /** * Path to the output directory */ output: string; /** * Path to the site directory */ sitePath: string; /** * Path to the github repository */ githubPath: string; /** * Site title */ siteTitle: string; /** * Site description */ siteDescription: string; /** * Site URL */ siteUrl: string; /** * Port to run the server */ port: number; /** * Sections */ sections?: DoculaSection[]; /** * OpenAPI specification for API documentation. * Pass a string URL for a single spec, or an array of DoculaOpenApiSpec for multiple specs. * When provided, creates a dedicated /api page. */ openApiUrl?: string | DoculaOpenApiSpec[]; /** * When true, GitHub releases are converted to changelog entries and merged * with file-based changelog entries. Requires a changelog template to exist. */ enableReleaseChangelog: boolean; /** * Number of changelog entries to display per page on the changelog index. */ changelogPerPage: number; /** * When true, generates llms.txt and llms-full.txt files for the built site. */ enableLlmsTxt: boolean; /** * Override the default theme toggle. By default the site follows the system * preference. Set to "light" or "dark" to use that theme when no user * preference is stored in localStorage. */ themeMode?: "light" | "dark"; /** * When true, automatically adds generated paths (e.g., .cache) to the * site directory's .gitignore file if not already present. */ autoUpdateIgnores: boolean; /** * When true, automatically renders the project root README.md as the home * page if no README exists in the site directory. The README is read in * place and never copied into the site directory. The package.json name * field is used to prepend a title heading when the README lacks one. */ autoReadme: boolean; /** * When true, suppresses all non-error console output during the build. */ quiet: boolean; /** * URL for the logo/home link in the header. Defaults to baseUrl or "/". * Useful when hosting docs under a subpath but the logo should link to the parent site. */ homeUrl?: string; /** * Base URL path prefix for all generated paths (e.g., "/docs"). * When set, all asset and navigation URLs are prefixed with this path. */ baseUrl: string; /** * Output subdirectory and URL segment for documentation pages. * Set to empty string to place docs at the output root. */ docsPath: string; /** * Output subdirectory and URL segment for API reference pages. */ apiPath: string; /** * Output subdirectory and URL segment for changelog pages. */ changelogPath: string; /** * Base URL for "Edit this page" links on documentation pages. * When set, an edit link is shown at the bottom of each doc page. * The document's relative path is appended to this URL. * Example: "https://github.com/owner/repo/edit/main/site/docs" */ editPageUrl?: string; /** * OpenGraph meta tags for social sharing. When set, og: and twitter: * meta tags are rendered in the page head. Fields fall back to * siteTitle / siteDescription / siteUrl when omitted. */ openGraph?: DoculaOpenGraph; /** * Cookie-based authentication. When set, shows a Login/Logout button * in the header based on whether a JWT cookie is present. */ cookieAuth?: DoculaCookieAuth; /** * Additional links to display in the site header navigation. * Each link requires a label and url. */ headerLinks?: DoculaHeaderLink[]; /** * Google Tag Manager container ID (e.g., "GTM-XXXXXX") or * Google Analytics 4 measurement ID (e.g., "G-XXXXXXXXXX"). * When set, injects the appropriate tracking script on every page. */ googleTagManager?: string; /** * AI-powered metadata enrichment configuration. When set, uses AI to fill * missing OpenGraph and HTML meta tag fields during the build. * Requires provider name and API key. Omit to disable AI enrichment. */ ai?: DoculaAIOptions; /** * Cache settings. Controls caching of external data (e.g., GitHub API responses) * in the .cache directory within the site path. */ cache: DoculaCacheOptions; /** * File extensions to copy as assets from docs/ and changelog/ directories. * Override in docula.config to customize. */ allowedAssets: string[]; constructor(options?: Record); parseOptions(options: Record): void; } //#endregion //#region src/builder.d.ts type DoculaBuilderOptions = { console?: DoculaConsole; } & DoculaOptions; declare class DoculaBuilder { private readonly _options; private readonly _ecto; private readonly _console; private readonly _hash; onReleaseChangelog?: (entries: DoculaChangelogEntry[], console: DoculaConsole) => Promise | DoculaChangelogEntry[]; get console(): DoculaConsole; constructor(options?: DoculaBuilderOptions, engineOptions?: any); get options(): DoculaOptions; build(): Promise; validateOptions(options: DoculaOptions): void; autoReadme(): Promise<{ sourcePath: string; content: string; } | undefined>; getGithubData(githubPath: string): Promise; getTemplates(templatePath: string, hasDocuments: boolean, hasChangelog?: boolean): Promise; getTemplateFile(path: string, name: string): Promise; buildRobotsPage(options: DoculaOptions): Promise; buildSiteMapPage(data: DoculaData): Promise; buildFeedPage(data: DoculaData): Promise; buildChangelogFeedJson(data: DoculaData): Promise; buildChangelogLatestFeedJson(data: DoculaData): Promise; buildLlmsFiles(data: DoculaData): Promise; resolveOpenGraphData(data: DoculaData, pageUrl: string, pageData?: Partial & { previewImage?: string; preview?: string; }): Record; resolveJsonLd(pageType: "home" | "docs" | "api" | "changelog" | "changelog-entry", data: DoculaData, pageUrl: string, pageData?: Partial & { date?: string; preview?: string; previewImage?: string; }): string; buildIndexPage(data: DoculaData): Promise; buildDocsHomePage(data: DoculaData): Promise; buildReadmeSection(data: DoculaData): Promise; buildAnnouncementSection(data: DoculaData): Promise; buildDocsPages(data: DoculaData): Promise; renderApiContent(data: DoculaData): Promise; buildApiPage(data: DoculaData): Promise; buildAllApiPages(data: DoculaData): Promise; buildApiHomePage(data: DoculaData): Promise; getChangelogEntries(changelogPath: string, cachedEntries?: Map, previousHashes?: Record, currentHashes?: Record): DoculaChangelogEntry[]; parseChangelogEntry(filePath: string): DoculaChangelogEntry; generateChangelogPreview(markdown: string, maxLength?: number, mdx?: boolean): string; convertReleaseToChangelogEntry(release: Record): DoculaChangelogEntry; getReleasesAsChangelogEntries(releases: any[]): DoculaChangelogEntry[]; buildChangelogPage(data: DoculaData): Promise; buildChangelogEntryPages(data: DoculaData): Promise; generateSidebarItems(data: DoculaData): DoculaSection[]; getDocuments(sitePath: string, doculaData: DoculaData, cachedDocs?: Map, previousDocHashes?: Record, currentDocHashes?: Record): DoculaDocument[]; getDocumentInDirectory(sitePath: string, docsRootPath: string, cachedDocs?: Map, previousDocHashes?: Record, currentDocHashes?: Record): DoculaDocument[]; getSections(sitePath: string, doculaOptions: DoculaOptions): DoculaSection[]; mergeSectionWithOptions(section: DoculaSection, options: DoculaOptions): DoculaSection; parseDocumentData(documentPath: string): DoculaDocument; } //#endregion //#region src/docula.d.ts declare class Docula { private _options; private readonly _console; private _configFileModule; private _server; private _watcher; get console(): DoculaConsole; /** * Initialize the Docula class * @param {DoculaOptions} options * @returns {void} * @constructor */ constructor(options?: DoculaOptions); /** * Get the options * @returns {DoculaOptions} */ get options(): DoculaOptions; /** * Set the options * @param {DoculaOptions} value */ set options(value: DoculaOptions); /** * The http server used to serve the site * @returns {http.Server | undefined} */ get server(): http.Server | undefined; /** * The file watcher used in watch mode * @returns {fs.FSWatcher | undefined} */ get watcher(): fs.FSWatcher | undefined; /** * The config file module. This is the module that is loaded from the docula.config.ts or docula.config.mjs file * @returns {any} */ get configFileModule(): any; /** * Remove the .cache directory inside the site path. * Resolves the path and verifies it stays within sitePath to prevent * path-traversal attacks. * @param {string} sitePath */ private cleanCache; /** * Check for updates * @returns {void} */ checkForUpdates(): void; /** * Is the execution process that runs the docula command * @param {NodeJS.Process} process * @returns {Promise} */ execute(process: NodeJS.Process): Promise; private runBuild; /** * Detect if the current project uses TypeScript by checking for tsconfig.json * @returns {boolean} */ detectTypeScript(): boolean; /** * Generate the init files * @param {string} sitePath * @param {boolean} typescript - If true, generates docula.config.ts instead of docula.config.mjs * @returns {void} */ generateInit(sitePath: string, typescript?: boolean): void; /** * Copy the template's variables.css to the site directory. * If the file already exists and overwrite is false, prints an error. * @param {string} sitePath * @param {string} templatePath * @param {string} templateName * @param {boolean} overwrite * @returns {void} */ downloadVariables(sitePath: string, templatePath: string, templateName: string, overwrite?: boolean): void; /** * Copy the full template directory to {sitePath}/templates/{outputName}/. * If the directory already exists and overwrite is false, prints an error. * @param {string} sitePath * @param {string} templatePath * @param {string} templateName * @param {boolean} overwrite * @returns {void} */ downloadTemplate(sitePath: string, templatePath: string, templateName: string, overwrite?: boolean): void; /** * Get the version of the package * @returns {string} */ getVersion(): string; /** * Load the config file. Supports both .mjs and .ts config files. * Priority: docula.config.ts > docula.config.mjs * @param {string} sitePath * @returns {Promise} */ loadConfigFile(sitePath: string): Promise; /** * Watch the site path for file changes and rebuild on change * @param {DoculaOptions} options * @param {DoculaBuilder} builder * @returns {fs.FSWatcher} */ watch(options: DoculaOptions, builder: DoculaBuilder): fs.FSWatcher; /** * Serve the site based on the options (port and output path) * @param {DoculaOptions} options * @returns {Promise} */ serve(options: DoculaOptions): Promise; } //#endregion export { type DoculaAIOptions, type DoculaCacheOptions, type DoculaChangelogEntry, DoculaConsole, type DoculaCookieAuth, type DoculaHeaderLink, type DoculaOpenApiSpec, DoculaOptions, Writr, Docula as default };