Skip to content

Commit ed70884

Browse files
committed
Add plugin for TypeStrong/typedoc#2775
1 parent ef61847 commit ed70884

File tree

6 files changed

+108
-3
lines changed

6 files changed

+108
-3
lines changed

build/bin/docs.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function createTypeDocOptionsForFrontendProjects(frontendProjects) {
3333
out: DocsDir,
3434
tsconfig: tsConfig,
3535
plugin: [
36+
"./build/typedoc-plugin/typeof-class-plugin.mjs",
3637
"typedoc-plugin-merge-modules",
3738
// "typedoc-plugin-missing-exports",
3839
"typedoc-plugin-dt-links",

build/common/find-frontend-projects.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from "node:path";
22
import fs from "node:fs/promises";
33

4-
import { assertDoesNotExist, assertExistsAndIsFile, ensureDirectoryExists, existsAndIsDirectory, existsAndIsFile } from "./file.mjs";
4+
import { assertDoesNotExist, assertExistsAndIsFile, ensureDirectoryExists, existsAndIsFile } from "./file.mjs";
55
import { PackagesDir } from "./environment.mjs";
66

77
/**

build/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
"types": ["node"],
1212
"lib": ["esnext"],
1313
},
14-
"include": ["bin", "common", "esbuild-plugin"]
14+
"include": ["bin", "common", "esbuild-plugin", "typedoc-plugin"]
1515
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/** @import { Application, DeclarationReflection } from "typedoc" */
2+
3+
import { Converter, ReflectionKind } from "typedoc";
4+
5+
/** @param {DeclarationReflection} declaration */
6+
function hackInheritance(declaration) {
7+
if (!declaration.extendedTypes) {
8+
return;
9+
}
10+
11+
for (let i = 0; i < declaration.extendedTypes.length; ++i) {
12+
const type = declaration.extendedTypes[i];
13+
if (type === undefined) {
14+
continue;
15+
}
16+
if (type.type !== "reference") {
17+
continue;
18+
}
19+
if (!type.reflection) {
20+
continue;
21+
}
22+
23+
const target = /** @type {DeclarationReflection} */(type.reflection);
24+
25+
if (target.kindOf(ReflectionKind.ClassOrInterface)) {
26+
continue;
27+
}
28+
29+
const targetType = target.type;
30+
if (targetType === undefined || targetType.type !== "query") {
31+
continue;
32+
}
33+
if (!targetType.queryType.reflection?.kindOf(ReflectionKind.ClassOrInterface)) {
34+
continue;
35+
}
36+
37+
// We inherit from a property somewhere which is declared as `typeof SomeClass`
38+
// So re-point the inheritance to SomeClass
39+
declaration.extendedTypes[i] = targetType.queryType;
40+
}
41+
}
42+
43+
/**
44+
* Plugin for TypeDoc to handle `typeof` class inheritance. When `X` is
45+
* a class, `A = X` is a variable assigned to the class with a declared
46+
* type of `typeof X`, and another class uses `A` as a base class, then
47+
* TypeDoc will not resolve the class hierarchy correctly. For example,
48+
*
49+
* ```ts
50+
* class X {}
51+
*
52+
* interface Registry {
53+
* X: typeof X;
54+
* }
55+
* declare const registry: Registry;
56+
*
57+
* class Y extends registry.X {}
58+
* ```
59+
*
60+
* This plugin scans for such cases where a class has an expression
61+
* in its extends clause. If it finds the type of the expression is
62+
* `typeof X`, it replaces the extends clause with `X`. This way,
63+
* the class hierarchy is correctly resolved.
64+
*
65+
* See also:
66+
* https://github.com/TypeStrong/typedoc/issues/2775
67+
*
68+
* @param {Application} app
69+
*/
70+
export function load(app) {
71+
app.converter.on(
72+
Converter.EVENT_RESOLVE_BEGIN,
73+
(context) => {
74+
for (const decl of context.project.getReflectionsByKind(ReflectionKind.ClassOrInterface)) {
75+
hackInheritance(/** @type {DeclarationReflection} */(decl));
76+
}
77+
},
78+
1e6,
79+
);
80+
}

packages/components/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
import { InputText } from "./src/InputText.js";
12
import { InputTextArea } from "./src/InputTextArea.js";
23

34
declare global {
45
namespace PrimeType {
56
export interface WidgetRegistry {
7+
InputText: typeof InputText;
68
InputTextArea: typeof InputTextArea;
79
}
810
}
911
namespace PrimeType.widget {
12+
export type InputText = import("./src/InputText.js").InputText;
1013
export type InputTextAreaCfg = import("./src/InputTextArea.js").InputTextAreaCfg;
1114
}
1215
}
1316

1417
// @ts-expect-errors
1518
(window.PrimeFaces ??= {}).widget ??= {};
16-
PrimeFaces.widget.BaseWidget = InputTextArea;
19+
PrimeFaces.widget.InputText = InputText;
20+
PrimeFaces.widget.InputTextArea = InputTextArea;

packages/components/src/InputText.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export interface InputTextCfg extends PrimeType.widget.BaseWidgetCfg {
2+
id: string;
3+
resize: boolean;
4+
}
5+
6+
export class InputText extends PrimeFaces.widget.BaseWidget {
7+
readonly input: string;
8+
constructor(cfg: InputTextCfg) {
9+
super(cfg);
10+
this.input = "textarea";
11+
}
12+
13+
focus(): void {
14+
this.jq.focus();
15+
}
16+
17+
override render(): void {
18+
this.jq.animate({ opacity: 0 }, 500);
19+
}
20+
}

0 commit comments

Comments
 (0)