diff --git a/CHANGELOG.md b/CHANGELOG.md index a003f7593..4e6247b40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,20 @@ # Unreleased +### Features + +- Added `headings` option to control optional headings, #2729. + ### Bug Fixes - `externalSymbolLinkMappings` now uses the TypeScript reported link target if available, #2725. - TypeDoc will no longer omit the modules page if a project contains only modules/documents, #2730. - Fixed missing breadcrumbs on project page, #2728. +- TypeDoc will no longer render an empty readme page if no readme was found. + +### Thanks! + +- @lriggle-strib +- @mrfigg ## v0.26.8 (2024-10-04) diff --git a/src/lib/internationalization/translatable.ts b/src/lib/internationalization/translatable.ts index 0d5c32aab..52c014bcf 100644 --- a/src/lib/internationalization/translatable.ts +++ b/src/lib/internationalization/translatable.ts @@ -300,6 +300,7 @@ export const translatable = { help_navigationLeaves: "Branches of the navigation tree which should not be expanded", help_navigation: "Determines how the navigation sidebar is organized", + help_headings: "Determines which optional headings are rendered", help_visibilityFilters: "Specify the default visibility for builtin filters and additional filters according to modifier tags", help_searchCategoryBoosts: diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 622ccab44..1a58fd514 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -205,7 +205,7 @@ export class DefaultTheme extends Theme { const urls: UrlMapping[] = []; this.sluggers.set(project, new Slugger()); - if (!hasReadme(this.application.options.getValue("readme"))) { + if (!project.readme?.length) { project.url = "index.html"; urls.push(new UrlMapping("index.html", project, this.reflectionTemplate)); } else { @@ -507,10 +507,6 @@ export class DefaultTheme extends Theme { } } -function hasReadme(readme: string) { - return !readme.endsWith("none"); -} - function getReflectionClasses( reflection: DeclarationReflection | DocumentReflection, filters: Record, diff --git a/src/lib/output/themes/default/partials/header.tsx b/src/lib/output/themes/default/partials/header.tsx index 429dc76a3..dedfe375b 100644 --- a/src/lib/output/themes/default/partials/header.tsx +++ b/src/lib/output/themes/default/partials/header.tsx @@ -2,19 +2,39 @@ import { classNames, getDisplayName, hasTypeParameters, join } from "../../lib"; import { JSX } from "../../../../utils"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import type { PageEvent } from "../../../events"; -import { type Reflection, ReflectionKind } from "../../../../models"; +import type { Reflection } from "../../../../models"; export const header = (context: DefaultThemeRenderContext, props: PageEvent) => { - const HeadingLevel = props.model.isProject() ? "h2" : "h1"; + const opts = context.options.getValue("headings"); + + // Don't render on the index page or the class hierarchy page + // We should probably someday render on the class hierarchy page, but currently breadcrumbs + // are entirely dependent on the reflection hierarchy, so it doesn't make sense today. + const renderBreadcrumbs = props.url !== "index.html" && props.url !== "hierarchy.html"; + + // Titles are always rendered on DeclarationReflection pages and the modules page for the project. + // They are also rendered on the readme + document pages if configured to do so by the user. + let renderTitle: boolean; + let titleKindString = ""; + if (props.model.isProject()) { + if (props.url === "index.html" && props.model.readme?.length) { + renderTitle = opts.readme; + } else { + renderTitle = true; + } + } else if (props.model.isDocument()) { + renderTitle = opts.document; + } else { + renderTitle = true; + titleKindString = " " + context.internationalization.kindSingularString(props.model.kind); + } + return (
- {props.url !== "index.html" && props.url !== "hierarchy.html" && ( -
    {context.breadcrumb(props.model)}
- )} - {!props.model.isDocument() && ( - - {props.model.kind !== ReflectionKind.Project && - `${context.internationalization.kindSingularString(props.model.kind)} `} + {renderBreadcrumbs &&
    {context.breadcrumb(props.model)}
} + {renderTitle && ( +

+ {titleKindString} {getDisplayName(props.model)} {hasTypeParameters(props.model) && ( <> @@ -24,7 +44,7 @@ export const header = (context: DefaultThemeRenderContext, props: PageEvent )} {context.reflectionFlags(props.model)} - +

)}
); diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 9188a19ba..d9236a2a3 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -185,6 +185,10 @@ export interface TypeDocOptionMap { compactFolders: boolean; excludeReferences: boolean; }; + headings: { + readme: boolean; + document: boolean; + }; visibilityFilters: ManuallyValidatedOption<{ protected?: boolean; private?: boolean; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 94f9b589c..963ea5e8b 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -564,6 +564,16 @@ export function addTypeDocOptions(options: Pick) { }, }); + options.addDeclaration({ + name: "headings", + help: (i18n) => i18n.help_headings(), + type: ParameterType.Flags, + defaults: { + readme: true, + document: false, + }, + }); + options.addDeclaration({ name: "visibilityFilters", help: (i18n) => i18n.help_visibilityFilters(),