芝麻web文件管理V1.00
编辑当前文件:/home/freeclou/app.optimyar.com/backend/node_modules/match-sorter/dist/match-sorter.cjs.js
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = require('@babel/runtime/helpers/extends'); var removeAccents = require('remove-accents'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends); var removeAccents__default = /*#__PURE__*/_interopDefaultLegacy(removeAccents); var rankings = { CASE_SENSITIVE_EQUAL: 9, EQUAL: 8, STARTS_WITH: 7, WORD_STARTS_WITH: 6, STRING_CASE: 5, STRING_CASE_ACRONYM: 4, CONTAINS: 3, ACRONYM: 2, MATCHES: 1, NO_MATCH: 0 }; var caseRankings = { CAMEL: 0.8, PASCAL: 0.6, KEBAB: 0.4, SNAKE: 0.2, NO_CASE: 0 }; matchSorter.rankings = rankings; matchSorter.caseRankings = caseRankings; var defaultBaseSortFn = function (a, b) { return String(a.rankedItem).localeCompare(b.rankedItem); }; /** * Takes an array of items and a value and returns a new array with the items that match the given value * @param {Array} items - the items to sort * @param {String} value - the value to use for ranking * @param {Object} options - Some options to configure the sorter * @return {Array} - the new sorted array */ function matchSorter(items, value, options) { if (options === void 0) { options = {}; } var _options = options, keys = _options.keys, _options$threshold = _options.threshold, threshold = _options$threshold === void 0 ? rankings.MATCHES : _options$threshold, _options$baseSort = _options.baseSort, baseSort = _options$baseSort === void 0 ? defaultBaseSortFn : _options$baseSort; var matchedItems = items.reduce(reduceItemsToRanked, []); return matchedItems.sort(function (a, b) { return sortRankedItems(a, b, baseSort); }).map(function (_ref) { var item = _ref.item; return item; }); function reduceItemsToRanked(matches, item, index) { var _getHighestRanking = getHighestRanking(item, keys, value, options), rankedItem = _getHighestRanking.rankedItem, rank = _getHighestRanking.rank, keyIndex = _getHighestRanking.keyIndex, _getHighestRanking$ke = _getHighestRanking.keyThreshold, keyThreshold = _getHighestRanking$ke === void 0 ? threshold : _getHighestRanking$ke; if (rank >= keyThreshold) { matches.push({ rankedItem: rankedItem, item: item, rank: rank, index: index, keyIndex: keyIndex }); } return matches; } } /** * Gets the highest ranking for value for the given item based on its values for the given keys * @param {*} item - the item to rank * @param {Array} keys - the keys to get values from the item for the ranking * @param {String} value - the value to rank against * @param {Object} options - options to control the ranking * @return {{rank: Number, keyIndex: Number, keyThreshold: Number}} - the highest ranking */ function getHighestRanking(item, keys, value, options) { if (!keys) { return { // ends up being duplicate of 'item' in matches but consistent rankedItem: item, rank: getMatchRanking(item, value, options), keyIndex: -1, keyThreshold: options.threshold }; } var valuesToRank = getAllValuesToRank(item, keys); return valuesToRank.reduce(function (_ref2, _ref3, i) { var rank = _ref2.rank, rankedItem = _ref2.rankedItem, keyIndex = _ref2.keyIndex, keyThreshold = _ref2.keyThreshold; var itemValue = _ref3.itemValue, attributes = _ref3.attributes; var newRank = getMatchRanking(itemValue, value, options); var newRankedItem = rankedItem; var minRanking = attributes.minRanking, maxRanking = attributes.maxRanking, threshold = attributes.threshold; if (newRank < minRanking && newRank >= rankings.MATCHES) { newRank = minRanking; } else if (newRank > maxRanking) { newRank = maxRanking; } if (newRank > rank) { rank = newRank; keyIndex = i; keyThreshold = threshold; newRankedItem = itemValue; } return { rankedItem: newRankedItem, rank: rank, keyIndex: keyIndex, keyThreshold: keyThreshold }; }, { rank: rankings.NO_MATCH, keyIndex: -1, keyThreshold: options.threshold }); } /** * Gives a rankings score based on how well the two strings match. * @param {String} testString - the string to test against * @param {String} stringToRank - the string to rank * @param {Object} options - options for the match (like keepDiacritics for comparison) * @returns {Number} the ranking for how well stringToRank matches testString */ function getMatchRanking(testString, stringToRank, options) { /* eslint complexity:[2, 12] */ testString = prepareValueForComparison(testString, options); stringToRank = prepareValueForComparison(stringToRank, options); // too long if (stringToRank.length > testString.length) { return rankings.NO_MATCH; } // case sensitive equals if (testString === stringToRank) { return rankings.CASE_SENSITIVE_EQUAL; } var caseRank = getCaseRanking(testString); var isPartial = isPartialOfCase(testString, stringToRank, caseRank); var isCasedAcronym = isCaseAcronym(testString, stringToRank, caseRank); // Lower casing before further comparison testString = testString.toLowerCase(); stringToRank = stringToRank.toLowerCase(); // case insensitive equals if (testString === stringToRank) { return rankings.EQUAL + caseRank; } // starts with if (testString.indexOf(stringToRank) === 0) { return rankings.STARTS_WITH + caseRank; } // word starts with if (testString.indexOf(" " + stringToRank) !== -1) { return rankings.WORD_STARTS_WITH + caseRank; } // is a part inside a cased string if (isPartial) { return rankings.STRING_CASE + caseRank; } // is acronym for a cased string if (caseRank > 0 && isCasedAcronym) { return rankings.STRING_CASE_ACRONYM + caseRank; } // contains if (testString.indexOf(stringToRank) !== -1) { return rankings.CONTAINS + caseRank; } else if (stringToRank.length === 1) { // If the only character in the given stringToRank // isn't even contained in the testString, then // it's definitely not a match. return rankings.NO_MATCH; } // acronym if (getAcronym(testString).indexOf(stringToRank) !== -1) { return rankings.ACRONYM + caseRank; } // will return a number between rankings.MATCHES and // rankings.MATCHES + 1 depending on how close of a match it is. return getClosenessRanking(testString, stringToRank); } /** * Generates an acronym for a string. * * @param {String} string the string for which to produce the acronym * @returns {String} the acronym */ function getAcronym(string) { var acronym = ''; var wordsInString = string.split(' '); wordsInString.forEach(function (wordInString) { var splitByHyphenWords = wordInString.split('-'); splitByHyphenWords.forEach(function (splitByHyphenWord) { acronym += splitByHyphenWord.substr(0, 1); }); }); return acronym; } /** * Returns a score base on the case of the testString * @param {String} testString - the string to test against * @returns {Number} the number of the ranking, * based on the case between 0 and 1 for how the testString matches the case */ function getCaseRanking(testString) { var containsUpperCase = testString.toLowerCase() !== testString; var containsDash = testString.indexOf('-') >= 0; var containsUnderscore = testString.indexOf('_') >= 0; if (!containsUpperCase && !containsUnderscore && containsDash) { return caseRankings.KEBAB; } if (!containsUpperCase && containsUnderscore && !containsDash) { return caseRankings.SNAKE; } if (containsUpperCase && !containsDash && !containsUnderscore) { var startsWithUpperCase = testString[0].toUpperCase() === testString[0]; if (startsWithUpperCase) { return caseRankings.PASCAL; } return caseRankings.CAMEL; } return caseRankings.NO_CASE; } /** * Returns whether the stringToRank is one of the case parts in the testString (works with any string case) * @example * // returns true * isPartialOfCase('helloWorld', 'world', caseRankings.CAMEL) * @example * // returns false * isPartialOfCase('helloWorld', 'oworl', caseRankings.CAMEL) * @param {String} testString - the string to test against * @param {String} stringToRank - the string to rank * @param {Number} caseRanking - the ranking score based on case of testString * @returns {Boolean} whether the stringToRank is one of the case parts in the testString */ function isPartialOfCase(testString, stringToRank, caseRanking) { var testIndex = testString.toLowerCase().indexOf(stringToRank.toLowerCase()); switch (caseRanking) { case caseRankings.SNAKE: return testString[testIndex - 1] === '_'; case caseRankings.KEBAB: return testString[testIndex - 1] === '-'; case caseRankings.PASCAL: case caseRankings.CAMEL: return testIndex !== -1 && testString[testIndex] === testString[testIndex].toUpperCase(); default: return false; } } /** * Check if stringToRank is an acronym for a partial case * @example * // returns true * isCaseAcronym('super_duper_file', 'sdf', caseRankings.SNAKE) * @param {String} testString - the string to test against * @param {String} stringToRank - the acronym to test * @param {Number} caseRank - the ranking of the case * @returns {Boolean} whether the stringToRank is an acronym for the testString */ function isCaseAcronym(testString, stringToRank, caseRank) { var splitValue = null; switch (caseRank) { case caseRankings.SNAKE: splitValue = '_'; break; case caseRankings.KEBAB: splitValue = '-'; break; case caseRankings.PASCAL: case caseRankings.CAMEL: splitValue = /(?=[A-Z])/; break; default: splitValue = null; } var splitTestString = testString.split(splitValue); return stringToRank.toLowerCase().split('').reduce(function (correct, char, charIndex) { var splitItem = splitTestString[charIndex]; return correct && splitItem && splitItem[0].toLowerCase() === char; }, true); } /** * Returns a score based on how spread apart the * characters from the stringToRank are within the testString. * A number close to rankings.MATCHES represents a loose match. A number close * to rankings.MATCHES + 1 represents a tighter match. * @param {String} testString - the string to test against * @param {String} stringToRank - the string to rank * @returns {Number} the number between rankings.MATCHES and * rankings.MATCHES + 1 for how well stringToRank matches testString */ function getClosenessRanking(testString, stringToRank) { var matchingInOrderCharCount = 0; var charNumber = 0; function findMatchingCharacter(matchChar, string, index) { for (var j = index; j < string.length; j++) { var stringChar = string[j]; if (stringChar === matchChar) { matchingInOrderCharCount += 1; return j + 1; } } return -1; } function getRanking(spread) { var inOrderPercentage = matchingInOrderCharCount / stringToRank.length; var ranking = rankings.MATCHES + inOrderPercentage * (1 / spread); return ranking; } var firstIndex = findMatchingCharacter(stringToRank[0], testString, 0); if (firstIndex < 0) { return rankings.NO_MATCH; } charNumber = firstIndex; for (var i = 1; i < stringToRank.length; i++) { var matchChar = stringToRank[i]; charNumber = findMatchingCharacter(matchChar, testString, charNumber); var found = charNumber > -1; if (!found) { return rankings.NO_MATCH; } } var spread = charNumber - firstIndex; return getRanking(spread); } /** * Sorts items that have a rank, index, and keyIndex * @param {Object} a - the first item to sort * @param {Object} b - the second item to sort * @return {Number} -1 if a should come first, 1 if b should come first, 0 if equal */ function sortRankedItems(a, b, baseSort) { var aFirst = -1; var bFirst = 1; var aRank = a.rank, aKeyIndex = a.keyIndex; var bRank = b.rank, bKeyIndex = b.keyIndex; if (aRank === bRank) { if (aKeyIndex === bKeyIndex) { // use the base sort function as a tie-breaker return baseSort(a, b); } else { return aKeyIndex < bKeyIndex ? aFirst : bFirst; } } else { return aRank > bRank ? aFirst : bFirst; } } /** * Prepares value for comparison by stringifying it, removing diacritics (if specified) * @param {String} value - the value to clean * @param {Object} options - {keepDiacritics: whether to remove diacritics} * @return {String} the prepared value */ function prepareValueForComparison(value, _ref4) { var keepDiacritics = _ref4.keepDiacritics; value = "" + value; // toString if (!keepDiacritics) { value = removeAccents__default['default'](value); } return value; } /** * Gets value for key in item at arbitrarily nested keypath * @param {Object} item - the item * @param {Object|Function} key - the potentially nested keypath or property callback * @return {Array} - an array containing the value(s) at the nested keypath */ function getItemValues(item, key) { if (typeof key === 'object') { key = key.key; } var value; if (typeof key === 'function') { value = key(item); // eslint-disable-next-line no-negated-condition } else if (key.indexOf('.') !== -1) { // handle nested keys value = key.split('.').reduce(function (itemObj, nestedKey) { return itemObj ? itemObj[nestedKey] : null; }, item); } else { value = item[key]; } // concat because `value` can be a string or an array // eslint-disable-next-line return value != null ? [].concat(value) : null; } /** * Gets all the values for the given keys in the given item and returns an array of those values * @param {Object} item - the item from which the values will be retrieved * @param {Array} keys - the keys to use to retrieve the values * @return {Array} objects with {itemValue, attributes} */ function getAllValuesToRank(item, keys) { return keys.reduce(function (allVals, key) { var values = getItemValues(item, key); if (values) { values.forEach(function (itemValue) { allVals.push({ itemValue: itemValue, attributes: getKeyAttributes(key) }); }); } return allVals; }, []); } /** * Gets all the attributes for the given key * @param {Object|String} key - the key from which the attributes will be retrieved * @return {Object} object containing the key's attributes */ function getKeyAttributes(key) { if (typeof key === 'string') { key = { key: key }; } return _extends__default['default']({ maxRanking: Infinity, minRanking: -Infinity }, key); } exports.default = matchSorter; exports.rankings = rankings;