'use strict'; var alphabet; var alphabetIndexMap; var alphabetIndexMapLength = 0; function isNumberCode(code) { return code >= 48 && code <= 57; } function naturalCompare(a, b) { var lengthA = (a += '').length; var lengthB = (b += '').length; var aIndex = 0; var bIndex = 0; while (aIndex < lengthA && bIndex < lengthB) { var charCodeA = a.charCodeAt(aIndex); var charCodeB = b.charCodeAt(bIndex); if (isNumberCode(charCodeA)) { if (!isNumberCode(charCodeB)) { return charCodeA - charCodeB; } var numStartA = aIndex; var numStartB = bIndex; while (charCodeA === 48 && ++numStartA < lengthA) { charCodeA = a.charCodeAt(numStartA); } while (charCodeB === 48 && ++numStartB < lengthB) { charCodeB = b.charCodeAt(numStartB); } var numEndA = numStartA; var numEndB = numStartB; while (numEndA < lengthA && isNumberCode(a.charCodeAt(numEndA))) { ++numEndA; } while (numEndB < lengthB && isNumberCode(b.charCodeAt(numEndB))) { ++numEndB; } var difference = numEndA - numStartA - numEndB + numStartB; // numA length - numB length if (difference) { return difference; } while (numStartA < numEndA) { difference = a.charCodeAt(numStartA++) - b.charCodeAt(numStartB++); if (difference) { return difference; } } aIndex = numEndA; bIndex = numEndB; continue; } if (charCodeA !== charCodeB) { if ( charCodeA < alphabetIndexMapLength && charCodeB < alphabetIndexMapLength && alphabetIndexMap[charCodeA] !== -1 && alphabetIndexMap[charCodeB] !== -1 ) { return alphabetIndexMap[charCodeA] - alphabetIndexMap[charCodeB]; } return charCodeA - charCodeB; } ++aIndex; ++bIndex; } return lengthA - lengthB; } naturalCompare.caseInsensitive = naturalCompare.i = function(a, b) { return naturalCompare(('' + a).toLowerCase(), ('' + b).toLowerCase()); }; Object.defineProperties(naturalCompare, { alphabet: { get: function() { return alphabet; }, set: function(value) { alphabet = value; alphabetIndexMap = []; var i = 0; if (alphabet) { for (; i < alphabet.length; i++) { alphabetIndexMap[alphabet.charCodeAt(i)] = i; } } alphabetIndexMapLength = alphabetIndexMap.length; for (i = 0; i < alphabetIndexMapLength; i++) { if (alphabetIndexMap[i] === undefined) { alphabetIndexMap[i] = -1; } } }, }, }); module.exports = naturalCompare;