Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

21
node_modules/@tanstack/match-sorter-utils/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Tanner Linsley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,57 @@
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
export type AccessorAttributes = {
threshold?: Ranking;
maxRanking: Ranking;
minRanking: Ranking;
};
export interface RankingInfo {
rankedValue: any;
rank: Ranking;
accessorIndex: number;
accessorThreshold: Ranking | undefined;
passed: boolean;
}
export interface AccessorOptions<TItem> {
accessor: AccessorFn<TItem>;
threshold?: Ranking;
maxRanking?: Ranking;
minRanking?: Ranking;
}
export type AccessorFn<TItem> = (item: TItem) => string | Array<string>;
export type Accessor<TItem> = AccessorFn<TItem> | AccessorOptions<TItem>;
export interface RankItemOptions<TItem = unknown> {
accessors?: ReadonlyArray<Accessor<TItem>>;
threshold?: Ranking;
keepDiacritics?: boolean;
}
export declare const rankings: {
readonly CASE_SENSITIVE_EQUAL: 7;
readonly EQUAL: 6;
readonly STARTS_WITH: 5;
readonly WORD_STARTS_WITH: 4;
readonly CONTAINS: 3;
readonly ACRONYM: 2;
readonly MATCHES: 1;
readonly NO_MATCH: 0;
};
export type Ranking = (typeof rankings)[keyof typeof rankings];
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
export declare function rankItem<TItem>(item: TItem, value: string, options?: RankItemOptions<TItem>): RankingInfo;
/**
* Sorts items that have a rank, index, and accessorIndex
* @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
*/
export declare function compareItems<TItem>(a: RankingInfo, b: RankingInfo): number;

View File

