From 751021f9e1029600266cc8c3bea8232e385bbbc3 Mon Sep 17 00:00:00 2001 From: HiDeoo <494699+HiDeoo@users.noreply.github.com> Date: Tue, 25 Mar 2025 17:35:32 +0100 Subject: [PATCH] feat: typedoc 0.28 support (#77) --- .changeset/kind-owls-thank.md | 7 + docs/src/content/docs/guides/frontmatter.mdx | 2 +- example/package.json | 8 +- example/src/plugins/frontmatter.js | 2 +- packages/starlight-typedoc/index.ts | 7 +- packages/starlight-typedoc/libs/starlight.ts | 50 +++++-- packages/starlight-typedoc/libs/theme.ts | 140 +++++++++--------- packages/starlight-typedoc/libs/typedoc.ts | 61 +++++--- packages/starlight-typedoc/package.json | 4 +- .../tests/e2e/basics/content.test.ts | 8 +- .../tests/e2e/basics/sidebar.test.ts | 10 +- .../tests/e2e/packages/content.test.ts | 2 +- .../tests/unit/sidebar.test.ts | 2 +- .../tests/unit/typedoc.test.ts | 22 ++- packages/starlight-typedoc/vitest.config.ts | 5 + pnpm-lock.yaml | 90 ++++++----- 16 files changed, 247 insertions(+), 173 deletions(-) create mode 100644 .changeset/kind-owls-thank.md diff --git a/.changeset/kind-owls-thank.md b/.changeset/kind-owls-thank.md new file mode 100644 index 0000000..1ca06ca --- /dev/null +++ b/.changeset/kind-owls-thank.md @@ -0,0 +1,7 @@ +--- +'starlight-typedoc': minor +--- + +⚠️ **BREAKING CHANGE:** The minimum supported version of `typedoc` is now `0.28.0`. + +⚠️ **BREAKING CHANGE:** The minimum supported version of `typedoc-plugin-markdown` is now `4.6.0`. diff --git a/docs/src/content/docs/guides/frontmatter.mdx b/docs/src/content/docs/guides/frontmatter.mdx index 2912db6..ef6ece0 100644 --- a/docs/src/content/docs/guides/frontmatter.mdx +++ b/docs/src/content/docs/guides/frontmatter.mdx @@ -33,7 +33,7 @@ import { PackageManagers } from '@hideoo/starlight-plugins-docs-components' /** @param {MarkdownPageEvent} page */ (page) => { // Customize the frontmatter for a specific page. - if (page.model.url === 'variables/something.md') { + if (page.url === 'variables/something.md') { // Update the frontmatter of the generated page. page.frontmatter = { // Include a sidebar badge with the text 'New'. diff --git a/example/package.json b/example/package.json index 43e7871..e49d1c8 100644 --- a/example/package.json +++ b/example/package.json @@ -29,10 +29,10 @@ "astro": "^5.3.0", "sharp": "^0.33.5", "starlight-typedoc": "workspace:*", - "typedoc": "^0.26.5", - "typedoc-plugin-frontmatter": "^1.0.0", - "typedoc-plugin-markdown": "^4.1.1", - "typedoc-plugin-mdn-links": "^3.0.3" + "typedoc": "^0.28.1", + "typedoc-plugin-frontmatter": "^1.3.0", + "typedoc-plugin-markdown": "^4.6.0", + "typedoc-plugin-mdn-links": "^5.0.1" }, "engines": { "node": ">=18.17.1" diff --git a/example/src/plugins/frontmatter.js b/example/src/plugins/frontmatter.js index 3fd655f..91a3eab 100644 --- a/example/src/plugins/frontmatter.js +++ b/example/src/plugins/frontmatter.js @@ -6,7 +6,7 @@ export function load(app) { MarkdownPageEvent.BEGIN, /** @param {MarkdownPageEvent} page */ (page) => { - if (page.model.url === 'variables/anObject.md') { + if (page.url === 'variables/anObject.md') { page.frontmatter = { sidebar: { badge: { diff --git a/packages/starlight-typedoc/index.ts b/packages/starlight-typedoc/index.ts index 8b229f4..4897e36 100644 --- a/packages/starlight-typedoc/index.ts +++ b/packages/starlight-typedoc/index.ts @@ -32,7 +32,7 @@ function makeStarlightTypeDocPlugin(sidebarGroup: SidebarGroup): (options: Starl if (command === 'preview') return try { - const { outputDirectory, reflections } = await generateTypeDoc(options, astroConfig, logger) + const { definitions, outputDirectory, reflections } = await generateTypeDoc(options, astroConfig, logger) updateConfig({ sidebar: getSidebarFromReflections( @@ -40,6 +40,7 @@ function makeStarlightTypeDocPlugin(sidebarGroup: SidebarGroup): (options: Starl sidebarGroup, options.sidebar, reflections, + definitions, outputDirectory, ), }) @@ -62,7 +63,7 @@ export interface StarlightTypeDocOptions { /** * The path(s) to the entry point(s) to document. */ - entryPoints: TypeDocOptions['entryPoints'] + entryPoints: NonNullable /** * Whether the plugin should error when no TypeDoc documentation is generated. * @default true @@ -86,7 +87,7 @@ export interface StarlightTypeDocOptions { /** * The path to the `tsconfig.json` file to use for the documentation generation. */ - tsconfig: TypeDocOptions['tsconfig'] + tsconfig: NonNullable /** * Additional TypeDoc configuration. * @see https://typedoc.org/options diff --git a/packages/starlight-typedoc/libs/starlight.ts b/packages/starlight-typedoc/libs/starlight.ts index 71b2b8e..c1beda0 100644 --- a/packages/starlight-typedoc/libs/starlight.ts +++ b/packages/starlight-typedoc/libs/starlight.ts @@ -12,6 +12,8 @@ import { import type { StarlightTypeDocSidebarOptions } from '..' +import type { TypeDocDefinitions } from './typedoc' + const externalLinkRegex = /^(http|ftp)s?:\/\// const sidebarDefaultOptions = { @@ -33,13 +35,20 @@ export function getSidebarFromReflections( sidebarGroupPlaceholder: SidebarGroup, options: StarlightTypeDocSidebarOptions = {}, reflections: ProjectReflection | DeclarationReflection, + definitions: TypeDocDefinitions, baseOutputDirectory: string, ): StarlightUserConfigSidebar { if (!sidebar || sidebar.length === 0) { return sidebar } - const sidebarGroup = getSidebarGroupFromReflections(options, reflections, baseOutputDirectory, baseOutputDirectory) + const sidebarGroup = getSidebarGroupFromReflections( + options, + reflections, + definitions, + baseOutputDirectory, + baseOutputDirectory, + ) function replaceSidebarGroupPlaceholder(group: SidebarManualGroup): SidebarGroup { if (group.label === sidebarGroupPlaceholder.label) { @@ -99,20 +108,24 @@ export function getSidebarWithoutReflections( function getSidebarGroupFromPackageReflections( options: StarlightTypeDocSidebarOptions, reflections: ProjectReflection | DeclarationReflection, + definitions: TypeDocDefinitions, baseOutputDirectory: string, ): SidebarGroup { const groups = (reflections.children ?? []).map((child) => { - if (!child.url) { + const url = definitions[child.id] + + if (!url) { return undefined } - const url = path.parse(child.url) + const parsedPath = path.parse(url) return getSidebarGroupFromReflections( options, child, + definitions, baseOutputDirectory, - `${baseOutputDirectory}/${url.dir}`, + `${baseOutputDirectory}/${parsedPath.dir}`, child.name, ) }) @@ -127,12 +140,13 @@ function getSidebarGroupFromPackageReflections( function getSidebarGroupFromReflections( options: StarlightTypeDocSidebarOptions, reflections: ProjectReflection | DeclarationReflection, + definitions: TypeDocDefinitions, baseOutputDirectory: string, outputDirectory: string, label?: string, ): SidebarGroup { if ((!reflections.groups || reflections.groups.length === 0) && reflections.children) { - return getSidebarGroupFromPackageReflections(options, reflections, outputDirectory) + return getSidebarGroupFromPackageReflections(options, reflections, definitions, outputDirectory) } const groups = reflections.groups ?? [] @@ -144,32 +158,37 @@ function getSidebarGroupFromReflections( .flatMap((group) => { if (group.title === 'Modules') { return group.children.map((child) => { - if (!child.url || child.variant === 'document') { + const url = definitions[child.id] + + if (!url || child.variant === 'document') { return undefined } - const url = path.parse(child.url) + const parsedPath = path.parse(url) const isParentKindModule = child.parent?.kind === ReflectionKind.Module return getSidebarGroupFromReflections( { collapsed: true, label: child.name }, child, + definitions, baseOutputDirectory, - `${outputDirectory}/${isParentKindModule ? url.dir.split('/').slice(1).join('/') : url.dir}`, + `${outputDirectory}/${isParentKindModule ? parsedPath.dir.split('/').slice(1).join('/') : parsedPath.dir}`, ) }) } if (isReferenceReflectionGroup(group)) { - return getReferencesSidebarGroup(group, baseOutputDirectory) + return getReferencesSidebarGroup(group, definitions, baseOutputDirectory) } const directory = `${outputDirectory}/${slug(group.title.toLowerCase())}` // The groups generated using the `@group` tag do not have an associated directory on disk. - const isGroupWithDirectory = group.children.some((child) => - path.posix.join(baseOutputDirectory, child.url?.replace('\\', '/') ?? '').startsWith(directory), - ) + const isGroupWithDirectory = group.children.some((child) => { + return path.posix + .join(baseOutputDirectory, definitions[child.id]?.replace('\\', '/') ?? '') + .startsWith(directory) + }) if (!isGroupWithDirectory) { return undefined @@ -190,6 +209,7 @@ function getSidebarGroupFromReflections( function getReferencesSidebarGroup( group: ReflectionGroup, + definitions: TypeDocDefinitions, baseOutputDirectory: string, ): SidebarManualGroup | undefined { const referenceItems: LinkItem[] = group.children @@ -205,13 +225,15 @@ function getReferencesSidebarGroup( target = target.parent } - if (!target.url) { + const url = definitions[target.id] + + if (!url) { return undefined } return { label: reference.name, - link: getRelativeURL(target.url, getStarlightTypeDocOutputDirectory(baseOutputDirectory)), + link: getRelativeURL(url, getStarlightTypeDocOutputDirectory(baseOutputDirectory)), } }) .filter((item): item is LinkItem => item !== undefined) diff --git a/packages/starlight-typedoc/libs/theme.ts b/packages/starlight-typedoc/libs/theme.ts index 6359d37..3bca8ff 100644 --- a/packages/starlight-typedoc/libs/theme.ts +++ b/packages/starlight-typedoc/libs/theme.ts @@ -1,5 +1,3 @@ -import path from 'node:path' - import { Reflection, type Comment, type CommentTag, type Options, type CommentDisplayPart } from 'typedoc' import { MarkdownTheme, MarkdownThemeContext, type MarkdownPageEvent } from 'typedoc-plugin-markdown' @@ -9,99 +7,93 @@ const customBlockTagTypes = ['@deprecated'] as const const customModifiersTagTypes = ['@alpha', '@beta', '@experimental'] as const export class StarlightTypeDocTheme extends MarkdownTheme { - override getRenderContext(event: MarkdownPageEvent): StarlightTypeDocThemeRenderContext { + override getRenderContext(event: MarkdownPageEvent): StarlightTypeDocThemeRenderContext { return new StarlightTypeDocThemeRenderContext(this, event, this.application.options) } } class StarlightTypeDocThemeRenderContext extends MarkdownThemeContext { - #markdownThemeContext: MarkdownThemeContext - - constructor(theme: MarkdownTheme, event: MarkdownPageEvent, options: Options) { + constructor(theme: MarkdownTheme, event: MarkdownPageEvent, options: Options) { super(theme, event, options) - this.#markdownThemeContext = new MarkdownThemeContext(theme, event, options) + const superPartials = this.partials + + this.partials = { + ...superPartials, + comment: (comment, options) => { + const filteredComment = { ...comment } as Comment + filteredComment.blockTags = [] + filteredComment.modifierTags = new Set<`@${string}`>() + + const customTags: CustomTag[] = [] + + for (const blockTag of comment.blockTags) { + if (this.#isCustomBlockCommentTagType(blockTag.tag)) { + customTags.push({ blockTag, type: blockTag.tag }) + } else { + blockTag.content = blockTag.content.map((part) => this.#parseCommentDisplayPart(part)) + filteredComment.blockTags.push(blockTag) + } + } + + for (const modifierTag of comment.modifierTags) { + if (this.#isCustomModifierCommentTagType(modifierTag)) { + customTags.push({ type: modifierTag }) + } else { + filteredComment.modifierTags.add(modifierTag) + } + } + + filteredComment.summary = comment.summary.map((part) => this.#parseCommentDisplayPart(part)) + + let markdown = superPartials.comment(filteredComment, options) + + if (options?.showSummary === false) { + return markdown + } + + for (const customCommentTag of customTags) { + switch (customCommentTag.type) { + case '@alpha': { + markdown = this.#addReleaseStageAside(markdown, 'Alpha') + break + } + case '@beta': { + markdown = this.#addReleaseStageAside(markdown, 'Beta') + break + } + case '@deprecated': { + markdown = this.#addDeprecatedAside(markdown, customCommentTag.blockTag) + break + } + case '@experimental': { + markdown = this.#addReleaseStageAside(markdown, 'Experimental') + break + } + } + } + + return markdown + }, + } } - override getRelativeUrl(url: string): string { + override urlTo(reflection: Reflection): string { const outputDirectory = this.options.getValue('starlight-typedoc-output') const baseUrl = typeof outputDirectory === 'string' ? outputDirectory : '' - return getRelativeURL(url, baseUrl, this.page.url) - } - - override partials: MarkdownThemeContext['partials'] = { - // @ts-expect-error https://github.com/tgreyuk/typedoc-plugin-markdown/blob/2bc4136a364c1d1ab44789d6148cd19c425ce63c/docs/pages/docs/customizing-output.mdx#custom-theme - ...this.partials, - comment: (comment, options) => { - const filteredComment = { ...comment } as Comment - filteredComment.blockTags = [] - filteredComment.modifierTags = new Set<`@${string}`>() - - const customTags: CustomTag[] = [] - - for (const blockTag of comment.blockTags) { - if (this.#isCustomBlockCommentTagType(blockTag.tag)) { - customTags.push({ blockTag, type: blockTag.tag }) - } else { - blockTag.content = blockTag.content.map((part) => this.#parseCommentDisplayPart(part)) - filteredComment.blockTags.push(blockTag) - } - } - - for (const modifierTag of comment.modifierTags) { - if (this.#isCustomModifierCommentTagType(modifierTag)) { - customTags.push({ type: modifierTag }) - } else { - filteredComment.modifierTags.add(modifierTag) - } - } - - filteredComment.summary = comment.summary.map((part) => this.#parseCommentDisplayPart(part)) - - let markdown = this.#markdownThemeContext.partials.comment(filteredComment, options) - - if (options?.showSummary === false) { - return markdown - } - - for (const customCommentTag of customTags) { - switch (customCommentTag.type) { - case '@alpha': { - markdown = this.#addReleaseStageAside(markdown, 'Alpha') - break - } - case '@beta': { - markdown = this.#addReleaseStageAside(markdown, 'Beta') - break - } - case '@deprecated': { - markdown = this.#addDeprecatedAside(markdown, customCommentTag.blockTag) - break - } - case '@experimental': { - markdown = this.#addReleaseStageAside(markdown, 'Experimental') - break - } - } - } - - return markdown - }, + return getRelativeURL(this.router.getFullUrl(reflection), baseUrl, this.page.url) } #parseCommentDisplayPart = (part: CommentDisplayPart): CommentDisplayPart => { if ( part.kind === 'inline-tag' && (part.tag === '@link' || part.tag === '@linkcode' || part.tag === '@linkplain') && - part.target instanceof Reflection && - typeof part.target.url === 'string' + part.target instanceof Reflection ) { return { ...part, - target: this.getRelativeUrl( - path.posix.join(this.options.getValue('entryPointStrategy') === 'packages' ? '../..' : '..', part.target.url), - ), + target: this.urlTo(part.target), } } diff --git a/packages/starlight-typedoc/libs/typedoc.ts b/packages/starlight-typedoc/libs/typedoc.ts index 3ba699e..c973629 100644 --- a/packages/starlight-typedoc/libs/typedoc.ts +++ b/packages/starlight-typedoc/libs/typedoc.ts @@ -1,4 +1,4 @@ -import fs from 'node:fs' +import * as fs from 'node:fs' import path from 'node:path' import url from 'node:url' @@ -9,8 +9,8 @@ import { TSConfigReader, type TypeDocOptions, ParameterType, - type Reflection, RendererEvent, + type PageDefinition, } from 'typedoc' import type { MarkdownPageEvent, PluginOptions } from 'typedoc-plugin-markdown' @@ -47,11 +47,23 @@ export async function generateTypeDoc( options.entryPoints, options.tsconfig, options.typeDoc, - outputDirectory, + { + base: config.base, + directory: outputDirectory, + path: path.join(url.fileURLToPath(config.srcDir), 'content/docs', outputDirectory), + }, options.pagination ?? false, - config.base, logger, ) + + const definitions: TypeDocDefinitions = {} + app.renderer.on(RendererEvent.END, (event) => { + for (const page of event.pages) { + if (!('id' in page.model)) continue + definitions[page.model.id] = page.url + } + }) + const reflections = await app.convert() if ( @@ -61,26 +73,21 @@ export async function generateTypeDoc( throw new NoReflectionsError() } - const outputPath = path.join(url.fileURLToPath(config.srcDir), 'content/docs', outputDirectory) + await (options.watch + ? app.convertAndWatch(async (reflections) => { + await app.generateOutputs(reflections) + }) + : app.generateOutputs(reflections)) - if (options.watch) { - app.convertAndWatch(async (reflections) => { - await app.generateDocs(reflections, outputPath) - }) - } else { - await app.generateDocs(reflections, outputPath) - } - - return { outputDirectory, reflections } + return { definitions, outputDirectory, reflections } } async function bootstrapApp( - entryPoints: TypeDocOptions['entryPoints'], - tsconfig: TypeDocOptions['tsconfig'], + entryPoints: NonNullable, + tsconfig: NonNullable, config: TypeDocConfig = {}, - outputDirectory: string, + output: TypeDocOutput, pagination: boolean, - base: string, logger: AstroIntegrationLogger, ) { const pagesToRemove: string[] = [] @@ -93,15 +100,16 @@ async function bootstrapApp( plugin: [...(config.plugin ?? []), 'typedoc-plugin-markdown'], entryPoints, tsconfig, + outputs: [{ name: 'markdown', path: output.path }], }) app.logger = new StarlightTypeDocLogger(logger) app.options.addReader(new TSConfigReader()) app.renderer.defineTheme('starlight-typedoc', StarlightTypeDocTheme) - app.renderer.on(PageEvent.BEGIN, (event: PageEvent) => { - onRendererPageBegin(event, pagination) + app.renderer.on(PageEvent.BEGIN, (event) => { + onRendererPageBegin(event as MarkdownPageEvent, pagination) }) - app.renderer.on(PageEvent.END, (event: PageEvent) => { - const shouldRemovePage = onRendererPageEnd(event, pagination) + app.renderer.on(PageEvent.END, (event) => { + const shouldRemovePage = onRendererPageEnd(event as MarkdownPageEvent, pagination) if (shouldRemovePage) { pagesToRemove.push(event.filename) } @@ -110,7 +118,7 @@ async function bootstrapApp( onRendererEnd(pagesToRemove) }) app.options.addDeclaration({ - defaultValue: getStarlightTypeDocOutputDirectory(outputDirectory, base), + defaultValue: getStarlightTypeDocOutputDirectory(output.directory, output.base), help: 'The starlight-typedoc output directory containing the generated documentation markdown files relative to the `src/content/docs/` directory.', name: 'starlight-typedoc-output', type: ParameterType.String, @@ -166,3 +174,10 @@ export class NoReflectionsError extends Error { } export type TypeDocConfig = Partial & PluginOptions> +export type TypeDocDefinitions = Record + +interface TypeDocOutput { + base: string + directory: string + path: string +} diff --git a/packages/starlight-typedoc/package.json b/packages/starlight-typedoc/package.json index e272018..68f5df1 100644 --- a/packages/starlight-typedoc/package.json +++ b/packages/starlight-typedoc/package.json @@ -34,8 +34,8 @@ }, "peerDependencies": { "@astrojs/starlight": ">=0.32.0", - "typedoc": ">=0.26.5", - "typedoc-plugin-markdown": ">=4.1.1" + "typedoc": ">=0.28.0", + "typedoc-plugin-markdown": ">=4.6.0" }, "engines": { "node": ">=18.17.1" diff --git a/packages/starlight-typedoc/tests/e2e/basics/content.test.ts b/packages/starlight-typedoc/tests/e2e/basics/content.test.ts index e71a69d..a08fa61 100644 --- a/packages/starlight-typedoc/tests/e2e/basics/content.test.ts +++ b/packages/starlight-typedoc/tests/e2e/basics/content.test.ts @@ -37,7 +37,7 @@ test('should properly format links with anchors for a single entry point', async .getByRole('link', { exact: true, name: 'constructor' }) .getAttribute('href') - expect(barConstructorLinkHref).toEqual('/api/classes/bar/#constructors') + expect(barConstructorLinkHref).toEqual('/api/classes/bar/#constructor') }) test('should properly format links with anchors for multiple entry points', async ({ docPage }) => { @@ -49,7 +49,7 @@ test('should properly format links with anchors for multiple entry points', asyn .getByRole('link', { exact: true, name: 'constructor' }) .getAttribute('href') - expect(barConstructorLinkHref).toEqual('/multiple-entrypoints/api-multiple-entrypoints/bar/classes/bar/#constructors') + expect(barConstructorLinkHref).toEqual('/multiple-entrypoints/api-multiple-entrypoints/bar/classes/bar/#constructor') }) test('should disable edit links', async ({ docPage }) => { @@ -88,12 +88,12 @@ test('should properly format links in summary', async ({ docPage }) => { await docPage.goto('functions/dothingfaster') await docPage.content.getByRole('link', { exact: true, name: 'doThingB' }).click() - await docPage.page.waitForURL('**/api/functions/dothingb') + await docPage.page.waitForURL('**/api/functions/dothingb/') }) test('should properly format links in block tag comments', async ({ docPage }) => { await docPage.goto('classes/foo') await docPage.content.locator('h4:has-text("See") + p a').click() - await docPage.page.waitForURL('**/api/interfaces/thing') + await docPage.page.waitForURL('**/api/interfaces/thing/') }) diff --git a/packages/starlight-typedoc/tests/e2e/basics/sidebar.test.ts b/packages/starlight-typedoc/tests/e2e/basics/sidebar.test.ts index 5a07f5c..b2746f2 100644 --- a/packages/starlight-typedoc/tests/e2e/basics/sidebar.test.ts +++ b/packages/starlight-typedoc/tests/e2e/basics/sidebar.test.ts @@ -41,11 +41,6 @@ test('should generate the proper items for for a single entry point', async ({ d const items = await docPage.getTypeDocSidebarItems() expect(items).toMatchObject([ - { - label: 'References', - items: [{ name: 'doThingARef' }], - collapsed: true, - }, { label: 'Enumerations', items: [{ name: 'ANumericEnum' }, { name: 'AStringEnum' }], @@ -76,6 +71,11 @@ test('should generate the proper items for for a single entry point', async ({ d items: [{ name: 'doThingA' }, { name: 'doThingB' }, { name: 'doThingC' }, { name: 'doThingFaster' }], collapsed: true, }, + { + label: 'References', + items: [{ name: 'doThingARef' }], + collapsed: true, + }, // `MyCustomGroup` defined in `fixtures/basics/src/Baz.ts` does not have a directory on disk which means it should // not be included in the sidebar. ]) diff --git a/packages/starlight-typedoc/tests/e2e/packages/content.test.ts b/packages/starlight-typedoc/tests/e2e/packages/content.test.ts index 8b23325..e201b71 100644 --- a/packages/starlight-typedoc/tests/e2e/packages/content.test.ts +++ b/packages/starlight-typedoc/tests/e2e/packages/content.test.ts @@ -15,5 +15,5 @@ test('should properly format links in block tag comments', async ({ docPage }) = await docPage.goto('foo/functions/dofoofaster') await docPage.content.getByRole('link', { exact: true, name: 'doFoo' }).click() - await docPage.page.waitForURL('**/api-packages-entrypoints/foo/functions/dofoo') + await docPage.page.waitForURL('**/api-packages-entrypoints/foo/functions/dofoo/') }) diff --git a/packages/starlight-typedoc/tests/unit/sidebar.test.ts b/packages/starlight-typedoc/tests/unit/sidebar.test.ts index 1588718..6ffb431 100644 --- a/packages/starlight-typedoc/tests/unit/sidebar.test.ts +++ b/packages/starlight-typedoc/tests/unit/sidebar.test.ts @@ -184,7 +184,7 @@ describe('getSidebarWithoutReflections', () => { }) function getTestSidebar(sidebar: Parameters[0]) { - return getSidebarFromReflections(sidebar, typeDocSidebarGroup, {}, {} as ProjectReflection, 'api') + return getSidebarFromReflections(sidebar, typeDocSidebarGroup, {}, {} as ProjectReflection, {}, 'api') } function getTestSidebarWithoutReflections(sidebar: Parameters[0]) { diff --git a/packages/starlight-typedoc/tests/unit/typedoc.test.ts b/packages/starlight-typedoc/tests/unit/typedoc.test.ts index 628181a..722205e 100644 --- a/packages/starlight-typedoc/tests/unit/typedoc.test.ts +++ b/packages/starlight-typedoc/tests/unit/typedoc.test.ts @@ -1,4 +1,4 @@ -import fs from 'node:fs' +import * as fs from 'node:fs' import type { AstroIntegrationLogger, AstroConfig } from 'astro' import { afterAll, afterEach, beforeAll, expect, test, vi } from 'vitest' @@ -6,6 +6,16 @@ import { afterAll, afterEach, beforeAll, expect, test, vi } from 'vitest' import type { StarlightTypeDocOptions } from '../..' import { generateTypeDoc } from '../../libs/typedoc' +vi.mock(import('node:fs'), async (importOriginal) => { + const mod = await importOriginal() + return { + ...mod, + mkdirSync: vi.fn(), + rmSync: vi.fn(), + writeFileSync: vi.fn(), + } +}) + const starlightTypeDocOptions = { tsconfig: '../../fixtures/basics/tsconfig.json', typeDoc: { @@ -177,11 +187,11 @@ test('should output index with correct module path', async () => { expect( content.includes(` -- [bar](/api/namespaces/bar/) -- [foo](/api/namespaces/foo/) -- [functions](/api/namespaces/functions/) -- [shared](/api/namespaces/shared/) -- [types](/api/namespaces/types/)`), +- [bar](/api/starlight-typedoc/namespaces/bar/) +- [foo](/api/starlight-typedoc/namespaces/foo/) +- [functions](/api/starlight-typedoc/namespaces/functions/) +- [shared](/api/starlight-typedoc/namespaces/shared/) +- [types](/api/starlight-typedoc/namespaces/types/)`), ).toBe(true) }) diff --git a/packages/starlight-typedoc/vitest.config.ts b/packages/starlight-typedoc/vitest.config.ts index 04ac521..55b7015 100644 --- a/packages/starlight-typedoc/vitest.config.ts +++ b/packages/starlight-typedoc/vitest.config.ts @@ -3,5 +3,10 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { include: ['tests/unit/**/*.test.ts'], + server: { + deps: { + inline: ['typedoc'], + }, + }, }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b93991f..374a431 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,17 +69,17 @@ importers: specifier: workspace:* version: link:../packages/starlight-typedoc typedoc: - specifier: ^0.26.5 - version: 0.26.5(typescript@5.7.2) + specifier: ^0.28.1 + version: 0.28.1(typescript@5.7.2) typedoc-plugin-frontmatter: - specifier: ^1.0.0 - version: 1.0.0(typedoc-plugin-markdown@4.1.1) + specifier: ^1.3.0 + version: 1.3.0(typedoc-plugin-markdown@4.6.0) typedoc-plugin-markdown: - specifier: ^4.1.1 - version: 4.1.1(typedoc@0.26.5) + specifier: ^4.6.0 + version: 4.6.0(typedoc@0.28.1) typedoc-plugin-mdn-links: - specifier: ^3.0.3 - version: 3.0.3(typedoc@0.26.5) + specifier: ^5.0.1 + version: 5.0.1(typedoc@0.28.1) fixtures/basics: dependencies: @@ -102,11 +102,11 @@ importers: specifier: ^2.0.0 version: 2.0.0 typedoc: - specifier: '>=0.26.5' - version: 0.26.5(typescript@5.7.2) + specifier: '>=0.28.0' + version: 0.28.1(typescript@5.7.2) typedoc-plugin-markdown: - specifier: '>=4.1.1' - version: 4.1.1(typedoc@0.26.5) + specifier: '>=4.6.0' + version: 4.6.0(typedoc@0.28.1) devDependencies: '@playwright/test': specifier: ^1.49.1 @@ -328,7 +328,7 @@ packages: /@astrojs/yaml2ts@0.2.2: resolution: {integrity: sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==} dependencies: - yaml: 2.6.1 + yaml: 2.7.0 dev: true /@babel/code-frame@7.26.2: @@ -932,6 +932,14 @@ packages: '@expressive-code/core': 0.40.2 dev: false + /@gerrit0/mini-shiki@3.2.1: + resolution: {integrity: sha512-HbzRC6MKB6U8kQhczz0APKPIzFHTrcqhaC7es2EXInq1SpjPVnpVSIsBe6hNoLWqqCx1n5VKiPXq6PfXnHZKOQ==} + dependencies: + '@shikijs/engine-oniguruma': 3.2.1 + '@shikijs/types': 3.2.1 + '@shikijs/vscode-textmate': 10.0.2 + dev: false + /@hideoo/eslint-config@4.0.0(eslint@9.17.0)(typescript@5.7.2): resolution: {integrity: sha512-QtcFEH37jaCNp2oWBQ1goySA7LAgA334RIhigm3PV4sfvbtUInXO5Hau6DePHJOwgku5niRR/qvDq4dgsmjpsQ==} peerDependencies: @@ -1477,6 +1485,13 @@ packages: '@shikijs/types': 1.29.2 '@shikijs/vscode-textmate': 10.0.2 + /@shikijs/engine-oniguruma@3.2.1: + resolution: {integrity: sha512-wZZAkayEn6qu2+YjenEoFqj0OyQI64EWsNR6/71d1EkG4sxEOFooowKivsWPpaWNBu3sxAG+zPz5kzBL/SsreQ==} + dependencies: + '@shikijs/types': 3.2.1 + '@shikijs/vscode-textmate': 10.0.2 + dev: false + /@shikijs/langs@1.29.2: resolution: {integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==} dependencies: @@ -1493,6 +1508,13 @@ packages: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + /@shikijs/types@3.2.1: + resolution: {integrity: sha512-/NTWAk4KE2M8uac0RhOsIhYQf4pdU0OywQuYDGIGAJ6Mjunxl2cGiuLkvu4HLCMn+OTTLRWkjZITp+aYJv60yA==} + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + dev: false + /@shikijs/vscode-textmate@10.0.2: resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -6512,45 +6534,45 @@ packages: reflect.getprototypeof: 1.0.8 dev: true - /typedoc-plugin-frontmatter@1.0.0(typedoc-plugin-markdown@4.1.1): - resolution: {integrity: sha512-Mqn96+RjUjPUz/42H8MOp/8eOKjE5MVIgZRFDGmSI2YuggnMZSfh5MMpvd6ykjNTpq7gV5D2iwjqLt8nYRg9rg==} + /typedoc-plugin-frontmatter@1.3.0(typedoc-plugin-markdown@4.6.0): + resolution: {integrity: sha512-xYQFMAecMlsRUjmf9oM/Sq2FVz4zlgcbIeVFNLdO118CHTN06gIKJNSlyExh9+Xl8sK0YhIvoQwViUURxritWA==} peerDependencies: - typedoc-plugin-markdown: '>=4.0.0' + typedoc-plugin-markdown: '>=4.5.0' dependencies: - typedoc-plugin-markdown: 4.1.1(typedoc@0.26.5) - yaml: 2.6.1 + typedoc-plugin-markdown: 4.6.0(typedoc@0.28.1) + yaml: 2.7.0 dev: false - /typedoc-plugin-markdown@4.1.1(typedoc@0.26.5): - resolution: {integrity: sha512-ZQv8FXn1TBZAvhWMgOL8hE472rwv1dzSr/KIIUGPmdNXybeS6jmK7d1OwKhorLuGbPDQGl6U97BwfkFTcydAkw==} + /typedoc-plugin-markdown@4.6.0(typedoc@0.28.1): + resolution: {integrity: sha512-RG90uC1QqGN9kPBjzEckEf0v9yIYlLoNYKm4OqjwEGFJJGOLUDs5pIEQQDR2tAv1RD7D8GUSakRlcHMTipyaOA==} engines: {node: '>= 18'} peerDependencies: - typedoc: 0.26.x + typedoc: 0.28.x dependencies: - typedoc: 0.26.5(typescript@5.7.2) + typedoc: 0.28.1(typescript@5.7.2) dev: false - /typedoc-plugin-mdn-links@3.0.3(typedoc@0.26.5): - resolution: {integrity: sha512-NXhIpwQnsg7BcyMCHVqj3tUK+DL4g3Bt96JbFl4APzTGFkA+iM6GfZ/fn3TAqJ8O0CXG5R9BfWxolw1m1omNuQ==} + /typedoc-plugin-mdn-links@5.0.1(typedoc@0.28.1): + resolution: {integrity: sha512-eofdcc2nZZpipz/ubjG+7UYMi6Xu95svUwnZ+ClJh6NJdrv7kAOerL9N3iDOpo5kwQeK86GqPWwnv6LUGo5Wrw==} peerDependencies: - typedoc: '>= 0.23.14 || 0.24.x' + typedoc: 0.27.x || 0.28.x dependencies: - typedoc: 0.26.5(typescript@5.7.2) + typedoc: 0.28.1(typescript@5.7.2) dev: false - /typedoc@0.26.5(typescript@5.7.2): - resolution: {integrity: sha512-Vn9YKdjKtDZqSk+by7beZ+xzkkr8T8CYoiasqyt4TTRFy5+UHzL/mF/o4wGBjRF+rlWQHDb0t6xCpA3JNL5phg==} - engines: {node: '>= 18'} + /typedoc@0.28.1(typescript@5.7.2): + resolution: {integrity: sha512-Mn2VPNMaxoe/hlBiLriG4U55oyAa3Xo+8HbtEwV7F5WEOPXqtxzGuMZhJYHaqFJpajeQ6ZDUC2c990NAtTbdgw==} + engines: {node: '>= 18', pnpm: '>= 10'} hasBin: true peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.7.2 + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.7.2 dependencies: + '@gerrit0/mini-shiki': 3.2.1 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 - shiki: 1.29.2 typescript: 5.7.2 - yaml: 2.6.1 + yaml: 2.7.0 dev: false /typesafe-path@0.2.2: @@ -7279,8 +7301,8 @@ packages: engines: {node: '>= 14'} dev: true - /yaml@2.6.1: - resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} + /yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} engines: {node: '>= 14'} hasBin: true