From 977adc79a97e4d9cebee1c128c663c421c421e12 Mon Sep 17 00:00:00 2001 From: Pascal Garber Date: Mon, 26 Jun 2023 17:33:24 +0200 Subject: [PATCH] chore(typedoc-theme): Generate navigation json file for each module --- .gitmodules | 3 - .../typedoc-build-docs/typedoc.try-gjs.json | 15 +- .../src/plugin/plugin.tsx | 2 +- .../typedoc-theme/src/partials/navigation.tsx | 152 +++++++++++++++--- .../typedoc-theme/src/theme-render-context.ts | 6 +- packages/typedoc-theme/src/theme.tsx | 26 ++- packages/typedoc-theme/src/types/index.ts | 1 + .../src/types/navigation-data.ts | 12 ++ vendor/ts-for-gjs | 1 - 9 files changed, 190 insertions(+), 28 deletions(-) create mode 100644 packages/typedoc-theme/src/types/navigation-data.ts delete mode 160000 vendor/ts-for-gjs diff --git a/.gitmodules b/.gitmodules index d1d36a253..5ee3bb44a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,6 +11,3 @@ [submodule "@types"] path = @types url = https://github.com/gjsify/types.git -[submodule "vendor/ts-for-gjs"] - path = vendor/ts-for-gjs - url = https://github.com/gjsify/ts-for-gir.git diff --git a/packages/typedoc-build-docs/typedoc.try-gjs.json b/packages/typedoc-build-docs/typedoc.try-gjs.json index ac0b1a21c..083691c34 100644 --- a/packages/typedoc-build-docs/typedoc.try-gjs.json +++ b/packages/typedoc-build-docs/typedoc.try-gjs.json @@ -11,5 +11,18 @@ "noScript": true, "noReplaceElement": true, "serverBaseUrl": "https://try-gjs-docs.gjsify.org/", - "theme": "gjsify" + "theme": "gjsify", + "navigation": { + "includeCategories": true, + "includeGroups": true + }, + "categorizeByGroup": true, + "visibilityFilters": { + "protected": true, + "private": true, + "inherited": true, + "external": true, + "@alpha": true, + "@beta": true + } } \ No newline at end of file diff --git a/packages/typedoc-plugin-remote-search/src/plugin/plugin.tsx b/packages/typedoc-plugin-remote-search/src/plugin/plugin.tsx index 23b031eec..71b98f810 100644 --- a/packages/typedoc-plugin-remote-search/src/plugin/plugin.tsx +++ b/packages/typedoc-plugin-remote-search/src/plugin/plugin.tsx @@ -212,7 +212,7 @@ export class RemoteSearchIndexPlugin { private async onRenderDone() { this.copyScripts(); - await this.convertSearch(); + // await this.convertSearch(); } /** diff --git a/packages/typedoc-theme/src/partials/navigation.tsx b/packages/typedoc-theme/src/partials/navigation.tsx index d15e26567..f44ef57cb 100644 --- a/packages/typedoc-theme/src/partials/navigation.tsx +++ b/packages/typedoc-theme/src/partials/navigation.tsx @@ -11,7 +11,7 @@ import { classNames, getDisplayName, wbr } from "../lib"; import type { PageEvent } from "typedoc"; import type { GjsifyThemeRenderContext } from "../theme-render-context"; -import type { Module } from "../types"; +import type { Module, NavigationData } from "../types"; export function sidebarLinks(context: GjsifyThemeRenderContext) { const links = Object.entries(context.options.getValue("sidebarLinks")); @@ -62,7 +62,7 @@ function getNavigationElements( return parent.children || []; } -export function getModules( +export function getModulesData( context: GjsifyThemeRenderContext, props: PageEvent ) { @@ -86,6 +86,111 @@ export function getModules( return modules; } +export function navigationData( + context: GjsifyThemeRenderContext, + props: PageEvent, + forceOptions: { + includeCategories?: boolean; + includeGroups?: boolean; + fullTree?: boolean; + } = {} +): NavigationData { + const opts = { ...context.options.getValue("navigation"), ...forceOptions }; + // Create the navigation for the current page + // Recurse to children if the parent is some kind of module + + return createNavElementData(props.project); + + function linksData( + mod: NavigationElement, + parents: string[] + ): NavigationData { + const nameClasses = classNames( + { deprecated: mod instanceof Reflection && mod.isDeprecated() }, + mod instanceof DeclarationReflection + ? context.getReflectionClasses(mod) + : void 0 + ); + + const _children = getNavigationElements(mod, opts); + + if ( + !_children.length || + (!opts.fullTree && + mod instanceof Reflection && + !navigationInPath(props, mod)) + ) { + return createNavElementData(mod, parents, nameClasses); + } + + const nav = createNavElementData(mod, parents); + + nav.children = _children.map((c) => + linksData( + c, + mod instanceof Reflection + ? [mod.getFullName()] + : [...parents, mod.title] + ) + ); + + return nav; + } + + function createNavElementData( + child: NavigationElement | ProjectReflection, + parents: string[] = [], + nameClasses?: string + ): NavigationData { + const key = + child instanceof Reflection + ? child.getFullName() + : [...parents, child.title].join("$"); + + // const active = child instanceof Reflection && inPath(child); + // const current = child === props.model; + // const classes = classNames({}, nameClasses); + + const children: NavigationData[] = []; + + for (const c of getNavigationElements(child, opts)) { + // Ignore root Modules which are not active / in path on not fullTree + if (!opts.fullTree && !navigationInPath(props, c)) continue; + + const parentsNext = + child instanceof Reflection + ? [child.getFullName()] + : [...parents, child.title]; + + children.push(linksData(c, parentsNext)); + } + + if (child instanceof Reflection) { + return { + key, + // active, + // current, + url: context.absoluteUrl(child.url), + title: getDisplayName(child), // TODO wbr + // classes, + kind: child.kind, + children, + }; + } + + return { + // key, + // active, + // current, + title: child.title, + isGroup: child instanceof ReflectionGroup, + + // classes, + children, + }; + } +} + export function navigation( context: GjsifyThemeRenderContext, props: PageEvent @@ -94,13 +199,19 @@ export function navigation( // Create the navigation for the current page // Recurse to children if the parent is some kind of module + // console.debug("navigation", navigationData(context, props)); + + const addTitle = false; + return ( ); @@ -117,7 +228,9 @@ export function navigation( if ( !children.length || - (!opts.fullTree && mod instanceof Reflection && !inPath(mod)) + (!opts.fullTree && + mod instanceof Reflection && + !navigationInPath(props, mod)) ) { return createNavElement(mod, nameClasses); } @@ -125,7 +238,7 @@ export function navigation( return (
{child.title}; } - - function inPath(mod: DeclarationReflection | ProjectReflection) { - let iter: Reflection | undefined = props.model; - do { - if (iter == mod) return true; - iter = iter.parent; - } while (iter); - return false; - } } export function pageNavigation( @@ -192,7 +296,7 @@ export function pageNavigation( function finalizeLevel() { const built = (
    - {levels.pop()!.map((l) => ( + {levels.pop()?.map((l) => (
  • {l}
  • ))}
@@ -284,3 +388,15 @@ function inPath( return false; } + +function navigationInPath( + props: PageEvent, + mod: NavigationElement +) { + let iter: Reflection | undefined = props.model; + do { + if (iter == mod) return true; + iter = iter.parent; + } while (iter); + return false; +} diff --git a/packages/typedoc-theme/src/theme-render-context.ts b/packages/typedoc-theme/src/theme-render-context.ts index 6356badbd..bc918ccf8 100644 --- a/packages/typedoc-theme/src/theme-render-context.ts +++ b/packages/typedoc-theme/src/theme-render-context.ts @@ -27,9 +27,10 @@ import { members } from "./partials/members"; import { membersGroup } from "./partials/members.group"; import { navigation, + navigationData, pageNavigation, sidebarLinks, - getModules, + getModulesData, getCurrentModule, } from "./partials/navigation"; import { gjsifySidebar, gjsifySidebarContent } from "./partials/gjsify-sidebar"; @@ -162,7 +163,8 @@ export class GjsifyThemeRenderContext { navigation = bind(navigation, this); gjsifySidebar = bind(gjsifySidebar, this); gjsifySidebarContent = bind(gjsifySidebarContent, this); - getModules = bind(getModules, this); + getModulesData = bind(getModulesData, this); + navigationData = bind(navigationData, this); getCurrentModule = bind(getCurrentModule, this); pageNavigation = bind(pageNavigation, this); parameter = bind(parameter, this); diff --git a/packages/typedoc-theme/src/theme.tsx b/packages/typedoc-theme/src/theme.tsx index 35e4028ac..53bf6cf4d 100644 --- a/packages/typedoc-theme/src/theme.tsx +++ b/packages/typedoc-theme/src/theme.tsx @@ -13,7 +13,6 @@ import { PageEvent, } from "typedoc"; import { JSX } from "./jsx/index.js"; -import type { Renderer } from "typedoc"; import { MarkedPlugin } from "typedoc/dist/lib/output/themes/MarkedPlugin"; import { toStyleClass } from "./lib"; @@ -22,6 +21,9 @@ import { AssetService } from "./services/asset.service"; import { writeFileSync } from "./utils"; import { join } from "path"; +import type { Renderer } from "typedoc"; +import type { NavigationData } from "./types"; + /** * Defines a mapping of a {@link Models.Kind} to a template file. * @@ -152,6 +154,7 @@ export class GjsifyTheme extends Theme { onPageHomeEnd(page: PageEvent) { this.writeModulesJsonFile(page); + this.writeModuleNavigationJsonFiles(page); } onRendererEnd(event: RendererEvent) { @@ -312,10 +315,29 @@ export class GjsifyTheme extends Theme { const target = join(outputDirectory, "assets", filename); - const modules = context.getModules(page); + const modules = context.getModulesData(page); writeFileSync(target, JSON.stringify(modules, null, 0)); } + writeModuleNavigationJsonFiles(page: PageEvent) { + const context = this.getRenderContext(page); + const navData = context.navigationData(page, { fullTree: true }); + for (const child of navData.children) { + this.writeModuleNavigationJsonFile(child); + } + } + + writeModuleNavigationJsonFile(mod: NavigationData) { + if (mod.kind !== ReflectionKind.Module) { + throw new Error(`Expected module, got ${mod.kind}`); + } + const filename = `navigation-${mod.title.toLowerCase()}.json`; + this.logger.info(`[GjsifyTheme] Generate ${filename}...`); + const outputDirectory = this.application.options.getValue("out"); + const target = join(outputDirectory, "assets", filename); + writeFileSync(target, JSON.stringify(mod, null, 0)); + } + render( page: PageEvent, template: RenderTemplate> diff --git a/packages/typedoc-theme/src/types/index.ts b/packages/typedoc-theme/src/types/index.ts index 88d059c51..9f9a5883e 100644 --- a/packages/typedoc-theme/src/types/index.ts +++ b/packages/typedoc-theme/src/types/index.ts @@ -1,2 +1,3 @@ export * from "@gjsify/typedoc-theme-client/scripts/types/index.js"; export * from "./internal.js"; +export * from "./navigation-data.js"; diff --git a/packages/typedoc-theme/src/types/navigation-data.ts b/packages/typedoc-theme/src/types/navigation-data.ts new file mode 100644 index 000000000..08174f7c8 --- /dev/null +++ b/packages/typedoc-theme/src/types/navigation-data.ts @@ -0,0 +1,12 @@ +import type { ReflectionKind } from "typedoc"; + +export interface NavigationData { + key?: string; + title: string; + url?: string; + // classes?: string | undefined; + kind?: ReflectionKind; + children: NavigationData[]; + // active: boolean; + isGroup?: boolean; +} diff --git a/vendor/ts-for-gjs b/vendor/ts-for-gjs deleted file mode 160000 index f5bcfd1e8..000000000 --- a/vendor/ts-for-gjs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f5bcfd1e830d7c1eda588d55aa071d01509e9065