@@ -25,7 +25,7 @@ $( document ).ready(function() {
25
25
} ,
26
26
mark_exclude : [ ] , // ['.hljs']
27
27
current_searchterm : "" ,
28
- teaser_size_half : 80 ,
28
+ teaser_words : 30 ,
29
29
resultcount_limit : 30 ,
30
30
SEARCH_PARAM : 'search' ,
31
31
MARK_PARAM : 'highlight' ,
@@ -160,24 +160,7 @@ $( document ).ready(function() {
160
160
,
161
161
formatSearchResult : function ( result , searchterms ) {
162
162
// Show text around first occurrence of first search term.
163
- var firstoccurence = result . doc . body . search ( searchterms [ 0 ] ) ;
164
- var teaser = "" ;
165
- if ( firstoccurence != - 1 ) {
166
- var teaserstartindex = firstoccurence - this . teaser_size_half ;
167
- var nextwordindex = result . doc . body . indexOf ( " " , teaserstartindex ) ;
168
- if ( nextwordindex != - 1 ) {
169
- teaserstartindex = nextwordindex ;
170
- }
171
- var teaserendindex = firstoccurence + this . teaser_size_half ;
172
- nextwordindex = result . doc . body . indexOf ( " " , teaserendindex ) ;
173
- if ( nextwordindex != - 1 ) {
174
- teaserendindex = nextwordindex ;
175
- }
176
- teaser = ( teaserstartindex > 0 ) ? "... " : "" ;
177
- teaser += result . doc . body . substring ( teaserstartindex , teaserendindex ) + " ..." ;
178
- } else {
179
- teaser = result . doc . body . substr ( 0 , this . teaser_size_half * 2 ) + " ..." ;
180
- }
163
+ var teaser = this . makeTeaser ( this . escapeHTML ( result . doc . body ) , searchterms ) ;
181
164
182
165
// The ?MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor
183
166
var url = result . ref . split ( "#" ) ;
@@ -189,10 +172,104 @@ $( document ).ready(function() {
189
172
+ url [ 0 ] + '?' + this . MARK_PARAM + '=' + searchterms + '#' + url [ 1 ]
190
173
+ '">' + result . doc . breadcrumbs + '</a>' // doc.title
191
174
+ '<span class="breadcrumbs">' + '</span>'
192
- + '<span class="teaser">' + this . escapeHTML ( teaser ) + '</span>'
175
+ + '<span class="teaser">' + teaser + '</span>'
193
176
+ '</li>' ) ;
194
177
}
195
178
,
179
+ makeTeaser : function ( body , searchterms ) {
180
+ // The strategy is as follows:
181
+ // First, assign a value to each word in the document:
182
+ // Words that correspond to search terms (stemmer aware): 40
183
+ // Normal words: 2
184
+ // First word in a sentence: 8
185
+ // Then use a sliding window with a constant number of words and count the
186
+ // sum of the values of the words within the window. Then use the window that got the
187
+ // maximum sum. If there are multiple maximas, then get the last one.
188
+ // Enclose the terms in <em>.
189
+ var stemmed_searchterms = searchterms . map ( elasticlunr . stemmer ) ;
190
+ var searchterm_weight = 40 ;
191
+ var weighted = [ ] ; // contains elements of ["word", weight, index_in_document]
192
+ // split in sentences, then words
193
+ var sentences = body . split ( '. ' ) ;
194
+ var index = 0 ;
195
+ var value = 0 ;
196
+ var searchterm_found = false ;
197
+ for ( var sentenceindex in sentences ) {
198
+ var words = sentences [ sentenceindex ] . split ( ' ' ) ;
199
+ value = 8 ;
200
+ for ( var wordindex in words ) {
201
+ var word = words [ wordindex ] ;
202
+ if ( word . length > 0 ) {
203
+ for ( var searchtermindex in stemmed_searchterms ) {
204
+ if ( elasticlunr . stemmer ( word ) . startsWith ( stemmed_searchterms [ searchtermindex ] ) ) {
205
+ value = searchterm_weight ;
206
+ searchterm_found = true ;
207
+ }
208
+ } ;
209
+ weighted . push ( [ word , value , index ] ) ;
210
+ value = 2 ;
211
+ }
212
+ index += word . length ;
213
+ index += 1 ; // ' ' or '.' if last word in sentence
214
+ } ;
215
+ index += 1 ; // because we split at a two-char boundary '. '
216
+ } ;
217
+
218
+ if ( weighted . length == 0 ) {
219
+ return body ;
220
+ }
221
+
222
+ var window_weight = [ ] ;
223
+ var window_size = Math . min ( weighted . length , this . teaser_words ) ;
224
+
225
+ var cur_sum = 0 ;
226
+ for ( var wordindex = 0 ; wordindex < window_size ; wordindex ++ ) {
227
+ cur_sum += weighted [ wordindex ] [ 1 ] ;
228
+ } ;
229
+ window_weight . push ( cur_sum ) ;
230
+ for ( var wordindex = 0 ; wordindex < weighted . length - window_size ; wordindex ++ ) {
231
+ cur_sum -= weighted [ wordindex ] [ 1 ] ;
232
+ cur_sum += weighted [ wordindex + window_size ] [ 1 ] ;
233
+ window_weight . push ( cur_sum ) ;
234
+ } ;
235
+
236
+ if ( searchterm_found ) {
237
+ var max_sum = 0 ;
238
+ var max_sum_window_index = 0 ;
239
+ // backwards
240
+ for ( var i = window_weight . length - 1 ; i >= 0 ; i -- ) {
241
+ if ( window_weight [ i ] > max_sum ) {
242
+ max_sum = window_weight [ i ] ;
243
+ max_sum_window_index = i ;
244
+ }
245
+ } ;
246
+ } else {
247
+ max_sum_window_index = 0 ;
248
+ }
249
+
250
+ // add <em/> around searchterms
251
+ var teaser_split = [ ] ;
252
+ var index = weighted [ max_sum_window_index ] [ 2 ] ;
253
+ for ( var i = max_sum_window_index ; i < max_sum_window_index + window_size ; i ++ ) {
254
+ var word = weighted [ i ] ;
255
+ if ( index < word [ 2 ] ) {
256
+ // missing text from index to start of `word`
257
+ teaser_split . push ( body . substring ( index , word [ 2 ] ) ) ;
258
+ index = word [ 2 ] ;
259
+ }
260
+ if ( word [ 1 ] == searchterm_weight ) {
261
+ teaser_split . push ( "<em>" )
262
+ }
263
+ index = word [ 2 ] + word [ 0 ] . length ;
264
+ teaser_split . push ( body . substring ( word [ 2 ] , index ) ) ;
265
+ if ( word [ 1 ] == searchterm_weight ) {
266
+ teaser_split . push ( "</em>" )
267
+ }
268
+ } ;
269
+
270
+ return teaser_split . join ( '' ) ;
271
+ }
272
+ ,
196
273
doSearch : function ( searchterm ) {
197
274
198
275
// Don't search the same twice
@@ -245,7 +322,6 @@ $( document ).ready(function() {
245
322
,
246
323
init : function ( ) {
247
324
var this_ = this ;
248
- window . md = this ;
249
325
250
326
// For testing purposes: Index current page
251
327
//this.create_test_searchindex();
@@ -296,6 +372,7 @@ $( document ).ready(function() {
296
372
( this . searchbar [ 0 ] . value . trim ( ) != 0 ) ? "push" : "replace" ) ;
297
373
this . unfocusSearchbar ( ) ;
298
374
this . searchbar_outer . slideUp ( ) ;
375
+ this . content . unmark ( ) ;
299
376
return ;
300
377
}
301
378
if ( ! this . hasFocus ( ) && e . keyCode == this . SEARCH_HOTKEY_KEYCODE ) {
0 commit comments