Skip to content

Commit 09d7c26

Browse files
committed
Add additional validation for boost options
1 parent d6e5b18 commit 09d7c26

File tree

4 files changed

+74
-18
lines changed

4 files changed

+74
-18
lines changed

src/lib/output/plugins/JavascriptIndexPlugin.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export class JavascriptIndexPlugin extends RendererComponent {
6464
}
6565

6666
let parent = reflection.parent;
67+
let boost = reflection.relevanceBoost ?? 1;
6768
if (parent instanceof ProjectReflection) {
6869
parent = undefined;
6970
}
@@ -73,10 +74,9 @@ export class JavascriptIndexPlugin extends RendererComponent {
7374
reflection.kind
7475
);
7576

76-
const boost = kindBoosts[kinds[reflection.kind] ?? ""];
77-
if (boost != undefined) {
78-
reflection.relevanceBoost =
79-
(reflection.relevanceBoost ?? 1) * boost;
77+
const kindBoost = kindBoosts[kinds[reflection.kind] ?? ""];
78+
if (kindBoost != undefined) {
79+
boost *= kindBoost;
8080
}
8181
}
8282

@@ -86,9 +86,12 @@ export class JavascriptIndexPlugin extends RendererComponent {
8686
name: reflection.name,
8787
url: reflection.url,
8888
classes: reflection.cssClasses,
89-
relevanceBoost: reflection.relevanceBoost,
9089
};
9190

91+
if (boost !== 1) {
92+
row.boost = boost;
93+
}
94+
9295
if (parent) {
9396
row.parent = parent.getFullName();
9497
}

src/lib/output/themes/default/assets/typedoc/components/Search.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface IDocument {
88
url: string;
99
classes?: string;
1010
parent?: string;
11-
relevanceBoost?: number;
11+
boost?: number;
1212
}
1313

1414
interface IData {
@@ -169,7 +169,7 @@ function updateResults(
169169
}
170170

171171
// boost by relevanceBoost
172-
boost *= row.relevanceBoost ?? 1;
172+
boost *= row.boost ?? 1;
173173

174174
item.score *= boost;
175175
}

src/lib/utils/options/sources/typedoc.ts

+32-11
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,36 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
7474
name: "searchCategoryBoosts",
7575
help: "Configure search to give a relevance boost to selected categories",
7676
type: ParameterType.Mixed,
77+
validate(value) {
78+
if (!isObject(value)) {
79+
throw new Error(
80+
"The 'searchCategoryBoosts' option must be a non-array object."
81+
);
82+
}
83+
84+
if (Object.values(value).some((x) => typeof x !== "number")) {
85+
throw new Error(
86+
"All values of 'searchCategoryBoosts' must be numbers."
87+
);
88+
}
89+
},
7790
});
7891
options.addDeclaration({
7992
name: "searchGroupBoosts",
8093
help: 'Configure search to give a relevance boost to selected kinds (eg "class")',
8194
type: ParameterType.Mixed,
8295
validate(value: unknown) {
96+
if (!isObject(value)) {
97+
throw new Error(
98+
"The 'searchGroupBoosts' option must be a non-array object."
99+
);
100+
}
101+
83102
const validValues = Object.values(ReflectionKind)
84103
.filter((v) => typeof v === "string")
85104
.map((v) => v.toString());
86105

87-
for (const kindName in value as { [key: string]: number }) {
106+
for (const kindName in value) {
88107
if (validValues.indexOf(kindName) < 0) {
89108
throw new Error(
90109
`'${kindName}' is an invalid value for 'searchGroupBoosts'. Must be one of: ${validValues.join(
@@ -93,6 +112,12 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
93112
);
94113
}
95114
}
115+
116+
if (Object.values(value).some((x) => typeof x !== "number")) {
117+
throw new Error(
118+
"All values of 'searchGroupBoosts' must be numbers."
119+
);
120+
}
96121
},
97122
});
98123
options.addDeclaration({
@@ -341,11 +366,7 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
341366
help: "Specify the options passed to Marked, the Markdown parser used by TypeDoc.",
342367
type: ParameterType.Mixed,
343368
validate(value) {
344-
if (
345-
typeof value !== "object" ||
346-
Array.isArray(value) ||
347-
value == null
348-
) {
369+
if (!isObject(value)) {
349370
throw new Error(
350371
"The 'markedOptions' option must be a non-array object."
351372
);
@@ -357,11 +378,7 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
357378
help: "Selectively override the TypeScript compiler options used by TypeDoc.",
358379
type: ParameterType.Mixed,
359380
validate(value) {
360-
if (
361-
typeof value !== "object" ||
362-
Array.isArray(value) ||
363-
value == null
364-
) {
381+
if (!isObject(value)) {
365382
throw new Error(
366383
"The 'compilerOptions' option must be a non-array object."
367384
);
@@ -429,3 +446,7 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
429446
},
430447
});
431448
}
449+
450+
function isObject(x: unknown): x is Record<string, unknown> {
451+
return !!x && typeof x === "object" && !Array.isArray(x);
452+
}

src/test/utils/options/default-options.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,36 @@ describe("Default Options", () => {
7676
);
7777
});
7878
});
79+
80+
describe("searchCategoryBoosts", () => {
81+
it("Should disallow non-objects", () => {
82+
throws(() => opts.setValue("searchCategoryBoosts", null as never));
83+
});
84+
85+
it("Should disallow non-numbers", () => {
86+
throws(() =>
87+
opts.setValue("searchCategoryBoosts", {
88+
cat: true,
89+
})
90+
);
91+
});
92+
});
93+
94+
describe("searchGroupBoosts", () => {
95+
it("Should disallow non-objects", () => {
96+
throws(() => opts.setValue("searchGroupBoosts", null as never));
97+
});
98+
99+
it("Should disallow invalid kind names", () => {
100+
throws(() => opts.setValue("searchGroupBoosts", { Enum2: 123 }));
101+
});
102+
103+
it("Should disallow non-numbers", () => {
104+
throws(() => opts.setValue("searchGroupBoosts", { Enum: true }));
105+
});
106+
107+
it("Should allow groups", () => {
108+
doesNotThrow(() => opts.setValue("searchGroupBoosts", { Enum: 5 }));
109+
});
110+
});
79111
});

0 commit comments

Comments
 (0)