import { writeFileSync } from 'node:fs'; import { resolve } from 'node:path'; import type { ProjectReflection } from 'typedoc'; import { ReflectionKind } from 'typedoc'; import type { Method } from '../../docs/.vitepress/components/api-docs/method'; import type { APIGroup } from '../../docs/api/api-types'; import { formatMarkdown, formatTypescript } from './format'; import { extractSourceBaseUrl } from './typedoc'; import type { DocsApiDiffIndex, ModuleSummary, Page } from './utils'; import { diffHash, methodDiffHash, pathDocsDiffIndexFile, pathDocsDir, pathOutputDir, } from './utils'; const pathDocsApiPages = resolve(pathDocsDir, '.vitepress', 'api-pages.ts'); const pathDocsApiSearchIndex = resolve( pathDocsDir, 'api', 'api-search-index.json' ); const scriptCommand = 'pnpm run generate:api-docs'; // Moved here because this must not be formatted by prettier const vitePressInFileOptions = `--- editLink: false --- `; /** * Writes the api docs for the given modules. * * @param moduleName The name of the module to write the docs for. * @param lowerModuleName The lowercase name of the module. * @param comment The module comments. * @param deprecated The deprecation message. * @param methods The methods of the module. */ export function writeApiDocsModule( moduleName: string, lowerModuleName: string, comment: string, deprecated: string | undefined, methods: Method[] ): ModuleSummary { writeApiDocsModulePage( moduleName, lowerModuleName, comment, deprecated, methods ); writeApiDocsModuleData(lowerModuleName, methods); return { text: moduleName, link: `/api/${lowerModuleName}.html`, methods, diff: methods.reduce( (data, method) => ({ ...data, [method.name]: methodDiffHash(method), }), { moduleHash: diffHash({ name: moduleName, field: lowerModuleName, deprecated, comment, }), } ), }; } /** * Writes the api page for the given module to the correct location. * * @param moduleName The name of the module to write the docs for. * @param lowerModuleName The lowercase name of the module. * @param comment The module comments. * @param methods The methods of the module. */ function writeApiDocsModulePage( moduleName: string, lowerModuleName: string, comment: string, deprecated: string | undefined, methods: Method[] ): void { // Write api docs page let content = ` # ${moduleName} ::: v-pre ${ deprecated == null ? '' : `

Deprecated

This module is deprecated and will be removed in a future version.

${deprecated}
` } ${comment} ::: ${methods .map( (method) => ` ## ${method.name} ` ) .join('')} `.replace(/\n +/g, '\n'); content = vitePressInFileOptions + formatMarkdown(content); writeFileSync(resolve(pathOutputDir, `${lowerModuleName}.md`), content); } /** * Writes the api docs data to correct location. * * @param lowerModuleName The lowercase name of the module. * @param methods The methods data to save. */ function writeApiDocsModuleData( lowerModuleName: string, methods: Method[] ): void { const content = JSON.stringify( methods.reduce>( (map, method) => ({ ...map, [method.name]: method, }), {} ) ); writeFileSync(resolve(pathOutputDir, `${lowerModuleName}.json`), content); } /** * Writes the api docs index to correct location. * * @param pages The pages to write into the index. */ export function writeApiPagesIndex(pages: Page[]): void { // Write api-pages.ts console.log('Updating api-pages.ts'); pages.splice(0, 0, { text: 'Overview', link: '/api/' }); let apiPagesContent = ` // This file is automatically generated. // Run '${scriptCommand}' to update export const apiPages = ${JSON.stringify(pages)}; `.replace(/\n +/, '\n'); apiPagesContent = formatTypescript(apiPagesContent); writeFileSync(pathDocsApiPages, apiPagesContent); } /** * Writes the api diff index to the correct location. * * @param diffIndex The diff index project to write. */ export function writeApiDiffIndex(diffIndex: DocsApiDiffIndex): void { writeFileSync(pathDocsDiffIndexFile, JSON.stringify(diffIndex)); } /** * Writes the api search index to the correct location. * * @param project The typedoc project. */ export function writeApiSearchIndex(pages: ModuleSummary[]): void { const apiIndex: APIGroup[] = [ { text: 'Module API', items: pages.map((module) => ({ text: module.text, link: module.link, headers: module.methods.map((method) => ({ anchor: method.name, text: method.name, deprecated: !!method.deprecated, })), })), }, ]; writeFileSync(pathDocsApiSearchIndex, JSON.stringify(apiIndex)); } /** * Writes the source base url to the correct location. * * @param project The typedoc project. */ export function writeSourceBaseUrl(project: ProjectReflection): void { const baseUrl = extractSourceBaseUrl( project.getChildrenByKind(ReflectionKind.Class)[0] ); let content = ` // This file is automatically generated. // Run '${scriptCommand}' to update export const sourceBaseUrl = '${baseUrl}'; `.replace(/\n +/, '\n'); content = formatTypescript(content); writeFileSync(resolve(pathOutputDir, 'source-base-url.ts'), content); }