{"version":3,"sources":["jsdelivr-header.js","/npm/quick-score@0.1.0/lib/index.js"],"names":[],"mappings":"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","file":"/npm/quick-score@0.1.0/lib/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/quick-score@0.1.0/lib/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.quickScore = {}));\n})(this, (function (exports) { 'use strict';\n\n\t/**\n\t * A class representing a half-open interval of characters.  A range's `location`\n\t * property and `max()` value can be used as arguments for the `substring()`\n\t * method to extract a range of characters.\n\t */\n\tclass Range {\n\t\t/**\n\t\t * @memberOf Range.prototype\n\t\t * @member {number} location  Starting index of the range.\n\t\t */\n\n\t\t/**\n\t\t * @memberOf Range.prototype\n\t\t * @member {number} length  Number of characters in the range.\n\t\t */\n\n\t\t/**\n\t\t * @param {number} [location=-1]  Starting index of the range.\n\t\t * @param {number} [length=0]  Number of characters in the range.\n\t\t */\n\t\tconstructor(\n\t\t\tlocation = -1,\n\t\t\tlength = 0)\n\t\t{\n\t\t\tthis.location = location;\n\t\t\tthis.length = length;\n\t\t}\n\n\n\t\t/* eslint no-inline-comments: 0 */\n\t\t/**\n\t\t * Gets the end index of the range, which indicates the character\n\t\t * immediately after the last one in the range.\n\t\t *\n\t\t * @returns {number}\n\t\t */\n\t\t/**\n\t\t * Sets the end index of the range, which indicates the character\n\t\t * immediately after the last one in the range.\n\t\t *\n\t\t * @param {number} [value]  End of the range.\n\t\t *\n\t\t * @returns {number}\n\t\t */\n\t\tmax(\n\t\t\tvalue)\n\t\t{\n\t\t\tif (typeof value == \"number\") {\n\t\t\t\tthis.length = value - this.location;\n\t\t\t}\n\n\t\t\t\t// the NSMaxRange() function in Objective-C returns this value\n\t\t\treturn this.location + this.length;\n\t\t}\n\n\n\t\t/**\n\t\t * Returns whether the range contains a location >= 0.\n\t\t *\n\t\t * @returns {boolean}\n\t\t */\n\t\tisValid()\n\t\t{\n\t\t\treturn (this.location > -1);\n\t\t}\n\n\n\t\t/**\n\t\t * Returns an array of the range's start and end indexes.\n\t\t *\n\t\t * @returns {RangeTuple}\n\t\t */\n\t\ttoArray()\n\t\t{\n\t\t\treturn [this.location, this.max()];\n\t\t}\n\n\n\t\t/**\n\t\t * Returns a string representation of the range's open interval.\n\t\t *\n\t\t * @returns {string}\n\t\t */\n\t\ttoString()\n\t\t{\n\t\t\tif (this.location == -1) {\n\t\t\t\treturn \"invalid range\";\n\t\t\t} else {\n\t\t\t\treturn \"[\" + this.location + \",\" + this.max() + \")\";\n\t\t\t}\n\t\t}\n\t}\n\n\tconst BaseConfigDefaults = {\n\t\twordSeparators: \"-/\\\\:()<>%._=&[]+ \\t\\n\\r\",\n\t\tuppercaseLetters: (() => {\n\t\t\tconst charCodeA = \"A\".charCodeAt(0);\n\t\t\tconst uppercase = [];\n\n\t\t\tfor (let i = 0; i < 26; i++) {\n\t\t\t\tuppercase.push(String.fromCharCode(charCodeA + i));\n\t\t\t}\n\n\t\t\treturn uppercase.join(\"\");\n\t\t})(),\n\t\tignoredScore: 0.9,\n\t\tskippedScore: 0.15,\n\t\temptyQueryScore: 0,\n\t\t\t// long, nearly-matching queries can generate up to 2^queryLength loops,\n\t\t\t// so support worst-case queries up to 16 characters and then give up\n\t\t\t// and return 0 for longer queries that may or may not actually match\n\t\tmaxIterations: Math.pow(2, 16)\n\t};\n\tconst QSConfigDefaults = {\n\t\tlongStringLength: 150,\n\t\tmaxMatchStartPct: 0.15,\n\t\tminMatchDensityPct: 0.75,\n\t\tmaxMatchDensityPct: 0.95,\n\t\tbeginningOfStringPct: 0.1\n\t};\n\n\n\tclass Config {\n\t\tconstructor(\n\t\t\toptions)\n\t\t{\n\t\t\tObject.assign(this, BaseConfigDefaults, options);\n\t\t}\n\n\n\t\tuseSkipReduction()\n\t\t{\n\t\t\treturn true;\n\t\t}\n\n\n\t\tadjustRemainingScore(\n\t\t\tstring,\n\t\t\tquery,\n\t\t\tremainingScore,\n\t\t\tskippedSpecialChar,\n\t\t\tsearchRange,\n\t\t\tremainingSearchRange,\n\t\t\tmatchedRange,\n\t\t\tfullMatchedRange)\n\t\t{\n\t\t\t\t// use the original Quicksilver expression for the remainingScore\n\t\t\treturn remainingScore * remainingSearchRange.length;\n\t\t}\n\t}\n\n\n\tclass QuickScoreConfig extends Config {\n\t\tconstructor(\n\t\t\toptions)\n\t\t{\n\t\t\tsuper(Object.assign({}, QSConfigDefaults, options));\n\t\t}\n\n\n\t\tuseSkipReduction(\n\t\t\tstring,\n\t\t\tquery,\n\t\t\tremainingScore,\n\t\t\tsearchRange,\n\t\t\tremainingSearchRange,\n\t\t\tmatchedRange,\n\t\t\tfullMatchedRange)\n\t\t{\n\t\t\tconst len = string.length;\n\t\t\tconst isShortString = len <= this.longStringLength;\n\t\t\tconst matchStartPercentage = fullMatchedRange.location / len;\n\n\t\t\treturn isShortString || matchStartPercentage < this.maxMatchStartPct;\n\t\t}\n\n\n\t\tadjustRemainingScore(\n\t\t\tstring,\n\t\t\tquery,\n\t\t\tremainingScore,\n\t\t\tskippedSpecialChar,\n\t\t\tsearchRange,\n\t\t\tremainingSearchRange,\n\t\t\tmatchedRange,\n\t\t\tfullMatchedRange)\n\t\t{\n\t\t\tconst isShortString = string.length <= this.longStringLength;\n\t\t\tconst matchStartPercentage = fullMatchedRange.location / string.length;\n\t\t\tlet matchRangeDiscount = 1;\n\t\t\tlet matchStartDiscount = (1 - matchStartPercentage);\n\n\t\t\t\t// discount the remainingScore based on how much larger the match is\n\t\t\t\t// than the query, unless the match is in the first 10% of the\n\t\t\t\t// string, the match range isn't too sparse and the whole string is\n\t\t\t\t// not too long.  also only discount if we didn't skip any whitespace\n\t\t\t\t// or capitals.\n\t\t\tif (!skippedSpecialChar) {\n\t\t\t\tmatchRangeDiscount = query.length / fullMatchedRange.length;\n\t\t\t\tmatchRangeDiscount = (isShortString &&\n\t\t\t\t\tmatchStartPercentage <= this.beginningOfStringPct &&\n\t\t\t\t\tmatchRangeDiscount >= this.minMatchDensityPct) ?\n\t\t\t\t\t1 : matchRangeDiscount;\n\t\t\t\tmatchStartDiscount = matchRangeDiscount >= this.maxMatchDensityPct ?\n\t\t\t\t\t1 : matchStartDiscount;\n\t\t\t}\n\n\t\t\t\t// discount the scores of very long strings\n\t\t\treturn remainingScore *\n\t\t\t\tMath.min(remainingSearchRange.length, this.longStringLength) *\n\t\t\t\tmatchRangeDiscount * matchStartDiscount;\n\t\t}\n\t}\n\n\n\tfunction createConfig(\n\t\toptions)\n\t{\n\t\tif (options instanceof Config) {\n\t\t\t\t// this is a full-fledged Config instance, so we don't need to do\n\t\t\t\t// anything to it\n\t\t\treturn options;\n\t\t} else {\n\t\t\t\t// create a complete config from this\n\t\t\treturn new QuickScoreConfig(options);\n\t\t}\n\t}\n\n\n\tconst DefaultConfig = createConfig();\n\tconst BaseConfig = new Config();\n\tconst QuicksilverConfig = new Config({\n\t\t\t// the Quicksilver algorithm returns .9 for empty queries\n\t\temptyQueryScore: 0.9,\n\t\tadjustRemainingScore: function(\n\t\t\tstring,\n\t\t\tquery,\n\t\t\tremainingScore,\n\t\t\tskippedSpecialChar,\n\t\t\tsearchRange,\n\t\t\tremainingSearchRange,\n\t\t\tmatchedRange,\n\t\t\tfullMatchedRange)\n\t\t{\n\t\t\tlet score = remainingScore * remainingSearchRange.length;\n\n\t\t\tif (!skippedSpecialChar) {\n\t\t\t\t\t// the current QuickSilver algorithm reduces the score by half\n\t\t\t\t\t// this value when no special chars are skipped, so add the half\n\t\t\t\t\t// back in to match it\n\t\t\t\tscore += ((matchedRange.location - searchRange.location) / 2.0);\n\t\t\t}\n\n\t\t\treturn score;\n\t\t}\n\t});\n\n\t/**\n\t * Scores a string against a query.\n\t *\n\t * @param {string} string  The string to score.\n\t *\n\t * @param {string} query  The query string to score the `string` parameter against.\n\t *\n\t * @param {Array<RangeTuple>} [matches]  If supplied, `quickScore()` will push onto\n\t * `matches` an array with start and end indexes for each substring range of\n\t * `string` that matches `query`.  These indexes can be used to highlight the\n\t * matching characters in an auto-complete UI.\n\t *\n\t * @param {string} [transformedString]  A transformed version of the string that\n\t * will be used for matching.  This defaults to a lowercase version of `string`,\n\t * but it could also be used to match against a string with all the diacritics\n\t * removed, so an unaccented character in the query would match an accented one\n\t * in the string.\n\t *\n\t * @param {string} [transformedQuery]  A transformed version of `query`.  The\n\t * same transformation applied to `transformedString` should be applied to this\n\t * parameter, or both can be left as `undefined` for the default lowercase\n\t * transformation.\n\t *\n\t * @param {object} [config]  A configuration object that can modify how the\n\t * `quickScore` algorithm behaves.\n\t *\n\t * @param {Range} [stringRange]  The range of characters in `string` that should\n\t * be checked for matches against `query`.  Defaults to the entire `string`\n\t * parameter.\n\t *\n\t * @returns {number}  A number between 0 and 1 that represents how well the\n\t * `query` matches the `string`.\n\t */\n\tfunction quickScore(\n\t\tstring,\n\t\tquery,\n\t\tmatches,\n\t\ttransformedString = string.toLocaleLowerCase(),\n\t\ttransformedQuery = query.toLocaleLowerCase(),\n\t\tconfig = DefaultConfig,\n\t\tstringRange = new Range(0, string.length))\n\t{\n\t\tlet iterations = 0;\n\n\t\tif (query) {\n\t\t\treturn calcScore(stringRange, new Range(0, query.length), new Range());\n\t\t} else {\n\t\t\treturn config.emptyQueryScore;\n\t\t}\n\n\n\t\tfunction calcScore(\n\t\t\tsearchRange,\n\t\t\tqueryRange,\n\t\t\tfullMatchedRange)\n\t\t{\n\t\t\tif (!queryRange.length) {\n\t\t\t\t\t// deduct some points for all remaining characters\n\t\t\t\treturn config.ignoredScore;\n\t\t\t} else if (queryRange.length > searchRange.length) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst initialMatchesLength = matches && matches.length;\n\n\t\t\tfor (let i = queryRange.length; i > 0; i--) {\n\t\t\t\tif (iterations > config.maxIterations) {\n\t\t\t\t\t\t// a long query that matches the string except for the last\n\t\t\t\t\t\t// character can generate 2^queryLength iterations of this\n\t\t\t\t\t\t// loop before returning 0, so short-circuit that when we've\n\t\t\t\t\t\t// seen too many iterations (bit of an ugly kludge, but it\n\t\t\t\t\t\t// avoids locking up the UI if the user somehow types an\n\t\t\t\t\t\t// edge-case query)\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\titerations++;\n\n\t\t\t\tconst querySubstring = transformedQuery.substring(queryRange.location, queryRange.location + i);\n\t\t\t\t\t// reduce the length of the search range by the number of chars\n\t\t\t\t\t// we're skipping in the query, to make sure there's enough string\n\t\t\t\t\t// left to possibly contain the skipped chars\n\t\t\t\tconst matchedRange = getRangeOfSubstring(transformedString, querySubstring,\n\t\t\t\t\tnew Range(searchRange.location, searchRange.length - queryRange.length + i));\n\n\t\t\t\tif (!matchedRange.isValid()) {\n\t\t\t\t\t\t// we didn't find the query substring, so try again with a\n\t\t\t\t\t\t// shorter substring\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!fullMatchedRange.isValid()) {\n\t\t\t\t\tfullMatchedRange.location = matchedRange.location;\n\t\t\t\t} else {\n\t\t\t\t\tfullMatchedRange.location = Math.min(fullMatchedRange.location, matchedRange.location);\n\t\t\t\t}\n\n\t\t\t\tfullMatchedRange.max(matchedRange.max());\n\n\t\t\t\tif (matches) {\n\t\t\t\t\tmatches.push(matchedRange.toArray());\n\t\t\t\t}\n\n\t\t\t\tconst remainingSearchRange = new Range(matchedRange.max(), searchRange.max() - matchedRange.max());\n\t\t\t\tconst remainingQueryRange = new Range(queryRange.location + i, queryRange.length - i);\n\t\t\t\tconst remainingScore = calcScore(remainingSearchRange, remainingQueryRange, fullMatchedRange);\n\n\t\t\t\tif (remainingScore) {\n\t\t\t\t\tlet score = remainingSearchRange.location - searchRange.location;\n\t\t\t\t\t\t// default to true since we only want to apply a discount if\n\t\t\t\t\t\t// we hit the final else clause below, and we won't get to\n\t\t\t\t\t\t// any of them if the match is right at the start of the\n\t\t\t\t\t\t// searchRange\n\t\t\t\t\tlet skippedSpecialChar = true;\n\t\t\t\t\tconst useSkipReduction = config.useSkipReduction(string, query,\n\t\t\t\t\t\tremainingScore, remainingSearchRange, searchRange,\n\t\t\t\t\t\tremainingSearchRange, matchedRange, fullMatchedRange);\n\n\t\t\t\t\tif (matchedRange.location > searchRange.location) {\n\t\t\t\t\t\t\t// some letters were skipped when finding this match, so\n\t\t\t\t\t\t\t// adjust the score based on whether spaces or capital\n\t\t\t\t\t\t\t// letters were skipped\n\t\t\t\t\t\tif (useSkipReduction &&\n\t\t\t\t\t\t\t\tconfig.wordSeparators.indexOf(string[matchedRange.location - 1]) > -1) {\n\t\t\t\t\t\t\tfor (let j = matchedRange.location - 2; j >= searchRange.location; j--) {\n\t\t\t\t\t\t\t\tif (config.wordSeparators.indexOf(string[j]) > -1) {\n\t\t\t\t\t\t\t\t\tscore--;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tscore -= config.skippedScore;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (useSkipReduction &&\n\t\t\t\t\t\t\t\tconfig.uppercaseLetters.indexOf(string[matchedRange.location]) > -1) {\n\t\t\t\t\t\t\tfor (let j = matchedRange.location - 1; j >= searchRange.location; j--) {\n\t\t\t\t\t\t\t\tif (config.uppercaseLetters.indexOf(string[j]) > -1) {\n\t\t\t\t\t\t\t\t\tscore--;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tscore -= config.skippedScore;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// reduce the score by the number of chars we've\n\t\t\t\t\t\t\t\t// skipped since the beginning of the search range\n\t\t\t\t\t\t\tscore -= matchedRange.location - searchRange.location;\n\t\t\t\t\t\t\tskippedSpecialChar = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tscore += config.adjustRemainingScore(string,\n\t\t\t\t\t\tquery, remainingScore, skippedSpecialChar, searchRange,\n\t\t\t\t\t\tremainingSearchRange, matchedRange, fullMatchedRange);\n\t\t\t\t\tscore /= searchRange.length;\n\n\t\t\t\t\treturn score;\n\t\t\t\t} else if (matches) {\n\t\t\t\t\t\t// the remaining query does not appear in the remaining\n\t\t\t\t\t\t// string, so strip off any matches we've added during the\n\t\t\t\t\t\t// current call, as they'll be invalid when we start over\n\t\t\t\t\t\t// with a shorter piece of the query\n\t\t\t\t\tmatches.length = initialMatchesLength;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t\t// make createConfig() available on quickScore so that the QuickScore\n\t\t// constructor has access to it\n\tquickScore.createConfig = createConfig;\n\n\n\tfunction getRangeOfSubstring(\n\t\tstring,\n\t\tquery,\n\t\tsearchRange)\n\t{\n\t\tconst index = string.indexOf(query, searchRange.location);\n\t\tconst result = new Range();\n\n\t\tif (index > -1 && index < searchRange.max()) {\n\t\t\tresult.location = index;\n\t\t\tresult.length = query.length;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * A class for scoring and sorting a list of items against a query string.  Each\n\t * item receives a floating point score between `0` and `1`.\n\t */\n\tclass QuickScore {\n\t\t/**\n\t\t * @memberOf QuickScore.prototype\n\t\t * @member {Array<object>} items  The array of items to search, which\n\t\t * should only be modified via the [setItems()]{@link QuickScore#setItems}\n\t\t * method.\n\t\t * @readonly\n\t\t */\n\n\t\t/**\n\t\t * @memberOf QuickScore.prototype\n\t\t * @member {Array<ItemKey>} keys  The keys to search on each item, which\n\t\t * should only be modified via the [setItems()]{@link QuickScore#setKeys}\n\t\t * method.\n\t\t * @readonly\n\t\t */\n\n\t\t/**\n\t\t * @param {Array<string|object>} [items]  The list of items to score.  If\n\t\t * the list is not a flat array of strings, a `keys` array must be supplied\n\t\t * via the second parameter.  QuickScore makes a shallow copy of the `items`\n\t\t * array, so changes to it won't have any affect, but changes to the objects\n\t\t * referenced by the array need to be passed to the instance by a call to\n\t\t * its [setItems()]{@link QuickScore#setItems} method.\n\t\t *\n\t\t * @param {Array<ItemKey>|Options} [options]  If the `items` parameter\n\t\t * is an array of flat strings, the `options` parameter can be left out.  If\n\t\t * it is a list of objects containing keys that should be scored, the\n\t\t * `options` parameter must either be an array of key names or an object\n\t\t * containing a `keys` property.\n\t\t *\n\t\t * @param {Array<ItemKey>} [options.keys]  In the simplest case, an array of\n\t\t * key names to score on the objects in the `items` array.\n\t\t *\n\t\t * The key names can point to a nested key by passing either a dot-delimited\n\t\t * string or an array of sub-keys that specify the path to the value.  So a\n\t\t * key `name` of `\"foo.bar\"` would evaluate to `\"baz\"` given an object like\n\t\t * `{ foo: { bar: \"baz\" } }`.  Alternatively, that path could be passed as\n\t\t * an array, like `[\"foo\", \"bar\"]`.  In either case, if this sub-key's match\n\t\t * produces the highest score for an item in the search results, its\n\t\t * `scoreKey` name will be `\"foo.bar\"`.\n\t\t *\n\t\t * If your items have keys that contain periods, e.g., `\"first.name\"`, but\n\t\t * you don't want these names to be treated as paths to nested keys, simply\n\t\t * wrap the name in an array, like `{ keys: [\"ssn\", [\"first.name\"],\n\t\t * [\"last.name\"]] }`.\n\t\t *\n\t\t * Instead of a string or string array, an item in `keys` can also be passed\n\t\t * as a `{name, scorer}` object, which lets you specify a different scoring\n\t\t * function for each key.  The scoring function should behave as described\n\t\t * next.\n\t\t *\n\t\t * @param {string} [options.sortKey=options.keys[0]]  An optional key name\n\t\t * that will be used to sort items with identical scores.  Defaults to the\n\t\t * name of the first item in the `keys` parameter.  If `sortKey` points to\n\t\t * a nested key, use a dot-delimited string instead of an array to specify\n\t\t * the path.\n\t\t *\n\t\t * @param {number} [options.minimumScore=0]  An optional value that\n\t\t * specifies the minimum score an item must have to appear in the results\n\t\t * returned from [search()]{@link QuickScore#search}.  Defaults to `0`,\n\t\t * so items that don't match the full `query` will not be returned.  This\n\t\t * value is ignored if the `query` is empty or undefined, in which case all\n\t\t * items are returned, sorted alphabetically and case-insensitively on the\n\t\t * `sortKey`, if any.\n\t\t *\n\t\t * @param {TransformStringFunction} [options.transformString]  An optional\n\t\t * function that takes a `string` parameter and returns a transformed\n\t\t * version of that string.  This function will be called on each of the\n\t\t * searchable keys in the `items` array as well as on the `query`\n\t\t * parameter to the `search()` method.  The default function calls\n\t\t * `toLocaleLowerCase()` on each string, for a case-insensitive search.  The\n\t\t * result of this function is cached for each searchable key on each item.\n\t\t *\n\t\t * You can pass a function here to do other kinds of preprocessing, such as\n\t\t * removing diacritics from all the strings or converting Chinese characters\n\t\t * to pinyin.  For example, you could use the\n\t\t * [`latinize`](https://www.npmjs.com/package/latinize) npm package to\n\t\t * convert characters with diacritics to the base character so that your\n\t\t * users can type an unaccented character in the query while still matching\n\t\t * items that have accents or diacritics.  Pass in an `options` object like\n\t\t * this to use a custom `transformString()` function:\n\t\t * `{ transformString: s => latinize(s.toLocaleLowerCase()) }`\n\t\t *\n\t\t * @param {ScorerFunction} [options.scorer]  An optional function that takes\n\t\t * `string` and `query` parameters and returns a floating point number\n\t\t * between 0 and 1 that represents how well the `query` matches the\n\t\t * `string`.  It defaults to the [quickScore()]{@link quickScore} function\n\t\t * in this library.\n\t\t *\n\t\t * If the function gets a third `matches` parameter, it should fill the\n\t\t * passed-in array with indexes corresponding to where the query\n\t\t * matches the string, as described in the [search()]{@link QuickScore#search}\n\t\t * method.\n\t\t *\n\t\t * @param {Config} [options.config]  An optional object that is passed to\n\t\t * the scorer function to further customize its behavior.  If the\n\t\t * `scorer` function has a `createConfig()` method on it, the `QuickScore`\n\t\t * instance will call that with the `config` value and store the result.\n\t\t * This can be used to extend the `config` parameter with default values.\n\t\t */\n\t\tconstructor(\n\t\t\titems = [],\n\t\t\toptions = {})\n\t\t{\n\t\t\tconst {\n\t\t\t\tscorer = quickScore,\n\t\t\t\ttransformString = toLocaleLowerCase,\n\t\t\t\tkeys = [],\n\t\t\t\tsortKey = \"\",\n\t\t\t\tminimumScore = 0,\n\t\t\t\tconfig\n\t\t\t} = Array.isArray(options)\n\t\t\t\t? { keys: options }\n\t\t\t\t: options;\n\n\t\t\tthis.scorer = scorer;\n\t\t\tthis.minimumScore = minimumScore;\n\t\t\tthis.config = config;\n\t\t\tthis.transformStringFunc = transformString;\n\n\t\t\tif (typeof scorer.createConfig === \"function\") {\n\t\t\t\t\t// let the scorer fill out the config with default values\n\t\t\t\tthis.config = scorer.createConfig(config);\n\t\t\t}\n\n\t\t\tthis.setKeys(keys, sortKey);\n\t\t\tthis.setItems(items);\n\n\t\t\t\t// the scoring function needs access to this.sortKey\n\t\t\tthis.compareScoredStrings = this.compareScoredStrings.bind(this);\n\t\t}\n\n\n\t\t/**\n\t\t * Scores the instance's items against the `query` and sorts them from\n\t\t * highest to lowest.\n\t\t *\n\t\t * @param {string} query  The string to score each item against.  The\n\t\t * instance's `transformString()` function is called on this string before\n\t\t * it's matched against each item.\n\t\t *\n\t\t * @returns {Array<ScoredString|ScoredObject>}  When the instance's `items`\n\t\t * are flat strings, an array of [`ScoredString`]{@link ScoredString}\n\t\t * objects containing the following properties is returned:\n\t\t *\n\t\t * - `item`: the string that was scored\n\t\t * - `score`: the floating point score of the string for the current query\n\t\t * - `matches`: an array of arrays that specify the character ranges\n\t\t *   where the query matched the string\n\t\t *\n\t\t * When the `items` are objects, an array of [`ScoredObject`]{@link ScoredObject}\n\t\t * results is returned:\n\t\t *\n\t\t * - `item`: the object that was scored\n\t\t * - `score`: the highest score from among the individual key scores\n\t\t * - `scoreKey`: the name of the key with the highest score, which will be\n\t\t *   an empty string if they're all zero\n\t\t * - `scoreValue`: the value of the key with the highest score, which makes\n\t\t *   it easier to access if it's a nested string\n\t\t * - `scores`: a hash of the individual scores for each key\n\t\t * - `matches`: a hash of arrays that specify the character ranges of the\n\t\t *   query match for each key\n\t\t *\n\t\t * The results array is sorted high to low on each item's score.  Items with\n\t\t * identical scores are sorted alphabetically and case-insensitively on the\n\t\t * `sortKey` option.  Items with scores that are <= the `minimumScore` option\n\t\t * (defaults to `0`) are not returned, unless the `query` is falsy, in which\n\t\t * case all of the items are returned, sorted alphabetically.\n\t\t *\n\t\t * The start and end indices in each [`RangeTuple`]{@link RangeTuple} in the\n\t\t * `matches` array can be used as parameters to the `substring()` method to\n\t\t * extract the characters from each string that match the query.  This can\n\t\t * then be used to format the matching characters with a different color or\n\t\t * style.\n\t\t *\n\t\t * Each `ScoredObject` item also has a `_` property, which caches transformed\n\t\t * versions of the item's strings, and might contain additional internal\n\t\t * metadata in the future.  It can be ignored.\n\t\t */\n\t\tsearch(\n\t\t\tquery)\n\t\t{\n\t\t\tconst results = [];\n\t\t\tconst {items, transformedItems, keys: sharedKeys, config} = this;\n\t\t\t\t// if the query is empty, we want to return all items, so make the\n\t\t\t\t// minimum score less than 0\n\t\t\tconst minScore = query ? this.minimumScore : -1;\n\t\t\tconst transformedQuery = this.transformString(query);\n\t\t\tconst itemCount = items.length;\n\t\t\tconst sharedKeyCount = sharedKeys.length;\n\n\t\t\tif (typeof items[0] === \"string\") {\n\t\t\t\t\t// items is an array of strings\n\t\t\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\t\t\tconst item = items[i];\n\t\t\t\t\tconst transformedItem = transformedItems[i];\n\t\t\t\t\tconst matches = [];\n\t\t\t\t\tconst score = this.scorer(item, query, matches, transformedItem,\n\t\t\t\t\t\ttransformedQuery, config);\n\n\t\t\t\t\tif (score > minScore) {\n\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\tscore,\n\t\t\t\t\t\t\tmatches,\n\t\t\t\t\t\t\t_: transformedItem\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\t\t\tconst item = items[i];\n\t\t\t\t\tconst transformedItem = transformedItems[i];\n\t\t\t\t\tconst result = {\n\t\t\t\t\t\titem,\n\t\t\t\t\t\tscore: 0,\n\t\t\t\t\t\tscoreKey: \"\",\n\t\t\t\t\t\tscoreValue: \"\",\n\t\t\t\t\t\tscores: {},\n\t\t\t\t\t\tmatches: {},\n\t\t\t\t\t\t_: transformedItem\n\t\t\t\t\t};\n\t\t\t\t\t\t// if an empty keys array was passed into the constructor,\n\t\t\t\t\t\t// score all of the non-empty string keys on the object\n\t\t\t\t\tconst keys = sharedKeyCount ? sharedKeys : Object.keys(transformedItem);\n\t\t\t\t\tconst keyCount = keys.length;\n\t\t\t\t\tlet highScore = 0;\n\t\t\t\t\tlet scoreKey = \"\";\n\t\t\t\t\tlet scoreValue = \"\";\n\n\t\t\t\t\t\t// find the highest score for each keyed string on this item\n\t\t\t\t\tfor (let j = 0; j < keyCount; j++) {\n\t\t\t\t\t\tconst key = keys[j];\n\t\t\t\t\t\t\t// use the key as the name if it's just a string, and\n\t\t\t\t\t\t\t// default to the instance's scorer function\n\t\t\t\t\t\tconst {name = key, scorer = this.scorer} = key;\n\t\t\t\t\t\tconst transformedString = transformedItem[name];\n\n\t\t\t\t\t\t\t// setItems() checks for non-strings and empty strings\n\t\t\t\t\t\t\t// when creating the transformed objects, so if the key\n\t\t\t\t\t\t\t// doesn't exist there, we can skip the processing\n\t\t\t\t\t\t\t// below for this key in this item\n\t\t\t\t\t\tif (transformedString) {\n\t\t\t\t\t\t\tconst string = this.getItemString(item, key);\n\t\t\t\t\t\t\tconst matches = [];\n\t\t\t\t\t\t\tconst newScore = scorer(string, query, matches,\n\t\t\t\t\t\t\t\ttransformedString, transformedQuery, config);\n\n\t\t\t\t\t\t\tresult.scores[name] = newScore;\n\t\t\t\t\t\t\tresult.matches[name] = matches;\n\n\t\t\t\t\t\t\tif (newScore > highScore) {\n\t\t\t\t\t\t\t\thighScore = newScore;\n\t\t\t\t\t\t\t\tscoreKey = name;\n\t\t\t\t\t\t\t\tscoreValue = string;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (highScore > minScore) {\n\t\t\t\t\t\tresult.score = highScore;\n\t\t\t\t\t\tresult.scoreKey = scoreKey;\n\t\t\t\t\t\tresult.scoreValue = scoreValue;\n\t\t\t\t\t\tresults.push(result);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresults.sort(this.compareScoredStrings);\n\n\t\t\treturn results;\n\t\t}\n\n\n\t\t/**\n\t\t * Sets the `keys` configuration.  `setItems()` must be called after\n\t\t * changing the keys so that the items' transformed strings get cached.\n\t\t *\n\t\t * @param {Array<ItemKey>} keys  List of keys to score, as either strings\n\t\t * or `{name, scorer}` objects.\n\t\t *\n\t\t * @param {string} [sortKey=keys[0]]  Name of key on which to sort\n\t\t * identically scored items.  Defaults to the first `keys` item.\n\t\t */\n\t\tsetKeys(\n\t\t\tkeys,\n\t\t\tsortKey)\n\t\t{\n\t\t\t\t// create a shallow copy of the keys array so that changes to its\n\t\t\t\t// order outside of this instance won't affect searching\n\t\t\tthis.keys = keys.slice();\n\t\t\tthis.sortKey = sortKey;\n\n\t\t\tif (this.keys.length) {\n\t\t\t\tconst {scorer} = this;\n\n\t\t\t\t\t// associate each key with the scorer function, if it isn't already\n\t\t\t\tthis.keys = this.keys.map(itemKey => {\n\t\t\t\t\t\t// items in the keys array should either be a string or\n\t\t\t\t\t\t// array specifying a key name, or a { name, scorer } object\n\t\t\t\t\tconst key = itemKey.length\n\t\t\t\t\t\t? { name: itemKey, scorer }\n\t\t\t\t\t\t: itemKey;\n\n\t\t\t\t\tif (Array.isArray(key.name)) {\n\t\t\t\t\t\tif (key.name.length > 1) {\n\t\t\t\t\t\t\tkey.path = key.name;\n\t\t\t\t\t\t\tkey.name = key.path.join(\".\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// this path consists of just one key name, which was\n\t\t\t\t\t\t\t\t// probably wrapped in an array because it contains\n\t\t\t\t\t\t\t\t// dots but isn't intended as a key path.  so don't\n\t\t\t\t\t\t\t\t// create a path array on this key, so that we're not\n\t\t\t\t\t\t\t\t// constantly calling reduce() to get this one key.\n\t\t\t\t\t\t\t[key.name] = key.name;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (key.name.indexOf(\".\") > -1) {\n\t\t\t\t\t\tkey.path = key.name.split(\".\");\n\t\t\t\t\t}\n\n\t\t\t\t\treturn key;\n\t\t\t\t});\n\n\t\t\t\tthis.sortKey = this.sortKey || this.keys[0].name;\n\t\t\t}\n\t\t}\n\n\n\t\t/**\n\t\t * Sets the `items` array and caches a transformed copy of all the item\n\t\t * strings specified by the `keys` parameter to the constructor, using the\n\t\t * `transformString` option (which defaults to `toLocaleLowerCase()`).\n\t\t *\n\t\t * @param {Array<string|object>} items  List of items to score.\n\t\t */\n\t\tsetItems(\n\t\t\titems)\n\t\t{\n\t\t\t\t// create a shallow copy of the items array so that changes to its\n\t\t\t\t// order outside of this instance won't affect searching\n\t\t\tconst itemArray = items.slice();\n\t\t\tconst itemCount = itemArray.length;\n\t\t\tconst transformedItems = [];\n\t\t\tconst sharedKeys = this.keys;\n\t\t\tconst sharedKeyCount = sharedKeys.length;\n\n\t\t\tif (typeof itemArray[0] === \"string\") {\n\t\t\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\t\t\ttransformedItems.push(this.transformString(itemArray[i]));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\t\t\tconst item = itemArray[i];\n\t\t\t\t\tconst transformedItem = {};\n\t\t\t\t\tconst keys = sharedKeyCount ? sharedKeys : Object.keys(item);\n\t\t\t\t\tconst keyCount = keys.length;\n\n\t\t\t\t\tfor (let j = 0; j < keyCount; j++) {\n\t\t\t\t\t\tconst key = keys[j];\n\t\t\t\t\t\tconst string = this.getItemString(item, key);\n\n\t\t\t\t\t\tif (string && typeof string === \"string\") {\n\t\t\t\t\t\t\ttransformedItem[key.name || key] =\n\t\t\t\t\t\t\t\tthis.transformString(string);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttransformedItems.push(transformedItem);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.items = itemArray;\n\t\t\tthis.transformedItems = transformedItems;\n\t\t}\n\n\n\t\t/**\n\t\t * Gets an item's key, possibly at a nested path.\n\t\t *\n\t\t * @private\n\t\t * @param {object} item  An object with multiple string properties.\n\t\t * @param {object|string} key  A key object with\n\t\t * the name of the string to get from `item`, or a plain string when all\n\t\t * keys on an item are being matched.\n\t\t * @returns {string}\n\t\t */\n\t\tgetItemString(\n\t\t\titem,\n\t\t\tkey)\n\t\t{\n\t\t\tconst {name, path} = key;\n\n\t\t\tif (path) {\n\t\t\t\treturn path.reduce((value, prop) => value && value[prop], item);\n\t\t\t} else {\n\t\t\t\t\t// if this instance is scoring all the keys on each item, key\n\t\t\t\t\t// will just be a string, not a { name, scorer } object\n\t\t\t\treturn item[name || key];\n\t\t\t}\n\t\t}\n\n\n\t\t/**\n\t\t * Transforms a string into a canonical form for scoring.\n\t\t *\n\t\t * @private\n\t\t * @param {string} string  The string to transform.\n\t\t * @returns {string}\n\t\t */\n\t\ttransformString(\n\t\t\tstring)\n\t\t{\n\t\t\treturn this.transformStringFunc(string);\n\t\t}\n\n\n\t\t/**\n\t\t * Compares two items based on their scores, or on their `sortKey` if the\n\t\t * scores are identical.\n\t\t *\n\t\t * @private\n\t\t * @param {object} a  First item.\n\t\t * @param {object} b  Second item.\n\t\t * @returns {number}\n\t\t */\n\t\tcompareScoredStrings(\n\t\t\ta,\n\t\t\tb)\n\t\t{\n\t\t\t\t// use the transformed versions of the strings for sorting\n\t\t\tconst itemA = a._;\n\t\t\tconst itemB = b._;\n\t\t\tconst itemAString = typeof itemA === \"string\"\n\t\t\t\t? itemA\n\t\t\t\t: itemA[this.sortKey];\n\t\t\tconst itemBString = typeof itemB === \"string\"\n\t\t\t\t? itemB\n\t\t\t\t: itemB[this.sortKey];\n\n\t\t\tif (a.score === b.score) {\n\t\t\t\t\t// sort undefineds to the end of the array, as per the ES spec\n\t\t\t\tif (itemAString === undefined || itemBString === undefined) {\n\t\t\t\t\tif (itemAString === undefined && itemBString === undefined) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t} else if (itemAString === undefined) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t} else if (itemAString === itemBString) {\n\t\t\t\t\treturn 0;\n\t\t\t\t} else if (itemAString < itemBString) {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn b.score - a.score;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Default function for transforming each string to be searched.\n\t *\n\t * @private\n\t * @param {string} string  The string to transform.\n\t * @returns {string}  The transformed string.\n\t */\n\tfunction toLocaleLowerCase(\n\t\tstring)\n\t{\n\t\treturn string.toLocaleLowerCase();\n\t}\n\n\texports.BaseConfig = BaseConfig;\n\texports.DefaultConfig = DefaultConfig;\n\texports.QuickScore = QuickScore;\n\texports.QuicksilverConfig = QuicksilverConfig;\n\texports.Range = Range;\n\texports.createConfig = createConfig;\n\texports.quickScore = quickScore;\n\n\tObject.defineProperty(exports, '__esModule', { value: true });\n\n}));\n"]}