@@ -0,0 +1,710 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
const characterMap = {
À: 'A',
Á: 'A',
Â: 'A',
Ã: 'A',
Ä: 'A',
Å: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
Æ: 'AE',
: 'A',
: 'A',
Ȃ: 'A',
Ç: 'C',
: 'C',
È: 'E',
É: 'E',
Ê: 'E',
Ë: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
Ȇ: 'E',
Ì: 'I',
Í: 'I',
Î: 'I',
Ï: 'I',
: 'I',
Ȋ: 'I',
Ð: 'D',
Ñ: 'N',
Ò: 'O',
Ó: 'O',
Ô: 'O',
Õ: 'O',
Ö: 'O',
Ø: 'O',
: 'O',
: 'O',
: 'O',
Ȏ: 'O',
Ù: 'U',
Ú: 'U',
Û: 'U',
Ü: 'U',
Ý: 'Y',
à: 'a',
á: 'a',
â: 'a',
ã: 'a',
ä: 'a',
å: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
æ: 'ae',
: 'a',
: 'a',
ȃ: 'a',
ç: 'c',
: 'c',
è: 'e',
é: 'e',
ê: 'e',
ë: 'e',
ế: 'e',
: 'e',
: 'e',
: 'e',
: 'e',
ȇ: 'e',
ì: 'i',
í: 'i',
î: 'i',
ï: 'i',
: 'i',
ȋ: 'i',
ð: 'd',
ñ: 'n',
ò: 'o',
ó: 'o',
ô: 'o',
õ: 'o',
ö: 'o',
ø: 'o',
: 'o',
: 'o',
: 'o',
ȏ: 'o',
ù: 'u',
ú: 'u',
û: 'u',
ü: 'u',
ý: 'y',
ÿ: 'y',
Ā: 'A',
ā: 'a',
Ă: 'A',
ă: 'a',
Ą: 'A',
ą: 'a',
Ć: 'C',
ć: 'c',
Ĉ: 'C',
ĉ: 'c',
Ċ: 'C',
ċ: 'c',
Č: 'C',
č: 'c',
C̆: 'C',
c̆: 'c',
Ď: 'D',
ď: 'd',
Đ: 'D',
đ: 'd',
Ē: 'E',
ē: 'e',
Ĕ: 'E',
ĕ: 'e',
Ė: 'E',
ė: 'e',
Ę: 'E',
ę: 'e',
Ě: 'E',
ě: 'e',
Ĝ: 'G',
Ǵ: 'G',
ĝ: 'g',
ǵ: 'g',
Ğ: 'G',
ğ: 'g',
Ġ: 'G',
ġ: 'g',
Ģ: 'G',
ģ: 'g',
Ĥ: 'H',
ĥ: 'h',
Ħ: 'H',
ħ: 'h',
: 'H',
: 'h',
Ĩ: 'I',
ĩ: 'i',
Ī: 'I',
ī: 'i',
Ĭ: 'I',
ĭ: 'i',
Į: 'I',
į: 'i',
İ: 'I',
ı: 'i',
IJ: 'IJ',
ij: 'ij',
Ĵ: 'J',
ĵ: 'j',
Ķ: 'K',
ķ: 'k',
: 'K',
: 'k',
K̆: 'K',
k̆: 'k',
Ĺ: 'L',
ĺ: 'l',
Ļ: 'L',
ļ: 'l',
Ľ: 'L',
ľ: 'l',
Ŀ: 'L',
ŀ: 'l',
Ł: 'l',
ł: 'l',
: 'M',
ḿ: 'm',
M̆: 'M',
m̆: 'm',
Ń: 'N',
ń: 'n',
Ņ: 'N',
ņ: 'n',
Ň: 'N',
ň: 'n',
ʼn: 'n',
N̆: 'N',
n̆: 'n',
Ō: 'O',
ō: 'o',
Ŏ: 'O',
ŏ: 'o',
Ő: 'O',
ő: 'o',
Œ: 'OE',
œ: 'oe',
P̆: 'P',
p̆: 'p',
Ŕ: 'R',
ŕ: 'r',
Ŗ: 'R',
ŗ: 'r',
Ř: 'R',
ř: 'r',
R̆: 'R',
r̆: 'r',
Ȓ: 'R',
ȓ: 'r',
Ś: 'S',
ś: 's',
Ŝ: 'S',
ŝ: 's',
Ş: 'S',
Ș: 'S',
ș: 's',
ş: 's',
Š: 'S',
š: 's',
Ţ: 'T',
ţ: 't',
ț: 't',
Ț: 'T',
Ť: 'T',
ť: 't',
Ŧ: 'T',
ŧ: 't',
T̆: 'T',
t̆: 't',
Ũ: 'U',
ũ: 'u',
Ū: 'U',
ū: 'u',
Ŭ: 'U',
ŭ: 'u',
Ů: 'U',
ů: 'u',
Ű: 'U',
ű: 'u',
Ų: 'U',
ų: 'u',
Ȗ: 'U',
ȗ: 'u',
V̆: 'V',
v̆: 'v',
Ŵ: 'W',
ŵ: 'w',
: 'W',
: 'w',
X̆: 'X',
x̆: 'x',
Ŷ: 'Y',
ŷ: 'y',
Ÿ: 'Y',
Y̆: 'Y',
y̆: 'y',
Ź: 'Z',
ź: 'z',
Ż: 'Z',
ż: 'z',
Ž: 'Z',
ž: 'z',
ſ: 's',
ƒ: 'f',
Ơ: 'O',
ơ: 'o',
Ư: 'U',
ư: 'u',
Ǎ: 'A',
ǎ: 'a',
Ǐ: 'I',
ǐ: 'i',
Ǒ: 'O',
ǒ: 'o',
Ǔ: 'U',
ǔ: 'u',
Ǖ: 'U',
ǖ: 'u',
Ǘ: 'U',
ǘ: 'u',
Ǚ: 'U',
ǚ: 'u',
Ǜ: 'U',
ǜ: 'u',
: 'U',
: 'u',
: 'U',
: 'u',
Ǻ: 'A',
ǻ: 'a',
Ǽ: 'AE',
ǽ: 'ae',
Ǿ: 'O',
ǿ: 'o',
Þ: 'TH',
þ: 'th',
: 'P',
: 'p',
: 'S',
: 's',
X́: 'X',
x́: 'x',
Ѓ: 'Г',
ѓ: 'г',
Ќ: 'К',
ќ: 'к',
A̋: 'A',
a̋: 'a',
E̋: 'E',
e̋: 'e',
I̋: 'I',
i̋: 'i',
Ǹ: 'N',
ǹ: 'n',
: 'O',
: 'o',
: 'O',
: 'o',
: 'U',
: 'u',
: 'W',
: 'w',
: 'Y',
: 'y',
Ȁ: 'A',
ȁ: 'a',
Ȅ: 'E',
ȅ: 'e',
Ȉ: 'I',
ȉ: 'i',
Ȍ: 'O',
ȍ: 'o',
Ȑ: 'R',
ȑ: 'r',
Ȕ: 'U',
ȕ: 'u',
B̌: 'B',
b̌: 'b',
Č̣: 'C',
č̣: 'c',
Ê̌: 'E',
ê̌: 'e',
F̌: 'F',
f̌: 'f',
Ǧ: 'G',
ǧ: 'g',
Ȟ: 'H',
ȟ: 'h',
J̌: 'J',
ǰ: 'j',
Ǩ: 'K',
ǩ: 'k',
M̌: 'M',
m̌: 'm',
P̌: 'P',
p̌: 'p',
Q̌: 'Q',
q̌: 'q',
Ř̩: 'R',
ř̩: 'r',
: 'S',
: 's',
V̌: 'V',
v̌: 'v',
W̌: 'W',
w̌: 'w',
X̌: 'X',
x̌: 'x',
Y̌: 'Y',
y̌: 'y',
A̧: 'A',
a̧: 'a',
B̧: 'B',
b̧: 'b',
: 'D',
: 'd',
Ȩ: 'E',
ȩ: 'e',
Ɛ̧: 'E',
ɛ̧: 'e',
: 'H',
: 'h',
I̧: 'I',
i̧: 'i',
Ɨ̧: 'I',
ɨ̧: 'i',
M̧: 'M',
m̧: 'm',
O̧: 'O',
o̧: 'o',
Q̧: 'Q',
q̧: 'q',
U̧: 'U',
u̧: 'u',
X̧: 'X',
x̧: 'x',
Z̧: 'Z',
z̧: 'z'
};
const chars = Object.keys(characterMap).join('|');
const allAccents = new RegExp(chars, 'g');
function removeAccents(str) {
return str.replace(allAccents, match => {
return characterMap[match];
});
}
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
const rankings = {
CASE_SENSITIVE_EQUAL: 7,
EQUAL: 6,
STARTS_WITH: 5,
WORD_STARTS_WITH: 4,
CONTAINS: 3,
ACRONYM: 2,
MATCHES: 1,
NO_MATCH: 0
};
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
function rankItem(item, value, options) {
var _options$threshold;
options = options || {};
options.threshold = (_options$threshold = options.threshold) != null ? _options$threshold : rankings.MATCHES;
if (!options.accessors) {
// if keys is not specified, then we assume the item given is ready to be matched
const rank = getMatchRanking(item, value, options);
return {
// ends up being duplicate of 'item' in matches but consistent
rankedValue: item,
rank,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: rank >= options.threshold
};
}
const valuesToRank = getAllValuesToRank(item, options.accessors);
const rankingInfo = {
rankedValue: item,
rank: rankings.NO_MATCH,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: false
};
for (let i = 0; i < valuesToRank.length; i++) {
const rankValue = valuesToRank[i];
let newRank = getMatchRanking(rankValue.itemValue, value, options);
const {
minRanking,
maxRanking,
threshold = options.threshold
} = rankValue.attributes;
if (newRank < minRanking && newRank >= rankings.MATCHES) {
newRank = minRanking;
} else if (newRank > maxRanking) {
newRank = maxRanking;
}
newRank = Math.min(newRank, maxRanking);
if (newRank >= threshold && newRank > rankingInfo.rank) {
rankingInfo.rank = newRank;
rankingInfo.passed = true;
rankingInfo.accessorIndex = i;
rankingInfo.accessorThreshold = threshold;
rankingInfo.rankedValue = rankValue.itemValue;
}
}
return rankingInfo;
}
/**
* 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) {
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;
}
// Lower casing before further comparison
testString = testString.toLowerCase();
stringToRank = stringToRank.toLowerCase();
// case insensitive equals
if (testString === stringToRank) {
return rankings.EQUAL;
}
// starts with
if (testString.startsWith(stringToRank)) {
return rankings.STARTS_WITH;
}
// word starts with
if (testString.includes(` ${stringToRank}`)) {
return rankings.WORD_STARTS_WITH;
}
// contains
if (testString.includes(stringToRank)) {
return rankings.CONTAINS;
} 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).includes(stringToRank)) {
return rankings.ACRONYM;
}
// 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) {
let acronym = '';
const wordsInString = string.split(' ');
wordsInString.forEach(wordInString => {
const splitByHyphenWords = wordInString.split('-');
splitByHyphenWords.forEach(splitByHyphenWord => {
acronym += splitByHyphenWord.substr(0, 1);
});
});
return acronym;
}
/**
* 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) {
let matchingInOrderCharCount = 0;
let charNumber = 0;
function findMatchingCharacter(matchChar, string, index) {
for (let j = index, J = string.length; j < J; j++) {
const stringChar = string[j];
if (stringChar === matchChar) {
matchingInOrderCharCount += 1;
return j + 1;
}
}
return -1;
}
function getRanking(spread) {
const spreadPercentage = 1 / spread;
const inOrderPercentage = matchingInOrderCharCount / stringToRank.length;
const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage;
return ranking;
}
const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0);
if (firstIndex < 0) {
return rankings.NO_MATCH;
}
charNumber = firstIndex;
for (let i = 1, I = stringToRank.length; i < I; i++) {
const matchChar = stringToRank[i];
charNumber = findMatchingCharacter(matchChar, testString, charNumber);
const found = charNumber > -1;
if (!found) {
return rankings.NO_MATCH;
}
}
const spread = charNumber - firstIndex;
return getRanking(spread);
}
/**
* Sorts items that have a rank, index, and accessorIndex
* @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 compareItems(a, b) {
return a.rank === b.rank ? 0 : a.rank > b.rank ? -1 : 1;
}
/**
* 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, _ref) {
let {
keepDiacritics
} = _ref;
// value might not actually be a string at this point (we don't get to choose)
// so part of preparing the value for comparison is ensure that it is a string
value = `${value}`; // toString
if (!keepDiacritics) {
value = removeAccents(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, accessor) {
let accessorFn = accessor;
if (typeof accessor === 'object') {
accessorFn = accessor.accessor;
}
const value = accessorFn(item);
// because `value` can also be undefined
if (value == null) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [String(value)];
}
/**
* Gets all the values for the given keys in the given item and returns an array of those values
* @param item - the item from which the values will be retrieved
* @param keys - the keys to use to retrieve the values
* @return objects with {itemValue, attributes}
*/
function getAllValuesToRank(item, accessors) {
const allValues = [];
for (let j = 0, J = accessors.length; j < J; j++) {
const accessor = accessors[j];
const attributes = getAccessorAttributes(accessor);
const itemValues = getItemValues(item, accessor);
for (let i = 0, I = itemValues.length; i < I; i++) {
allValues.push({
itemValue: itemValues[i],
attributes
});
}
}
return allValues;
}
const defaultKeyAttributes = {
maxRanking: Infinity,
minRanking: -Infinity
};
/**
* Gets all the attributes for the given accessor
* @param accessor - the accessor from which the attributes will be retrieved
* @return object containing the accessor's attributes
*/
function getAccessorAttributes(accessor) {
if (typeof accessor === 'function') {
return defaultKeyAttributes;
}
return {
...defaultKeyAttributes,
...accessor
};
}
export { compareItems, rankItem, rankings };
//# sourceMappingURL=index.esm.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,307 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
'use strict';
var removeAccents = require('./remove-accents.js');
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
const rankings = {
CASE_SENSITIVE_EQUAL: 7,
EQUAL: 6,
STARTS_WITH: 5,
WORD_STARTS_WITH: 4,
CONTAINS: 3,
ACRONYM: 2,
MATCHES: 1,
NO_MATCH: 0
};
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
function rankItem(item, value, options) {
var _options$threshold;
options = options || {};
options.threshold = (_options$threshold = options.threshold) != null ? _options$threshold : rankings.MATCHES;
if (!options.accessors) {
// if keys is not specified, then we assume the item given is ready to be matched
const rank = getMatchRanking(item, value, options);
return {
// ends up being duplicate of 'item' in matches but consistent
rankedValue: item,
rank,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: rank >= options.threshold
};
}
const valuesToRank = getAllValuesToRank(item, options.accessors);
const rankingInfo = {
rankedValue: item,
rank: rankings.NO_MATCH,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: false
};
for (let i = 0; i < valuesToRank.length; i++) {
const rankValue = valuesToRank[i];
let newRank = getMatchRanking(rankValue.itemValue, value, options);
const {
minRanking,
maxRanking,
threshold = options.threshold
} = rankValue.attributes;
if (newRank < minRanking && newRank >= rankings.MATCHES) {
newRank = minRanking;
} else if (newRank > maxRanking) {
newRank = maxRanking;
}
newRank = Math.min(newRank, maxRanking);
if (newRank >= threshold && newRank > rankingInfo.rank) {
rankingInfo.rank = newRank;
rankingInfo.passed = true;
rankingInfo.accessorIndex = i;
rankingInfo.accessorThreshold = threshold;
rankingInfo.rankedValue = rankValue.itemValue;
}
}
return rankingInfo;
}
/**
* 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) {
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;
}
// Lower casing before further comparison
testString = testString.toLowerCase();
stringToRank = stringToRank.toLowerCase();
// case insensitive equals
if (testString === stringToRank) {
return rankings.EQUAL;
}
// starts with
if (testString.startsWith(stringToRank)) {
return rankings.STARTS_WITH;
}
// word starts with
if (testString.includes(` ${stringToRank}`)) {
return rankings.WORD_STARTS_WITH;
}
// contains
if (testString.includes(stringToRank)) {
return rankings.CONTAINS;
} 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).includes(stringToRank)) {
return rankings.ACRONYM;
}
// 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) {
let acronym = '';
const wordsInString = string.split(' ');
wordsInString.forEach(wordInString => {
const splitByHyphenWords = wordInString.split('-');
splitByHyphenWords.forEach(splitByHyphenWord => {
acronym += splitByHyphenWord.substr(0, 1);
});
});
return acronym;
}
/**
* 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) {
let matchingInOrderCharCount = 0;
let charNumber = 0;
function findMatchingCharacter(matchChar, string, index) {
for (let j = index, J = string.length; j < J; j++) {
const stringChar = string[j];
if (stringChar === matchChar) {
matchingInOrderCharCount += 1;
return j + 1;
}
}
return -1;
}
function getRanking(spread) {
const spreadPercentage = 1 / spread;
const inOrderPercentage = matchingInOrderCharCount / stringToRank.length;
const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage;
return ranking;
}
const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0);
if (firstIndex < 0) {
return rankings.NO_MATCH;
}
charNumber = firstIndex;
for (let i = 1, I = stringToRank.length; i < I; i++) {
const matchChar = stringToRank[i];
charNumber = findMatchingCharacter(matchChar, testString, charNumber);
const found = charNumber > -1;
if (!found) {
return rankings.NO_MATCH;
}
}
const spread = charNumber - firstIndex;
return getRanking(spread);
}
/**
* Sorts items that have a rank, index, and accessorIndex
* @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 compareItems(a, b) {
return a.rank === b.rank ? 0 : a.rank > b.rank ? -1 : 1;
}
/**
* 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, _ref) {
let {
keepDiacritics
} = _ref;
// value might not actually be a string at this point (we don't get to choose)
// so part of preparing the value for comparison is ensure that it is a string
value = `${value}`; // toString
if (!keepDiacritics) {
value = removeAccents.removeAccents(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, accessor) {
let accessorFn = accessor;
if (typeof accessor === 'object') {
accessorFn = accessor.accessor;
}
const value = accessorFn(item);
// because `value` can also be undefined
if (value == null) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [String(value)];
}
/**
* Gets all the values for the given keys in the given item and returns an array of those values
* @param item - the item from which the values will be retrieved
* @param keys - the keys to use to retrieve the values
* @return objects with {itemValue, attributes}
*/
function getAllValuesToRank(item, accessors) {
const allValues = [];
for (let j = 0, J = accessors.length; j < J; j++) {
const accessor = accessors[j];
const attributes = getAccessorAttributes(accessor);
const itemValues = getItemValues(item, accessor);
for (let i = 0, I = itemValues.length; i < I; i++) {
allValues.push({
itemValue: itemValues[i],
attributes
});
}
}
return allValues;
}
const defaultKeyAttributes = {
maxRanking: Infinity,
minRanking: -Infinity
};
/**
* Gets all the attributes for the given accessor
* @param accessor - the accessor from which the attributes will be retrieved
* @return object containing the accessor's attributes
*/
function getAccessorAttributes(accessor) {
if (typeof accessor === 'function') {
return defaultKeyAttributes;
}
return {
...defaultKeyAttributes,
...accessor
};
}
exports.compareItems = compareItems;
exports.rankItem = rankItem;
exports.rankings = rankings;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,710 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
const characterMap = {
À: 'A',
Á: 'A',
Â: 'A',
Ã: 'A',
Ä: 'A',
Å: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
Æ: 'AE',
: 'A',
: 'A',
Ȃ: 'A',
Ç: 'C',
: 'C',
È: 'E',
É: 'E',
Ê: 'E',
Ë: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
Ȇ: 'E',
Ì: 'I',
Í: 'I',
Î: 'I',
Ï: 'I',
: 'I',
Ȋ: 'I',
Ð: 'D',
Ñ: 'N',
Ò: 'O',
Ó: 'O',
Ô: 'O',
Õ: 'O',
Ö: 'O',
Ø: 'O',
: 'O',
: 'O',
: 'O',
Ȏ: 'O',
Ù: 'U',
Ú: 'U',
Û: 'U',
Ü: 'U',
Ý: 'Y',
à: 'a',
á: 'a',
â: 'a',
ã: 'a',
ä: 'a',
å: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
æ: 'ae',
: 'a',
: 'a',
ȃ: 'a',
ç: 'c',
: 'c',
è: 'e',
é: 'e',
ê: 'e',
ë: 'e',
ế: 'e',
: 'e',
: 'e',
: 'e',
: 'e',
ȇ: 'e',
ì: 'i',
í: 'i',
î: 'i',
ï: 'i',
: 'i',
ȋ: 'i',
ð: 'd',
ñ: 'n',
ò: 'o',
ó: 'o',
ô: 'o',
õ: 'o',
ö: 'o',
ø: 'o',
: 'o',
: 'o',
: 'o',
ȏ: 'o',
ù: 'u',
ú: 'u',
û: 'u',
ü: 'u',
ý: 'y',
ÿ: 'y',
Ā: 'A',
ā: 'a',
Ă: 'A',
ă: 'a',
Ą: 'A',
ą: 'a',
Ć: 'C',
ć: 'c',
Ĉ: 'C',
ĉ: 'c',
Ċ: 'C',
ċ: 'c',
Č: 'C',
č: 'c',
C̆: 'C',
c̆: 'c',
Ď: 'D',
ď: 'd',
Đ: 'D',
đ: 'd',
Ē: 'E',
ē: 'e',
Ĕ: 'E',
ĕ: 'e',
Ė: 'E',
ė: 'e',
Ę: 'E',
ę: 'e',
Ě: 'E',
ě: 'e',
Ĝ: 'G',
Ǵ: 'G',
ĝ: 'g',
ǵ: 'g',
Ğ: 'G',
ğ: 'g',
Ġ: 'G',
ġ: 'g',
Ģ: 'G',
ģ: 'g',
Ĥ: 'H',
ĥ: 'h',
Ħ: 'H',
ħ: 'h',
: 'H',
: 'h',
Ĩ: 'I',
ĩ: 'i',
Ī: 'I',
ī: 'i',
Ĭ: 'I',
ĭ: 'i',
Į: 'I',
į: 'i',
İ: 'I',
ı: 'i',
IJ: 'IJ',
ij: 'ij',
Ĵ: 'J',
ĵ: 'j',
Ķ: 'K',
ķ: 'k',
: 'K',
: 'k',
K̆: 'K',
k̆: 'k',
Ĺ: 'L',
ĺ: 'l',
Ļ: 'L',
ļ: 'l',
Ľ: 'L',
ľ: 'l',
Ŀ: 'L',
ŀ: 'l',
Ł: 'l',
ł: 'l',
: 'M',
ḿ: 'm',
M̆: 'M',
m̆: 'm',
Ń: 'N',
ń: 'n',
Ņ: 'N',
ņ: 'n',
Ň: 'N',
ň: 'n',
ʼn: 'n',
N̆: 'N',
n̆: 'n',
Ō: 'O',
ō: 'o',
Ŏ: 'O',
ŏ: 'o',
Ő: 'O',
ő: 'o',
Œ: 'OE',
œ: 'oe',
P̆: 'P',
p̆: 'p',
Ŕ: 'R',
ŕ: 'r',
Ŗ: 'R',
ŗ: 'r',
Ř: 'R',
ř: 'r',
R̆: 'R',
r̆: 'r',
Ȓ: 'R',
ȓ: 'r',
Ś: 'S',
ś: 's',
Ŝ: 'S',
ŝ: 's',
Ş: 'S',
Ș: 'S',
ș: 's',
ş: 's',
Š: 'S',
š: 's',
Ţ: 'T',
ţ: 't',
ț: 't',
Ț: 'T',
Ť: 'T',
ť: 't',
Ŧ: 'T',
ŧ: 't',
T̆: 'T',
t̆: 't',
Ũ: 'U',
ũ: 'u',
Ū: 'U',
ū: 'u',
Ŭ: 'U',
ŭ: 'u',
Ů: 'U',
ů: 'u',
Ű: 'U',
ű: 'u',
Ų: 'U',
ų: 'u',
Ȗ: 'U',
ȗ: 'u',
V̆: 'V',
v̆: 'v',
Ŵ: 'W',
ŵ: 'w',
: 'W',
: 'w',
X̆: 'X',
x̆: 'x',
Ŷ: 'Y',
ŷ: 'y',
Ÿ: 'Y',
Y̆: 'Y',
y̆: 'y',
Ź: 'Z',
ź: 'z',
Ż: 'Z',
ż: 'z',
Ž: 'Z',
ž: 'z',
ſ: 's',
ƒ: 'f',
Ơ: 'O',
ơ: 'o',
Ư: 'U',
ư: 'u',
Ǎ: 'A',
ǎ: 'a',
Ǐ: 'I',
ǐ: 'i',
Ǒ: 'O',
ǒ: 'o',
Ǔ: 'U',
ǔ: 'u',
Ǖ: 'U',
ǖ: 'u',
Ǘ: 'U',
ǘ: 'u',
Ǚ: 'U',
ǚ: 'u',
Ǜ: 'U',
ǜ: 'u',
: 'U',
: 'u',
: 'U',
: 'u',
Ǻ: 'A',
ǻ: 'a',
Ǽ: 'AE',
ǽ: 'ae',
Ǿ: 'O',
ǿ: 'o',
Þ: 'TH',
þ: 'th',
: 'P',
: 'p',
: 'S',
: 's',
X́: 'X',
x́: 'x',
Ѓ: 'Г',
ѓ: 'г',
Ќ: 'К',
ќ: 'к',
A̋: 'A',
a̋: 'a',
E̋: 'E',
e̋: 'e',
I̋: 'I',
i̋: 'i',
Ǹ: 'N',
ǹ: 'n',
: 'O',
: 'o',
: 'O',
: 'o',
: 'U',
: 'u',
: 'W',
: 'w',
: 'Y',
: 'y',
Ȁ: 'A',
ȁ: 'a',
Ȅ: 'E',
ȅ: 'e',
Ȉ: 'I',
ȉ: 'i',
Ȍ: 'O',
ȍ: 'o',
Ȑ: 'R',
ȑ: 'r',
Ȕ: 'U',
ȕ: 'u',
B̌: 'B',
b̌: 'b',
Č̣: 'C',
č̣: 'c',
Ê̌: 'E',
ê̌: 'e',
F̌: 'F',
f̌: 'f',
Ǧ: 'G',
ǧ: 'g',
Ȟ: 'H',
ȟ: 'h',
J̌: 'J',
ǰ: 'j',
Ǩ: 'K',
ǩ: 'k',
M̌: 'M',
m̌: 'm',
P̌: 'P',
p̌: 'p',
Q̌: 'Q',
q̌: 'q',
Ř̩: 'R',
ř̩: 'r',
: 'S',
: 's',
V̌: 'V',
v̌: 'v',
W̌: 'W',
w̌: 'w',
X̌: 'X',
x̌: 'x',
Y̌: 'Y',
y̌: 'y',
A̧: 'A',
a̧: 'a',
B̧: 'B',
b̧: 'b',
: 'D',
: 'd',
Ȩ: 'E',
ȩ: 'e',
Ɛ̧: 'E',
ɛ̧: 'e',
: 'H',
: 'h',
I̧: 'I',
i̧: 'i',
Ɨ̧: 'I',
ɨ̧: 'i',
M̧: 'M',
m̧: 'm',
O̧: 'O',
o̧: 'o',
Q̧: 'Q',
q̧: 'q',
U̧: 'U',
u̧: 'u',
X̧: 'X',
x̧: 'x',
Z̧: 'Z',
z̧: 'z'
};
const chars = Object.keys(characterMap).join('|');
const allAccents = new RegExp(chars, 'g');
function removeAccents(str) {
return str.replace(allAccents, match => {
return characterMap[match];
});
}
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
const rankings = {
CASE_SENSITIVE_EQUAL: 7,
EQUAL: 6,
STARTS_WITH: 5,
WORD_STARTS_WITH: 4,
CONTAINS: 3,
ACRONYM: 2,
MATCHES: 1,
NO_MATCH: 0
};
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
function rankItem(item, value, options) {
var _options$threshold;
options = options || {};
options.threshold = (_options$threshold = options.threshold) != null ? _options$threshold : rankings.MATCHES;
if (!options.accessors) {
// if keys is not specified, then we assume the item given is ready to be matched
const rank = getMatchRanking(item, value, options);
return {
// ends up being duplicate of 'item' in matches but consistent
rankedValue: item,
rank,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: rank >= options.threshold
};
}
const valuesToRank = getAllValuesToRank(item, options.accessors);
const rankingInfo = {
rankedValue: item,
rank: rankings.NO_MATCH,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: false
};
for (let i = 0; i < valuesToRank.length; i++) {
const rankValue = valuesToRank[i];
let newRank = getMatchRanking(rankValue.itemValue, value, options);
const {
minRanking,
maxRanking,
threshold = options.threshold
} = rankValue.attributes;
if (newRank < minRanking && newRank >= rankings.MATCHES) {
newRank = minRanking;
} else if (newRank > maxRanking) {
newRank = maxRanking;
}
newRank = Math.min(newRank, maxRanking);
if (newRank >= threshold && newRank > rankingInfo.rank) {
rankingInfo.rank = newRank;
rankingInfo.passed = true;
rankingInfo.accessorIndex = i;
rankingInfo.accessorThreshold = threshold;
rankingInfo.rankedValue = rankValue.itemValue;
}
}
return rankingInfo;
}
/**
* 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) {
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;
}
// Lower casing before further comparison
testString = testString.toLowerCase();
stringToRank = stringToRank.toLowerCase();
// case insensitive equals
if (testString === stringToRank) {
return rankings.EQUAL;
}
// starts with
if (testString.startsWith(stringToRank)) {
return rankings.STARTS_WITH;
}
// word starts with
if (testString.includes(` ${stringToRank}`)) {
return rankings.WORD_STARTS_WITH;
}
// contains
if (testString.includes(stringToRank)) {
return rankings.CONTAINS;
} 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).includes(stringToRank)) {
return rankings.ACRONYM;
}
// 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) {
let acronym = '';
const wordsInString = string.split(' ');
wordsInString.forEach(wordInString => {
const splitByHyphenWords = wordInString.split('-');
splitByHyphenWords.forEach(splitByHyphenWord => {
acronym += splitByHyphenWord.substr(0, 1);
});
});
return acronym;
}
/**
* 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) {
let matchingInOrderCharCount = 0;
let charNumber = 0;
function findMatchingCharacter(matchChar, string, index) {
for (let j = index, J = string.length; j < J; j++) {
const stringChar = string[j];
if (stringChar === matchChar) {
matchingInOrderCharCount += 1;
return j + 1;
}
}
return -1;
}
function getRanking(spread) {
const spreadPercentage = 1 / spread;
const inOrderPercentage = matchingInOrderCharCount / stringToRank.length;
const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage;
return ranking;
}
const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0);
if (firstIndex < 0) {
return rankings.NO_MATCH;
}
charNumber = firstIndex;
for (let i = 1, I = stringToRank.length; i < I; i++) {
const matchChar = stringToRank[i];
charNumber = findMatchingCharacter(matchChar, testString, charNumber);
const found = charNumber > -1;
if (!found) {
return rankings.NO_MATCH;
}
}
const spread = charNumber - firstIndex;
return getRanking(spread);
}
/**
* Sorts items that have a rank, index, and accessorIndex
* @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 compareItems(a, b) {
return a.rank === b.rank ? 0 : a.rank > b.rank ? -1 : 1;
}
/**
* 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, _ref) {
let {
keepDiacritics
} = _ref;
// value might not actually be a string at this point (we don't get to choose)
// so part of preparing the value for comparison is ensure that it is a string
value = `${value}`; // toString
if (!keepDiacritics) {
value = removeAccents(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, accessor) {
let accessorFn = accessor;
if (typeof accessor === 'object') {
accessorFn = accessor.accessor;
}
const value = accessorFn(item);
// because `value` can also be undefined
if (value == null) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [String(value)];
}
/**
* Gets all the values for the given keys in the given item and returns an array of those values
* @param item - the item from which the values will be retrieved
* @param keys - the keys to use to retrieve the values
* @return objects with {itemValue, attributes}
*/
function getAllValuesToRank(item, accessors) {
const allValues = [];
for (let j = 0, J = accessors.length; j < J; j++) {
const accessor = accessors[j];
const attributes = getAccessorAttributes(accessor);
const itemValues = getItemValues(item, accessor);
for (let i = 0, I = itemValues.length; i < I; i++) {
allValues.push({
itemValue: itemValues[i],
attributes
});
}
}
return allValues;
}
const defaultKeyAttributes = {
maxRanking: Infinity,
minRanking: -Infinity
};
/**
* Gets all the attributes for the given accessor
* @param accessor - the accessor from which the attributes will be retrieved
* @return object containing the accessor's attributes
*/
function getAccessorAttributes(accessor) {
if (typeof accessor === 'function') {
return defaultKeyAttributes;
}
return {
...defaultKeyAttributes,
...accessor
};
}
export { compareItems, rankItem, rankings };
//# sourceMappingURL=index.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export declare function removeAccents(str: string): string;

