@@ -5,6 +5,7 @@ import { qs, escapeHtmlEntities, isBlank, getQueryParamByName, getProjectNameAnd
55import  {  setSearchInputValue  }  from  './search-bar' 
66import  searchResultsTemplate  from  './handlebars/templates/search-results.handlebars' 
77import  {  getSearchNodes  }  from  './globals' 
8+ import  {  highlightMatches  }  from  './highlighter' 
89
910const  EXCERPT_RADIUS  =  80 
1011const  SEARCH_CONTAINER_SELECTOR  =  '#search' 
@@ -24,7 +25,7 @@ lunr.Pipeline.registerFunction(docTrimmerFunction, 'docTrimmer')
2425window . addEventListener ( 'swup:page:view' ,  initialize ) 
2526initialize ( ) 
2627
27- function  initialize   ( )  { 
28+ function  initialize ( )  { 
2829  const  pathname  =  window . location . pathname 
2930  if  ( pathname . endsWith ( '/search.html' )  ||  pathname . endsWith ( '/search' ) )  { 
3031    const  query  =  getQueryParamByName ( 'q' ) 
@@ -33,7 +34,7 @@ function initialize () {
3334  } 
3435} 
3536
36- async  function  search   ( value ,  queryType )  { 
37+ async  function  search ( value ,  queryType )  { 
3738  if  ( isBlank ( value ) )  { 
3839    renderResults ( {  value } ) 
3940  }  else  { 
@@ -56,7 +57,7 @@ async function search (value, queryType) {
5657  } 
5758} 
5859
59- async  function  localSearch   ( value )  { 
60+ async  function  localSearch ( value )  { 
6061  const  index  =  await  getIndex ( ) 
6162
6263  // We cannot match on atoms :foo because that would be considered 
@@ -65,7 +66,7 @@ async function localSearch (value) {
6566  return  searchResultsToDecoratedSearchItems ( index . search ( fixedValue ) ) 
6667} 
6768
68- async  function  remoteSearch   ( value ,  queryType ,  searchNodes )  { 
69+ async  function  remoteSearch ( value ,  queryType ,  searchNodes )  { 
6970  let  filterNodes  =  searchNodes 
7071
7172  if  ( queryType  ===  'latest' )  { 
@@ -86,7 +87,7 @@ async function remoteSearch (value, queryType, searchNodes) {
8687    return  payload . hits . map ( result  =>  { 
8788      const  [ packageName ,  packageVersion ]  =  result . document . package . split ( '-' ) 
8889
89-       const  doc  =  result . document . doc 
90+       const  doc  =  highlightMatches ( result . document . doc ,   value ,   {   multiline :  true   } ) 
9091      const  excerpts  =  [ doc ] 
9192      const  metadata  =  { } 
9293      const  ref  =  `https://hexdocs.pm/${ packageName } ${ packageVersion } ${ result . document . ref }  
@@ -107,13 +108,13 @@ async function remoteSearch (value, queryType, searchNodes) {
107108  } 
108109} 
109110
110- function  renderResults   ( {  value,  results,  errorMessage } )  { 
111+ function  renderResults ( {  value,  results,  errorMessage } )  { 
111112  const  searchContainer  =  qs ( SEARCH_CONTAINER_SELECTOR ) 
112113  const  resultsHtml  =  searchResultsTemplate ( {  value,  results,  errorMessage } ) 
113114  searchContainer . innerHTML  =  resultsHtml 
114115} 
115116
116- async  function  getIndex   ( )  { 
117+ async  function  getIndex ( )  { 
117118  const  cachedIndex  =  await  loadIndex ( ) 
118119  if  ( cachedIndex )  {  return  cachedIndex  } 
119120
@@ -122,7 +123,7 @@ async function getIndex () {
122123  return  index 
123124} 
124125
125- async  function  loadIndex   ( )  { 
126+ async  function  loadIndex ( )  { 
126127  try  { 
127128    const  serializedIndex  =  sessionStorage . getItem ( indexStorageKey ( ) ) 
128129    if  ( serializedIndex )  { 
@@ -137,7 +138,7 @@ async function loadIndex () {
137138  } 
138139} 
139140
140- async  function  saveIndex   ( index )  { 
141+ async  function  saveIndex ( index )  { 
141142  try  { 
142143    const  serializedIndex  =  await  compress ( index ) 
143144    sessionStorage . setItem ( indexStorageKey ( ) ,  serializedIndex ) 
@@ -146,7 +147,7 @@ async function saveIndex (index) {
146147  } 
147148} 
148149
149- async  function  compress   ( index )  { 
150+ async  function  compress ( index )  { 
150151  const  stream  =  new  Blob ( [ JSON . stringify ( index ) ] ,  { 
151152    type : 'application/json' 
152153  } ) . stream ( ) . pipeThrough ( new  window . CompressionStream ( 'gzip' ) ) 
@@ -156,7 +157,7 @@ async function compress (index) {
156157  return  b64encode ( buffer ) 
157158} 
158159
159- async  function  decompress   ( index )  { 
160+ async  function  decompress ( index )  { 
160161  const  stream  =  new  Blob ( [ b64decode ( index ) ] ,  { 
161162    type : 'application/json' 
162163  } ) . stream ( ) . pipeThrough ( new  window . DecompressionStream ( 'gzip' ) ) 
@@ -165,7 +166,7 @@ async function decompress (index) {
165166  return  JSON . parse ( blob ) 
166167} 
167168
168- function  b64encode   ( buffer )  { 
169+ function  b64encode ( buffer )  { 
169170  let  binary  =  '' 
170171  const  bytes  =  new  Uint8Array ( buffer ) 
171172  const  len  =  bytes . byteLength 
@@ -175,7 +176,7 @@ function b64encode (buffer) {
175176  return  window . btoa ( binary ) 
176177} 
177178
178- function  b64decode   ( str )  { 
179+ function  b64decode ( str )  { 
179180  const  binaryString  =  window . atob ( str ) 
180181  const  len  =  binaryString . length 
181182  const  bytes  =  new  Uint8Array ( new  ArrayBuffer ( len ) ) 
@@ -185,11 +186,11 @@ function b64decode (str) {
185186  return  bytes 
186187} 
187188
188- function  indexStorageKey   ( )  { 
189+ function  indexStorageKey ( )  { 
189190  return  `idv5:${ getProjectNameAndVersion ( ) }  
190191} 
191192
192- function  createIndex   ( )  { 
193+ function  createIndex ( )  { 
193194  return  lunr ( function  ( )  { 
194195    this . ref ( 'ref' ) 
195196    this . field ( 'title' ,  {  boost : 3  } ) 
@@ -207,11 +208,11 @@ function createIndex () {
207208  } ) 
208209} 
209210
210- function  docTokenSplitter   ( builder )  { 
211+ function  docTokenSplitter ( builder )  { 
211212  builder . pipeline . before ( lunr . stemmer ,  docTokenFunction ) 
212213} 
213214
214- function  docTokenFunction   ( token )  { 
215+ function  docTokenFunction ( token )  { 
215216  // If we have something with an arity, we split on : . to make partial 
216217  // matches easier. We split only when tokenizing, not when searching. 
217218  // Below we use ExDoc.Markdown.to_ast/2 as an example. 
@@ -275,11 +276,11 @@ function docTokenFunction (token) {
275276  return  tokens 
276277} 
277278
278- function  docTrimmer   ( builder )  { 
279+ function  docTrimmer ( builder )  { 
279280  builder . pipeline . before ( lunr . stemmer ,  docTrimmerFunction ) 
280281} 
281282
282- function  docTrimmerFunction   ( token )  { 
283+ function  docTrimmerFunction ( token )  { 
283284  // Preserve @ and : at the beginning of tokens, 
284285  // and ? and ! at the end of tokens. It needs to 
285286  // be done before stemming, otherwise search and 
@@ -289,7 +290,7 @@ function docTrimmerFunction (token) {
289290  } ) 
290291} 
291292
292- function  searchResultsToDecoratedSearchItems   ( results )  { 
293+ function  searchResultsToDecoratedSearchItems ( results )  { 
293294  return  results 
294295    // If the docs are regenerated without changing its version, 
295296    // a reference may have been doc'ed false in the code but 
@@ -306,11 +307,11 @@ function searchResultsToDecoratedSearchItems (results) {
306307    } ) 
307308} 
308309
309- function  getSearchItemByRef   ( ref )  { 
310+ function  getSearchItemByRef ( ref )  { 
310311  return  searchData . items . find ( searchItem  =>  searchItem . ref  ===  ref )  ||  null 
311312} 
312313
313- function  getExcerpts   ( searchItem ,  metadata )  { 
314+ function  getExcerpts ( searchItem ,  metadata )  { 
314315  const  {  doc }  =  searchItem 
315316  const  searchTerms  =  Object . keys ( metadata ) 
316317
@@ -331,7 +332,7 @@ function getExcerpts (searchItem, metadata) {
331332  return  excerpts . slice ( 0 ,  1 ) 
332333} 
333334
334- function  excerpt   ( doc ,  sliceStart ,  sliceLength )  { 
335+ function  excerpt ( doc ,  sliceStart ,  sliceLength )  { 
335336  const  startPos  =  Math . max ( sliceStart  -  EXCERPT_RADIUS ,  0 ) 
336337  const  endPos  =  Math . min ( sliceStart  +  sliceLength  +  EXCERPT_RADIUS ,  doc . length ) 
337338  return  [ 
0 commit comments