mirror of
https://github.com/McShelby/hugo-theme-relearn.git
synced 2024-11-23 07:47:54 +00:00
search: improve handling of multiterm search #407
This commit is contained in:
parent
8debc83a77
commit
57b73a5f47
3 changed files with 66 additions and 21 deletions
|
@ -1 +1 @@
|
||||||
7.1.1+fc960aa5eaf2240ba8a6de92943ac838423e1269
|
7.1.1+8debc83a770553885b78318e2651a127a82d2b0c
|
|
@ -3,6 +3,10 @@ import { init, search } from './orama-adapter.js';
|
||||||
|
|
||||||
(function(){
|
(function(){
|
||||||
|
|
||||||
|
function escapeRegex( string ){
|
||||||
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
||||||
|
|
||||||
window.relearn = window.relearn || {};
|
window.relearn = window.relearn || {};
|
||||||
|
|
||||||
window.relearn.executeInitialSearch =
|
window.relearn.executeInitialSearch =
|
||||||
|
@ -95,12 +99,19 @@ function executeSearch( value ) {
|
||||||
a.forEach( function(item){
|
a.forEach( function(item){
|
||||||
var page = item.page;
|
var page = item.page;
|
||||||
var context = [];
|
var context = [];
|
||||||
if( item.matches ){
|
if( item.matches && item.matches.length ){
|
||||||
var numContextWords = 10;
|
var numContextWords = 10;
|
||||||
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
||||||
item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') +
|
escapeRegex( item.matches[0] ) +
|
||||||
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
||||||
context = page.content.match(new RegExp(contextPattern, 'i'));
|
context = page.content.match(new RegExp(contextPattern, 'i'));
|
||||||
|
if( !context ){
|
||||||
|
item.matches.shift();
|
||||||
|
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
||||||
|
item.matches.map( escapeRegex ).join('|') +
|
||||||
|
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
||||||
|
context = page.content.match(new RegExp(contextPattern, 'i'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var divsuggestion = document.createElement('a');
|
var divsuggestion = document.createElement('a');
|
||||||
divsuggestion.className = 'autocomplete-suggestion';
|
divsuggestion.className = 'autocomplete-suggestion';
|
||||||
|
@ -169,12 +180,19 @@ function initSearchAfterLoad(){
|
||||||
renderItem: function( item, term ) {
|
renderItem: function( item, term ) {
|
||||||
var page = item.page;
|
var page = item.page;
|
||||||
var context = [];
|
var context = [];
|
||||||
if( item.matches ){
|
if( item.matches && item.matches.length ){
|
||||||
var numContextWords = 2;
|
var numContextWords = 2;
|
||||||
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
||||||
item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') +
|
escapeRegex( item.matches[0] ) +
|
||||||
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
||||||
context = page.content.match(new RegExp(contextPattern, 'i'));
|
context = page.content.match(new RegExp(contextPattern, 'i'));
|
||||||
|
if( !context ){
|
||||||
|
item.matches.shift();
|
||||||
|
var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
|
||||||
|
item.matches.map( escapeRegex ).join('|') +
|
||||||
|
')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
|
||||||
|
context = page.content.match(new RegExp(contextPattern, 'i'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var divsuggestion = document.createElement('div');
|
var divsuggestion = document.createElement('div');
|
||||||
divsuggestion.className = 'autocomplete-suggestion';
|
divsuggestion.className = 'autocomplete-suggestion';
|
||||||
|
|
|
@ -1327,10 +1327,12 @@ function scrollToPositions() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var search = sessionStorage.getItem( window.relearn.absBaseUri+'/search-value' );
|
|
||||||
if( search && search.length ){
|
var value = sessionStorage.getItem( window.relearn.absBaseUri+'/search-value' );
|
||||||
search = regexEscape( search );
|
var words = (value ?? '') .split( ' ' ).filter( word => word.trim() != '' );
|
||||||
var found = elementContains( search, elc );
|
if( words && words.length ){
|
||||||
|
unmark();
|
||||||
|
var found = elementContains( words, elc );
|
||||||
var searchedElem = found.length && found[ 0 ];
|
var searchedElem = found.length && found[ 0 ];
|
||||||
if( searchedElem ){
|
if( searchedElem ){
|
||||||
searchedElem.scrollIntoView();
|
searchedElem.scrollIntoView();
|
||||||
|
@ -1339,6 +1341,8 @@ function scrollToPositions() {
|
||||||
window.scroll( 0, scrolledY - 125 );
|
window.scroll( 0, scrolledY - 125 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sessionStorage.setItem( window.relearn.absBaseUri+'/search-value', value );
|
||||||
|
mark();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1371,7 +1375,7 @@ function mark() {
|
||||||
bodyInnerLinks[i].classList.add( 'highlight' );
|
bodyInnerLinks[i].classList.add( 'highlight' );
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = sessionStorage.getItem( window.relearn.absBaseUri + '/search-value' );
|
var value = (sessionStorage.getItem( window.relearn.absBaseUri + '/search-value' ) ?? '').split( ' ' ).filter( word => word.trim() != '' );
|
||||||
var highlightableElements = document.querySelectorAll( '.highlightable' );
|
var highlightableElements = document.querySelectorAll( '.highlightable' );
|
||||||
highlight( highlightableElements, value, { element: 'mark', className: 'search' } );
|
highlight( highlightableElements, value, { element: 'mark', className: 'search' } );
|
||||||
|
|
||||||
|
@ -1411,17 +1415,10 @@ function highlight( es, words, options ){
|
||||||
};
|
};
|
||||||
Object.assign( settings, options );
|
Object.assign( settings, options );
|
||||||
|
|
||||||
if( !words ){ return; }
|
if( !words.length ){ return; }
|
||||||
if( words.constructor === String ){
|
|
||||||
words = [ words ];
|
|
||||||
}
|
|
||||||
words = words.filter( function( word, i ){
|
|
||||||
return word != '';
|
|
||||||
});
|
|
||||||
words = words.map( function( word, i ){
|
words = words.map( function( word, i ){
|
||||||
return regexEscape( word );
|
return regexEscape( word );
|
||||||
});
|
});
|
||||||
if( words.length == 0 ){ return this; }
|
|
||||||
|
|
||||||
var flag = settings.caseSensitive ? '' : 'i';
|
var flag = settings.caseSensitive ? '' : 'i';
|
||||||
var pattern = "(" + words.join( '|' ) + ')';
|
var pattern = "(" + words.join( '|' ) + ')';
|
||||||
|
@ -1507,8 +1504,24 @@ function unhighlight( es, options ){
|
||||||
};
|
};
|
||||||
|
|
||||||
// replace jQuery.createPseudo with https://stackoverflow.com/a/66318392
|
// replace jQuery.createPseudo with https://stackoverflow.com/a/66318392
|
||||||
function elementContains( txt, e ){
|
function elementContains( words, e ){
|
||||||
var regex = RegExp( txt, 'i' );
|
var settings = {
|
||||||
|
caseSensitive: false,
|
||||||
|
wordsOnly: false
|
||||||
|
};
|
||||||
|
|
||||||
|
if( !words.length ){ return; }
|
||||||
|
words = words.map( function( word, i ){
|
||||||
|
return regexEscape( word );
|
||||||
|
});
|
||||||
|
|
||||||
|
var flag = settings.caseSensitive ? '' : 'i';
|
||||||
|
var pattern = "(" + words.join( '\\s+' ) + ')';
|
||||||
|
if( settings.wordsOnly ){
|
||||||
|
pattern = '\\b' + pattern + '\\b';
|
||||||
|
}
|
||||||
|
var regex = new RegExp( pattern, flag );
|
||||||
|
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
if( e ){
|
if( e ){
|
||||||
var tree = document.createTreeWalker( e, 4 /* NodeFilter.SHOW_TEXT */, function( node ){
|
var tree = document.createTreeWalker( e, 4 /* NodeFilter.SHOW_TEXT */, function( node ){
|
||||||
|
@ -1518,6 +1531,20 @@ function elementContains( txt, e ){
|
||||||
while( node = tree.nextNode() ){
|
while( node = tree.nextNode() ){
|
||||||
nodes.push( node.parentElement );
|
nodes.push( node.parentElement );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pattern = "(" + words.join( '|' ) + ')';
|
||||||
|
if( settings.wordsOnly ){
|
||||||
|
pattern = '\\b' + pattern + '\\b';
|
||||||
|
}
|
||||||
|
regex = new RegExp( pattern, flag );
|
||||||
|
|
||||||
|
tree = document.createTreeWalker( e, 4 /* NodeFilter.SHOW_TEXT */, function( node ){
|
||||||
|
return regex.test( node.data );
|
||||||
|
}, false );
|
||||||
|
node = null;
|
||||||
|
while( node = tree.nextNode() ){
|
||||||
|
nodes.push( node.parentElement );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
@ -1537,7 +1564,7 @@ function initSearch() {
|
||||||
e.addEventListener( 'keydown', function( event ){
|
e.addEventListener( 'keydown', function( event ){
|
||||||
if( event.key == 'Escape' ){
|
if( event.key == 'Escape' ){
|
||||||
var input = event.target;
|
var input = event.target;
|
||||||
var search = sessionStorage.getItem( window.relearn.absBaseUri+'/search-value' );
|
var search = (sessionStorage.getItem( window.relearn.absBaseUri+'/search-value' ) ?? '').split( ' ' ).filter( word => word.trim() != '' );
|
||||||
if( !search || !search.length ){
|
if( !search || !search.length ){
|
||||||
input.blur();
|
input.blur();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue