@@ -2,23 +2,38 @@ import * as Path from "path";
22import { Builder , trimmer } from "lunr" ;
33
44import {
5+ Comment ,
56 DeclarationReflection ,
67 ProjectReflection ,
78 ReflectionKind ,
89} from "../../models" ;
910import { GroupPlugin } from "../../converter/plugins" ;
1011import { Component , RendererComponent } from "../components" ;
11- import { RendererEvent } from "../events" ;
12- import { writeFileSync } from "../../utils" ;
12+ import { IndexEvent , RendererEvent } from "../events" ;
13+ import { BindOption , writeFileSync } from "../../utils" ;
1314import { DefaultTheme } from "../themes/default/DefaultTheme" ;
1415
16+ /**
17+ * Keep this in sync with the interface in src/lib/output/themes/default/assets/typedoc/components/Search.ts
18+ */
19+ interface SearchDocument {
20+ kind : number ;
21+ name : string ;
22+ url : string ;
23+ classes ?: string ;
24+ parent ?: string ;
25+ }
26+
1527/**
1628 * A plugin that exports an index of the project to a javascript file.
1729 *
1830 * The resulting javascript file can be used to build a simple search function.
1931 */
2032@Component ( { name : "javascript-index" } )
2133export class JavascriptIndexPlugin extends RendererComponent {
34+ @BindOption ( "searchInComments" )
35+ searchComments ! : boolean ;
36+
2237 /**
2338 * Create a new JavascriptIndexPlugin instance.
2439 */
@@ -39,30 +54,52 @@ export class JavascriptIndexPlugin extends RendererComponent {
3954 return ;
4055 }
4156
42- const rows : any [ ] = [ ] ;
57+ const rows : SearchDocument [ ] = [ ] ;
4358 const kinds : { [ K in ReflectionKind ] ?: string } = { } ;
4459
45- for ( const reflection of event . project . getReflectionsByKind (
46- ReflectionKind . All
60+ const initialSearchResults = Object . values (
61+ event . project . reflections
62+ ) . filter ( ( refl ) => {
63+ return (
64+ refl instanceof DeclarationReflection &&
65+ refl . url &&
66+ refl . name &&
67+ ! refl . flags . isExternal
68+ ) ;
69+ } ) as DeclarationReflection [ ] ;
70+
71+ const indexEvent = new IndexEvent (
72+ IndexEvent . PREPARE_INDEX ,
73+ initialSearchResults
74+ ) ;
75+
76+ this . owner . trigger ( indexEvent ) ;
77+
78+ if ( indexEvent . isDefaultPrevented ) {
79+ return ;
80+ }
81+
82+ const builder = new Builder ( ) ;
83+ builder . pipeline . add ( trimmer ) ;
84+
85+ builder . ref ( "id" ) ;
86+ for ( const [ key , boost ] of Object . entries (
87+ indexEvent . searchFieldWeights
4788 ) ) {
48- if ( ! ( reflection instanceof DeclarationReflection ) ) {
49- continue ;
50- }
89+ builder . field ( key , { boost } ) ;
90+ }
5191
52- if (
53- ! reflection . url ||
54- ! reflection . name ||
55- reflection . flags . isExternal
56- ) {
92+ for ( const reflection of indexEvent . searchResults ) {
93+ if ( ! reflection . url ) {
5794 continue ;
5895 }
5996
60- let parent = reflection . parent ;
6197 const boost = reflection . relevanceBoost ?? 1 ;
6298 if ( boost <= 0 ) {
6399 continue ;
64100 }
65101
102+ let parent = reflection . parent ;
66103 if ( parent instanceof ProjectReflection ) {
67104 parent = undefined ;
68105 }
@@ -73,34 +110,29 @@ export class JavascriptIndexPlugin extends RendererComponent {
73110 ) ;
74111 }
75112
76- const row : any = {
77- id : rows . length ,
113+ const row : SearchDocument = {
78114 kind : reflection . kind ,
79115 name : reflection . name ,
80116 url : reflection . url ,
81117 classes : reflection . cssClasses ,
82118 } ;
83119
84- if ( boost !== 1 ) {
85- row . boost = boost ;
86- }
87-
88120 if ( parent ) {
89121 row . parent = parent . getFullName ( ) ;
90122 }
91123
124+ builder . add (
125+ {
126+ name : reflection . name ,
127+ comment : this . getCommentSearchText ( reflection ) ,
128+ ...indexEvent . searchFields [ rows . length ] ,
129+ id : rows . length ,
130+ } ,
131+ { boost }
132+ ) ;
92133 rows . push ( row ) ;
93134 }
94135
95- const builder = new Builder ( ) ;
96- builder . pipeline . add ( trimmer ) ;
97-
98- builder . ref ( "id" ) ;
99- builder . field ( "name" , { boost : 10 } ) ;
100- builder . field ( "parent" ) ;
101-
102- rows . forEach ( ( row ) => builder . add ( row ) ) ;
103-
104136 const index = builder . build ( ) ;
105137
106138 const jsonFileName = Path . join (
@@ -120,4 +152,29 @@ export class JavascriptIndexPlugin extends RendererComponent {
120152 `window.searchData = JSON.parse(${ JSON . stringify ( jsonData ) } );`
121153 ) ;
122154 }
155+
156+ private getCommentSearchText ( reflection : DeclarationReflection ) {
157+ if ( ! this . searchComments ) return ;
158+
159+ const comments : Comment [ ] = [ ] ;
160+ if ( reflection . comment ) comments . push ( reflection . comment ) ;
161+ reflection . signatures ?. forEach (
162+ ( s ) => s . comment && comments . push ( s . comment )
163+ ) ;
164+ reflection . getSignature ?. comment &&
165+ comments . push ( reflection . getSignature . comment ) ;
166+ reflection . setSignature ?. comment &&
167+ comments . push ( reflection . setSignature . comment ) ;
168+
169+ if ( ! comments . length ) {
170+ return ;
171+ }
172+
173+ return comments
174+ . flatMap ( ( c ) => {
175+ return [ ...c . summary , ...c . blockTags . flatMap ( ( t ) => t . content ) ] ;
176+ } )
177+ . map ( ( part ) => part . text )
178+ . join ( "\n" ) ;
179+ }
123180}
0 commit comments