diff --git a/build/scripts/fuse.js b/build/scripts/fuse.js new file mode 100644 index 0000000..c984b28 --- /dev/null +++ b/build/scripts/fuse.js @@ -0,0 +1,2010 @@ +/** + * Fuse.js v7.0.0 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2023 Kiro Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Fuse = factory()); +})(this, (function () { 'use strict'; + + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + return keys; + } + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + return target; + } + function _typeof(obj) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _defineProperty(obj, key, value) { + key = _toPropertyKey(key); + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; + } + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + Object.defineProperty(subClass, "prototype", { + writable: false + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return self; + } + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + return _assertThisInitialized(self); + } + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + return _possibleConstructorReturn(this, result); + }; + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + function isArray(value) { + return !Array.isArray ? getTag(value) === '[object Array]' : Array.isArray(value); + } + + // Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js + var INFINITY = 1 / 0; + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + var result = value + ''; + return result == '0' && 1 / value == -INFINITY ? '-0' : result; + } + function toString(value) { + return value == null ? '' : baseToString(value); + } + function isString(value) { + return typeof value === 'string'; + } + function isNumber(value) { + return typeof value === 'number'; + } + + // Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && getTag(value) == '[object Boolean]'; + } + function isObject(value) { + return _typeof(value) === 'object'; + } + + // Checks if `value` is object-like. + function isObjectLike(value) { + return isObject(value) && value !== null; + } + function isDefined(value) { + return value !== undefined && value !== null; + } + function isBlank(value) { + return !value.trim().length; + } + + // Gets the `toStringTag` of `value`. + // Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js + function getTag(value) { + return value == null ? value === undefined ? '[object Undefined]' : '[object Null]' : Object.prototype.toString.call(value); + } + + var EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available'; + var INCORRECT_INDEX_TYPE = "Incorrect 'index' type"; + var LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = function LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key) { + return "Invalid value for key ".concat(key); + }; + var PATTERN_LENGTH_TOO_LARGE = function PATTERN_LENGTH_TOO_LARGE(max) { + return "Pattern length exceeds max of ".concat(max, "."); + }; + var MISSING_KEY_PROPERTY = function MISSING_KEY_PROPERTY(name) { + return "Missing ".concat(name, " property in key"); + }; + var INVALID_KEY_WEIGHT_VALUE = function INVALID_KEY_WEIGHT_VALUE(key) { + return "Property 'weight' in key '".concat(key, "' must be a positive integer"); + }; + + var hasOwn = Object.prototype.hasOwnProperty; + var KeyStore = /*#__PURE__*/function () { + function KeyStore(keys) { + var _this = this; + _classCallCheck(this, KeyStore); + this._keys = []; + this._keyMap = {}; + var totalWeight = 0; + keys.forEach(function (key) { + var obj = createKey(key); + _this._keys.push(obj); + _this._keyMap[obj.id] = obj; + totalWeight += obj.weight; + }); + + // Normalize weights so that their sum is equal to 1 + this._keys.forEach(function (key) { + key.weight /= totalWeight; + }); + } + _createClass(KeyStore, [{ + key: "get", + value: function get(keyId) { + return this._keyMap[keyId]; + } + }, { + key: "keys", + value: function keys() { + return this._keys; + } + }, { + key: "toJSON", + value: function toJSON() { + return JSON.stringify(this._keys); + } + }]); + return KeyStore; + }(); + function createKey(key) { + var path = null; + var id = null; + var src = null; + var weight = 1; + var getFn = null; + if (isString(key) || isArray(key)) { + src = key; + path = createKeyPath(key); + id = createKeyId(key); + } else { + if (!hasOwn.call(key, 'name')) { + throw new Error(MISSING_KEY_PROPERTY('name')); + } + var name = key.name; + src = name; + if (hasOwn.call(key, 'weight')) { + weight = key.weight; + if (weight <= 0) { + throw new Error(INVALID_KEY_WEIGHT_VALUE(name)); + } + } + path = createKeyPath(name); + id = createKeyId(name); + getFn = key.getFn; + } + return { + path: path, + id: id, + weight: weight, + src: src, + getFn: getFn + }; + } + function createKeyPath(key) { + return isArray(key) ? key : key.split('.'); + } + function createKeyId(key) { + return isArray(key) ? key.join('.') : key; + } + + function get(obj, path) { + var list = []; + var arr = false; + var deepGet = function deepGet(obj, path, index) { + if (!isDefined(obj)) { + return; + } + if (!path[index]) { + // If there's no path left, we've arrived at the object we care about. + list.push(obj); + } else { + var key = path[index]; + var value = obj[key]; + if (!isDefined(value)) { + return; + } + + // If we're at the last value in the path, and if it's a string/number/bool, + // add it to the list + if (index === path.length - 1 && (isString(value) || isNumber(value) || isBoolean(value))) { + list.push(toString(value)); + } else if (isArray(value)) { + arr = true; + // Search each item in the array. + for (var i = 0, len = value.length; i < len; i += 1) { + deepGet(value[i], path, index + 1); + } + } else if (path.length) { + // An object. Recurse further. + deepGet(value, path, index + 1); + } + } + }; + + // Backwards compatibility (since path used to be a string) + deepGet(obj, isString(path) ? path.split('.') : path, 0); + return arr ? list : list[0]; + } + + var MatchOptions = { + // Whether the matches should be included in the result set. When `true`, each record in the result + // set will include the indices of the matched characters. + // These can consequently be used for highlighting purposes. + includeMatches: false, + // When `true`, the matching function will continue to the end of a search pattern even if + // a perfect match has already been located in the string. + findAllMatches: false, + // Minimum number of characters that must be matched before a result is considered a match + minMatchCharLength: 1 + }; + var BasicOptions = { + // When `true`, the algorithm continues searching to the end of the input even if a perfect + // match is found before the end of the same input. + isCaseSensitive: false, + // When true, the matching function will continue to the end of a search pattern even if + includeScore: false, + // List of properties that will be searched. This also supports nested properties. + keys: [], + // Whether to sort the result list, by score + shouldSort: true, + // Default sort function: sort by ascending score, ascending index + sortFn: function sortFn(a, b) { + return a.score === b.score ? a.idx < b.idx ? -1 : 1 : a.score < b.score ? -1 : 1; + } + }; + var FuzzyOptions = { + // Approximately where in the text is the pattern expected to be found? + location: 0, + // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match + // (of both letters and location), a threshold of '1.0' would match anything. + threshold: 0.6, + // Determines how close the match must be to the fuzzy location (specified above). + // An exact letter match which is 'distance' characters away from the fuzzy location + // would score as a complete mismatch. A distance of '0' requires the match be at + // the exact location specified, a threshold of '1000' would require a perfect match + // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. + distance: 100 + }; + var AdvancedOptions = { + // When `true`, it enables the use of unix-like search commands + useExtendedSearch: false, + // The get function to use when fetching an object's properties. + // The default will search nested paths *ie foo.bar.baz* + getFn: get, + // When `true`, search will ignore `location` and `distance`, so it won't matter + // where in the string the pattern appears. + // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score + ignoreLocation: false, + // When `true`, the calculation for the relevance score (used for sorting) will + // ignore the field-length norm. + // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm + ignoreFieldNorm: false, + // The weight to determine how much field length norm effects scoring. + fieldNormWeight: 1 + }; + var Config = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, BasicOptions), MatchOptions), FuzzyOptions), AdvancedOptions); + + var SPACE = /[^ ]+/g; + + // Field-length norm: the shorter the field, the higher the weight. + // Set to 3 decimals to reduce index size. + function norm() { + var weight = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; + var mantissa = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3; + var cache = new Map(); + var m = Math.pow(10, mantissa); + return { + get: function get(value) { + var numTokens = value.match(SPACE).length; + if (cache.has(numTokens)) { + return cache.get(numTokens); + } + + // Default function is 1/sqrt(x), weight makes that variable + var norm = 1 / Math.pow(numTokens, 0.5 * weight); + + // In place of `toFixed(mantissa)`, for faster computation + var n = parseFloat(Math.round(norm * m) / m); + cache.set(numTokens, n); + return n; + }, + clear: function clear() { + cache.clear(); + } + }; + } + + var FuseIndex = /*#__PURE__*/function () { + function FuseIndex() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$getFn = _ref.getFn, + getFn = _ref$getFn === void 0 ? Config.getFn : _ref$getFn, + _ref$fieldNormWeight = _ref.fieldNormWeight, + fieldNormWeight = _ref$fieldNormWeight === void 0 ? Config.fieldNormWeight : _ref$fieldNormWeight; + _classCallCheck(this, FuseIndex); + this.norm = norm(fieldNormWeight, 3); + this.getFn = getFn; + this.isCreated = false; + this.setIndexRecords(); + } + _createClass(FuseIndex, [{ + key: "setSources", + value: function setSources() { + var docs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + this.docs = docs; + } + }, { + key: "setIndexRecords", + value: function setIndexRecords() { + var records = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + this.records = records; + } + }, { + key: "setKeys", + value: function setKeys() { + var _this = this; + var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + this.keys = keys; + this._keysMap = {}; + keys.forEach(function (key, idx) { + _this._keysMap[key.id] = idx; + }); + } + }, { + key: "create", + value: function create() { + var _this2 = this; + if (this.isCreated || !this.docs.length) { + return; + } + this.isCreated = true; + + // List is Array + if (isString(this.docs[0])) { + this.docs.forEach(function (doc, docIndex) { + _this2._addString(doc, docIndex); + }); + } else { + // List is Array + this.docs.forEach(function (doc, docIndex) { + _this2._addObject(doc, docIndex); + }); + } + this.norm.clear(); + } + // Adds a doc to the end of the index + }, { + key: "add", + value: function add(doc) { + var idx = this.size(); + if (isString(doc)) { + this._addString(doc, idx); + } else { + this._addObject(doc, idx); + } + } + // Removes the doc at the specified index of the index + }, { + key: "removeAt", + value: function removeAt(idx) { + this.records.splice(idx, 1); + + // Change ref index of every subsquent doc + for (var i = idx, len = this.size(); i < len; i += 1) { + this.records[i].i -= 1; + } + } + }, { + key: "getValueForItemAtKeyId", + value: function getValueForItemAtKeyId(item, keyId) { + return item[this._keysMap[keyId]]; + } + }, { + key: "size", + value: function size() { + return this.records.length; + } + }, { + key: "_addString", + value: function _addString(doc, docIndex) { + if (!isDefined(doc) || isBlank(doc)) { + return; + } + var record = { + v: doc, + i: docIndex, + n: this.norm.get(doc) + }; + this.records.push(record); + } + }, { + key: "_addObject", + value: function _addObject(doc, docIndex) { + var _this3 = this; + var record = { + i: docIndex, + $: {} + }; + + // Iterate over every key (i.e, path), and fetch the value at that key + this.keys.forEach(function (key, keyIndex) { + var value = key.getFn ? key.getFn(doc) : _this3.getFn(doc, key.path); + if (!isDefined(value)) { + return; + } + if (isArray(value)) { + var subRecords = []; + var stack = [{ + nestedArrIndex: -1, + value: value + }]; + while (stack.length) { + var _stack$pop = stack.pop(), + nestedArrIndex = _stack$pop.nestedArrIndex, + _value = _stack$pop.value; + if (!isDefined(_value)) { + continue; + } + if (isString(_value) && !isBlank(_value)) { + var subRecord = { + v: _value, + i: nestedArrIndex, + n: _this3.norm.get(_value) + }; + subRecords.push(subRecord); + } else if (isArray(_value)) { + _value.forEach(function (item, k) { + stack.push({ + nestedArrIndex: k, + value: item + }); + }); + } else ; + } + record.$[keyIndex] = subRecords; + } else if (isString(value) && !isBlank(value)) { + var _subRecord = { + v: value, + n: _this3.norm.get(value) + }; + record.$[keyIndex] = _subRecord; + } + }); + this.records.push(record); + } + }, { + key: "toJSON", + value: function toJSON() { + return { + keys: this.keys, + records: this.records + }; + } + }]); + return FuseIndex; + }(); + function createIndex(keys, docs) { + var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref2$getFn = _ref2.getFn, + getFn = _ref2$getFn === void 0 ? Config.getFn : _ref2$getFn, + _ref2$fieldNormWeight = _ref2.fieldNormWeight, + fieldNormWeight = _ref2$fieldNormWeight === void 0 ? Config.fieldNormWeight : _ref2$fieldNormWeight; + var myIndex = new FuseIndex({ + getFn: getFn, + fieldNormWeight: fieldNormWeight + }); + myIndex.setKeys(keys.map(createKey)); + myIndex.setSources(docs); + myIndex.create(); + return myIndex; + } + function parseIndex(data) { + var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref3$getFn = _ref3.getFn, + getFn = _ref3$getFn === void 0 ? Config.getFn : _ref3$getFn, + _ref3$fieldNormWeight = _ref3.fieldNormWeight, + fieldNormWeight = _ref3$fieldNormWeight === void 0 ? Config.fieldNormWeight : _ref3$fieldNormWeight; + var keys = data.keys, + records = data.records; + var myIndex = new FuseIndex({ + getFn: getFn, + fieldNormWeight: fieldNormWeight + }); + myIndex.setKeys(keys); + myIndex.setIndexRecords(records); + return myIndex; + } + + function computeScore$1(pattern) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$errors = _ref.errors, + errors = _ref$errors === void 0 ? 0 : _ref$errors, + _ref$currentLocation = _ref.currentLocation, + currentLocation = _ref$currentLocation === void 0 ? 0 : _ref$currentLocation, + _ref$expectedLocation = _ref.expectedLocation, + expectedLocation = _ref$expectedLocation === void 0 ? 0 : _ref$expectedLocation, + _ref$distance = _ref.distance, + distance = _ref$distance === void 0 ? Config.distance : _ref$distance, + _ref$ignoreLocation = _ref.ignoreLocation, + ignoreLocation = _ref$ignoreLocation === void 0 ? Config.ignoreLocation : _ref$ignoreLocation; + var accuracy = errors / pattern.length; + if (ignoreLocation) { + return accuracy; + } + var proximity = Math.abs(expectedLocation - currentLocation); + if (!distance) { + // Dodge divide by zero error. + return proximity ? 1.0 : accuracy; + } + return accuracy + proximity / distance; + } + + function convertMaskToIndices() { + var matchmask = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var minMatchCharLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Config.minMatchCharLength; + var indices = []; + var start = -1; + var end = -1; + var i = 0; + for (var len = matchmask.length; i < len; i += 1) { + var match = matchmask[i]; + if (match && start === -1) { + start = i; + } else if (!match && start !== -1) { + end = i - 1; + if (end - start + 1 >= minMatchCharLength) { + indices.push([start, end]); + } + start = -1; + } + } + + // (i-1 - start) + 1 => i - start + if (matchmask[i - 1] && i - start >= minMatchCharLength) { + indices.push([start, i - 1]); + } + return indices; + } + + // Machine word size + var MAX_BITS = 32; + + function search(text, pattern, patternAlphabet) { + var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}, + _ref$location = _ref.location, + location = _ref$location === void 0 ? Config.location : _ref$location, + _ref$distance = _ref.distance, + distance = _ref$distance === void 0 ? Config.distance : _ref$distance, + _ref$threshold = _ref.threshold, + threshold = _ref$threshold === void 0 ? Config.threshold : _ref$threshold, + _ref$findAllMatches = _ref.findAllMatches, + findAllMatches = _ref$findAllMatches === void 0 ? Config.findAllMatches : _ref$findAllMatches, + _ref$minMatchCharLeng = _ref.minMatchCharLength, + minMatchCharLength = _ref$minMatchCharLeng === void 0 ? Config.minMatchCharLength : _ref$minMatchCharLeng, + _ref$includeMatches = _ref.includeMatches, + includeMatches = _ref$includeMatches === void 0 ? Config.includeMatches : _ref$includeMatches, + _ref$ignoreLocation = _ref.ignoreLocation, + ignoreLocation = _ref$ignoreLocation === void 0 ? Config.ignoreLocation : _ref$ignoreLocation; + if (pattern.length > MAX_BITS) { + throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS)); + } + var patternLen = pattern.length; + // Set starting location at beginning text and initialize the alphabet. + var textLen = text.length; + // Handle the case when location > text.length + var expectedLocation = Math.max(0, Math.min(location, textLen)); + // Highest score beyond which we give up. + var currentThreshold = threshold; + // Is there a nearby exact match? (speedup) + var bestLocation = expectedLocation; + + // Performance: only computer matches when the minMatchCharLength > 1 + // OR if `includeMatches` is true. + var computeMatches = minMatchCharLength > 1 || includeMatches; + // A mask of the matches, used for building the indices + var matchMask = computeMatches ? Array(textLen) : []; + var index; + + // Get all exact matches, here for speed up + while ((index = text.indexOf(pattern, bestLocation)) > -1) { + var score = computeScore$1(pattern, { + currentLocation: index, + expectedLocation: expectedLocation, + distance: distance, + ignoreLocation: ignoreLocation + }); + currentThreshold = Math.min(score, currentThreshold); + bestLocation = index + patternLen; + if (computeMatches) { + var i = 0; + while (i < patternLen) { + matchMask[index + i] = 1; + i += 1; + } + } + } + + // Reset the best location + bestLocation = -1; + var lastBitArr = []; + var finalScore = 1; + var binMax = patternLen + textLen; + var mask = 1 << patternLen - 1; + for (var _i = 0; _i < patternLen; _i += 1) { + // Scan for the best match; each iteration allows for one more error. + // Run a binary search to determine how far from the match location we can stray + // at this error level. + var binMin = 0; + var binMid = binMax; + while (binMin < binMid) { + var _score = computeScore$1(pattern, { + errors: _i, + currentLocation: expectedLocation + binMid, + expectedLocation: expectedLocation, + distance: distance, + ignoreLocation: ignoreLocation + }); + if (_score <= currentThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } + + // Use the result from this iteration as the maximum for the next. + binMax = binMid; + var start = Math.max(1, expectedLocation - binMid + 1); + var finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen; + + // Initialize the bit array + var bitArr = Array(finish + 2); + bitArr[finish + 1] = (1 << _i) - 1; + for (var j = finish; j >= start; j -= 1) { + var currentLocation = j - 1; + var charMatch = patternAlphabet[text.charAt(currentLocation)]; + if (computeMatches) { + // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`) + matchMask[currentLocation] = +!!charMatch; + } + + // First pass: exact match + bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch; + + // Subsequent passes: fuzzy match + if (_i) { + bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1]; + } + if (bitArr[j] & mask) { + finalScore = computeScore$1(pattern, { + errors: _i, + currentLocation: currentLocation, + expectedLocation: expectedLocation, + distance: distance, + ignoreLocation: ignoreLocation + }); + + // This match will almost certainly be better than any existing match. + // But check anyway. + if (finalScore <= currentThreshold) { + // Indeed it is + currentThreshold = finalScore; + bestLocation = currentLocation; + + // Already passed `loc`, downhill from here on in. + if (bestLocation <= expectedLocation) { + break; + } + + // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`. + start = Math.max(1, 2 * expectedLocation - bestLocation); + } + } + } + + // No hope for a (better) match at greater error levels. + var _score2 = computeScore$1(pattern, { + errors: _i + 1, + currentLocation: expectedLocation, + expectedLocation: expectedLocation, + distance: distance, + ignoreLocation: ignoreLocation + }); + if (_score2 > currentThreshold) { + break; + } + lastBitArr = bitArr; + } + var result = { + isMatch: bestLocation >= 0, + // Count exact matches (those with a score of 0) to be "almost" exact + score: Math.max(0.001, finalScore) + }; + if (computeMatches) { + var indices = convertMaskToIndices(matchMask, minMatchCharLength); + if (!indices.length) { + result.isMatch = false; + } else if (includeMatches) { + result.indices = indices; + } + } + return result; + } + + function createPatternAlphabet(pattern) { + var mask = {}; + for (var i = 0, len = pattern.length; i < len; i += 1) { + var _char = pattern.charAt(i); + mask[_char] = (mask[_char] || 0) | 1 << len - i - 1; + } + return mask; + } + + var BitapSearch = /*#__PURE__*/function () { + function BitapSearch(pattern) { + var _this = this; + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$location = _ref.location, + location = _ref$location === void 0 ? Config.location : _ref$location, + _ref$threshold = _ref.threshold, + threshold = _ref$threshold === void 0 ? Config.threshold : _ref$threshold, + _ref$distance = _ref.distance, + distance = _ref$distance === void 0 ? Config.distance : _ref$distance, + _ref$includeMatches = _ref.includeMatches, + includeMatches = _ref$includeMatches === void 0 ? Config.includeMatches : _ref$includeMatches, + _ref$findAllMatches = _ref.findAllMatches, + findAllMatches = _ref$findAllMatches === void 0 ? Config.findAllMatches : _ref$findAllMatches, + _ref$minMatchCharLeng = _ref.minMatchCharLength, + minMatchCharLength = _ref$minMatchCharLeng === void 0 ? Config.minMatchCharLength : _ref$minMatchCharLeng, + _ref$isCaseSensitive = _ref.isCaseSensitive, + isCaseSensitive = _ref$isCaseSensitive === void 0 ? Config.isCaseSensitive : _ref$isCaseSensitive, + _ref$ignoreLocation = _ref.ignoreLocation, + ignoreLocation = _ref$ignoreLocation === void 0 ? Config.ignoreLocation : _ref$ignoreLocation; + _classCallCheck(this, BitapSearch); + this.options = { + location: location, + threshold: threshold, + distance: distance, + includeMatches: includeMatches, + findAllMatches: findAllMatches, + minMatchCharLength: minMatchCharLength, + isCaseSensitive: isCaseSensitive, + ignoreLocation: ignoreLocation + }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.chunks = []; + if (!this.pattern.length) { + return; + } + var addChunk = function addChunk(pattern, startIndex) { + _this.chunks.push({ + pattern: pattern, + alphabet: createPatternAlphabet(pattern), + startIndex: startIndex + }); + }; + var len = this.pattern.length; + if (len > MAX_BITS) { + var i = 0; + var remainder = len % MAX_BITS; + var end = len - remainder; + while (i < end) { + addChunk(this.pattern.substr(i, MAX_BITS), i); + i += MAX_BITS; + } + if (remainder) { + var startIndex = len - MAX_BITS; + addChunk(this.pattern.substr(startIndex), startIndex); + } + } else { + addChunk(this.pattern, 0); + } + } + _createClass(BitapSearch, [{ + key: "searchIn", + value: function searchIn(text) { + var _this$options = this.options, + isCaseSensitive = _this$options.isCaseSensitive, + includeMatches = _this$options.includeMatches; + if (!isCaseSensitive) { + text = text.toLowerCase(); + } + + // Exact match + if (this.pattern === text) { + var _result = { + isMatch: true, + score: 0 + }; + if (includeMatches) { + _result.indices = [[0, text.length - 1]]; + } + return _result; + } + + // Otherwise, use Bitap algorithm + var _this$options2 = this.options, + location = _this$options2.location, + distance = _this$options2.distance, + threshold = _this$options2.threshold, + findAllMatches = _this$options2.findAllMatches, + minMatchCharLength = _this$options2.minMatchCharLength, + ignoreLocation = _this$options2.ignoreLocation; + var allIndices = []; + var totalScore = 0; + var hasMatches = false; + this.chunks.forEach(function (_ref2) { + var pattern = _ref2.pattern, + alphabet = _ref2.alphabet, + startIndex = _ref2.startIndex; + var _search = search(text, pattern, alphabet, { + location: location + startIndex, + distance: distance, + threshold: threshold, + findAllMatches: findAllMatches, + minMatchCharLength: minMatchCharLength, + includeMatches: includeMatches, + ignoreLocation: ignoreLocation + }), + isMatch = _search.isMatch, + score = _search.score, + indices = _search.indices; + if (isMatch) { + hasMatches = true; + } + totalScore += score; + if (isMatch && indices) { + allIndices = [].concat(_toConsumableArray(allIndices), _toConsumableArray(indices)); + } + }); + var result = { + isMatch: hasMatches, + score: hasMatches ? totalScore / this.chunks.length : 1 + }; + if (hasMatches && includeMatches) { + result.indices = allIndices; + } + return result; + } + }]); + return BitapSearch; + }(); + + var BaseMatch = /*#__PURE__*/function () { + function BaseMatch(pattern) { + _classCallCheck(this, BaseMatch); + this.pattern = pattern; + } + _createClass(BaseMatch, [{ + key: "search", + value: function search( /*text*/) {} + }], [{ + key: "isMultiMatch", + value: function isMultiMatch(pattern) { + return getMatch(pattern, this.multiRegex); + } + }, { + key: "isSingleMatch", + value: function isSingleMatch(pattern) { + return getMatch(pattern, this.singleRegex); + } + }]); + return BaseMatch; + }(); + function getMatch(pattern, exp) { + var matches = pattern.match(exp); + return matches ? matches[1] : null; + } + + var ExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(ExactMatch, _BaseMatch); + var _super = _createSuper(ExactMatch); + function ExactMatch(pattern) { + _classCallCheck(this, ExactMatch); + return _super.call(this, pattern); + } + _createClass(ExactMatch, [{ + key: "search", + value: function search(text) { + var isMatch = text === this.pattern; + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^="(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^=(.*)$/; + } + }]); + return ExactMatch; + }(BaseMatch); + + var InverseExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(InverseExactMatch, _BaseMatch); + var _super = _createSuper(InverseExactMatch); + function InverseExactMatch(pattern) { + _classCallCheck(this, InverseExactMatch); + return _super.call(this, pattern); + } + _createClass(InverseExactMatch, [{ + key: "search", + value: function search(text) { + var index = text.indexOf(this.pattern); + var isMatch = index === -1; + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'inverse-exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^!"(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^!(.*)$/; + } + }]); + return InverseExactMatch; + }(BaseMatch); + + var PrefixExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(PrefixExactMatch, _BaseMatch); + var _super = _createSuper(PrefixExactMatch); + function PrefixExactMatch(pattern) { + _classCallCheck(this, PrefixExactMatch); + return _super.call(this, pattern); + } + _createClass(PrefixExactMatch, [{ + key: "search", + value: function search(text) { + var isMatch = text.startsWith(this.pattern); + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'prefix-exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^\^"(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^\^(.*)$/; + } + }]); + return PrefixExactMatch; + }(BaseMatch); + + var InversePrefixExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(InversePrefixExactMatch, _BaseMatch); + var _super = _createSuper(InversePrefixExactMatch); + function InversePrefixExactMatch(pattern) { + _classCallCheck(this, InversePrefixExactMatch); + return _super.call(this, pattern); + } + _createClass(InversePrefixExactMatch, [{ + key: "search", + value: function search(text) { + var isMatch = !text.startsWith(this.pattern); + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'inverse-prefix-exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^!\^"(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^!\^(.*)$/; + } + }]); + return InversePrefixExactMatch; + }(BaseMatch); + + var SuffixExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(SuffixExactMatch, _BaseMatch); + var _super = _createSuper(SuffixExactMatch); + function SuffixExactMatch(pattern) { + _classCallCheck(this, SuffixExactMatch); + return _super.call(this, pattern); + } + _createClass(SuffixExactMatch, [{ + key: "search", + value: function search(text) { + var isMatch = text.endsWith(this.pattern); + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [text.length - this.pattern.length, text.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'suffix-exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^"(.*)"\$$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^(.*)\$$/; + } + }]); + return SuffixExactMatch; + }(BaseMatch); + + var InverseSuffixExactMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(InverseSuffixExactMatch, _BaseMatch); + var _super = _createSuper(InverseSuffixExactMatch); + function InverseSuffixExactMatch(pattern) { + _classCallCheck(this, InverseSuffixExactMatch); + return _super.call(this, pattern); + } + _createClass(InverseSuffixExactMatch, [{ + key: "search", + value: function search(text) { + var isMatch = !text.endsWith(this.pattern); + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + }], [{ + key: "type", + get: function get() { + return 'inverse-suffix-exact'; + } + }, { + key: "multiRegex", + get: function get() { + return /^!"(.*)"\$$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^!(.*)\$$/; + } + }]); + return InverseSuffixExactMatch; + }(BaseMatch); + + var FuzzyMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(FuzzyMatch, _BaseMatch); + var _super = _createSuper(FuzzyMatch); + function FuzzyMatch(pattern) { + var _this; + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$location = _ref.location, + location = _ref$location === void 0 ? Config.location : _ref$location, + _ref$threshold = _ref.threshold, + threshold = _ref$threshold === void 0 ? Config.threshold : _ref$threshold, + _ref$distance = _ref.distance, + distance = _ref$distance === void 0 ? Config.distance : _ref$distance, + _ref$includeMatches = _ref.includeMatches, + includeMatches = _ref$includeMatches === void 0 ? Config.includeMatches : _ref$includeMatches, + _ref$findAllMatches = _ref.findAllMatches, + findAllMatches = _ref$findAllMatches === void 0 ? Config.findAllMatches : _ref$findAllMatches, + _ref$minMatchCharLeng = _ref.minMatchCharLength, + minMatchCharLength = _ref$minMatchCharLeng === void 0 ? Config.minMatchCharLength : _ref$minMatchCharLeng, + _ref$isCaseSensitive = _ref.isCaseSensitive, + isCaseSensitive = _ref$isCaseSensitive === void 0 ? Config.isCaseSensitive : _ref$isCaseSensitive, + _ref$ignoreLocation = _ref.ignoreLocation, + ignoreLocation = _ref$ignoreLocation === void 0 ? Config.ignoreLocation : _ref$ignoreLocation; + _classCallCheck(this, FuzzyMatch); + _this = _super.call(this, pattern); + _this._bitapSearch = new BitapSearch(pattern, { + location: location, + threshold: threshold, + distance: distance, + includeMatches: includeMatches, + findAllMatches: findAllMatches, + minMatchCharLength: minMatchCharLength, + isCaseSensitive: isCaseSensitive, + ignoreLocation: ignoreLocation + }); + return _this; + } + _createClass(FuzzyMatch, [{ + key: "search", + value: function search(text) { + return this._bitapSearch.searchIn(text); + } + }], [{ + key: "type", + get: function get() { + return 'fuzzy'; + } + }, { + key: "multiRegex", + get: function get() { + return /^"(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^(.*)$/; + } + }]); + return FuzzyMatch; + }(BaseMatch); + + var IncludeMatch = /*#__PURE__*/function (_BaseMatch) { + _inherits(IncludeMatch, _BaseMatch); + var _super = _createSuper(IncludeMatch); + function IncludeMatch(pattern) { + _classCallCheck(this, IncludeMatch); + return _super.call(this, pattern); + } + _createClass(IncludeMatch, [{ + key: "search", + value: function search(text) { + var location = 0; + var index; + var indices = []; + var patternLen = this.pattern.length; + + // Get all exact matches + while ((index = text.indexOf(this.pattern, location)) > -1) { + location = index + patternLen; + indices.push([index, location - 1]); + } + var isMatch = !!indices.length; + return { + isMatch: isMatch, + score: isMatch ? 0 : 1, + indices: indices + }; + } + }], [{ + key: "type", + get: function get() { + return 'include'; + } + }, { + key: "multiRegex", + get: function get() { + return /^'"(.*)"$/; + } + }, { + key: "singleRegex", + get: function get() { + return /^'(.*)$/; + } + }]); + return IncludeMatch; + }(BaseMatch); + + // ā¯—Order is important. DO NOT CHANGE. + var searchers = [ExactMatch, IncludeMatch, PrefixExactMatch, InversePrefixExactMatch, InverseSuffixExactMatch, SuffixExactMatch, InverseExactMatch, FuzzyMatch]; + var searchersLen = searchers.length; + + // Regex to split by spaces, but keep anything in quotes together + var SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/; + var OR_TOKEN = '|'; + + // Return a 2D array representation of the query, for simpler parsing. + // Example: + // "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]] + function parseQuery(pattern) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return pattern.split(OR_TOKEN).map(function (item) { + var query = item.trim().split(SPACE_RE).filter(function (item) { + return item && !!item.trim(); + }); + var results = []; + for (var i = 0, len = query.length; i < len; i += 1) { + var queryItem = query[i]; + + // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`) + var found = false; + var idx = -1; + while (!found && ++idx < searchersLen) { + var searcher = searchers[idx]; + var token = searcher.isMultiMatch(queryItem); + if (token) { + results.push(new searcher(token, options)); + found = true; + } + } + if (found) { + continue; + } + + // 2. Handle single query matches (i.e, once that are *not* quoted) + idx = -1; + while (++idx < searchersLen) { + var _searcher = searchers[idx]; + var _token = _searcher.isSingleMatch(queryItem); + if (_token) { + results.push(new _searcher(_token, options)); + break; + } + } + } + return results; + }); + } + + // These extended matchers can return an array of matches, as opposed + // to a singl match + var MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]); + + /** + * Command-like searching + * ====================== + * + * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`, + * search in a given text. + * + * Search syntax: + * + * | Token | Match type | Description | + * | ----------- | -------------------------- | -------------------------------------- | + * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` | + * | `=scheme` | exact-match | Items that are `scheme` | + * | `'python` | include-match | Items that include `python` | + * | `!ruby` | inverse-exact-match | Items that do not include `ruby` | + * | `^java` | prefix-exact-match | Items that start with `java` | + * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` | + * | `.js$` | suffix-exact-match | Items that end with `.js` | + * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` | + * + * A single pipe character acts as an OR operator. For example, the following + * query matches entries that start with `core` and end with either`go`, `rb`, + * or`py`. + * + * ``` + * ^core go$ | rb$ | py$ + * ``` + */ + var ExtendedSearch = /*#__PURE__*/function () { + function ExtendedSearch(pattern) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$isCaseSensitive = _ref.isCaseSensitive, + isCaseSensitive = _ref$isCaseSensitive === void 0 ? Config.isCaseSensitive : _ref$isCaseSensitive, + _ref$includeMatches = _ref.includeMatches, + includeMatches = _ref$includeMatches === void 0 ? Config.includeMatches : _ref$includeMatches, + _ref$minMatchCharLeng = _ref.minMatchCharLength, + minMatchCharLength = _ref$minMatchCharLeng === void 0 ? Config.minMatchCharLength : _ref$minMatchCharLeng, + _ref$ignoreLocation = _ref.ignoreLocation, + ignoreLocation = _ref$ignoreLocation === void 0 ? Config.ignoreLocation : _ref$ignoreLocation, + _ref$findAllMatches = _ref.findAllMatches, + findAllMatches = _ref$findAllMatches === void 0 ? Config.findAllMatches : _ref$findAllMatches, + _ref$location = _ref.location, + location = _ref$location === void 0 ? Config.location : _ref$location, + _ref$threshold = _ref.threshold, + threshold = _ref$threshold === void 0 ? Config.threshold : _ref$threshold, + _ref$distance = _ref.distance, + distance = _ref$distance === void 0 ? Config.distance : _ref$distance; + _classCallCheck(this, ExtendedSearch); + this.query = null; + this.options = { + isCaseSensitive: isCaseSensitive, + includeMatches: includeMatches, + minMatchCharLength: minMatchCharLength, + findAllMatches: findAllMatches, + ignoreLocation: ignoreLocation, + location: location, + threshold: threshold, + distance: distance + }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.query = parseQuery(this.pattern, this.options); + } + _createClass(ExtendedSearch, [{ + key: "searchIn", + value: function searchIn(text) { + var query = this.query; + if (!query) { + return { + isMatch: false, + score: 1 + }; + } + var _this$options = this.options, + includeMatches = _this$options.includeMatches, + isCaseSensitive = _this$options.isCaseSensitive; + text = isCaseSensitive ? text : text.toLowerCase(); + var numMatches = 0; + var allIndices = []; + var totalScore = 0; + + // ORs + for (var i = 0, qLen = query.length; i < qLen; i += 1) { + var searchers = query[i]; + + // Reset indices + allIndices.length = 0; + numMatches = 0; + + // ANDs + for (var j = 0, pLen = searchers.length; j < pLen; j += 1) { + var searcher = searchers[j]; + var _searcher$search = searcher.search(text), + isMatch = _searcher$search.isMatch, + indices = _searcher$search.indices, + score = _searcher$search.score; + if (isMatch) { + numMatches += 1; + totalScore += score; + if (includeMatches) { + var type = searcher.constructor.type; + if (MultiMatchSet.has(type)) { + allIndices = [].concat(_toConsumableArray(allIndices), _toConsumableArray(indices)); + } else { + allIndices.push(indices); + } + } + } else { + totalScore = 0; + numMatches = 0; + allIndices.length = 0; + break; + } + } + + // OR condition, so if TRUE, return + if (numMatches) { + var result = { + isMatch: true, + score: totalScore / numMatches + }; + if (includeMatches) { + result.indices = allIndices; + } + return result; + } + } + + // Nothing was matched + return { + isMatch: false, + score: 1 + }; + } + }], [{ + key: "condition", + value: function condition(_, options) { + return options.useExtendedSearch; + } + }]); + return ExtendedSearch; + }(); + + var registeredSearchers = []; + function register() { + registeredSearchers.push.apply(registeredSearchers, arguments); + } + function createSearcher(pattern, options) { + for (var i = 0, len = registeredSearchers.length; i < len; i += 1) { + var searcherClass = registeredSearchers[i]; + if (searcherClass.condition(pattern, options)) { + return new searcherClass(pattern, options); + } + } + return new BitapSearch(pattern, options); + } + + var LogicalOperator = { + AND: '$and', + OR: '$or' + }; + var KeyType = { + PATH: '$path', + PATTERN: '$val' + }; + var isExpression = function isExpression(query) { + return !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); + }; + var isPath = function isPath(query) { + return !!query[KeyType.PATH]; + }; + var isLeaf = function isLeaf(query) { + return !isArray(query) && isObject(query) && !isExpression(query); + }; + var convertToExplicit = function convertToExplicit(query) { + return _defineProperty({}, LogicalOperator.AND, Object.keys(query).map(function (key) { + return _defineProperty({}, key, query[key]); + })); + }; + + // When `auto` is `true`, the parse function will infer and initialize and add + // the appropriate `Searcher` instance + function parse(query, options) { + var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref3$auto = _ref3.auto, + auto = _ref3$auto === void 0 ? true : _ref3$auto; + var next = function next(query) { + var keys = Object.keys(query); + var isQueryPath = isPath(query); + if (!isQueryPath && keys.length > 1 && !isExpression(query)) { + return next(convertToExplicit(query)); + } + if (isLeaf(query)) { + var key = isQueryPath ? query[KeyType.PATH] : keys[0]; + var pattern = isQueryPath ? query[KeyType.PATTERN] : query[key]; + if (!isString(pattern)) { + throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)); + } + var obj = { + keyId: createKeyId(key), + pattern: pattern + }; + if (auto) { + obj.searcher = createSearcher(pattern, options); + } + return obj; + } + var node = { + children: [], + operator: keys[0] + }; + keys.forEach(function (key) { + var value = query[key]; + if (isArray(value)) { + value.forEach(function (item) { + node.children.push(next(item)); + }); + } + }); + return node; + }; + if (!isExpression(query)) { + query = convertToExplicit(query); + } + return next(query); + } + + // Practical scoring function + function computeScore(results, _ref) { + var _ref$ignoreFieldNorm = _ref.ignoreFieldNorm, + ignoreFieldNorm = _ref$ignoreFieldNorm === void 0 ? Config.ignoreFieldNorm : _ref$ignoreFieldNorm; + results.forEach(function (result) { + var totalScore = 1; + result.matches.forEach(function (_ref2) { + var key = _ref2.key, + norm = _ref2.norm, + score = _ref2.score; + var weight = key ? key.weight : null; + totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm)); + }); + result.score = totalScore; + }); + } + + function transformMatches(result, data) { + var matches = result.matches; + data.matches = []; + if (!isDefined(matches)) { + return; + } + matches.forEach(function (match) { + if (!isDefined(match.indices) || !match.indices.length) { + return; + } + var indices = match.indices, + value = match.value; + var obj = { + indices: indices, + value: value + }; + if (match.key) { + obj.key = match.key.src; + } + if (match.idx > -1) { + obj.refIndex = match.idx; + } + data.matches.push(obj); + }); + } + + function transformScore(result, data) { + data.score = result.score; + } + + function format(results, docs) { + var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref$includeMatches = _ref.includeMatches, + includeMatches = _ref$includeMatches === void 0 ? Config.includeMatches : _ref$includeMatches, + _ref$includeScore = _ref.includeScore, + includeScore = _ref$includeScore === void 0 ? Config.includeScore : _ref$includeScore; + var transformers = []; + if (includeMatches) transformers.push(transformMatches); + if (includeScore) transformers.push(transformScore); + return results.map(function (result) { + var idx = result.idx; + var data = { + item: docs[idx], + refIndex: idx + }; + if (transformers.length) { + transformers.forEach(function (transformer) { + transformer(result, data); + }); + } + return data; + }); + } + + var Fuse$1 = /*#__PURE__*/function () { + function Fuse(docs) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var index = arguments.length > 2 ? arguments[2] : undefined; + _classCallCheck(this, Fuse); + this.options = _objectSpread2(_objectSpread2({}, Config), options); + if (this.options.useExtendedSearch && !true) { + throw new Error(EXTENDED_SEARCH_UNAVAILABLE); + } + this._keyStore = new KeyStore(this.options.keys); + this.setCollection(docs, index); + } + _createClass(Fuse, [{ + key: "setCollection", + value: function setCollection(docs, index) { + this._docs = docs; + if (index && !(index instanceof FuseIndex)) { + throw new Error(INCORRECT_INDEX_TYPE); + } + this._myIndex = index || createIndex(this.options.keys, this._docs, { + getFn: this.options.getFn, + fieldNormWeight: this.options.fieldNormWeight + }); + } + }, { + key: "add", + value: function add(doc) { + if (!isDefined(doc)) { + return; + } + this._docs.push(doc); + this._myIndex.add(doc); + } + }, { + key: "remove", + value: function remove() { + var predicate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function /* doc, idx */ () { + return false; + }; + var results = []; + for (var i = 0, len = this._docs.length; i < len; i += 1) { + var doc = this._docs[i]; + if (predicate(doc, i)) { + this.removeAt(i); + i -= 1; + len -= 1; + results.push(doc); + } + } + return results; + } + }, { + key: "removeAt", + value: function removeAt(idx) { + this._docs.splice(idx, 1); + this._myIndex.removeAt(idx); + } + }, { + key: "getIndex", + value: function getIndex() { + return this._myIndex; + } + }, { + key: "search", + value: function search(query) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$limit = _ref.limit, + limit = _ref$limit === void 0 ? -1 : _ref$limit; + var _this$options = this.options, + includeMatches = _this$options.includeMatches, + includeScore = _this$options.includeScore, + shouldSort = _this$options.shouldSort, + sortFn = _this$options.sortFn, + ignoreFieldNorm = _this$options.ignoreFieldNorm; + var results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query); + computeScore(results, { + ignoreFieldNorm: ignoreFieldNorm + }); + if (shouldSort) { + results.sort(sortFn); + } + if (isNumber(limit) && limit > -1) { + results = results.slice(0, limit); + } + return format(results, this._docs, { + includeMatches: includeMatches, + includeScore: includeScore + }); + } + }, { + key: "_searchStringList", + value: function _searchStringList(query) { + var searcher = createSearcher(query, this.options); + var records = this._myIndex.records; + var results = []; + + // Iterate over every string in the index + records.forEach(function (_ref2) { + var text = _ref2.v, + idx = _ref2.i, + norm = _ref2.n; + if (!isDefined(text)) { + return; + } + var _searcher$searchIn = searcher.searchIn(text), + isMatch = _searcher$searchIn.isMatch, + score = _searcher$searchIn.score, + indices = _searcher$searchIn.indices; + if (isMatch) { + results.push({ + item: text, + idx: idx, + matches: [{ + score: score, + value: text, + norm: norm, + indices: indices + }] + }); + } + }); + return results; + } + }, { + key: "_searchLogical", + value: function _searchLogical(query) { + var _this = this; + var expression = parse(query, this.options); + var evaluate = function evaluate(node, item, idx) { + if (!node.children) { + var keyId = node.keyId, + searcher = node.searcher; + var matches = _this._findMatches({ + key: _this._keyStore.get(keyId), + value: _this._myIndex.getValueForItemAtKeyId(item, keyId), + searcher: searcher + }); + if (matches && matches.length) { + return [{ + idx: idx, + item: item, + matches: matches + }]; + } + return []; + } + var res = []; + for (var i = 0, len = node.children.length; i < len; i += 1) { + var child = node.children[i]; + var result = evaluate(child, item, idx); + if (result.length) { + res.push.apply(res, _toConsumableArray(result)); + } else if (node.operator === LogicalOperator.AND) { + return []; + } + } + return res; + }; + var records = this._myIndex.records; + var resultMap = {}; + var results = []; + records.forEach(function (_ref3) { + var item = _ref3.$, + idx = _ref3.i; + if (isDefined(item)) { + var expResults = evaluate(expression, item, idx); + if (expResults.length) { + // Dedupe when adding + if (!resultMap[idx]) { + resultMap[idx] = { + idx: idx, + item: item, + matches: [] + }; + results.push(resultMap[idx]); + } + expResults.forEach(function (_ref4) { + var _resultMap$idx$matche; + var matches = _ref4.matches; + (_resultMap$idx$matche = resultMap[idx].matches).push.apply(_resultMap$idx$matche, _toConsumableArray(matches)); + }); + } + } + }); + return results; + } + }, { + key: "_searchObjectList", + value: function _searchObjectList(query) { + var _this2 = this; + var searcher = createSearcher(query, this.options); + var _this$_myIndex = this._myIndex, + keys = _this$_myIndex.keys, + records = _this$_myIndex.records; + var results = []; + + // List is Array + records.forEach(function (_ref5) { + var item = _ref5.$, + idx = _ref5.i; + if (!isDefined(item)) { + return; + } + var matches = []; + + // Iterate over every key (i.e, path), and fetch the value at that key + keys.forEach(function (key, keyIndex) { + matches.push.apply(matches, _toConsumableArray(_this2._findMatches({ + key: key, + value: item[keyIndex], + searcher: searcher + }))); + }); + if (matches.length) { + results.push({ + idx: idx, + item: item, + matches: matches + }); + } + }); + return results; + } + }, { + key: "_findMatches", + value: function _findMatches(_ref6) { + var key = _ref6.key, + value = _ref6.value, + searcher = _ref6.searcher; + if (!isDefined(value)) { + return []; + } + var matches = []; + if (isArray(value)) { + value.forEach(function (_ref7) { + var text = _ref7.v, + idx = _ref7.i, + norm = _ref7.n; + if (!isDefined(text)) { + return; + } + var _searcher$searchIn2 = searcher.searchIn(text), + isMatch = _searcher$searchIn2.isMatch, + score = _searcher$searchIn2.score, + indices = _searcher$searchIn2.indices; + if (isMatch) { + matches.push({ + score: score, + key: key, + value: text, + idx: idx, + norm: norm, + indices: indices + }); + } + }); + } else { + var text = value.v, + norm = value.n; + var _searcher$searchIn3 = searcher.searchIn(text), + isMatch = _searcher$searchIn3.isMatch, + score = _searcher$searchIn3.score, + indices = _searcher$searchIn3.indices; + if (isMatch) { + matches.push({ + score: score, + key: key, + value: text, + norm: norm, + indices: indices + }); + } + } + return matches; + } + }]); + return Fuse; + }(); + + Fuse$1.version = '7.0.0'; + Fuse$1.createIndex = createIndex; + Fuse$1.parseIndex = parseIndex; + Fuse$1.config = Config; + { + Fuse$1.parseQuery = parse; + } + { + register(ExtendedSearch); + } + var Fuse = Fuse$1; + + return Fuse; + +})); diff --git a/build/scripts/lunr.js b/build/scripts/lunr.js deleted file mode 100644 index 477222c..0000000 --- a/build/scripts/lunr.js +++ /dev/null @@ -1,974 +0,0 @@ -/** - * elasticlunr - http://weixsong.github.io - * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 - * - * Copyright (C) 2017 Oliver Nightingale - * Copyright (C) 2017 Wei Song - * MIT Licensed - * @license - */ -!(function () { - function e(e) { - if (null === e || "object" != typeof e) return e; - var t = e.constructor(); - for (var n in e) e.hasOwnProperty(n) && (t[n] = e[n]); - return t; - } - var t = function (e) { - var n = new t.Index(); - return ( - n.pipeline.add(t.trimmer, t.stopWordFilter, t.stemmer), - e && e.call(n, n), - n - ); - }; - (t.version = "0.9.5"), - (lunr = t), - (t.utils = {}), - (t.utils.warn = (function (e) { - return function (t) { - e.console && console.warn && console.warn(t); - }; - })(this)), - (t.utils.toString = function (e) { - return void 0 === e || null === e ? "" : e.toString(); - }), - (t.EventEmitter = function () { - this.events = {}; - }), - (t.EventEmitter.prototype.addListener = function () { - var e = Array.prototype.slice.call(arguments), - t = e.pop(), - n = e; - if ("function" != typeof t) - throw new TypeError("last argument must be a function"); - n.forEach(function (e) { - this.hasHandler(e) || (this.events[e] = []), this.events[e].push(t); - }, this); - }), - (t.EventEmitter.prototype.removeListener = function (e, t) { - if (this.hasHandler(e)) { - var n = this.events[e].indexOf(t); - -1 !== n && - (this.events[e].splice(n, 1), - 0 == this.events[e].length && delete this.events[e]); - } - }), - (t.EventEmitter.prototype.emit = function (e) { - if (this.hasHandler(e)) { - var t = Array.prototype.slice.call(arguments, 1); - this.events[e].forEach(function (e) { - e.apply(void 0, t); - }, this); - } - }), - (t.EventEmitter.prototype.hasHandler = function (e) { - return e in this.events; - }), - (t.tokenizer = function (e) { - if (!arguments.length || null === e || void 0 === e) return []; - if (Array.isArray(e)) { - var n = e.filter(function (e) { - return null === e || void 0 === e ? !1 : !0; - }); - n = n.map(function (e) { - return t.utils.toString(e).toLowerCase(); - }); - var i = []; - return ( - n.forEach(function (e) { - var n = e.split(t.tokenizer.seperator); - i = i.concat(n); - }, this), - i - ); - } - return e.toString().trim().toLowerCase().split(t.tokenizer.seperator); - }), - (t.tokenizer.defaultSeperator = /[\s\-]+/), - (t.tokenizer.seperator = t.tokenizer.defaultSeperator), - (t.tokenizer.setSeperator = function (e) { - null !== e && - void 0 !== e && - "object" == typeof e && - (t.tokenizer.seperator = e); - }), - (t.tokenizer.resetSeperator = function () { - t.tokenizer.seperator = t.tokenizer.defaultSeperator; - }), - (t.tokenizer.getSeperator = function () { - return t.tokenizer.seperator; - }), - (t.Pipeline = function () { - this._queue = []; - }), - (t.Pipeline.registeredFunctions = {}), - (t.Pipeline.registerFunction = function (e, n) { - n in t.Pipeline.registeredFunctions && - t.utils.warn("Overwriting existing registered function: " + n), - (e.label = n), - (t.Pipeline.registeredFunctions[n] = e); - }), - (t.Pipeline.getRegisteredFunction = function (e) { - return e in t.Pipeline.registeredFunctions != !0 - ? null - : t.Pipeline.registeredFunctions[e]; - }), - (t.Pipeline.warnIfFunctionNotRegistered = function (e) { - var n = e.label && e.label in this.registeredFunctions; - n || - t.utils.warn( - "Function is not registered with pipeline. This may cause problems when serialising the index.\n", - e, - ); - }), - (t.Pipeline.load = function (e) { - var n = new t.Pipeline(); - return ( - e.forEach(function (e) { - var i = t.Pipeline.getRegisteredFunction(e); - if (!i) throw new Error("Cannot load un-registered function: " + e); - n.add(i); - }), - n - ); - }), - (t.Pipeline.prototype.add = function () { - var e = Array.prototype.slice.call(arguments); - e.forEach(function (e) { - t.Pipeline.warnIfFunctionNotRegistered(e), this._queue.push(e); - }, this); - }), - (t.Pipeline.prototype.after = function (e, n) { - t.Pipeline.warnIfFunctionNotRegistered(n); - var i = this._queue.indexOf(e); - if (-1 === i) throw new Error("Cannot find existingFn"); - this._queue.splice(i + 1, 0, n); - }), - (t.Pipeline.prototype.before = function (e, n) { - t.Pipeline.warnIfFunctionNotRegistered(n); - var i = this._queue.indexOf(e); - if (-1 === i) throw new Error("Cannot find existingFn"); - this._queue.splice(i, 0, n); - }), - (t.Pipeline.prototype.remove = function (e) { - var t = this._queue.indexOf(e); - -1 !== t && this._queue.splice(t, 1); - }), - (t.Pipeline.prototype.run = function (e) { - for ( - var t = [], n = e.length, i = this._queue.length, o = 0; - n > o; - o++ - ) { - for ( - var r = e[o], s = 0; - i > s && ((r = this._queue[s](r, o, e)), void 0 !== r && null !== r); - s++ - ); - void 0 !== r && null !== r && t.push(r); - } - return t; - }), - (t.Pipeline.prototype.reset = function () { - this._queue = []; - }), - (t.Pipeline.prototype.get = function () { - return this._queue; - }), - (t.Pipeline.prototype.toJSON = function () { - return this._queue.map(function (e) { - return t.Pipeline.warnIfFunctionNotRegistered(e), e.label; - }); - }), - (t.Index = function () { - (this._fields = []), - (this._ref = "id"), - (this.pipeline = new t.Pipeline()), - (this.documentStore = new t.DocumentStore()), - (this.index = {}), - (this.eventEmitter = new t.EventEmitter()), - (this._idfCache = {}), - this.on( - "add", - "remove", - "update", - function () { - this._idfCache = {}; - }.bind(this), - ); - }), - (t.Index.prototype.on = function () { - var e = Array.prototype.slice.call(arguments); - return this.eventEmitter.addListener.apply(this.eventEmitter, e); - }), - (t.Index.prototype.off = function (e, t) { - return this.eventEmitter.removeListener(e, t); - }), - (t.Index.load = function (e) { - e.version !== t.version && - t.utils.warn( - "version mismatch: current " + t.version + " importing " + e.version, - ); - var n = new this(); - (n._fields = e.fields), - (n._ref = e.ref), - (n.documentStore = t.DocumentStore.load(e.documentStore)), - (n.pipeline = t.Pipeline.load(e.pipeline)), - (n.index = {}); - for (var i in e.index) n.index[i] = t.InvertedIndex.load(e.index[i]); - return n; - }), - (t.Index.prototype.addField = function (e) { - return ( - this._fields.push(e), (this.index[e] = new t.InvertedIndex()), this - ); - }), - (t.Index.prototype.setRef = function (e) { - return (this._ref = e), this; - }), - (t.Index.prototype.saveDocument = function (e) { - return (this.documentStore = new t.DocumentStore(e)), this; - }), - (t.Index.prototype.addDoc = function (e, n) { - if (e) { - var n = void 0 === n ? !0 : n, - i = e[this._ref]; - this.documentStore.addDoc(i, e), - this._fields.forEach(function (n) { - var o = this.pipeline.run(t.tokenizer(e[n])); - this.documentStore.addFieldLength(i, n, o.length); - var r = {}; - o.forEach(function (e) { - e in r ? (r[e] += 1) : (r[e] = 1); - }, this); - for (var s in r) { - var u = r[s]; - (u = Math.sqrt(u)), this.index[n].addToken(s, { ref: i, tf: u }); - } - }, this), - n && this.eventEmitter.emit("add", e, this); - } - }), - (t.Index.prototype.removeDocByRef = function (e) { - if ( - e && - this.documentStore.isDocStored() !== !1 && - this.documentStore.hasDoc(e) - ) { - var t = this.documentStore.getDoc(e); - this.removeDoc(t, !1); - } - }), - (t.Index.prototype.removeDoc = function (e, n) { - if (e) { - var n = void 0 === n ? !0 : n, - i = e[this._ref]; - this.documentStore.hasDoc(i) && - (this.documentStore.removeDoc(i), - this._fields.forEach(function (n) { - var o = this.pipeline.run(t.tokenizer(e[n])); - o.forEach(function (e) { - this.index[n].removeToken(e, i); - }, this); - }, this), - n && this.eventEmitter.emit("remove", e, this)); - } - }), - (t.Index.prototype.updateDoc = function (e, t) { - var t = void 0 === t ? !0 : t; - this.removeDocByRef(e[this._ref], !1), - this.addDoc(e, !1), - t && this.eventEmitter.emit("update", e, this); - }), - (t.Index.prototype.idf = function (e, t) { - var n = "@" + t + "/" + e; - if (Object.prototype.hasOwnProperty.call(this._idfCache, n)) - return this._idfCache[n]; - var i = this.index[t].getDocFreq(e), - o = 1 + Math.log(this.documentStore.length / (i + 1)); - return (this._idfCache[n] = o), o; - }), - (t.Index.prototype.getFields = function () { - return this._fields.slice(); - }), - (t.Index.prototype.search = function (e, n) { - if (!e) return []; - e = "string" == typeof e ? { any: e } : JSON.parse(JSON.stringify(e)); - var i = null; - null != n && (i = JSON.stringify(n)); - for ( - var o = new t.Configuration(i, this.getFields()).get(), - r = {}, - s = Object.keys(e), - u = 0; - u < s.length; - u++ - ) { - var a = s[u]; - r[a] = this.pipeline.run(t.tokenizer(e[a])); - } - var l = {}; - for (var c in o) { - var d = r[c] || r.any; - if (d) { - var f = this.fieldSearch(d, c, o), - h = o[c].boost; - for (var p in f) f[p] = f[p] * h; - for (var p in f) p in l ? (l[p] += f[p]) : (l[p] = f[p]); - } - } - var v, - g = []; - for (var p in l) - (v = { ref: p, score: l[p] }), - this.documentStore.hasDoc(p) && - (v.doc = this.documentStore.getDoc(p)), - g.push(v); - return ( - g.sort(function (e, t) { - return t.score - e.score; - }), - g - ); - }), - (t.Index.prototype.fieldSearch = function (e, t, n) { - var i = n[t].bool, - o = n[t].expand, - r = n[t].boost, - s = null, - u = {}; - return 0 !== r - ? (e.forEach(function (e) { - var n = [e]; - 1 == o && (n = this.index[t].expandToken(e)); - var r = {}; - n.forEach(function (n) { - var o = this.index[t].getDocs(n), - a = this.idf(n, t); - if (s && "AND" == i) { - var l = {}; - for (var c in s) c in o && (l[c] = o[c]); - o = l; - } - n == e && this.fieldSearchStats(u, n, o); - for (var c in o) { - var d = this.index[t].getTermFrequency(n, c), - f = this.documentStore.getFieldLength(c, t), - h = 1; - 0 != f && (h = 1 / Math.sqrt(f)); - var p = 1; - n != e && (p = 0.15 * (1 - (n.length - e.length) / n.length)); - var v = d * a * h * p; - c in r ? (r[c] += v) : (r[c] = v); - } - }, this), - (s = this.mergeScores(s, r, i)); - }, this), - (s = this.coordNorm(s, u, e.length))) - : void 0; - }), - (t.Index.prototype.mergeScores = function (e, t, n) { - if (!e) return t; - if ("AND" == n) { - var i = {}; - for (var o in t) o in e && (i[o] = e[o] + t[o]); - return i; - } - for (var o in t) o in e ? (e[o] += t[o]) : (e[o] = t[o]); - return e; - }), - (t.Index.prototype.fieldSearchStats = function (e, t, n) { - for (var i in n) i in e ? e[i].push(t) : (e[i] = [t]); - }), - (t.Index.prototype.coordNorm = function (e, t, n) { - for (var i in e) - if (i in t) { - var o = t[i].length; - e[i] = (e[i] * o) / n; - } - return e; - }), - (t.Index.prototype.toJSON = function () { - var e = {}; - return ( - this._fields.forEach(function (t) { - e[t] = this.index[t].toJSON(); - }, this), - { - version: t.version, - fields: this._fields, - ref: this._ref, - documentStore: this.documentStore.toJSON(), - index: e, - pipeline: this.pipeline.toJSON(), - } - ); - }), - (t.Index.prototype.use = function (e) { - var t = Array.prototype.slice.call(arguments, 1); - t.unshift(this), e.apply(this, t); - }), - (t.DocumentStore = function (e) { - (this._save = null === e || void 0 === e ? !0 : e), - (this.docs = {}), - (this.docInfo = {}), - (this.length = 0); - }), - (t.DocumentStore.load = function (e) { - var t = new this(); - return ( - (t.length = e.length), - (t.docs = e.docs), - (t.docInfo = e.docInfo), - (t._save = e.save), - t - ); - }), - (t.DocumentStore.prototype.isDocStored = function () { - return this._save; - }), - (t.DocumentStore.prototype.addDoc = function (t, n) { - this.hasDoc(t) || this.length++, - (this.docs[t] = this._save === !0 ? e(n) : null); - }), - (t.DocumentStore.prototype.getDoc = function (e) { - return this.hasDoc(e) === !1 ? null : this.docs[e]; - }), - (t.DocumentStore.prototype.hasDoc = function (e) { - return e in this.docs; - }), - (t.DocumentStore.prototype.removeDoc = function (e) { - this.hasDoc(e) && - (delete this.docs[e], delete this.docInfo[e], this.length--); - }), - (t.DocumentStore.prototype.addFieldLength = function (e, t, n) { - null !== e && - void 0 !== e && - 0 != this.hasDoc(e) && - (this.docInfo[e] || (this.docInfo[e] = {}), (this.docInfo[e][t] = n)); - }), - (t.DocumentStore.prototype.updateFieldLength = function (e, t, n) { - null !== e && - void 0 !== e && - 0 != this.hasDoc(e) && - this.addFieldLength(e, t, n); - }), - (t.DocumentStore.prototype.getFieldLength = function (e, t) { - return null === e || void 0 === e - ? 0 - : e in this.docs && t in this.docInfo[e] - ? this.docInfo[e][t] - : 0; - }), - (t.DocumentStore.prototype.toJSON = function () { - return { - docs: this.docs, - docInfo: this.docInfo, - length: this.length, - save: this._save, - }; - }), - (t.stemmer = (function () { - var e = { - ational: "ate", - tional: "tion", - enci: "ence", - anci: "ance", - izer: "ize", - bli: "ble", - alli: "al", - entli: "ent", - eli: "e", - ousli: "ous", - ization: "ize", - ation: "ate", - ator: "ate", - alism: "al", - iveness: "ive", - fulness: "ful", - ousness: "ous", - aliti: "al", - iviti: "ive", - biliti: "ble", - logi: "log", - }, - t = { - icate: "ic", - ative: "", - alize: "al", - iciti: "ic", - ical: "ic", - ful: "", - ness: "", - }, - n = "[^aeiou]", - i = "[aeiouy]", - o = n + "[^aeiouy]*", - r = i + "[aeiou]*", - s = "^(" + o + ")?" + r + o, - u = "^(" + o + ")?" + r + o + "(" + r + ")?$", - a = "^(" + o + ")?" + r + o + r + o, - l = "^(" + o + ")?" + i, - c = new RegExp(s), - d = new RegExp(a), - f = new RegExp(u), - h = new RegExp(l), - p = /^(.+?)(ss|i)es$/, - v = /^(.+?)([^s])s$/, - g = /^(.+?)eed$/, - m = /^(.+?)(ed|ing)$/, - y = /.$/, - S = /(at|bl|iz)$/, - x = new RegExp("([^aeiouylsz])\\1$"), - w = new RegExp("^" + o + i + "[^aeiouwxy]$"), - I = /^(.+?[^aeiou])y$/, - b = - /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/, - E = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/, - D = - /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/, - F = /^(.+?)(s|t)(ion)$/, - _ = /^(.+?)e$/, - P = /ll$/, - k = new RegExp("^" + o + i + "[^aeiouwxy]$"), - z = function (n) { - var i, o, r, s, u, a, l; - if (n.length < 3) return n; - if ( - ((r = n.substr(0, 1)), - "y" == r && (n = r.toUpperCase() + n.substr(1)), - (s = p), - (u = v), - s.test(n) - ? (n = n.replace(s, "$1$2")) - : u.test(n) && (n = n.replace(u, "$1$2")), - (s = g), - (u = m), - s.test(n)) - ) { - var z = s.exec(n); - (s = c), s.test(z[1]) && ((s = y), (n = n.replace(s, ""))); - } else if (u.test(n)) { - var z = u.exec(n); - (i = z[1]), - (u = h), - u.test(i) && - ((n = i), - (u = S), - (a = x), - (l = w), - u.test(n) - ? (n += "e") - : a.test(n) - ? ((s = y), (n = n.replace(s, ""))) - : l.test(n) && (n += "e")); - } - if (((s = I), s.test(n))) { - var z = s.exec(n); - (i = z[1]), (n = i + "i"); - } - if (((s = b), s.test(n))) { - var z = s.exec(n); - (i = z[1]), (o = z[2]), (s = c), s.test(i) && (n = i + e[o]); - } - if (((s = E), s.test(n))) { - var z = s.exec(n); - (i = z[1]), (o = z[2]), (s = c), s.test(i) && (n = i + t[o]); - } - if (((s = D), (u = F), s.test(n))) { - var z = s.exec(n); - (i = z[1]), (s = d), s.test(i) && (n = i); - } else if (u.test(n)) { - var z = u.exec(n); - (i = z[1] + z[2]), (u = d), u.test(i) && (n = i); - } - if (((s = _), s.test(n))) { - var z = s.exec(n); - (i = z[1]), - (s = d), - (u = f), - (a = k), - (s.test(i) || (u.test(i) && !a.test(i))) && (n = i); - } - return ( - (s = P), - (u = d), - s.test(n) && u.test(n) && ((s = y), (n = n.replace(s, ""))), - "y" == r && (n = r.toLowerCase() + n.substr(1)), - n - ); - }; - return z; - })()), - t.Pipeline.registerFunction(t.stemmer, "stemmer"), - (t.stopWordFilter = function (e) { - return e && t.stopWordFilter.stopWords[e] !== !0 ? e : void 0; - }), - (t.clearStopWords = function () { - t.stopWordFilter.stopWords = {}; - }), - (t.addStopWords = function (e) { - null != e && - Array.isArray(e) !== !1 && - e.forEach(function (e) { - t.stopWordFilter.stopWords[e] = !0; - }, this); - }), - (t.resetStopWords = function () { - t.stopWordFilter.stopWords = t.defaultStopWords; - }), - (t.defaultStopWords = { - "": !0, - a: !0, - able: !0, - about: !0, - across: !0, - after: !0, - all: !0, - almost: !0, - also: !0, - am: !0, - among: !0, - an: !0, - and: !0, - any: !0, - are: !0, - as: !0, - at: !0, - be: !0, - because: !0, - been: !0, - but: !0, - by: !0, - can: !0, - cannot: !0, - could: !0, - dear: !0, - did: !0, - do: !0, - does: !0, - either: !0, - else: !0, - ever: !0, - every: !0, - for: !0, - from: !0, - get: !0, - got: !0, - had: !0, - has: !0, - have: !0, - he: !0, - her: !0, - hers: !0, - him: !0, - his: !0, - how: !0, - however: !0, - i: !0, - if: !0, - in: !0, - into: !0, - is: !0, - it: !0, - its: !0, - just: !0, - least: !0, - let: !0, - like: !0, - likely: !0, - may: !0, - me: !0, - might: !0, - most: !0, - must: !0, - my: !0, - neither: !0, - no: !0, - nor: !0, - not: !0, - of: !0, - off: !0, - often: !0, - on: !0, - only: !0, - or: !0, - other: !0, - our: !0, - own: !0, - rather: !0, - said: !0, - say: !0, - says: !0, - she: !0, - should: !0, - since: !0, - so: !0, - some: !0, - than: !0, - that: !0, - the: !0, - their: !0, - them: !0, - then: !0, - there: !0, - these: !0, - they: !0, - this: !0, - tis: !0, - to: !0, - too: !0, - twas: !0, - us: !0, - wants: !0, - was: !0, - we: !0, - were: !0, - what: !0, - when: !0, - where: !0, - which: !0, - while: !0, - who: !0, - whom: !0, - why: !0, - will: !0, - with: !0, - would: !0, - yet: !0, - you: !0, - your: !0, - }), - (t.stopWordFilter.stopWords = t.defaultStopWords), - t.Pipeline.registerFunction(t.stopWordFilter, "stopWordFilter"), - (t.trimmer = function (e) { - if (null === e || void 0 === e) - throw new Error("token should not be undefined"); - return e.replace(/^\W+/, "").replace(/\W+$/, ""); - }), - t.Pipeline.registerFunction(t.trimmer, "trimmer"), - (t.InvertedIndex = function () { - this.root = { docs: {}, df: 0 }; - }), - (t.InvertedIndex.load = function (e) { - var t = new this(); - return (t.root = e.root), t; - }), - (t.InvertedIndex.prototype.addToken = function (e, t, n) { - for (var n = n || this.root, i = 0; i <= e.length - 1; ) { - var o = e[i]; - o in n || (n[o] = { docs: {}, df: 0 }), (i += 1), (n = n[o]); - } - var r = t.ref; - n.docs[r] - ? (n.docs[r] = { tf: t.tf }) - : ((n.docs[r] = { tf: t.tf }), (n.df += 1)); - }), - (t.InvertedIndex.prototype.hasToken = function (e) { - if (!e) return !1; - for (var t = this.root, n = 0; n < e.length; n++) { - if (!t[e[n]]) return !1; - t = t[e[n]]; - } - return !0; - }), - (t.InvertedIndex.prototype.getNode = function (e) { - if (!e) return null; - for (var t = this.root, n = 0; n < e.length; n++) { - if (!t[e[n]]) return null; - t = t[e[n]]; - } - return t; - }), - (t.InvertedIndex.prototype.getDocs = function (e) { - var t = this.getNode(e); - return null == t ? {} : t.docs; - }), - (t.InvertedIndex.prototype.getTermFrequency = function (e, t) { - var n = this.getNode(e); - return null == n ? 0 : t in n.docs ? n.docs[t].tf : 0; - }), - (t.InvertedIndex.prototype.getDocFreq = function (e) { - var t = this.getNode(e); - return null == t ? 0 : t.df; - }), - (t.InvertedIndex.prototype.removeToken = function (e, t) { - if (e) { - var n = this.getNode(e); - null != n && t in n.docs && (delete n.docs[t], (n.df -= 1)); - } - }), - (t.InvertedIndex.prototype.expandToken = function (e, t, n) { - if (null == e || "" == e) return []; - var t = t || []; - if (void 0 == n && ((n = this.getNode(e)), null == n)) return t; - n.df > 0 && t.push(e); - for (var i in n) - "docs" !== i && "df" !== i && this.expandToken(e + i, t, n[i]); - return t; - }), - (t.InvertedIndex.prototype.toJSON = function () { - return { root: this.root }; - }), - (t.Configuration = function (e, n) { - var e = e || ""; - if (void 0 == n || null == n) - throw new Error("fields should not be null"); - this.config = {}; - var i; - try { - (i = JSON.parse(e)), this.buildUserConfig(i, n); - } catch (o) { - t.utils.warn( - "user configuration parse failed, will use default configuration", - ), - this.buildDefaultConfig(n); - } - }), - (t.Configuration.prototype.buildDefaultConfig = function (e) { - this.reset(), - e.forEach(function (e) { - this.config[e] = { boost: 1, bool: "OR", expand: !1 }; - }, this); - }), - (t.Configuration.prototype.buildUserConfig = function (e, n) { - var i = "OR", - o = !1; - if ( - (this.reset(), - "bool" in e && (i = e.bool || i), - "expand" in e && (o = e.expand || o), - "fields" in e) - ) - for (var r in e.fields) - if (n.indexOf(r) > -1) { - var s = e.fields[r], - u = o; - void 0 != s.expand && (u = s.expand), - (this.config[r] = { - boost: s.boost || 0 === s.boost ? s.boost : 1, - bool: s.bool || i, - expand: u, - }); - } else - t.utils.warn( - "field name in user configuration not found in index instance fields", - ); - else this.addAllFields2UserConfig(i, o, n); - }), - (t.Configuration.prototype.addAllFields2UserConfig = function (e, t, n) { - n.forEach(function (n) { - this.config[n] = { boost: 1, bool: e, expand: t }; - }, this); - }), - (t.Configuration.prototype.get = function () { - return this.config; - }), - (t.Configuration.prototype.reset = function () { - this.config = {}; - }), - (lunr.SortedSet = function () { - (this.length = 0), (this.elements = []); - }), - (lunr.SortedSet.load = function (e) { - var t = new this(); - return (t.elements = e), (t.length = e.length), t; - }), - (lunr.SortedSet.prototype.add = function () { - var e, t; - for (e = 0; e < arguments.length; e++) - (t = arguments[e]), - ~this.indexOf(t) || this.elements.splice(this.locationFor(t), 0, t); - this.length = this.elements.length; - }), - (lunr.SortedSet.prototype.toArray = function () { - return this.elements.slice(); - }), - (lunr.SortedSet.prototype.map = function (e, t) { - return this.elements.map(e, t); - }), - (lunr.SortedSet.prototype.forEach = function (e, t) { - return this.elements.forEach(e, t); - }), - (lunr.SortedSet.prototype.indexOf = function (e) { - for ( - var t = 0, - n = this.elements.length, - i = n - t, - o = t + Math.floor(i / 2), - r = this.elements[o]; - i > 1; - - ) { - if (r === e) return o; - e > r && (t = o), - r > e && (n = o), - (i = n - t), - (o = t + Math.floor(i / 2)), - (r = this.elements[o]); - } - return r === e ? o : -1; - }), - (lunr.SortedSet.prototype.locationFor = function (e) { - for ( - var t = 0, - n = this.elements.length, - i = n - t, - o = t + Math.floor(i / 2), - r = this.elements[o]; - i > 1; - - ) - e > r && (t = o), - r > e && (n = o), - (i = n - t), - (o = t + Math.floor(i / 2)), - (r = this.elements[o]); - return r > e ? o : e > r ? o + 1 : void 0; - }), - (lunr.SortedSet.prototype.intersect = function (e) { - for ( - var t = new lunr.SortedSet(), - n = 0, - i = 0, - o = this.length, - r = e.length, - s = this.elements, - u = e.elements; - ; - - ) { - if (n > o - 1 || i > r - 1) break; - s[n] !== u[i] - ? s[n] < u[i] - ? n++ - : s[n] > u[i] && i++ - : (t.add(s[n]), n++, i++); - } - return t; - }), - (lunr.SortedSet.prototype.clone = function () { - var e = new lunr.SortedSet(); - return (e.elements = this.toArray()), (e.length = e.elements.length), e; - }), - (lunr.SortedSet.prototype.union = function (e) { - var t, n, i; - this.length >= e.length ? ((t = this), (n = e)) : ((t = e), (n = this)), - (i = t.clone()); - for (var o = 0, r = n.toArray(); o < r.length; o++) i.add(r[o]); - return i; - }), - (lunr.SortedSet.prototype.toJSON = function () { - return this.toArray(); - }), - (function (e, t) { - "function" == typeof define && define.amd - ? define(t) - : "object" == typeof exports - ? (module.exports = t()) - : (e.elasticlunr = t()); - })(this, function () { - return t; - }); -})(); diff --git a/build/scripts/script.js b/build/scripts/script.js index 6d14778..ed41d49 100644 --- a/build/scripts/script.js +++ b/build/scripts/script.js @@ -45,9 +45,11 @@ const searchState = { */ let currentlyWantedPage = null; +let fuse = null; + /** * Contains the links to search results. - * The elements of this array are in this same order than `elasticlunr`'s index. + * The elements of this array are in this same order than `Fuse.js`'s index. * @type {Array.} */ let searchIndexLinks = []; @@ -88,15 +90,7 @@ const spinnerSvg = ` `; -/** Pre-initialize our search engine library with the right fields. */ -const searchEngine = elasticlunr(function () { - this.addField("h1"); - this.addField("h2"); - this.addField("h3"); - this.addField("body"); - this.setRef("id"); -}); - +const pageIndex = []; /** * Perform all actions and register all event handlers that should be done in * the page. @@ -444,7 +438,7 @@ function initializeSearchEngine() { anchorH2: elt.anchorH2, anchorH3: elt.anchorH3, }); - searchEngine.addDoc({ + pageIndex.push({ h1: elt.h1, h2: elt.h2, h3: elt.h3, @@ -454,6 +448,27 @@ function initializeSearchEngine() { id++; } } + fuse = new Fuse(pageIndex, { + // includeScore: true, + keys: [ + { + name: "h1", + weight: 100, + }, + { + name: "h2", + weight: 80, + }, + { + name: "h3", + weight: 10, + }, + { + name: "body", + weight: 1, + }, + ], + }); searchState.initStatus = "loaded"; }) .catch((err) => { @@ -498,24 +513,17 @@ function updateSearchResults(value) { } searchState.lastSearch = value; - const searchResults = searchEngine.search(value, { - fields: { - h1: { boost: 5, bool: "AND" }, - h2: { boost: 4, bool: "AND" }, - h3: { boost: 3, bool: "AND" }, - body: { boost: 1 }, - }, - expand: true, - }); + const searchResults = fuse.search(value); if (searchResults.length === 0) { searchResultsElt.innerHTML = '
' + "No result for that search." + "
"; return; } searchResultsElt.innerHTML = ""; + for (let resIdx = 0; resIdx < searchResults.length && resIdx < 30; resIdx++) { const res = searchResults[resIdx]; - const links = searchIndexLinks[+res.ref]; + const links = searchIndexLinks[+res.refIndex]; const contentDiv = document.createElement("div"); contentDiv.className = "search-result-item"; @@ -523,7 +531,7 @@ function updateSearchResults(value) { locationDiv.className = "search-result-location"; let needSeparator = false; - if (res.doc.h1 !== undefined && res.doc.h1 !== "") { + if (res.item.h1 !== undefined && res.item.h1 !== "") { let linkH1; if (links.anchorH1 !== undefined) { const href = rootUrl + "/" + links.file + "#" + links.anchorH1; @@ -533,12 +541,12 @@ function updateSearchResults(value) { linkH1 = document.createElement("span"); } linkH1.className = "h1"; - linkH1.textContent = res.doc.h1; + linkH1.textContent = res.item.h1; locationDiv.appendChild(linkH1); needSeparator = true; } - if (res.doc.h2 !== undefined && res.doc.h2 !== "") { + if (res.item.h2 !== undefined && res.item.h2 !== "") { if (needSeparator) { const separatorSpan = document.createElement("span"); separatorSpan.textContent = " > "; @@ -554,11 +562,11 @@ function updateSearchResults(value) { linkH2 = document.createElement("span"); } linkH2.className = "h2"; - linkH2.textContent = res.doc.h2; + linkH2.textContent = res.item.h2; locationDiv.appendChild(linkH2); needSeparator = true; } - if (res.doc.h3 !== undefined && res.doc.h3 !== "") { + if (res.item.h3 !== undefined && res.item.h3 !== "") { if (needSeparator) { const separatorSpan = document.createElement("span"); separatorSpan.textContent = " > "; @@ -574,12 +582,12 @@ function updateSearchResults(value) { linkH3 = document.createElement("span"); } linkH3.className = "h3"; - linkH3.textContent = res.doc.h3; + linkH3.textContent = res.item.h3; locationDiv.appendChild(linkH3); } const bodyDiv = document.createElement("div"); bodyDiv.className = "search-result-body"; - let body = res.doc.body ?? ""; + let body = res.item.body ?? ""; if (body.length > 300) { body = body.substring(0, 300) + "..."; } diff --git a/doc/Getting_Started/HTML_Page_Features.md b/doc/Getting_Started/HTML_Page_Features.md index 9b70acc..f1b3c9b 100644 --- a/doc/Getting_Started/HTML_Page_Features.md +++ b/doc/Getting_Started/HTML_Page_Features.md @@ -9,21 +9,17 @@ they have many supplementary features when JavaScript is enabled. ## Search Search in README is achieved without involving a third-party thanks to the -[elastic lunr](http://elasticlunr.com/) library. +[Fuse.js](https://www.fusejs.io) library. The idea is that an index is generated when your documentation is built, and that index is fetched the first time you search on the generated HTML page. -Elastic lunr then searches through that index to provide matches that are then +Fuse.js then searches through that index to provide matches that are then display in the page. Doing the search locally has the advantage of not having to rely on third parties for your search. It also allows to have a much faster search experience than if a server was requested for each search input. -Note however that elastic lunr is quite old and that some more recent local -search implementations exist that we're looking at today with the goal of -improving search accuracy. - ## Soft navigation Links to other documentation pages, as long as they concern the same category diff --git a/src/create_documentation.ts b/src/create_documentation.ts index ce7961d..0a5f6b5 100644 --- a/src/create_documentation.ts +++ b/src/create_documentation.ts @@ -48,7 +48,7 @@ export interface DocumentationCreationOptions { export default async function createDocumentation( baseInDir: string, baseOutDir: string, - options: DocumentationCreationOptions = {} + options: DocumentationCreationOptions = {}, ): Promise { if (options.clean === true) { rimrafSync(baseOutDir); @@ -138,7 +138,7 @@ export default async function createDocumentation( Anchor: ${check.anchor} `; const availableAnchors = anchorChecker.getAnchorsForInputFile( - check.inputFileLinkDestination + check.inputFileLinkDestination, ); if (availableAnchors !== undefined && availableAnchors.length > 0) { message += @@ -152,7 +152,7 @@ export default async function createDocumentation( try { const searchIndexLoc = path.join( path.resolve(baseOutDir), - "searchIndex.json" + "searchIndex.json", ); await promisify(fs.writeFile)(searchIndexLoc, JSON.stringify(searchIndex)); } catch (err) { @@ -210,21 +210,21 @@ export default async function createDocumentation( config.links, linkIndexInConfig, pageIndexesInLink, - outputFile + outputFile, ); const navBarHtml = generateHeaderHtml( config, linkIndexInConfig, outputFile, logoInfo, - version + version, ); const pages = link.pages; const sidebarHtml = generateSidebarHtml( pages, pageIndexesInLink, outputFile, - logoInfo + logoInfo, ); const firstLevelPage = pages[pageIndexesInLink[0]]; @@ -268,10 +268,10 @@ export default async function createDocumentation( : getRelativePageInfo(nextPageConfig, outputFile); const cssUrls = cssOutputPaths.map((cssOutput) => - toUriCompatibleRelativePath(cssOutput, outDir) + toUriCompatibleRelativePath(cssOutput, outDir), ); const scriptUrls = scriptOutputPaths.map((s) => - toUriCompatibleRelativePath(s, outDir) + toUriCompatibleRelativePath(s, outDir), ); // add link translation to options @@ -279,7 +279,7 @@ export default async function createDocumentation( inputFile, outputFile, fileMap, - anchorChecker + anchorChecker, ); const { anchors } = await createDocumentationPage({ baseOutDir, @@ -313,7 +313,7 @@ function linkTranslatorFactory( inputFile: string, outputFile: string, fileMap: Map, - anchorChecker: AnchorChecker + anchorChecker: AnchorChecker, ): (link: string) => string | undefined { const outputDir = path.dirname(outputFile); /** @@ -346,13 +346,13 @@ function linkTranslatorFactory( `A referenced link was not found. File: ${inputFile} Link: ${link} -` +`, ); } else if (anchor.length > 1) { anchorChecker.addAnchorReference( inputFile, normalizedLink, - anchor.substring(1) + anchor.substring(1), ); } return translation !== undefined @@ -363,7 +363,7 @@ function linkTranslatorFactory( function getRelativePageInfo( pageConfig: LocalDocPageInformation, - currentPath: string + currentPath: string, ): { name: string; link: string; @@ -371,7 +371,7 @@ function getRelativePageInfo( const { displayName: pDisplayName, outputFile: pOutputFile } = pageConfig; const relativeHref = toUriCompatibleRelativePath( pOutputFile, - path.dirname(currentPath) + path.dirname(currentPath), ); return { name: pDisplayName, link: relativeHref }; } @@ -379,7 +379,7 @@ function getRelativePageInfo( async function copyFileToOutputDir( filePathFromInputDir: string, inputDir: string, - outputDir: string + outputDir: string, ) { const inputPath = path.join(inputDir, filePathFromInputDir); const outputPath = path.join(outputDir, filePathFromInputDir); @@ -401,7 +401,7 @@ async function copyFileToOutputDir( const srcMessage = ((err as { message: string }) ?? {}).message ?? "Unknown error"; throw new Error( - `Could not create "${outputPath}" directory: ${srcMessage}` + `Could not create "${outputPath}" directory: ${srcMessage}`, ); } } @@ -437,7 +437,7 @@ async function copyCssFiles(baseOutDir: string): Promise { await Promise.all( cssFiles.map(async (cssInput: string, i: number) => { await promisify(fs.copyFile)(cssInput, outputPaths[i]); - }) + }), ); return outputPaths; } @@ -445,18 +445,18 @@ async function copyCssFiles(baseOutDir: string): Promise { async function copyJavaScriptFiles(baseOutDir: string): Promise { const scriptOutputDir = path.join(path.resolve(baseOutDir), "scripts"); const scripts = [ - path.join(currentDir, "scripts/lunr.js"), + path.join(currentDir, "scripts/fuse.js"), path.join(currentDir, "scripts/script.js"), ]; const outputPaths = scripts.map((s) => - path.join(scriptOutputDir, path.basename(s)) + path.join(scriptOutputDir, path.basename(s)), ); await createDirIfDoesntExist(scriptOutputDir); await Promise.all( scripts.map(async (s, i) => { await promisify(fs.copyFile)(s, outputPaths[i]); - }) + }), ); return outputPaths; }