View File

@@ -0,0 +1,423 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
'use strict';
const characterMap = {
À: 'A',
Á: 'A',
Â: 'A',
Ã: 'A',
Ä: 'A',
Å: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
Æ: 'AE',
: 'A',
: 'A',
Ȃ: 'A',
Ç: 'C',
: 'C',
È: 'E',
É: 'E',
Ê: 'E',
Ë: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
Ȇ: 'E',
Ì: 'I',
Í: 'I',
Î: 'I',
Ï: 'I',
: 'I',
Ȋ: 'I',
Ð: 'D',
Ñ: 'N',
Ò: 'O',
Ó: 'O',
Ô: 'O',
Õ: 'O',
Ö: 'O',
Ø: 'O',
: 'O',
: 'O',
: 'O',
Ȏ: 'O',
Ù: 'U',
Ú: 'U',
Û: 'U',
Ü: 'U',
Ý: 'Y',
à: 'a',
á: 'a',
â: 'a',
ã: 'a',
ä: 'a',
å: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
æ: 'ae',
: 'a',
: 'a',
ȃ: 'a',
ç: 'c',
: 'c',
è: 'e',
é: 'e',
ê: 'e',
ë: 'e',
ế: 'e',
: 'e',
: 'e',
: 'e',
: 'e',
ȇ: 'e',
ì: 'i',
í: 'i',
î: 'i',
ï: 'i',
: 'i',
ȋ: 'i',
ð: 'd',
ñ: 'n',
ò: 'o',
ó: 'o',
ô: 'o',
õ: 'o',
ö: 'o',
ø: 'o',
: 'o',
: 'o',
: 'o',
ȏ: 'o',
ù: 'u',
ú: 'u',
û: 'u',
ü: 'u',
ý: 'y',
ÿ: 'y',
Ā: 'A',
ā: 'a',
Ă: 'A',
ă: 'a',
Ą: 'A',
ą: 'a',
Ć: 'C',
ć: 'c',
Ĉ: 'C',
ĉ: 'c',
Ċ: 'C',
ċ: 'c',
Č: 'C',
č: 'c',
C̆: 'C',
c̆: 'c',
Ď: 'D',
ď: 'd',
Đ: 'D',
đ: 'd',
Ē: 'E',
ē: 'e',
Ĕ: 'E',
ĕ: 'e',
Ė: 'E',
ė: 'e',
Ę: 'E',
ę: 'e',
Ě: 'E',
ě: 'e',
Ĝ: 'G',
Ǵ: 'G',
ĝ: 'g',
ǵ: 'g',
Ğ: 'G',
ğ: 'g',
Ġ: 'G',
ġ: 'g',
Ģ: 'G',
ģ: 'g',
Ĥ: 'H',
ĥ: 'h',
Ħ: 'H',
ħ: 'h',
: 'H',
: 'h',
Ĩ: 'I',
ĩ: 'i',
Ī: 'I',
ī: 'i',
Ĭ: 'I',
ĭ: 'i',
Į: 'I',
į: 'i',
İ: 'I',
ı: 'i',
IJ: 'IJ',
ij: 'ij',
Ĵ: 'J',
ĵ: 'j',
Ķ: 'K',
ķ: 'k',
: 'K',
: 'k',
K̆: 'K',
k̆: 'k',
Ĺ: 'L',
ĺ: 'l',
Ļ: 'L',
ļ: 'l',
Ľ: 'L',
ľ: 'l',
Ŀ: 'L',
ŀ: 'l',
Ł: 'l',
ł: 'l',
: 'M',
ḿ: 'm',
M̆: 'M',
m̆: 'm',
Ń: 'N',
ń: 'n',
Ņ: 'N',
ņ: 'n',
Ň: 'N',
ň: 'n',
ʼn: 'n',
N̆: 'N',
n̆: 'n',
Ō: 'O',
ō: 'o',
Ŏ: 'O',
ŏ: 'o',
Ő: 'O',
ő: 'o',
Œ: 'OE',
œ: 'oe',
P̆: 'P',
p̆: 'p',
Ŕ: 'R',
ŕ: 'r',
Ŗ: 'R',
ŗ: 'r',
Ř: 'R',
ř: 'r',
R̆: 'R',
r̆: 'r',
Ȓ: 'R',
ȓ: 'r',
Ś: 'S',
ś: 's',
Ŝ: 'S',
ŝ: 's',
Ş: 'S',
Ș: 'S',
ș: 's',
ş: 's',
Š: 'S',
š: 's',
Ţ: 'T',
ţ: 't',
ț: 't',
Ț: 'T',
Ť: 'T',
ť: 't',
Ŧ: 'T',
ŧ: 't',
T̆: 'T',
t̆: 't',
Ũ: 'U',
ũ: 'u',
Ū: 'U',
ū: 'u',
Ŭ: 'U',
ŭ: 'u',
Ů: 'U',
ů: 'u',
Ű: 'U',
ű: 'u',
Ų: 'U',
ų: 'u',
Ȗ: 'U',
ȗ: 'u',
V̆: 'V',
v̆: 'v',
Ŵ: 'W',
ŵ: 'w',
: 'W',
: 'w',
X̆: 'X',
x̆: 'x',
Ŷ: 'Y',
ŷ: 'y',
Ÿ: 'Y',
Y̆: 'Y',
y̆: 'y',
Ź: 'Z',
ź: 'z',
Ż: 'Z',
ż: 'z',
Ž: 'Z',
ž: 'z',
ſ: 's',
ƒ: 'f',
Ơ: 'O',
ơ: 'o',
Ư: 'U',
ư: 'u',
Ǎ: 'A',
ǎ: 'a',
Ǐ: 'I',
ǐ: 'i',
Ǒ: 'O',
ǒ: 'o',
Ǔ: 'U',
ǔ: 'u',
Ǖ: 'U',
ǖ: 'u',
Ǘ: 'U',
ǘ: 'u',
Ǚ: 'U',
ǚ: 'u',
Ǜ: 'U',
ǜ: 'u',
: 'U',
: 'u',
: 'U',
: 'u',
Ǻ: 'A',
ǻ: 'a',
Ǽ: 'AE',
ǽ: 'ae',
Ǿ: 'O',
ǿ: 'o',
Þ: 'TH',
þ: 'th',
: 'P',
: 'p',
: 'S',
: 's',
X́: 'X',
x́: 'x',
Ѓ: 'Г',
ѓ: 'г',
Ќ: 'К',
ќ: 'к',
A̋: 'A',
a̋: 'a',
E̋: 'E',
e̋: 'e',
I̋: 'I',
i̋: 'i',
Ǹ: 'N',
ǹ: 'n',
: 'O',
: 'o',
: 'O',
: 'o',
: 'U',
: 'u',
: 'W',
: 'w',
: 'Y',
: 'y',
Ȁ: 'A',
ȁ: 'a',
Ȅ: 'E',
ȅ: 'e',
Ȉ: 'I',
ȉ: 'i',
Ȍ: 'O',
ȍ: 'o',
Ȑ: 'R',
ȑ: 'r',
Ȕ: 'U',
ȕ: 'u',
B̌: 'B',
b̌: 'b',
Č̣: 'C',
č̣: 'c',
Ê̌: 'E',
ê̌: 'e',
F̌: 'F',
f̌: 'f',
Ǧ: 'G',
ǧ: 'g',
Ȟ: 'H',
ȟ: 'h',
J̌: 'J',
ǰ: 'j',
Ǩ: 'K',
ǩ: 'k',
M̌: 'M',
m̌: 'm',
P̌: 'P',
p̌: 'p',
Q̌: 'Q',
q̌: 'q',
Ř̩: 'R',
ř̩: 'r',
: 'S',
: 's',
V̌: 'V',
v̌: 'v',
W̌: 'W',
w̌: 'w',
X̌: 'X',
x̌: 'x',
Y̌: 'Y',
y̌: 'y',
A̧: 'A',
a̧: 'a',
B̧: 'B',
b̧: 'b',
: 'D',
: 'd',
Ȩ: 'E',
ȩ: 'e',
Ɛ̧: 'E',
ɛ̧: 'e',
: 'H',
: 'h',
I̧: 'I',
i̧: 'i',
Ɨ̧: 'I',
ɨ̧: 'i',
M̧: 'M',
m̧: 'm',
O̧: 'O',
o̧: 'o',
Q̧: 'Q',
q̧: 'q',
U̧: 'U',
u̧: 'u',
X̧: 'X',
x̧: 'x',
Z̧: 'Z',
z̧: 'z'
};
const chars = Object.keys(characterMap).join('|');
const allAccents = new RegExp(chars, 'g');
function removeAccents(str) {
return str.replace(allAccents, match => {
return characterMap[match];
});
}
exports.removeAccents = removeAccents;
//# sourceMappingURL=remove-accents.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,720 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MatchSorterUtils = {}));
})(this, (function (exports) { 'use strict';
const characterMap = {
À: 'A',
Á: 'A',
Â: 'A',
Ã: 'A',
Ä: 'A',
Å: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
Æ: 'AE',
: 'A',
: 'A',
Ȃ: 'A',
Ç: 'C',
: 'C',
È: 'E',
É: 'E',
Ê: 'E',
Ë: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
Ȇ: 'E',
Ì: 'I',
Í: 'I',
Î: 'I',
Ï: 'I',
: 'I',
Ȋ: 'I',
Ð: 'D',
Ñ: 'N',
Ò: 'O',
Ó: 'O',
Ô: 'O',
Õ: 'O',
Ö: 'O',
Ø: 'O',
: 'O',
: 'O',
: 'O',
Ȏ: 'O',
Ù: 'U',
Ú: 'U',
Û: 'U',
Ü: 'U',
Ý: 'Y',
à: 'a',
á: 'a',
â: 'a',
ã: 'a',
ä: 'a',
å: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
æ: 'ae',
: 'a',
: 'a',
ȃ: 'a',
ç: 'c',
: 'c',
è: 'e',
é: 'e',
ê: 'e',
ë: 'e',
ế: 'e',
: 'e',
: 'e',
: 'e',
: 'e',
ȇ: 'e',
ì: 'i',
í: 'i',
î: 'i',
ï: 'i',
: 'i',
ȋ: 'i',
ð: 'd',
ñ: 'n',
ò: 'o',
ó: 'o',
ô: 'o',
õ: 'o',
ö: 'o',
ø: 'o',
: 'o',
: 'o',
: 'o',
ȏ: 'o',
ù: 'u',
ú: 'u',
û: 'u',
ü: 'u',
ý: 'y',
ÿ: 'y',
Ā: 'A',
ā: 'a',
Ă: 'A',
ă: 'a',
Ą: 'A',
ą: 'a',
Ć: 'C',
ć: 'c',
Ĉ: 'C',
ĉ: 'c',
Ċ: 'C',
ċ: 'c',
Č: 'C',
č: 'c',
C̆: 'C',
c̆: 'c',
Ď: 'D',
ď: 'd',
Đ: 'D',
đ: 'd',
Ē: 'E',
ē: 'e',
Ĕ: 'E',
ĕ: 'e',
Ė: 'E',
ė: 'e',
Ę: 'E',
ę: 'e',
Ě: 'E',
ě: 'e',
Ĝ: 'G',
Ǵ: 'G',
ĝ: 'g',
ǵ: 'g',
Ğ: 'G',
ğ: 'g',
Ġ: 'G',
ġ: 'g',
Ģ: 'G',
ģ: 'g',
Ĥ: 'H',
ĥ: 'h',
Ħ: 'H',
ħ: 'h',
: 'H',
: 'h',
Ĩ: 'I',
ĩ: 'i',
Ī: 'I',
ī: 'i',
Ĭ: 'I',
ĭ: 'i',
Į: 'I',
į: 'i',
İ: 'I',
ı: 'i',
IJ: 'IJ',
ij: 'ij',
Ĵ: 'J',
ĵ: 'j',
Ķ: 'K',
ķ: 'k',
: 'K',
: 'k',
K̆: 'K',
k̆: 'k',
Ĺ: 'L',
ĺ: 'l',
Ļ: 'L',
ļ: 'l',
Ľ: 'L',
ľ: 'l',
Ŀ: 'L',
ŀ: 'l',
Ł: 'l',
ł: 'l',
: 'M',
ḿ: 'm',
M̆: 'M',
m̆: 'm',
Ń: 'N',
ń: 'n',
Ņ: 'N',
ņ: 'n',
Ň: 'N',
ň: 'n',
ʼn: 'n',
N̆: 'N',
n̆: 'n',
Ō: 'O',
ō: 'o',
Ŏ: 'O',
ŏ: 'o',
Ő: 'O',
ő: 'o',
Œ: 'OE',
œ: 'oe',
P̆: 'P',
p̆: 'p',
Ŕ: 'R',
ŕ: 'r',
Ŗ: 'R',
ŗ: 'r',
Ř: 'R',
ř: 'r',
R̆: 'R',
r̆: 'r',
Ȓ: 'R',
ȓ: 'r',
Ś: 'S',
ś: 's',
Ŝ: 'S',
ŝ: 's',
Ş: 'S',
Ș: 'S',
ș: 's',
ş: 's',
Š: 'S',
š: 's',
Ţ: 'T',
ţ: 't',
ț: 't',
Ț: 'T',
Ť: 'T',
ť: 't',
Ŧ: 'T',
ŧ: 't',
T̆: 'T',
t̆: 't',
Ũ: 'U',
ũ: 'u',
Ū: 'U',
ū: 'u',
Ŭ: 'U',
ŭ: 'u',
Ů: 'U',
ů: 'u',
Ű: 'U',
ű: 'u',
Ų: 'U',
ų: 'u',
Ȗ: 'U',
ȗ: 'u',
V̆: 'V',
v̆: 'v',
Ŵ: 'W',
ŵ: 'w',
: 'W',
: 'w',
X̆: 'X',
x̆: 'x',
Ŷ: 'Y',
ŷ: 'y',
Ÿ: 'Y',
Y̆: 'Y',
y̆: 'y',
Ź: 'Z',
ź: 'z',
Ż: 'Z',
ż: 'z',
Ž: 'Z',
ž: 'z',
ſ: 's',
ƒ: 'f',
Ơ: 'O',
ơ: 'o',
Ư: 'U',
ư: 'u',
Ǎ: 'A',
ǎ: 'a',
Ǐ: 'I',
ǐ: 'i',
Ǒ: 'O',
ǒ: 'o',
Ǔ: 'U',
ǔ: 'u',
Ǖ: 'U',
ǖ: 'u',
Ǘ: 'U',
ǘ: 'u',
Ǚ: 'U',
ǚ: 'u',
Ǜ: 'U',
ǜ: 'u',
: 'U',
: 'u',
: 'U',
: 'u',
Ǻ: 'A',
ǻ: 'a',
Ǽ: 'AE',
ǽ: 'ae',
Ǿ: 'O',
ǿ: 'o',
Þ: 'TH',
þ: 'th',
: 'P',
: 'p',
: 'S',
: 's',
X́: 'X',
x́: 'x',
Ѓ: 'Г',
ѓ: 'г',
Ќ: 'К',
ќ: 'к',
A̋: 'A',
a̋: 'a',
E̋: 'E',
e̋: 'e',
I̋: 'I',
i̋: 'i',
Ǹ: 'N',
ǹ: 'n',
: 'O',
: 'o',
: 'O',
: 'o',
: 'U',
: 'u',
: 'W',
: 'w',
: 'Y',
: 'y',
Ȁ: 'A',
ȁ: 'a',
Ȅ: 'E',
ȅ: 'e',
Ȉ: 'I',
ȉ: 'i',
Ȍ: 'O',
ȍ: 'o',
Ȑ: 'R',
ȑ: 'r',
Ȕ: 'U',
ȕ: 'u',
B̌: 'B',
b̌: 'b',
Č̣: 'C',
č̣: 'c',
Ê̌: 'E',
ê̌: 'e',
F̌: 'F',
f̌: 'f',
Ǧ: 'G',
ǧ: 'g',
Ȟ: 'H',
ȟ: 'h',
J̌: 'J',
ǰ: 'j',
Ǩ: 'K',
ǩ: 'k',
M̌: 'M',
m̌: 'm',
P̌: 'P',
p̌: 'p',
Q̌: 'Q',
q̌: 'q',
Ř̩: 'R',
ř̩: 'r',
: 'S',
: 's',
V̌: 'V',
v̌: 'v',
W̌: 'W',
w̌: 'w',
X̌: 'X',
x̌: 'x',
Y̌: 'Y',
y̌: 'y',
A̧: 'A',
a̧: 'a',
B̧: 'B',
b̧: 'b',
: 'D',
: 'd',
Ȩ: 'E',
ȩ: 'e',
Ɛ̧: 'E',
ɛ̧: 'e',
: 'H',
: 'h',
I̧: 'I',
i̧: 'i',
Ɨ̧: 'I',
ɨ̧: 'i',
M̧: 'M',
m̧: 'm',
O̧: 'O',
o̧: 'o',
Q̧: 'Q',
q̧: 'q',
U̧: 'U',
u̧: 'u',
X̧: 'X',
x̧: 'x',
Z̧: 'Z',
z̧: 'z'
};
const chars = Object.keys(characterMap).join('|');
const allAccents = new RegExp(chars, 'g');
function removeAccents(str) {
return str.replace(allAccents, match => {
return characterMap[match];
});
}
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
const rankings = {
CASE_SENSITIVE_EQUAL: 7,
EQUAL: 6,
STARTS_WITH: 5,
WORD_STARTS_WITH: 4,
CONTAINS: 3,
ACRONYM: 2,
MATCHES: 1,
NO_MATCH: 0
};
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
function rankItem(item, value, options) {
var _options$threshold;
options = options || {};
options.threshold = (_options$threshold = options.threshold) != null ? _options$threshold : rankings.MATCHES;
if (!options.accessors) {
// if keys is not specified, then we assume the item given is ready to be matched
const rank = getMatchRanking(item, value, options);
return {
// ends up being duplicate of 'item' in matches but consistent
rankedValue: item,
rank,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: rank >= options.threshold
};
}
const valuesToRank = getAllValuesToRank(item, options.accessors);
const rankingInfo = {
rankedValue: item,
rank: rankings.NO_MATCH,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: false
};
for (let i = 0; i < valuesToRank.length; i++) {
const rankValue = valuesToRank[i];
let newRank = getMatchRanking(rankValue.itemValue, value, options);
const {
minRanking,
maxRanking,
threshold = options.threshold
} = rankValue.attributes;
if (newRank < minRanking && newRank >= rankings.MATCHES) {
newRank = minRanking;
} else if (newRank > maxRanking) {
newRank = maxRanking;
}
newRank = Math.min(newRank, maxRanking);
if (newRank >= threshold && newRank > rankingInfo.rank) {
rankingInfo.rank = newRank;
rankingInfo.passed = true;
rankingInfo.accessorIndex = i;
rankingInfo.accessorThreshold = threshold;
rankingInfo.rankedValue = rankValue.itemValue;
}
}
return rankingInfo;
}
/**
* 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) {
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;
}
// Lower casing before further comparison
testString = testString.toLowerCase();
stringToRank = stringToRank.toLowerCase();
// case insensitive equals
if (testString === stringToRank) {
return rankings.EQUAL;
}
// starts with
if (testString.startsWith(stringToRank)) {
return rankings.STARTS_WITH;
}
// word starts with
if (testString.includes(` ${stringToRank}`)) {
return rankings.WORD_STARTS_WITH;
}
// contains
if (testString.includes(stringToRank)) {
return rankings.CONTAINS;
} 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).includes(stringToRank)) {
return rankings.ACRONYM;
}
// 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) {
let acronym = '';
const wordsInString = string.split(' ');
wordsInString.forEach(wordInString => {
const splitByHyphenWords = wordInString.split('-');
splitByHyphenWords.forEach(splitByHyphenWord => {
acronym += splitByHyphenWord.substr(0, 1);
});
});
return acronym;
}
/**
* 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) {
let matchingInOrderCharCount = 0;
let charNumber = 0;
function findMatchingCharacter(matchChar, string, index) {
for (let j = index, J = string.length; j < J; j++) {
const stringChar = string[j];
if (stringChar === matchChar) {
matchingInOrderCharCount += 1;
return j + 1;
}
}
return -1;
}
function getRanking(spread) {
const spreadPercentage = 1 / spread;
const inOrderPercentage = matchingInOrderCharCount / stringToRank.length;
const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage;
return ranking;
}
const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0);
if (firstIndex < 0) {
return rankings.NO_MATCH;
}
charNumber = firstIndex;
for (let i = 1, I = stringToRank.length; i < I; i++) {
const matchChar = stringToRank[i];
charNumber = findMatchingCharacter(matchChar, testString, charNumber);
const found = charNumber > -1;
if (!found) {
return rankings.NO_MATCH;
}
}
const spread = charNumber - firstIndex;
return getRanking(spread);
}
/**
* Sorts items that have a rank, index, and accessorIndex
* @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 compareItems(a, b) {
return a.rank === b.rank ? 0 : a.rank > b.rank ? -1 : 1;
}
/**
* 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, _ref) {
let {
keepDiacritics
} = _ref;
// value might not actually be a string at this point (we don't get to choose)
// so part of preparing the value for comparison is ensure that it is a string
value = `${value}`; // toString
if (!keepDiacritics) {
value = removeAccents(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, accessor) {
let accessorFn = accessor;
if (typeof accessor === 'object') {
accessorFn = accessor.accessor;
}
const value = accessorFn(item);
// because `value` can also be undefined
if (value == null) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [String(value)];
}
/**
* Gets all the values for the given keys in the given item and returns an array of those values
* @param item - the item from which the values will be retrieved
* @param keys - the keys to use to retrieve the values
* @return objects with {itemValue, attributes}
*/
function getAllValuesToRank(item, accessors) {
const allValues = [];
for (let j = 0, J = accessors.length; j < J; j++) {
const accessor = accessors[j];
const attributes = getAccessorAttributes(accessor);
const itemValues = getItemValues(item, accessor);
for (let i = 0, I = itemValues.length; i < I; i++) {
allValues.push({
itemValue: itemValues[i],
attributes
});
}
}
return allValues;
}
const defaultKeyAttributes = {
maxRanking: Infinity,
minRanking: -Infinity
};
/**
* Gets all the attributes for the given accessor
* @param accessor - the accessor from which the attributes will be retrieved
* @return object containing the accessor's attributes
*/
function getAccessorAttributes(accessor) {
if (typeof accessor === 'function') {
return defaultKeyAttributes;
}
return {
...defaultKeyAttributes,
...accessor
};
}
exports.compareItems = compareItems;
exports.rankItem = rankItem;
exports.rankings = rankings;
}));
//# sourceMappingURL=index.development.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
/**
* match-sorter-utils
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).MatchSorterUtils={})}(this,(function(e){"use strict";const n={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Ấ":"A","Ắ":"A","Ẳ":"A","Ẵ":"A","Ặ":"A","Æ":"AE","Ầ":"A","Ằ":"A","Ȃ":"A","Ç":"C","Ḉ":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ế":"E","Ḗ":"E","Ề":"E","Ḕ":"E","Ḝ":"E","Ȇ":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ḯ":"I","Ȋ":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ố":"O","Ṍ":"O","Ṓ":"O","Ȏ":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","ấ":"a","ắ":"a","ẳ":"a","ẵ":"a","ặ":"a","æ":"ae","ầ":"a","ằ":"a","ȃ":"a","ç":"c","ḉ":"c","è":"e","é":"e","ê":"e","ë":"e","ế":"e","ḗ":"e","ề":"e","ḕ":"e","ḝ":"e","ȇ":"e","ì":"i","í":"i","î":"i","ï":"i","ḯ":"i","ȋ":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ố":"o","ṍ":"o","ṓ":"o","ȏ":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Ĉ":"C","ĉ":"c","Ċ":"C","ċ":"c","Č":"C","č":"c","C̆":"C","c̆":"c","Ď":"D","ď":"d","Đ":"D","đ":"d","Ē":"E","ē":"e","Ĕ":"E","ĕ":"e","Ė":"E","ė":"e","Ę":"E","ę":"e","Ě":"E","ě":"e","Ĝ":"G","Ǵ":"G","ĝ":"g","ǵ":"g","Ğ":"G","ğ":"g","Ġ":"G","ġ":"g","Ģ":"G","ģ":"g","Ĥ":"H","ĥ":"h","Ħ":"H","ħ":"h","Ḫ":"H","ḫ":"h","Ĩ":"I","ĩ":"i","Ī":"I","ī":"i","Ĭ":"I","ĭ":"i","Į":"I","į":"i","İ":"I","ı":"i","IJ":"IJ","ij":"ij","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","Ḱ":"K","ḱ":"k","K̆":"K","k̆":"k","Ĺ":"L","ĺ":"l","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ŀ":"L","ŀ":"l","Ł":"l","ł":"l","Ḿ":"M","ḿ":"m","M̆":"M","m̆":"m","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","ʼn":"n","N̆":"N","n̆":"n","Ō":"O","ō":"o","Ŏ":"O","ŏ":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","P̆":"P","p̆":"p","Ŕ":"R","ŕ":"r","Ŗ":"R","ŗ":"r","Ř":"R","ř":"r","R̆":"R","r̆":"r","Ȓ":"R","ȓ":"r","Ś":"S","ś":"s","Ŝ":"S","ŝ":"s","Ş":"S","Ș":"S","ș":"s","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","ț":"t","Ț":"T","Ť":"T","ť":"t","Ŧ":"T","ŧ":"t","T̆":"T","t̆":"t","Ũ":"U","ũ":"u","Ū":"U","ū":"u","Ŭ":"U","ŭ":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ȗ":"U","ȗ":"u","V̆":"V","v̆":"v","Ŵ":"W","ŵ":"w","Ẃ":"W","ẃ":"w","X̆":"X","x̆":"x","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Y̆":"Y","y̆":"y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","ſ":"s","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Ǎ":"A","ǎ":"a","Ǐ":"I","ǐ":"i","Ǒ":"O","ǒ":"o","Ǔ":"U","ǔ":"u","Ǖ":"U","ǖ":"u","Ǘ":"U","ǘ":"u","Ǚ":"U","ǚ":"u","Ǜ":"U","ǜ":"u","Ứ":"U","ứ":"u","Ṹ":"U","ṹ":"u","Ǻ":"A","ǻ":"a","Ǽ":"AE","ǽ":"ae","Ǿ":"O","ǿ":"o","Þ":"TH","þ":"th","Ṕ":"P","ṕ":"p","Ṥ":"S","ṥ":"s","X́":"X","x́":"x","Ѓ":"Г","ѓ":"г","Ќ":"К","ќ":"к","A̋":"A","a̋":"a","E̋":"E","e̋":"e","I̋":"I","i̋":"i","Ǹ":"N","ǹ":"n","Ồ":"O","ồ":"o","Ṑ":"O","ṑ":"o","Ừ":"U","ừ":"u","Ẁ":"W","ẁ":"w","Ỳ":"Y","ỳ":"y","Ȁ":"A","ȁ":"a","Ȅ":"E","ȅ":"e","Ȉ":"I","ȉ":"i","Ȍ":"O","ȍ":"o","Ȑ":"R","ȑ":"r","Ȕ":"U","ȕ":"u","B̌":"B","b̌":"b","Č̣":"C","č̣":"c","Ê̌":"E","ê̌":"e","F̌":"F","f̌":"f","Ǧ":"G","ǧ":"g","Ȟ":"H","ȟ":"h","J̌":"J","ǰ":"j","Ǩ":"K","ǩ":"k","M̌":"M","m̌":"m","P̌":"P","p̌":"p","Q̌":"Q","q̌":"q","Ř̩":"R","ř̩":"r","Ṧ":"S","ṧ":"s","V̌":"V","v̌":"v","W̌":"W","w̌":"w","X̌":"X","x̌":"x","Y̌":"Y","y̌":"y","A̧":"A","a̧":"a","B̧":"B","b̧":"b","Ḑ":"D","ḑ":"d","Ȩ":"E","ȩ":"e","Ɛ̧":"E","ɛ̧":"e","Ḩ":"H","ḩ":"h","I̧":"I","i̧":"i","Ɨ̧":"I","ɨ̧":"i","M̧":"M","m̧":"m","O̧":"O","o̧":"o","Q̧":"Q","q̧":"q","U̧":"U","u̧":"u","X̧":"X","x̧":"x","Z̧":"Z","z̧":"z"},t=Object.keys(n).join("|"),r=new RegExp(t,"g");
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
const o={CASE_SENSITIVE_EQUAL:7,EQUAL:6,STARTS_WITH:5,WORD_STARTS_WITH:4,CONTAINS:3,ACRONYM:2,MATCHES:1,NO_MATCH:0};function s(e,n,t){return e=a(e,t),(n=a(n,t)).length>e.length?o.NO_MATCH:e===n?o.CASE_SENSITIVE_EQUAL:(e=e.toLowerCase())===(n=n.toLowerCase())?o.EQUAL:e.startsWith(n)?o.STARTS_WITH:e.includes(` ${n}`)?o.WORD_STARTS_WITH:e.includes(n)?o.CONTAINS:1===n.length?o.NO_MATCH:function(e){let n="";return e.split(" ").forEach((e=>{e.split("-").forEach((e=>{n+=e.substr(0,1)}))})),n}(e).includes(n)?o.ACRONYM:function(e,n){let t=0,r=0;function s(e,n,r){for(let o=r,s=n.length;o<s;o++){if(n[o]===e)return t+=1,o+1}return-1}function a(e){const r=1/e,s=t/n.length;return o.MATCHES+s*r}const i=s(n[0],e,0);if(i<0)return o.NO_MATCH;r=i;for(let t=1,a=n.length;t<a;t++){r=s(n[t],e,r);if(!(r>-1))return o.NO_MATCH}return a(r-i)}(e,n)}function a(e,t){let{keepDiacritics:o}=t;return e=`${e}`,o||(e=e.replace(r,(e=>n[e]))),e}function i(e,n){let t=n;"object"==typeof n&&(t=n.accessor);const r=t(e);return null==r?[]:Array.isArray(r)?r:[String(r)]}const u={maxRanking:1/0,minRanking:-1/0};function c(e){return"function"==typeof e?u:{...u,...e}}e.compareItems=function(e,n){return e.rank===n.rank?0:e.rank>n.rank?-1:1},e.rankItem=function(e,n,t){var r;if((t=t||{}).threshold=null!=(r=t.threshold)?r:o.MATCHES,!t.accessors){const r=s(e,n,t);return{rankedValue:e,rank:r,accessorIndex:-1,accessorThreshold:t.threshold,passed:r>=t.threshold}}const a=function(e,n){const t=[];for(let r=0,o=n.length;r<o;r++){const o=n[r],s=c(o),a=i(e,o);for(let e=0,n=a.length;e<n;e++)t.push({itemValue:a[e],attributes:s})}return t}(e,t.accessors),u={rankedValue:e,rank:o.NO_MATCH,accessorIndex:-1,accessorThreshold:t.threshold,passed:!1};for(let e=0;e<a.length;e++){const r=a[e];let i=s(r.itemValue,n,t);const{minRanking:c,maxRanking:l,threshold:A=t.threshold}=r.attributes;i<c&&i>=o.MATCHES?i=c:i>l&&(i=l),i=Math.min(i,l),i>=A&&i>u.rank&&(u.rank=i,u.passed=!0,u.accessorIndex=e,u.accessorThreshold=A,u.rankedValue=r.itemValue)}return u},e.rankings=o}));
//# sourceMappingURL=index.production.js.map

File diff suppressed because one or more lines are too long

54
node_modules/@tanstack/match-sorter-utils/package.json generated vendored Normal file
View File

@@ -0,0 +1,54 @@
{
"name": "@tanstack/match-sorter-utils",
"version": "8.19.4",
"description": "A fork of match-sorter with separated filtering and sorting phases",
"contributors": [
"Kent C. Dodds",
"Tanner Linsley"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/TanStack/table.git",
"directory": "packages/match-sorter-utils"
},
"homepage": "https://tanstack.com/table",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"keywords": [
"react",
"table",
"match-sorter",
"utils",
"split",
"separate",
"datagrid"
],
"type": "commonjs",
"module": "build/lib/index.esm.js",
"main": "build/lib/index.js",
"types": "build/lib/index.d.ts",
"exports": {
".": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.mjs",
"default": "./build/lib/index.js"
},
"./package.json": "./package.json"
},
"sideEffects": false,
"engines": {
"node": ">=12"
},
"files": [
"build/lib/*",
"build/umd/*",
"src"
],
"dependencies": {
"remove-accents": "0.5.0"
},
"scripts": {}
}

379
node_modules/@tanstack/match-sorter-utils/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,379 @@
/**
* @name match-sorter
* @license MIT license.
* @copyright (c) 2099 Kent C. Dodds
* @author Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)
*/
// This is a fork of match-sorter. Instead of offering
// a unified API for filtering and sorting in a single pass,
// match-sorter-utils provides the lower-level utilities of
// ranking items and comparing ranks in a way that can
// be incrementally applied to a system rather than
// all-at-once.
// 1. Use the rankItem function to rank an item
// 2. Use the resulting rankingInfo.passed to filter
// 3. Use the resulting rankingInfo.rank to sort
// For bundling purposes (mainly remove-accents not being esm safe/ready),
// we've also hard-coded remove-accents into this source.
// The remove-accents package is still included as a dependency
// for attribution purposes, but it will not be imported and bundled.
import { removeAccents } from './remove-accents'
export type AccessorAttributes = {
threshold?: Ranking
maxRanking: Ranking
minRanking: Ranking
}
export interface RankingInfo {
rankedValue: any
rank: Ranking
accessorIndex: number
accessorThreshold: Ranking | undefined
passed: boolean
}
export interface AccessorOptions<TItem> {
accessor: AccessorFn<TItem>
threshold?: Ranking
maxRanking?: Ranking
minRanking?: Ranking
}
export type AccessorFn<TItem> = (item: TItem) => string | Array<string>
export type Accessor<TItem> = AccessorFn<TItem> | AccessorOptions<TItem>
export interface RankItemOptions<TItem = unknown> {
accessors?: ReadonlyArray<Accessor<TItem>>
threshold?: Ranking
keepDiacritics?: boolean
}
export const rankings = {
CASE_SENSITIVE_EQUAL: 7,
EQUAL: 6,
STARTS_WITH: 5,
WORD_STARTS_WITH: 4,
CONTAINS: 3,
ACRONYM: 2,
MATCHES: 1,
NO_MATCH: 0,
} as const
export type Ranking = (typeof rankings)[keyof typeof rankings]
/**
* 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 {String} value - the value to rank against
* @param {Object} options - options to control the ranking
* @return {{rank: Number, accessorIndex: Number, accessorThreshold: Number}} - the highest ranking
*/
export function rankItem<TItem>(
item: TItem,
value: string,
options?: RankItemOptions<TItem>
): RankingInfo {
options = options || {}
options.threshold = options.threshold ?? rankings.MATCHES
if (!options.accessors) {
// if keys is not specified, then we assume the item given is ready to be matched
const rank = getMatchRanking(item as unknown as string, value, options)
return {
// ends up being duplicate of 'item' in matches but consistent
rankedValue: item,
rank,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: rank >= options.threshold,
}
}
const valuesToRank = getAllValuesToRank(item, options.accessors)
const rankingInfo: RankingInfo = {
rankedValue: item,
rank: rankings.NO_MATCH as Ranking,
accessorIndex: -1,
accessorThreshold: options.threshold,
passed: false,
}
for (let i = 0; i < valuesToRank.length; i++) {
const rankValue = valuesToRank[i]!
let newRank = getMatchRanking(rankValue.itemValue, value, options)
const {
minRanking,
maxRanking,
threshold = options.threshold,
} = rankValue.attributes
if (newRank < minRanking && newRank >= rankings.MATCHES) {
newRank = minRanking
} else if (newRank > maxRanking) {
newRank = maxRanking
}
newRank = Math.min(newRank, maxRanking) as Ranking
if (newRank >= threshold && newRank > rankingInfo.rank) {
rankingInfo.rank = newRank
rankingInfo.passed = true
rankingInfo.accessorIndex = i
rankingInfo.accessorThreshold = threshold
rankingInfo.rankedValue = rankValue.itemValue
}
}
return rankingInfo
}
/**
* 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<TItem>(
testString: string,
stringToRank: string,
options: RankItemOptions<TItem>
): Ranking {
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
}
// Lower casing before further comparison
testString = testString.toLowerCase()
stringToRank = stringToRank.toLowerCase()
// case insensitive equals
if (testString === stringToRank) {
return rankings.EQUAL
}
// starts with
if (testString.startsWith(stringToRank)) {
return rankings.STARTS_WITH
}
// word starts with
if (testString.includes(` ${stringToRank}`)) {
return rankings.WORD_STARTS_WITH
}
// contains
if (testString.includes(stringToRank)) {
return rankings.CONTAINS
} 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).includes(stringToRank)) {
return rankings.ACRONYM
}
// 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: string): string {
let acronym = ''
const wordsInString = string.split(' ')
wordsInString.forEach(wordInString => {
const splitByHyphenWords = wordInString.split('-')
splitByHyphenWords.forEach(splitByHyphenWord => {
acronym += splitByHyphenWord.substr(0, 1)
})
})
return acronym
}
/**
* 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: string,
stringToRank: string
): Ranking {
let matchingInOrderCharCount = 0
let charNumber = 0
function findMatchingCharacter(
matchChar: undefined | string,
string: string,
index: number
) {
for (let j = index, J = string.length; j < J; j++) {
const stringChar = string[j]
if (stringChar === matchChar) {
matchingInOrderCharCount += 1
return j + 1
}
}
return -1
}
function getRanking(spread: number) {
const spreadPercentage = 1 / spread
const inOrderPercentage = matchingInOrderCharCount / stringToRank.length
const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage
return ranking as Ranking
}
const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0)
if (firstIndex < 0) {
return rankings.NO_MATCH
}
charNumber = firstIndex
for (let i = 1, I = stringToRank.length; i < I; i++) {
const matchChar = stringToRank[i]
charNumber = findMatchingCharacter(matchChar, testString, charNumber)
const found = charNumber > -1
if (!found) {
return rankings.NO_MATCH
}
}
const spread = charNumber - firstIndex
return getRanking(spread)
}
/**
* Sorts items that have a rank, index, and accessorIndex
* @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
*/
export function compareItems<TItem>(a: RankingInfo, b: RankingInfo): number {
return a.rank === b.rank ? 0 : a.rank > b.rank ? -1 : 1
}
/**
* 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<TItem>(
value: string,
{ keepDiacritics }: RankItemOptions<TItem>
): string {
// value might not actually be a string at this point (we don't get to choose)
// so part of preparing the value for comparison is ensure that it is a string
value = `${value}` // toString
if (!keepDiacritics) {
value = removeAccents(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<TItem>(
item: TItem,
accessor: Accessor<TItem>
): Array<string> {
let accessorFn = accessor as AccessorFn<TItem>
if (typeof accessor === 'object') {
accessorFn = accessor.accessor
}
const value = accessorFn(item)
// because `value` can also be undefined
if (value == null) {
return []
}
if (Array.isArray(value)) {
return value
}
return [String(value)]
}
/**
* Gets all the values for the given keys in the given item and returns an array of those values
* @param item - the item from which the values will be retrieved
* @param keys - the keys to use to retrieve the values
* @return objects with {itemValue, attributes}
*/
function getAllValuesToRank<TItem>(
item: TItem,
accessors: ReadonlyArray<Accessor<TItem>>
) {
const allValues: Array<{
itemValue: string
attributes: AccessorAttributes
}> = []
for (let j = 0, J = accessors.length; j < J; j++) {
const accessor = accessors[j]!
const attributes = getAccessorAttributes(accessor)
const itemValues = getItemValues(item, accessor)
for (let i = 0, I = itemValues.length; i < I; i++) {
allValues.push({
itemValue: itemValues[i]!,
attributes,
})
}
}
return allValues
}
const defaultKeyAttributes = {
maxRanking: Infinity as Ranking,
minRanking: -Infinity as Ranking,
}
/**
* Gets all the attributes for the given accessor
* @param accessor - the accessor from which the attributes will be retrieved
* @return object containing the accessor's attributes
*/
function getAccessorAttributes<TItem>(
accessor: Accessor<TItem>
): AccessorAttributes {
if (typeof accessor === 'function') {
return defaultKeyAttributes
}
return { ...defaultKeyAttributes, ...accessor }
}

