From 1d5da8195e3ebbd37e0e94005b1cfd0730b226ef Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 16 Oct 2022 11:17:15 -0400 Subject: [PATCH 1/4] Add support for `titleLink`, `navigationLinks`, and `sidebarLinks` options --- .../default/DefaultThemeRenderContext.ts | 2 + .../themes/default/partials/navigation.tsx | 15 +++++++ .../themes/default/partials/toolbar.tsx | 14 ++++-- src/lib/utils/options/declaration.ts | 3 ++ src/lib/utils/options/sources/typedoc.ts | 43 +++++++++++++++++++ static/style.css | 36 +++++++++++++++- 6 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/lib/output/themes/default/DefaultThemeRenderContext.ts b/src/lib/output/themes/default/DefaultThemeRenderContext.ts index af3c4928f..6c72ccee5 100644 --- a/src/lib/output/themes/default/DefaultThemeRenderContext.ts +++ b/src/lib/output/themes/default/DefaultThemeRenderContext.ts @@ -31,6 +31,7 @@ import { primaryNavigation, secondaryNavigation, settings, + sidebarLinks, } from "./partials/navigation"; import { parameter } from "./partials/parameter"; import { toolbar } from "./partials/toolbar"; @@ -105,6 +106,7 @@ export class DefaultThemeRenderContext { members = bind(members, this); membersGroup = bind(membersGroup, this); navigation = bind(navigation, this); + sidebarLinks = bind(sidebarLinks, this); settings = bind(settings, this); primaryNavigation = bind(primaryNavigation, this); secondaryNavigation = bind(secondaryNavigation, this); diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index e2cd16e6e..79884410d 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -7,6 +7,7 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; export function navigation(context: DefaultThemeRenderContext, props: PageEvent) { return ( <> + {context.sidebarLinks()} {context.settings()} {context.primaryNavigation(props)} {context.secondaryNavigation(props)} @@ -26,6 +27,20 @@ function buildFilterItem(context: DefaultThemeRenderContext, name: string, displ ); } +export function sidebarLinks(context: DefaultThemeRenderContext) { + const links = Object.entries(context.options.getValue("sidebarLinks")); + if (!links.length) return null; + return ( + + ); +} + export function settings(context: DefaultThemeRenderContext) { const defaultFilters = context.options.getValue("visibilityFilters") as Record; diff --git a/src/lib/output/themes/default/partials/toolbar.tsx b/src/lib/output/themes/default/partials/toolbar.tsx index 138a0b3d2..9f525fb22 100644 --- a/src/lib/output/themes/default/partials/toolbar.tsx +++ b/src/lib/output/themes/default/partials/toolbar.tsx @@ -8,24 +8,32 @@ export const toolbar = (context: DefaultThemeRenderContext, props: PageEvent diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index b47f8df79..ead4959c9 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -119,6 +119,9 @@ export interface TypeDocOptionMap { hideGenerator: boolean; searchInComments: boolean; cleanOutputDir: boolean; + titleLink: string; + navigationLinks: ManuallyValidatedOption>; + sidebarLinks: ManuallyValidatedOption>; commentStyle: typeof CommentStyle; blockTags: `@${string}`[]; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 85c2ce510..e1015481f 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -307,6 +307,49 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Boolean, defaultValue: true, }); + options.addDeclaration({ + name: "titleLink", + help: "Set the link the title in the header points to. Defaults to the documentation homepage.", + type: ParameterType.String, + }); + options.addDeclaration({ + name: "navigationLinks", + help: "Defines links to be included in the header.", + type: ParameterType.Mixed, + defaultValue: {}, + validate(value) { + if (!isObject(value)) { + throw new Error( + `navigationLinks must be an object with string labels as keys and URL values.` + ); + } + + if (Object.values(value).some((x) => typeof x !== "string")) { + throw new Error( + `All values of navigationLinks must be string URLs.` + ); + } + }, + }); + options.addDeclaration({ + name: "sidebarLinks", + help: "Defines links to be included in the sidebar.", + type: ParameterType.Mixed, + defaultValue: {}, + validate(value) { + if (!isObject(value)) { + throw new Error( + `sidebarLinks must be an object with string labels as keys and URL values.` + ); + } + + if (Object.values(value).some((x) => typeof x !== "string")) { + throw new Error( + `All values of sidebarLinks must be string URLs.` + ); + } + }, + }); /////////////////////////// ///// Comment Options ///// diff --git a/static/style.css b/static/style.css index 958d2c263..e5093854c 100644 --- a/static/style.css +++ b/static/style.css @@ -825,6 +825,15 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { padding-left: 5.5rem; } +#tsd-sidebar-links a { + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.25rem; +} +#tsd-sidebar-links a:last-of-type { + margin-bottom: 0; +} + a.tsd-index-link { margin: 0.25rem 0; font-size: 1rem; @@ -978,7 +987,8 @@ a.tsd-index-link { right: -40px; } #tsd-search .field input, -#tsd-search .title { +#tsd-search .title, +#tsd-toolbar-links a { transition: opacity 0.2s; } #tsd-search .results { @@ -1022,7 +1032,8 @@ a.tsd-index-link { top: 0; opacity: 1; } -#tsd-search.has-focus .title { +#tsd-search.has-focus .title, +#tsd-search.has-focus #tsd-toolbar-links a { z-index: 0; opacity: 0; } @@ -1036,6 +1047,22 @@ a.tsd-index-link { display: block; } +#tsd-toolbar-links { + position: absolute; + top: 0; + right: 2rem; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-end; +} +#tsd-toolbar-links a { + margin-left: 1.5rem; +} +#tsd-toolbar-links a:hover { + text-decoration: underline; +} + .tsd-signature { margin: 0 0 1rem 0; padding: 1rem 0.5rem; @@ -1134,6 +1161,11 @@ ul.tsd-type-parameter-list h5 { .tsd-page-toolbar .table-cell:first-child { width: 100%; } +.tsd-page-toolbar .tsd-toolbar-icon { + box-sizing: border-box; + line-height: 0; + padding: 12px 0; +} .tsd-page-toolbar--hide { transform: translateY(-100%); From 767b9b14f2ad5579a6ea2e3462d5a97a767252c8 Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 16 Oct 2022 11:18:45 -0400 Subject: [PATCH 2/4] Add navigationLinks and sidebarLinks to the example --- example/typedoc.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/example/typedoc.json b/example/typedoc.json index 6ebbe1921..6c90d7775 100644 --- a/example/typedoc.json +++ b/example/typedoc.json @@ -10,5 +10,12 @@ }, "searchGroupBoosts": { "Classes": 1.5 + }, + "navigationLinks": { + "Docs": "https://typedoc.org/guides/overview", + "GitHub": "https://github.com/TypeStrong/typedoc" + }, + "sidebarLinks": { + "API": "https://typedoc.org/api" } } From 3badd681f11fa37e77ee93e3b22aced3792a6f0c Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 16 Oct 2022 11:37:31 -0400 Subject: [PATCH 3/4] Tests --- .../utils/options/default-options.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/test/utils/options/default-options.test.ts b/src/test/utils/options/default-options.test.ts index 63badd718..3b02fd1fb 100644 --- a/src/test/utils/options/default-options.test.ts +++ b/src/test/utils/options/default-options.test.ts @@ -108,4 +108,32 @@ describe("Default Options", () => { doesNotThrow(() => opts.setValue("searchGroupBoosts", { Enum: 5 })); }); }); + + describe("headerLinks", () => { + it("Should disallow non-objects", () => { + throws(() => opts.setValue("navigationLinks", null as never)); + }); + + it("Should disallow non-strings", () => { + throws(() => + opts.setValue("navigationLinks", { + "Home": true as any as string, + }) + ); + }); + }); + + describe("sidebarLinks", () => { + it("Should disallow non-objects", () => { + throws(() => opts.setValue("sidebarLinks", null as never)); + }); + + it("Should disallow non-strings", () => { + throws(() => + opts.setValue("sidebarLinks", { + "Home": true as any as string, + }) + ); + }); + }); }); From c0b44200d8422a94d690aa7468403ea6b1f58ecb Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 16 Oct 2022 19:21:42 -0400 Subject: [PATCH 4/4] lint --- src/test/utils/options/default-options.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/utils/options/default-options.test.ts b/src/test/utils/options/default-options.test.ts index 3b02fd1fb..aa6bf93b3 100644 --- a/src/test/utils/options/default-options.test.ts +++ b/src/test/utils/options/default-options.test.ts @@ -117,7 +117,7 @@ describe("Default Options", () => { it("Should disallow non-strings", () => { throws(() => opts.setValue("navigationLinks", { - "Home": true as any as string, + Home: true as any as string, }) ); }); @@ -131,7 +131,7 @@ describe("Default Options", () => { it("Should disallow non-strings", () => { throws(() => opts.setValue("sidebarLinks", { - "Home": true as any as string, + Home: true as any as string, }) ); });