Skip to content

Commit 5a6c9bf

Browse files
mrfiggGerrit0
authored andcommitted
Implemented client side hierarchy
Removed unused translations Attempt to solve circular dependency Some requested changes, still more to do Simplified fake PageEvent for now Better hierarchy partial arguments Fix possible stray zero Removed braking changes, implemented static hierarchy summary, other requested changes
1 parent 2a89667 commit 5a6c9bf

File tree

17 files changed

+788
-75
lines changed

17 files changed

+788
-75
lines changed

example/src/classes/Customer.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ export abstract class Customer {
7979

8080
/**
8181
* A class that extends {@link Customer | `Customer`}.
82+
*
83+
* Notice how TypeDoc shows the inheritance hierarchy for our class.
8284
*/
8385
export class DeliveryCustomer extends Customer {
8486
/** A property defined on the subclass. */
@@ -118,3 +120,31 @@ export class DeliveryCustomer extends Customer {
118120
return typeof this.preferredCourierId === "undefined";
119121
}
120122
}
123+
124+
/**
125+
* A class that extends {@link Customer | `Customer`}.
126+
*
127+
* Notice how TypeDoc shows the inheritance hierarchy for our class.
128+
*/
129+
export class WalkInCustomer extends Customer {
130+
/** A property defined on the subclass. */
131+
trustedCustomer?: boolean;
132+
133+
/** A private property defined on the subclass. */
134+
private _ordersPlacedCount: number = 0;
135+
136+
/**
137+
* An example of overriding a public method.
138+
*/
139+
onOrderPlaced(): void {
140+
super.onOrderPlaced();
141+
142+
this._ordersPlacedCount++;
143+
144+
if (
145+
this._ordersPlacedCount > 10 &&
146+
typeof this.trustedCustomer === "undefined"
147+
)
148+
this.trustedCustomer = true;
149+
}
150+
}

src/lib/internationalization/locales/en.cts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ export = {
301301
help_sluggerConfiguration:
302302
"Determines how anchors within rendered HTML are determined.",
303303
help_navigation: "Determines how the navigation sidebar is organized",
304+
help_includeHierarchySummary:
305+
"If set, a reflections hierarchy summary will be rendered to a summary page. Defaults to `true`",
304306
help_visibilityFilters:
305307
"Specify the default visibility for builtin filters and additional filters according to modifier tags",
306308
help_searchCategoryBoosts:
@@ -480,15 +482,17 @@ export = {
480482
theme_type_declaration: "Type declaration",
481483
theme_index: "Index",
482484
theme_hierarchy: "Hierarchy",
483-
theme_hierarchy_view_full: "view full",
485+
theme_hierarchy_summary: "Hierarchy Summary",
486+
theme_hierarchy_view_summary: "View Summary",
487+
theme_hierarchy_expand: "Expand",
488+
theme_hierarchy_collapse: "Collapse",
484489
theme_implemented_by: "Implemented by",
485490
theme_defined_in: "Defined in",
486491
theme_implementation_of: "Implementation of",
487492
theme_inherited_from: "Inherited from",
488493
theme_overrides: "Overrides",
489494
theme_returns: "Returns",
490495
theme_generated_using_typedoc: "Generated using TypeDoc", // If this includes "TypeDoc", theme will insert a link at that location.
491-
theme_class_hierarchy_title: "Class Hierarchy",
492496
// Search
493497
theme_preparing_search_index: "Preparing search index...",
494498
theme_search_index_not_available: "The search index is not available",

src/lib/internationalization/locales/jp.cts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,6 @@ export = localeUtils.buildIncompleteTranslation({
458458
theme_type_declaration: "型宣言",
459459
theme_index: "インデックス",
460460
theme_hierarchy: "階層",
461-
theme_hierarchy_view_full: "完全な階層を表示",
462461
theme_implemented_by: "実装者",
463462
theme_defined_in: "定義",
464463
theme_implementation_of: "の実装",
@@ -485,6 +484,5 @@ export = localeUtils.buildIncompleteTranslation({
485484
theme_copied: "コピー完了!",
486485
theme_normally_hidden:
487486
"このメンバーは、フィルター設定のため、通常は非表示になっています。",
488-
theme_class_hierarchy_title: "クラス継承図",
489487
theme_loading: "読み込み中...",
490488
});

src/lib/internationalization/locales/ko.cts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,6 @@ export = localeUtils.buildIncompleteTranslation({
317317
theme_type_declaration: "타입 선언",
318318
theme_index: "둘러보기",
319319
theme_hierarchy: "계층",
320-
theme_hierarchy_view_full: "전체 보기",
321320
theme_implemented_by: "구현",
322321
theme_defined_in: "정의 위치:",
323322
theme_implementation_of: "구현하는 타입:",

src/lib/internationalization/locales/zh.cts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,15 +459,13 @@ export = localeUtils.buildIncompleteTranslation({
459459
theme_type_declaration: "类型声明",
460460
theme_index: "索引",
461461
theme_hierarchy: "层级",
462-
theme_hierarchy_view_full: "查看完整内容",
463462
theme_implemented_by: "实现于",
464463
theme_defined_in: "定义于",
465464
theme_implementation_of: "实现了",
466465
theme_inherited_from: "继承自",
467466
theme_overrides: "重写了",
468467
theme_returns: "返回",
469468
theme_generated_using_typedoc: "使用 TypeDoc 生成",
470-
theme_class_hierarchy_title: "类继承图表",
471469

472470
theme_preparing_search_index: "正在准备搜索索引...",
473471
theme_search_index_not_available: "搜索索引不可用",
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import * as Path from "path";
2+
import { RendererComponent } from "../components.js";
3+
import { PageEvent, RendererEvent } from "../events.js";
4+
import { JSX, writeFile } from "../../utils/index.js";
5+
import { DefaultTheme } from "../themes/default/DefaultTheme.js";
6+
import { gzip } from "zlib";
7+
import { promisify } from "util";
8+
import {
9+
DeclarationReflection,
10+
ReferenceType,
11+
ReflectionKind,
12+
} from "../../models/index.js";
13+
import type { Renderer } from "../index.js";
14+
15+
const gzipP = promisify(gzip);
16+
17+
export interface HierarchyElement {
18+
html: string;
19+
text: string;
20+
path: string;
21+
parents?: ({ path: string } | { html: string; text: string })[];
22+
children?: ({ path: string } | { html: string; text: string })[];
23+
}
24+
25+
export class HierarchyPlugin extends RendererComponent {
26+
constructor(renderer: Renderer) {
27+
super(renderer);
28+
this.owner.on(RendererEvent.BEGIN, this.onRendererBegin.bind(this));
29+
}
30+
31+
private onRendererBegin(_event: RendererEvent) {
32+
if (!(this.owner.theme instanceof DefaultTheme)) {
33+
return;
34+
}
35+
36+
this.owner.preRenderAsyncJobs.push((event) =>
37+
this.buildHierarchy(event),
38+
);
39+
}
40+
41+
private async buildHierarchy(event: RendererEvent) {
42+
const theme = this.owner.theme as DefaultTheme;
43+
44+
const context = theme.getRenderContext(new PageEvent(event.project));
45+
46+
const hierarchy = (
47+
event.project.getReflectionsByKind(
48+
ReflectionKind.ClassOrInterface,
49+
) as DeclarationReflection[]
50+
)
51+
.filter(
52+
(reflection) =>
53+
reflection.extendedTypes?.length ||
54+
reflection.extendedBy?.length,
55+
)
56+
.map((reflection) => ({
57+
html: JSX.renderElement(
58+
context.type(
59+
ReferenceType.createResolvedReference(
60+
reflection.name,
61+
reflection,
62+
reflection.project,
63+
),
64+
),
65+
),
66+
// Full name should be safe here, since this list only includes classes/interfaces.
67+
text: reflection.getFullName(),
68+
path: reflection.url!,
69+
parents: reflection.extendedTypes?.map((type) =>
70+
!(type instanceof ReferenceType) ||
71+
!(type.reflection instanceof DeclarationReflection)
72+
? {
73+
html: JSX.renderElement(context.type(type)),
74+
text: type.toString(),
75+
}
76+
: { path: type.reflection.url! },
77+
),
78+
children: reflection.extendedBy?.map((type) =>
79+
!(type instanceof ReferenceType) ||
80+
!(type.reflection instanceof DeclarationReflection)
81+
? {
82+
html: JSX.renderElement(context.type(type)),
83+
text: type.toString(),
84+
}
85+
: { path: type.reflection.url! },
86+
),
87+
}));
88+
89+
if (!hierarchy.length) return;
90+
91+
hierarchy.forEach((element) => {
92+
if (!element.parents?.length) delete element.parents;
93+
94+
if (!element.children?.length) delete element.children;
95+
});
96+
97+
const hierarchyJs = Path.join(
98+
event.outputDirectory,
99+
"assets",
100+
"hierarchy.js",
101+
);
102+
103+
const gz = await gzipP(Buffer.from(JSON.stringify(hierarchy)));
104+
105+
await writeFile(
106+
hierarchyJs,
107+
`window.hierarchyData = "data:application/octet-stream;base64,${gz.toString(
108+
"base64",
109+
)}"`,
110+
);
111+
}
112+
}

src/lib/output/plugins/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { MarkedPlugin } from "../themes/MarkedPlugin.js";
22
export { AssetsPlugin } from "./AssetsPlugin.js";
3+
export { HierarchyPlugin } from "./HierarchyPlugin.js";
34
export { IconsPlugin } from "./IconsPlugin.js";
45
export { JavascriptIndexPlugin } from "./JavascriptIndexPlugin.js";
56
export { NavigationPlugin } from "./NavigationPlugin.js";

src/lib/output/renderer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { setRenderSettings } from "../utils/jsx.js";
3434

3535
import {
3636
AssetsPlugin,
37+
HierarchyPlugin,
3738
IconsPlugin,
3839
JavascriptIndexPlugin,
3940
MarkedPlugin,
@@ -259,6 +260,7 @@ export class Renderer extends AbstractComponent<Application, RendererEvents> {
259260
this.markedPlugin = new MarkedPlugin(this);
260261
new AssetsPlugin(this);
261262
new IconsPlugin(this);
263+
new HierarchyPlugin(this);
262264
new JavascriptIndexPlugin(this);
263265
new NavigationPlugin(this);
264266
new SitemapPlugin(this);

src/lib/output/themes/default/DefaultTheme.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export class DefaultTheme extends Theme {
183183
urls.push(new UrlMapping("index.html", project, this.indexTemplate));
184184
}
185185

186-
if (getHierarchyRoots(project).length) {
186+
if (this.application.options.getValue("includeHierarchySummary") && getHierarchyRoots(project).length) {
187187
urls.push(new UrlMapping("hierarchy.html", project, this.hierarchyTemplate));
188188
}
189189

src/lib/output/themes/default/assets/bootstrap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Filter } from "./typedoc/components/Filter.js";
55
import { Accordion } from "./typedoc/components/Accordion.js";
66
import { initTheme } from "./typedoc/Theme.js";
77
import { initNav } from "./typedoc/Navigation.js";
8+
import { initHierarchy } from "./typedoc/Hierarchy.js";
89

910
registerComponent(Toggle, "a[data-toggle]");
1011
registerComponent(Accordion, ".tsd-accordion");
@@ -24,3 +25,4 @@ Object.defineProperty(window, "app", { value: app });
2425

2526
initSearch();
2627
initNav();
28+
initHierarchy();

0 commit comments

Comments
 (0)