View File

@@ -0,0 +1,410 @@
const characterMap: Record<string, string> = {
À: 'A',
Á: 'A',
Â: 'A',
Ã: 'A',
Ä: 'A',
Å: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
: 'A',
Æ: 'AE',
: 'A',
: 'A',
Ȃ: 'A',
Ç: 'C',
: 'C',
È: 'E',
É: 'E',
Ê: 'E',
Ë: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
: 'E',
Ȇ: 'E',
Ì: 'I',
Í: 'I',
Î: 'I',
Ï: 'I',
: 'I',
Ȋ: 'I',
Ð: 'D',
Ñ: 'N',
Ò: 'O',
Ó: 'O',
Ô: 'O',
Õ: 'O',
Ö: 'O',
Ø: 'O',
: 'O',
: 'O',
: 'O',
Ȏ: 'O',
Ù: 'U',
Ú: 'U',
Û: 'U',
Ü: 'U',
Ý: 'Y',
à: 'a',
á: 'a',
â: 'a',
ã: 'a',
ä: 'a',
å: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
: 'a',
æ: 'ae',
: 'a',
: 'a',
ȃ: 'a',
ç: 'c',
: 'c',
è: 'e',
é: 'e',
ê: 'e',
ë: 'e',
ế: 'e',
: 'e',
: 'e',
: 'e',
: 'e',
ȇ: 'e',
ì: 'i',
í: 'i',
î: 'i',
ï: 'i',
: 'i',
ȋ: 'i',
ð: 'd',
ñ: 'n',
ò: 'o',
ó: 'o',
ô: 'o',
õ: 'o',
ö: 'o',
ø: 'o',
: 'o',
: 'o',
: 'o',
ȏ: 'o',
ù: 'u',
ú: 'u',
û: 'u',
ü: 'u',
ý: 'y',
ÿ: 'y',
Ā: 'A',
ā: 'a',
Ă: 'A',
ă: 'a',
Ą: 'A',
ą: 'a',
Ć: 'C',
ć: 'c',
Ĉ: 'C',
ĉ: 'c',
Ċ: 'C',
ċ: 'c',
Č: 'C',
č: 'c',
: 'C',
: 'c',
Ď: 'D',
ď: 'd',
Đ: 'D',
đ: 'd',
Ē: 'E',
ē: 'e',
Ĕ: 'E',
ĕ: 'e',
Ė: 'E',
ė: 'e',
Ę: 'E',
ę: 'e',
Ě: 'E',
ě: 'e',
Ĝ: 'G',
Ǵ: 'G',
ĝ: 'g',
ǵ: 'g',
Ğ: 'G',
ğ: 'g',
Ġ: 'G',
ġ: 'g',
Ģ: 'G',
ģ: 'g',
Ĥ: 'H',
ĥ: 'h',
Ħ: 'H',
ħ: 'h',
: 'H',
: 'h',
Ĩ: 'I',
ĩ: 'i',
Ī: 'I',
ī: 'i',
Ĭ: 'I',
ĭ: 'i',
Į: 'I',
į: 'i',
İ: 'I',
ı: 'i',
IJ: 'IJ',
ij: 'ij',
Ĵ: 'J',
ĵ: 'j',
Ķ: 'K',
ķ: 'k',
: 'K',
: 'k',
: 'K',
: 'k',
Ĺ: 'L',
ĺ: 'l',
Ļ: 'L',
ļ: 'l',
Ľ: 'L',
ľ: 'l',
Ŀ: 'L',
ŀ: 'l',
Ł: 'l',
ł: 'l',
: 'M',
ḿ: 'm',
: 'M',
: 'm',
Ń: 'N',
ń: 'n',
Ņ: 'N',
ņ: 'n',
Ň: 'N',
ň: 'n',
ʼn: 'n',
: 'N',
: 'n',
Ō: 'O',
ō: 'o',
Ŏ: 'O',
ŏ: 'o',
Ő: 'O',
ő: 'o',
Œ: 'OE',
œ: 'oe',
: 'P',
: 'p',
Ŕ: 'R',
ŕ: 'r',
Ŗ: 'R',
ŗ: 'r',
Ř: 'R',
ř: 'r',
: 'R',
: 'r',
Ȓ: 'R',
ȓ: 'r',
Ś: 'S',
ś: 's',
Ŝ: 'S',
ŝ: 's',
Ş: 'S',
Ș: 'S',
ș: 's',
ş: 's',
Š: 'S',
š: 's',
Ţ: 'T',
ţ: 't',
ț: 't',
Ț: 'T',
Ť: 'T',
ť: 't',
Ŧ: 'T',
ŧ: 't',
: 'T',
: 't',
Ũ: 'U',
ũ: 'u',
Ū: 'U',
ū: 'u',
Ŭ: 'U',
ŭ: 'u',
Ů: 'U',
ů: 'u',
Ű: 'U',
ű: 'u',
Ų: 'U',
ų: 'u',
Ȗ: 'U',
ȗ: 'u',
: 'V',
: 'v',
Ŵ: 'W',
ŵ: 'w',
: 'W',
: 'w',
: 'X',
: 'x',
Ŷ: 'Y',
ŷ: 'y',
Ÿ: 'Y',
: 'Y',
: 'y',
Ź: 'Z',
ź: 'z',
Ż: 'Z',
ż: 'z',
Ž: 'Z',
ž: 'z',
ſ: 's',
ƒ: 'f',
Ơ: 'O',
ơ: 'o',
Ư: 'U',
ư: 'u',
Ǎ: 'A',
ǎ: 'a',
Ǐ: 'I',
ǐ: 'i',
Ǒ: 'O',
ǒ: 'o',
Ǔ: 'U',
ǔ: 'u',
Ǖ: 'U',
ǖ: 'u',
Ǘ: 'U',
ǘ: 'u',
Ǚ: 'U',
ǚ: 'u',
Ǜ: 'U',
ǜ: 'u',
: 'U',
: 'u',
: 'U',
: 'u',
Ǻ: 'A',
ǻ: 'a',
Ǽ: 'AE',
ǽ: 'ae',
Ǿ: 'O',
ǿ: 'o',
Þ: 'TH',
þ: 'th',
: 'P',
: 'p',
: 'S',
: 's',
: 'X',
: 'x',
Ѓ: 'Г',
ѓ: 'г',
Ќ: 'К',
ќ: 'к',
: 'A',
: 'a',
: 'E',
: 'e',
: 'I',
: 'i',
Ǹ: 'N',
ǹ: 'n',
: 'O',
: 'o',
: 'O',
: 'o',
: 'U',
: 'u',
: 'W',
: 'w',
: 'Y',
: 'y',
Ȁ: 'A',
ȁ: 'a',
Ȅ: 'E',
ȅ: 'e',
Ȉ: 'I',
ȉ: 'i',
Ȍ: 'O',
ȍ: 'o',
Ȑ: 'R',
ȑ: 'r',
Ȕ: 'U',
ȕ: 'u',
: 'B',
: 'b',
Č̣: 'C',
č̣: 'c',
Ê̌: 'E',
ê̌: 'e',
: 'F',
: 'f',
Ǧ: 'G',
ǧ: 'g',
Ȟ: 'H',
ȟ: 'h',
: 'J',
ǰ: 'j',
Ǩ: 'K',
ǩ: 'k',
: 'M',
: 'm',
: 'P',
: 'p',
: 'Q',
: 'q',
Ř̩: 'R',
ř̩: 'r',
: 'S',
: 's',
: 'V',
: 'v',
: 'W',
: 'w',
: 'X',
: 'x',
: 'Y',
: 'y',
: 'A',
: 'a',
: 'B',
: 'b',
: 'D',
: 'd',
Ȩ: 'E',
ȩ: 'e',
Ɛ̧: 'E',
ɛ̧: 'e',
: 'H',
: 'h',
: 'I',
: 'i',
Ɨ̧: 'I',
ɨ̧: 'i',
: 'M',
: 'm',
: 'O',
: 'o',
: 'Q',
: 'q',
: 'U',
: 'u',
: 'X',
: 'x',
: 'Z',
: 'z',
}
const chars = Object.keys(characterMap).join('|')
const allAccents = new RegExp(chars, 'g')
export function removeAccents(str: string) {
return str.replace(allAccents, match => {
return characterMap[match]!
})
}