1
- /* eslint-env browser */
2
- window . antoraLunr = ( function ( lunr ) {
1
+ /* global CustomEvent */
2
+ ; ( function ( globalScope ) {
3
+ /* eslint-disable no-var */
4
+ var config = document . getElementById ( 'search-ui-script' ) . dataset
5
+ var snippetLength = parseInt ( config . snippetLength || 100 , 10 )
6
+ var siteRootPath = config . siteRootPath || ''
7
+ appendStylesheet ( config . stylesheet )
3
8
var searchInput = document . getElementById ( 'search-input' )
4
9
var searchResult = document . createElement ( 'div' )
5
10
searchResult . classList . add ( 'search-result-dropdown-menu' )
6
11
searchInput . parentNode . appendChild ( searchResult )
7
12
13
+ function appendStylesheet ( href ) {
14
+ if ( ! href ) return
15
+ document . head . appendChild ( Object . assign ( document . createElement ( 'link' ) , { rel : 'stylesheet' , href : href } ) )
16
+ }
17
+
8
18
function highlightText ( doc , position ) {
9
19
var hits = [ ]
10
20
var start = position [ 0 ]
@@ -17,9 +27,8 @@ window.antoraLunr = (function (lunr) {
17
27
18
28
var end = start + length
19
29
var textEnd = text . length - 1
20
- var contextOffset = 15
21
- var contextAfter = end + contextOffset > textEnd ? textEnd : end + contextOffset
22
- var contextBefore = start - contextOffset < 0 ? 0 : start - contextOffset
30
+ var contextAfter = end + snippetLength > textEnd ? textEnd : end + snippetLength
31
+ var contextBefore = start - snippetLength < 0 ? 0 : start - snippetLength
23
32
if ( start === 0 && end === textEnd ) {
24
33
hits . push ( highlightSpan )
25
34
} else if ( start === 0 ) {
@@ -36,18 +45,16 @@ window.antoraLunr = (function (lunr) {
36
45
return hits
37
46
}
38
47
39
- function highlightTitle ( hash , doc , position ) {
48
+ function highlightTitle ( sectionTitle , doc , position ) {
40
49
var hits = [ ]
41
50
var start = position [ 0 ]
42
51
var length = position [ 1 ]
43
52
44
53
var highlightSpan = document . createElement ( 'span' )
45
54
highlightSpan . classList . add ( 'search-result-highlight' )
46
55
var title
47
- if ( hash ) {
48
- title = doc . titles . filter ( function ( item ) {
49
- return item . id === hash
50
- } ) [ 0 ] . text
56
+ if ( sectionTitle ) {
57
+ title = sectionTitle . text
51
58
} else {
52
59
title = doc . title
53
60
}
@@ -71,7 +78,7 @@ window.antoraLunr = (function (lunr) {
71
78
return hits
72
79
}
73
80
74
- function highlightHit ( metadata , hash , doc ) {
81
+ function highlightHit ( metadata , sectionTitle , doc ) {
75
82
var hits = [ ]
76
83
for ( var token in metadata ) {
77
84
var fields = metadata [ token ]
@@ -80,7 +87,7 @@ window.antoraLunr = (function (lunr) {
80
87
if ( positions . position ) {
81
88
var position = positions . position [ 0 ] // only higlight the first match
82
89
if ( field === 'title' ) {
83
- hits = highlightTitle ( hash , doc , position )
90
+ hits = highlightTitle ( sectionTitle , doc , position )
84
91
} else if ( field === 'text' ) {
85
92
hits = highlightText ( doc , position )
86
93
}
@@ -90,30 +97,32 @@ window.antoraLunr = (function (lunr) {
90
97
return hits
91
98
}
92
99
93
- function createSearchResult ( result , store , searchResultDataset ) {
100
+ function createSearchResult ( result , store , searchResultDataset ) {
94
101
result . forEach ( function ( item ) {
95
- var url = item . ref
96
- var hash
97
- if ( url . includes ( '#' ) ) {
98
- hash = url . substring ( url . indexOf ( '#' ) + 1 )
99
- url = url . replace ( '#' + hash , '' )
102
+ var ids = item . ref . split ( '-' )
103
+ var docId = ids [ 0 ]
104
+ var doc = store [ docId ]
105
+ var sectionTitle
106
+ if ( ids . length > 1 ) {
107
+ var titleId = ids [ 1 ]
108
+ sectionTitle = doc . titles . filter ( function ( item ) {
109
+ return String ( item . id ) === titleId
110
+ } ) [ 0 ]
100
111
}
101
- var doc = store [ url ]
102
112
var metadata = item . matchData . metadata
103
- var hits = highlightHit ( metadata , hash , doc )
104
- searchResultDataset . appendChild ( createSearchResultItem ( doc , item , hits ) )
113
+ var hits = highlightHit ( metadata , sectionTitle , doc )
114
+ searchResultDataset . appendChild ( createSearchResultItem ( doc , sectionTitle , item , hits ) )
105
115
} )
106
116
}
107
117
108
- function createSearchResultItem ( doc , item , hits ) {
118
+ function createSearchResultItem ( doc , sectionTitle , item , hits ) {
109
119
var documentTitle = document . createElement ( 'div' )
110
120
documentTitle . classList . add ( 'search-result-document-title' )
111
121
documentTitle . innerText = doc . title
112
122
var documentHit = document . createElement ( 'div' )
113
123
documentHit . classList . add ( 'search-result-document-hit' )
114
124
var documentHitLink = document . createElement ( 'a' )
115
- var rootPath = window . antora . basePath
116
- documentHitLink . href = rootPath + item . ref
125
+ documentHitLink . href = siteRootPath + doc . url + ( sectionTitle ? '#' + sectionTitle . hash : '' )
117
126
documentHit . appendChild ( documentHitLink )
118
127
hits . forEach ( function ( hit ) {
119
128
documentHitLink . appendChild ( hit )
@@ -140,6 +149,11 @@ window.antoraLunr = (function (lunr) {
140
149
return searchResultItem
141
150
}
142
151
152
+ function clearSearchResults ( reset ) {
153
+ if ( reset === true ) searchInput . value = ''
154
+ searchResult . innerHTML = ''
155
+ }
156
+
143
157
function search ( index , text ) {
144
158
// execute an exact match search
145
159
var result = index . search ( text )
@@ -157,10 +171,7 @@ window.antoraLunr = (function (lunr) {
157
171
}
158
172
159
173
function searchIndex ( index , store , text ) {
160
- // reset search result
161
- while ( searchResult . firstChild ) {
162
- searchResult . removeChild ( searchResult . firstChild )
163
- }
174
+ clearSearchResults ( false )
164
175
if ( text . trim ( ) === '' ) {
165
176
return
166
177
}
@@ -175,6 +186,10 @@ window.antoraLunr = (function (lunr) {
175
186
}
176
187
}
177
188
189
+ function confineEvent ( e ) {
190
+ e . stopPropagation ( )
191
+ }
192
+
178
193
function debounce ( func , wait , immediate ) {
179
194
var timeout
180
195
return function ( ) {
@@ -191,22 +206,43 @@ window.antoraLunr = (function (lunr) {
191
206
}
192
207
}
193
208
194
- function init ( data ) {
195
- var index = Object . assign ( { index : lunr . Index . load ( data . index ) , store : data . store } )
196
- var search = debounce ( function ( ) {
197
- searchIndex ( index . index , index . store , searchInput . value )
198
- } , 100 )
199
- searchInput . addEventListener ( 'keydown' , search )
200
-
201
- // this is prevented in case of mousedown attached to SearchResultItem
202
- searchInput . addEventListener ( 'blur' , function ( e ) {
203
- while ( searchResult . firstChild ) {
204
- searchResult . removeChild ( searchResult . firstChild )
205
- }
206
- } )
209
+ function enableSearchInput ( enabled ) {
210
+ searchInput . disabled = ! enabled
211
+ searchInput . title = enabled ? '' : 'Loading index...'
207
212
}
208
213
209
- return {
210
- init : init ,
214
+ function initSearch ( lunr , data ) {
215
+ var start = performance . now ( )
216
+ var index = Object . assign ( { index : lunr . Index . load ( data . index ) , store : data . store } )
217
+ enableSearchInput ( true )
218
+ searchInput . dispatchEvent (
219
+ new CustomEvent ( 'loadedindex' , {
220
+ detail : {
221
+ took : performance . now ( ) - start ,
222
+ } ,
223
+ } )
224
+ )
225
+ var debug = 'URLSearchParams' in globalScope && new URLSearchParams ( globalScope . location . search ) . has ( 'lunr-debug' )
226
+ searchInput . addEventListener (
227
+ 'keydown' ,
228
+ debounce ( function ( e ) {
229
+ if ( e . key === 'Escape' || e . key === 'Esc' ) return clearSearchResults ( true )
230
+ try {
231
+ var query = searchInput . value
232
+ if ( ! query ) return clearSearchResults ( )
233
+ searchIndex ( index . index , index . store , searchInput . value )
234
+ } catch ( err ) {
235
+ if ( debug ) console . debug ( 'Invalid search query: ' + query + ' (' + err . message + ')' )
236
+ }
237
+ } , 100 )
238
+ )
239
+ searchInput . addEventListener ( 'click' , confineEvent )
240
+ searchResult . addEventListener ( 'click' , confineEvent )
241
+ document . documentElement . addEventListener ( 'click' , clearSearchResults )
211
242
}
212
- } ) ( window . lunr )
243
+
244
+ // disable the search input until the index is loaded
245
+ enableSearchInput ( false )
246
+
247
+ globalScope . initSearch = initSearch
248
+ } ) ( typeof globalThis !== 'undefined' ? globalThis : window )
0 commit comments