@@ -99,10 +99,18 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
9999
100100 callback ( fuse . search ( query , searchOptions )
101101 . map ( result => {
102+ const addParam = ( url , name , value ) => {
103+ const anchorParts = url . split ( '#' ) ;
104+ const baseUrl = anchorParts [ 0 ] ;
105+ const sep = baseUrl . search ( "\\?" ) > 0 ? "&" : "?" ;
106+ anchorParts [ 0 ] = baseUrl + sep + name + "=" + value ;
107+ return anchorParts . join ( "#" ) ;
108+ }
109+
102110 return {
103111 title : result . item . title ,
104112 section : result . item . section ,
105- href : result . item . href ,
113+ href : addParam ( result . item . href , "q" , query ) ,
106114 text : highlightMatch ( query , result . item . text )
107115 }
108116 } )
@@ -157,4 +165,99 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
157165 console . log ( error ) ;
158166 } ) ;
159167
168+ // If there is a query param indicating that a search was performed, highlight any matching terms
169+ const params = new URLSearchParams ( window . location . search ) ;
170+ if ( params . has ( "q" ) ) {
171+
172+ // show the search term in the search box
173+ const searchterm = params . get ( "q" ) ;
174+ searchEl . value = searchterm ;
175+ searchEl . focus ( ) ;
176+
177+ // Search the main section of the document for matching terms to highlight
178+ const mainEl = window . document . querySelector ( "main" ) ;
179+ if ( mainEl ) {
180+ // highlight matches
181+ highlight ( searchterm , mainEl ) ;
182+
183+ // if the input changes, clear the highlighting
184+ let highlighting = true ;
185+ searchEl . addEventListener ( 'input' , ( ) => {
186+ if ( highlighting && searchEl . value !== searchterm ) {
187+ clearHighlight ( searchterm , mainEl )
188+ highlighting = false ;
189+ }
190+ } ) ;
191+
192+ // clear the search input if the user presses 'esc'
193+ searchEl . onkeydown = ( event ) => {
194+ if ( event . key === "Escape" ) {
195+ searchEl . value = "" ;
196+ }
197+ }
198+ }
199+ }
160200} ) ;
201+
202+ // removes highlighting as implemented by the mark tag
203+ function clearHighlight ( searchterm , el ) {
204+ const childNodes = el . childNodes ;
205+ for ( let i = childNodes . length - 1 ; i >= 0 ; i -- ) {
206+ const node = childNodes [ i ] ;
207+ if ( node . nodeType === Node . ELEMENT_NODE ) {
208+ if ( node . tagName === 'MARK' && node . innerText . toLowerCase ( ) === searchterm . toLowerCase ( ) ) {
209+ el . replaceChild ( document . createTextNode ( node . innerText ) , node ) ;
210+ } else {
211+ clearHighlight ( searchterm , node ) ;
212+ }
213+ }
214+ }
215+ }
216+
217+ // highlight matches
218+ function highlight ( term , el ) {
219+ const termRegex = new RegExp ( term , 'ig' )
220+ const childNodes = el . childNodes ;
221+
222+ // walk back to front avoid mutating elements in front of us
223+ for ( let i = childNodes . length - 1 ; i >= 0 ; i -- ) {
224+ const node = childNodes [ i ] ;
225+
226+
227+ if ( node . nodeType === Node . TEXT_NODE ) {
228+ // Search text nodes for text to highlight
229+ const text = node . nodeValue ;
230+
231+ let startIndex = 0 ;
232+ let matchIndex = text . search ( termRegex ) ;
233+ if ( matchIndex > - 1 ) {
234+ const markFragment = document . createDocumentFragment ( ) ;
235+ while ( matchIndex > - 1 ) {
236+ const prefix = text . slice ( startIndex , matchIndex ) ;
237+ markFragment . appendChild ( document . createTextNode ( prefix ) ) ;
238+
239+ const mark = document . createElement ( "mark" ) ;
240+ mark . appendChild ( document . createTextNode ( text . slice ( matchIndex , matchIndex + term . length ) ) ) ;
241+ markFragment . appendChild ( mark ) ;
242+
243+
244+ startIndex = matchIndex + term . length ;
245+ matchIndex = text . slice ( startIndex ) . search ( new RegExp ( term , 'ig' ) ) ;
246+ if ( matchIndex > - 1 ) {
247+ matchIndex = startIndex + matchIndex ;
248+ }
249+ }
250+ if ( startIndex < text . length ) {
251+ markFragment . appendChild ( document . createTextNode ( text . slice ( startIndex , text . length ) ) ) ;
252+ }
253+
254+ el . replaceChild ( markFragment , node ) ;
255+ }
256+ } else if ( node . nodeType === Node . ELEMENT_NODE ) {
257+ // recurse through elements
258+ highlight ( term , node ) ;
259+ }
260+ }
261+ }
262+
263+
0 commit comments