123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- /**
- * ESM Module: Natural Compare Function
- */
- function naturalCompareFactory(options) {
- function splitString(str) {
- return str
- .replace(tokenRegex, "\0$1\0")
- .replace(/\0$/, "")
- .replace(/^\0/, "")
- .split("\0");
- }
- function parseToken(token, length) {
- return (!token.match(leadingZeroRegex) || length === 1) && parseFloat(token) ||
- token.replace(whitespaceRegex, " ").replace(trimRegex, "") ||
- 0;
- }
- options = options || {};
- const leadingZeroRegex = /^0/,
- whitespaceRegex = /\s+/g,
- trimRegex = /^\s+|\s+$/g,
- unicodeRegex = /[^\x00-\x80]/,
- hexRegex = /^0x[0-9a-f]+$/i,
- tokenRegex = /(0x[\da-fA-F]+|(^[\+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|\d+)/g,
- dateRegex = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
- toLowerCase = String.prototype.toLocaleLowerCase || String.prototype.toLowerCase,
- ascending = options.desc ? -1 : 1,
- descending = -ascending,
- preprocess = options.insensitive
- ? (str) => toLowerCase.call("" + str).replace(trimRegex, "")
- : (str) => ("" + str).replace(trimRegex, "");
- return function compareStrings(a, b) {
- const strA = preprocess(a);
- const strB = preprocess(b);
- if (!strA && !strB) return 0;
- if (!strA && strB) return descending;
- if (strA && !strB) return ascending;
- const tokensA = splitString(strA);
- const tokensB = splitString(strB);
- const hexMatchA = strA.match(hexRegex);
- const hexMatchB = strB.match(hexRegex);
- const parsedDateA = hexMatchA && hexMatchB ? parseInt(hexMatchA[0], 16) : tokensA.length > 1 ? Date.parse(strA) : null;
- const parsedDateB = hexMatchA && hexMatchB ? parseInt(hexMatchB[0], 16) : parsedDateA && strB.match(dateRegex) ? Date.parse(strB) : null;
- if (parsedDateA && parsedDateB) {
- if (parsedDateA === parsedDateB) return 0;
- return parsedDateA < parsedDateB ? descending : ascending;
- }
- const maxTokens = Math.max(tokensA.length, tokensB.length);
- for (let i = 0; i < maxTokens; i++) {
- const tokenA = parseToken(tokensA[i] || "", tokensA.length);
- const tokenB = parseToken(tokensB[i] || "", tokensB.length);
- if (isNaN(tokenA) !== isNaN(tokenB)) return isNaN(tokenA) ? ascending : descending;
- if (unicodeRegex.test(tokenA + tokenB) && tokenA.localeCompare) {
- // const localeComparison = tokenA.localeCompare(tokenB);
- const localeComparison = tokenA.localeCompare(tokenB, 'zh-CN', {numeric: true, sensitivity: 'base'});
- if (localeComparison !== 0) return localeComparison * ascending;
- }
- if (tokenA < tokenB) return descending;
- if (tokenA > tokenB) return ascending;
- if ("" + tokenA < "" + tokenB) return descending;
- if ("" + tokenA > "" + tokenB) return ascending;
- }
- return 0;
- };
- }
- export default naturalCompareFactory;
- // 使用工厂函数创建比较器
- export const naturalCompare = naturalCompareFactory({desc: false, insensitive: true});
|