1/*! 2 * Simple-Jekyll-Search 3 * Copyright 2015-2020, Christian Fei 4 * Licensed under the MIT License. 5 */ 6 7(function () { 8 "use strict"; 9 10 var _$Templater_7 = { 11 compile: compile, 12 setOptions: setOptions, 13 }; 14 15 const options = {}; 16 options.pattern = /\{(.*?)\}/g; 17 options.template = ""; 18 options.middleware = function () {}; 19 20 function setOptions(_options) { 21 options.pattern = _options.pattern || options.pattern; 22 options.template = _options.template || options.template; 23 if (typeof _options.middleware === "function") { 24 options.middleware = _options.middleware; 25 } 26 27 } 28 29 function compile(data) { 30 return options.template.replace(options.pattern, function (match, prop) { 31 const value = options.middleware(prop, data[prop], options.template); 32 if (typeof value !== "undefined") { 33 return value; 34 } 35 return data[prop] || match; 36 }); 37 } 38 39 ("use strict"); 40 41 function fuzzysearch(needle, haystack) { 42 var tlen = haystack.length; 43 var qlen = needle.length; 44 if (qlen > tlen) { 45 return false; 46 } 47 if (qlen === tlen) { 48 return needle === haystack; 49 } 50 outer: for (var i = 0, j = 0; i < qlen; i++) { 51 var nch = needle.charCodeAt(i); 52 while (j < tlen) { 53 if (haystack.charCodeAt(j++) === nch) { 54 continue outer; 55 } 56 } 57 return false; 58 } 59 return true; 60 } 61 62 var _$fuzzysearch_1 = fuzzysearch; 63 64 ("use strict"); 65 66 /* removed: const _$fuzzysearch_1 = require('fuzzysearch') */ 67 68 var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy(); 69 70 function FuzzySearchStrategy() { 71 this.matches = function (string, crit) { 72 return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase()); 73 }; 74 } 75 76 ("use strict"); 77 78 var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy(); 79 80 function LiteralSearchStrategy() { 81 this.matches = function (str, crit) { 82 if (!str) return false; 83 84 str = str.trim().toLowerCase(); 85 crit = crit.trim().toLowerCase(); 86 87 return ( 88 crit.split(" ").filter(function (word) { 89 return str.indexOf(word) >= 0; 90 }).length === crit.split(" ").length 91 ); 92 }; 93 } 94 95 ("use strict"); 96 97 var _$Repository_4 = { 98 put: put, 99 clear: clear, 100 search: search, 101 setOptions: __setOptions_4, 102 }; 103 104 /* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */ /* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */ function NoSort() { 105 return 0; 106 } 107 108 const data = []; 109 let opt = {}; 110 111 opt.fuzzy = false; 112 opt.limit = 10; 113 opt.searchStrategy = opt.fuzzy 114 ? _$FuzzySearchStrategy_5 115 : _$LiteralSearchStrategy_6; 116 opt.sort = NoSort; 117 opt.exclude = []; 118 119 function put(data) { 120 if (isObject(data)) { 121 return addObject(data); 122 } 123 if (isArray(data)) { 124 return addArray(data); 125 } 126 return undefined; 127 } 128 function clear() { 129 data.length = 0; 130 return data; 131 } 132 133 function isObject(obj) { 134 return ( 135 Boolean(obj) && Object.prototype.toString.call(obj) === "[object Object]" 136 ); 137 } 138 139 function isArray(obj) { 140 return ( 141 Boolean(obj) && Object.prototype.toString.call(obj) === "[object Array]" 142 ); 143 } 144 145 function addObject(_data) { 146 data.push(_data); 147 return data; 148 } 149 150 function addArray(_data) { 151 const added = []; 152 clear(); 153 for (let i = 0, len = _data.length; i < len; i++) { 154 if (isObject(_data[i])) { 155 added.push(addObject(_data[i])); 156 } 157 } 158 return added; 159 } 160 161 function search(crit) { 162 if (!crit) { 163 return []; 164 } 165 return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort); 166 } 167 168 function __setOptions_4(_opt) { 169 opt = _opt || {}; 170 171 opt.fuzzy = _opt.fuzzy || false; 172 opt.limit = _opt.limit || 10; 173 opt.searchStrategy = _opt.fuzzy 174 ? _$FuzzySearchStrategy_5 175 : _$LiteralSearchStrategy_6; 176 opt.sort = _opt.sort || NoSort; 177 opt.exclude = _opt.exclude || []; 178 } 179 180 function findMatches(data, crit, strategy, opt) { 181 const matches = []; 182 for (let i = 0; i < data.length && matches.length < opt.limit; i++) { 183 const match = findMatchesInObject(data[i], crit, strategy, opt); 184 if (match) { 185 matches.push(match); 186 } 187 } 188 return matches; 189 } 190 191 function findMatchesInObject(obj, crit, strategy, opt) { 192 for (const key in obj) { 193 if ( 194 !isExcluded(obj[key], opt.exclude) && 195 strategy.matches(obj[key], crit) 196 ) { 197 return obj; 198 } 199 } 200 } 201 202 function isExcluded(term, excludedTerms) { 203 for (let i = 0, len = excludedTerms.length; i < len; i++) { 204 const excludedTerm = excludedTerms[i]; 205 if (new RegExp(excludedTerm).test(term)) { 206 return true; 207 } 208 } 209 return false;
210 } 211 212 /* globals ActiveXObject:false */ 213 214 ("use strict"); 215 216 var _$JSONLoader_2 = { 217 load: load, 218 }; 219 220 function load(location, callback) { 221 const xhr = getXHR(); 222 xhr.open("GET", location, true); 223 xhr.onreadystatechange = createStateChangeListener(xhr, callback); 224 xhr.send(); 225 } 226 227 function createStateChangeListener(xhr, callback) { 228 return function () { 229 if (xhr.readyState === 4 && xhr.status === 200) { 230 try { 231 callback(null, JSON.parse(xhr.responseText)); 232 } catch (err) { 233 callback(err, null); 234 } 235 } 236 }; 237 } 238 239 function getXHR() { 240 return window.XMLHttpRequest 241 ? new window.XMLHttpRequest() 242 : new ActiveXObject("Microsoft.XMLHTTP"); 243 } 244 245 ("use strict"); 246 247 var _$OptionsValidator_3 = function OptionsValidator(params) { 248 if (!validateParams(params)) { 249 throw new Error("-- OptionsValidator: required options missing"); 250 } 251 252 if (!(this instanceof OptionsValidator)) { 253 return new OptionsValidator(params); 254 } 255 256 const requiredOptions = params.required; 257 258 this.getRequiredOptions = function () { 259 return requiredOptions; 260 }; 261 262 this.validate = function (parameters) { 263 const errors = []; 264 requiredOptions.forEach(function (requiredOptionName) { 265 if (typeof parameters[requiredOptionName] === "undefined") { 266 errors.push(requiredOptionName); 267 } 268 }); 269 return errors; 270 }; 271 272 function validateParams(params) { 273 if (!params) { 274 return false; 275 } 276 return ( 277 typeof params.required !== "undefined" && 278 params.required instanceof Array 279 ); 280 } 281 }; 282 283 ("use strict"); 284 285 var _$utils_9 = { 286 merge: merge, 287 isJSON: isJSON, 288 }; 289 290 function merge(defaultParams, mergeParams) { 291 const mergedOptions = {}; 292 for (const option in defaultParams) { 293 mergedOptions[option] = defaultParams[option]; 294 if (typeof mergeParams[option] !== "undefined") { 295 mergedOptions[option] = mergeParams[option]; 296 } 297 } 298 return mergedOptions; 299 } 300 301 function isJSON(json) { 302 try { 303 if (json instanceof Object && JSON.parse(JSON.stringify(json))) { 304 return true; 305 } 306 return false; 307 } catch (err) { 308 return false; 309 } 310 } 311 312 var _$src_8 = {}; 313 (function (window) { 314 "use strict"; 315 316 let options = { 317 searchInput: null, 318 resultsContainer: null, 319 json: [], 320 success: Function.prototype, 321 searchResultTemplate: 322 '<li><a href="{url}" title="{desc}">{title}</a></li>', 323 templateMiddleware: Function.prototype, 324 sortMiddleware: function () { 325 return 0; 326 }, 327 noResultsText: "No results found", 328 limit: 10, 329 fuzzy: false, 330 debounceTime: null, 331 exclude: [], 332 }; 333 334 let debounceTimerHandle; 335 const debounce = function (func, delayMillis) { 336 if (delayMillis) { 337 clearTimeout(debounceTimerHandle); 338 debounceTimerHandle = setTimeout(func, delayMillis); 339 } else { 340 func.call(); 341 } 342 }; 343 344 const requiredOptions = ["searchInput", "resultsContainer", "json"]; 345 346 /* removed: const _$Templater_7 = require('./Templater') */ /* removed: const _$Repository_4 = require('./Repository') */ /* removed: const _$JSONLoader_2 = require('./JSONLoader') */ const optionsValidator = 347 _$OptionsValidator_3({ 348 required: requiredOptions, 349 }); 350 /* removed: const _$utils_9 = require('./utils') */ window.SimpleJekyllSearch = 351 function (_options) { 352 const errors = optionsValidator.validate(_options); 353 if (errors.length > 0) { 354 throwError( 355 "You must specify the following required options: " + 356 requiredOptions 357 ); 358 } 359 360 options = _$utils_9.merge(options, _options); 361 _$Templater_7.setOptions({ 362 template: options.searchResultTemplate, 363 middleware: options.templateMiddleware, 364 }); 365 366 _$Repository_4.setOptions({ 367 fuzzy: options.fuzzy, 368 limit: options.limit, 369 sort: options.sortMiddleware, 370 exclude: options.exclude, 371 }); 372 373 if (_$utils_9.isJSON(options.json)) { 374 initWithJSON(options.json); 375 } else { 376 initWithURL(options.json); 377 } 378 379 const rv = { 380 search: search, 381 }; 382 typeof options.success === "function" && options.success.call(rv); 383 return rv; 384 }; 385 386 function initWithJSON(json) { 387 _$Repository_4.put(json); 388 registerInput(); 389 } 390 391 function initWithURL(url) { 392 _$JSONLoader_2.load(url, function (err, json) { 393 if (err) { 394 throwError("failed to get JSON (" + url + ")"); 395 } 396 initWithJSON(json); 397 }); 398 } 399 400 function emptyResultsContainer() { 401 options.resultsContainer.innerHTML = ""; 402 options.resultsContainer.style.display = "block"; 403 } 404 405 function appendToResultsContainer(text) { 406 options.resultsContainer.innerHTML += text; 407 options.resultsContainer.style.display = "block"; 408 } 409 410 411 function registerInput() { 412 options.searchInput.addEventListener("input", function (e) { 413 if (isWhitelistedKey(e.which)) { 414 emptyResultsContainer(); 415 debounce(function () { 416 search(e.target.value); 417 }, options.debounceTime); 418 } 419 }); 420 } 421 function search(query) { 422 if (isValidQuery(query)) { 423 emptyResultsContainer();
424 render(_$Repository_4.search(query), query); 425 426 } 427 } 428 429 function render(results, query) { 430 const len = results.length; 431 432const ResultGroup = results.reduce((acc, item) => { 433 if (!acc[item.type]) { 434 acc[item.type] = []; 435 } 436 acc[item.type].push(item); 437 return acc; 438}, {}); 439 440Object.keys(ResultGroup).map(function(key, index) { 441 options.resultsContainer.innerHTML += 442 "<li>" + 443 key + 444 "<ul class='list-unstyled search_item'>" + 445 ResultGroup[key].map(function (val,ind) { 446 return _$Templater_7.compile(val) 447 }).join(' ') 448 + 449 "</ul>" + 450 "</li>"; 451}); 452 453 454 if (len === 0) { 455 return appendToResultsContainer(options.noResultsText); 456 } 457 // for (let i = 0; i < len; i++) { 458 // results[i].query = query; 459 460 // appendToResultsContainer(_$Templater_7.compile(results[i])); 461 // } 462 } 463 464 function isValidQuery(query) { 465 return query && query.length > 0; 466 } 467 468 function isWhitelistedKey(key) { 469 return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1; 470 } 471 472 function throwError(message) { 473 throw new Error("SimpleJekyllSearch --- " + message); 474 } 475 })(window); 476})();
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.