diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cab2a298..000dcb489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - It is now possible to link directly to a specific overload, #1326. - The JSON output will now include URLs to the file on the remote repository if possible. - Added a new `visibilityFilters` option which controls the available filters on a page. +- TypeDoc will now try to place block elements on a new line in HTML output, resulting in less overwhelming diffs when rebuilding docs, #1923. ### Bug Fixes diff --git a/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index 472336a5b..9b37f00d9 100644 --- a/src/lib/output/renderer.ts +++ b/src/lib/output/renderer.ts @@ -24,6 +24,7 @@ import type { Theme as ShikiTheme } from "shiki"; import { ReferenceType, Reflection } from "../models"; import type { JsxElement } from "../utils/jsx.elements"; import type { DefaultThemeRenderContext } from "./themes/default/DefaultThemeRenderContext"; +import { clearSeenIconCache } from "./themes/default/partials/icon"; /** * Describes the hooks available to inject output in the default theme. @@ -250,6 +251,7 @@ export class Renderer extends ChildableComponent< if (!output.isDefaultPrevented) { output.urls.forEach((mapping: UrlMapping) => { + clearSeenIconCache(); this.renderDocument(output.createPageEvent(mapping)); }); diff --git a/src/lib/output/themes/default/partials/icon.tsx b/src/lib/output/themes/default/partials/icon.tsx index 4474e46f6..ab861313b 100644 --- a/src/lib/output/themes/default/partials/icon.tsx +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -3,26 +3,53 @@ import { JSX } from "../../../../utils"; type UtilityIcons = Record<"chevronDown" | "checkbox" | "menu" | "search" | "chevronSmall", () => JSX.Element>; -const kindIcon = (letterPath: JSX.Element, color: string, circular = false) => ( - - - {letterPath} - -); +const seenIcons = new Set(); + +export function clearSeenIconCache() { + seenIcons.clear(); +} + +const kindIcon = (kind: ReflectionKind, letterPath: JSX.Element, color: string, circular = false) => { + const content: JSX.Element[] = []; + + if (seenIcons.has(kind)) { + content.push(); + content.push(); + } else { + seenIcons.add(kind); + content.push( + + ); + content.push({ + ...letterPath, + props: { + ...letterPath.props, + id: `icon-text-${kind}`, + }, + }); + } + + return ( + + {content} + + ); +}; export const icons: Record JSX.Element | null> & UtilityIcons = { - [ReflectionKind.All]: () => null, [ReflectionKind.Accessor]: () => kindIcon( + ReflectionKind.Accessor, JSX.Element | null> & UtilityIc }, [ReflectionKind.Class]: () => kindIcon( + ReflectionKind.Class, JSX.Element | null> & UtilityIc }, [ReflectionKind.Constructor]: () => kindIcon( + ReflectionKind.Constructor, JSX.Element | null> & UtilityIc }, [ReflectionKind.Enum]: () => kindIcon( + ReflectionKind.Enum, JSX.Element | null> & UtilityIc }, [ReflectionKind.Function]: () => kindIcon( + ReflectionKind.Function, , "var(--color-ts-function)" ), @@ -84,9 +115,9 @@ export const icons: Record JSX.Element | null> & UtilityIc [ReflectionKind.IndexSignature]() { return this[ReflectionKind.Property](); }, - [ReflectionKind.Inheritable]: () => null, [ReflectionKind.Interface]: () => kindIcon( + ReflectionKind.Interface, JSX.Element | null> & UtilityIc ), [ReflectionKind.Method]: () => kindIcon( + ReflectionKind.Method, JSX.Element | null> & UtilityIc [ReflectionKind.Namespace]: () => kindIcon( + ReflectionKind.Namespace, JSX.Element | null> & UtilityIc }, [ReflectionKind.Property]: () => kindIcon( + ReflectionKind.Property, JSX.Element | null> & UtilityIc [ReflectionKind.SetSignature]() { return this[ReflectionKind.Accessor](); }, - [ReflectionKind.SomeSignature]: () => null, - [ReflectionKind.SomeModule]: () => null, - [ReflectionKind.SomeType]: () => null, - [ReflectionKind.SomeValue]: () => null, [ReflectionKind.TypeAlias]: () => kindIcon( + ReflectionKind.TypeAlias, , "var(--color-ts)" ), @@ -153,15 +184,13 @@ export const icons: Record JSX.Element | null> & UtilityIc }, [ReflectionKind.Variable]: () => kindIcon( + ReflectionKind.Variable, , "var(--color-ts-variable)" ), - [ReflectionKind.VariableOrProperty]() { - return this[ReflectionKind.Variable](); - }, chevronDown: () => ( {prependName ? `${prependName} - ${item.title}` : item.title} diff --git a/src/lib/utils/jsx.elements.ts b/src/lib/utils/jsx.elements.ts index 883b2698b..bf91cb55d 100644 --- a/src/lib/utils/jsx.elements.ts +++ b/src/lib/utils/jsx.elements.ts @@ -117,6 +117,7 @@ export interface IntrinsicElements { svg: JsxSvgElementProps; path: JsxPathElementProps; rect: JsxRectElementProps; + use: JsxUseElementProps; } export const JsxFragment = Symbol(); @@ -1058,3 +1059,20 @@ export interface JsxRectElementProps x?: string | number; y?: string | number; } + +/** + * Properties permitted on the `` element. + * + * Reference: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use + */ +export interface JsxUseElementProps + extends JsxSvgCoreProps, + JsxSvgStyleProps, + JsxSvgConditionalProcessingProps, + JsxSvgPresentationProps { + href: string; + x?: string | number; + y?: string | number; + width?: string | number; + height?: string | number; +} diff --git a/src/lib/utils/jsx.ts b/src/lib/utils/jsx.ts index 0f8156add..3aff70359 100644 --- a/src/lib/utils/jsx.ts +++ b/src/lib/utils/jsx.ts @@ -83,6 +83,23 @@ const voidElements = new Set([ "wbr", ]); +const blockElements = new Set([ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "div", + "section", + "nav", + "details", + "p", + "ul", + "ol", + "li", +]); + /** * JSX factory function to create an "element" that can later be rendered with {@link renderElement} * @param tag @@ -114,6 +131,9 @@ export function renderElement(element: JsxElement | null | undefined): string { const html: string[] = []; if (tag !== Fragment) { + if (blockElements.has(tag)) { + html.push("\n"); + } html.push("<", tag); for (const [key, val] of Object.entries(props ?? {})) { diff --git a/src/test/capture-screenshots.ts b/src/test/capture-screenshots.ts index 66f8c83dd..274ee194f 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -1,6 +1,6 @@ import * as fs from "fs"; import { platform } from "os"; -import { resolve, join, dirname } from "path"; +import { resolve, join, dirname, relative } from "path"; import { Application, TSConfigReader, EntryPointStrategy } from ".."; import { remove } from "../lib/utils"; import { glob } from "../lib/utils/fs"; @@ -63,7 +63,6 @@ export async function captureRegressionScreenshots() { logger: "console", readme: join(src, "..", "README.md"), name: "typedoc", - disableSources: true, cleanOutputDir: true, tsconfig: join(src, "..", "tsconfig.json"), plugin: [], @@ -95,7 +94,7 @@ export async function captureScreenshots( const absPath = resolve(baseDirectory, file); const outputPath = resolve( outputDirectory, - file.replace(".html", "") + relative(baseDirectory, file).replace(".html", "") ); fs.mkdirSync(dirname(outputPath), { recursive: true });