1let searchVisible = true; 2 3// allow us to delay loading json data unless search activated 4let firstRun = true; 5 6// targets the <ul> 7const list = document.getElementById('searchResults'); 8 9// first child of search list 10let first = list.firstChild; 11 12// last child of search list 13let last = list.lastChild; 14 15// input box for search 16const maininput = document.getElementById('searchInput'); 17 18// Did we get any search results? 19let resultsAvailable = false; 20 21if(firstRun) { 22 23 // loads our json data and builds the search index 24 loadSearch(); 25 26 // let's never do this again 27 firstRun = false; 28} 29 30const stopWords = new Set(['and', 'or', 'to', 'in', 'a', 'the', /* ...and more */ ]); 31 32// Perform custom term processing (here discarding stop words and downcasing) 33let miniSearch = new MiniSearch({ 34 35 // fields to index for full-text search 36 fields: ['contents'], 37 38 processTerm: (term, _fieldName) => stopWords.has(term) ? null : term.toLowerCase(), 39 40 searchOptions: { 41 boost: { title: 2 }, 42 fuzzy: 0.2 43 }, 44 45 // fields to return with search results 46 storeFields: ['title', 'contents', 'permalink'] 47}); 48 49// ========================================== 50// execute search as each character is typed 51// 52document.getElementById("searchInput").onkeyup = function(e) { 53 executeSearch(this.value); 54} 55 56function fetchJSONFile(path, callback) { 57 const httpRequest = new XMLHttpRequest(); 58 httpRequest.onreadystatechange = function() { 59 if (httpRequest.readyState === 4) { 60 if (httpRequest.status === 200) { 61 const data = JSON.parse(httpRequest.responseText); 62 if (callback) callback(data); 63 } 64 } 65 }; 66 67 httpRequest.open('GET', path); 68 httpRequest.send(); 69 } 70 71function loadSearch() { 72 fetchJSONFile('/index.json', function(data){ 73 miniSearch.addAll(data); 74 }); 75} 76 77function executeSearch(term) { 78 79 // the actual query being run using miniSearch.js 80 let results = miniSearch.search(term); 81 82 // our results bucket 83 let searchitems = ''; 84 85 // no results based on what was typed into the input box 86 if (results.length === 0) { 87 resultsAvailable = false; 88 } 89 90 // build our html 91 else { 92 93 // https://stackoverflow.com/a/36744732/183692 94 // dedupe the results based on permalink 95 results = results.filter((value, index, self) => 96 index === self.findIndex((t) => ( 97 t.title === value.title 98 )) 99 ); 100 101 //console.log(`results" ${results.length}`) 102 103 const snippetLength = 400; 104 const side = snippetLength / 2; 105 106 results.forEach(item => { 107 108// contents: "â¦" 109// id: 32 110// match: Object { digitize: (1) [â¦] } 111// permalink: "http://localhost:1313/posts/bhl-and-plazi-partnership/" 112// score: 1.7846304978818683 113// terms: Array [ "digitize" ] 114// title: "BHL and Plazi partnership" 115 116 //const item = i.item; 117 const terms = item.terms; 118 const permalink = item.permalink; 119 const title = item.title; 120 //let content = item.contents.substring(0, 200); 121 let content = item.contents; 122 123 terms.forEach(term => { 124 const re = new RegExp(`(${term})`, 'i'); 125 const matchInfo = content.match(re); 126 const left = matchInfo.index - side; 127 const right = matchInfo.index + term.length + side; 128 content = content.substring(left, right); 129 //content = content.replace(re, '<span class="hilite">$1</span>'); 130 content = content.replace(re, '<mark>$1</mark>'); 131 }) 132 133 134 searchitems = searchitems + 135 `<li> 136 <a href="${permalink}" tabindex="0"> 137 <h2 class="title">${title}</h2> 138 <p>${content}â¦</p> 139 </a> 140 </li>` 141 }); 142 143 resultsAvailable = true; 144 } 145 146 document.getElementById("searchResults").innerHTML = searchitems; 147 if (results.length > 0) { 148 149 // first result container â used for checking against keyboard up/down location 150 first = list.firstChild.firstElementChild; 151 152 // last result container â used for checking against keyboard up/down location 153 last = list.lastChild.firstElementChild; 154 } 155}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.