UNPKG

tiny-version-compare

Version:

Compare two software versions, with any number of points (<1KB)

87 lines (70 loc) 1.82 kB
const splitDev = v => String(v).split('-'); const splitSub = v => String(v) .replace(/^[vr]/, '') // Drop initial 'v' or 'r' .replace(/([a-z]+)/gi, '.$1.') // Sort each word separately .replace(/\.+/g, '.') // Trim repeating separators .split('.'); // Development versions are considered "negative", // but localeCompare doesn't handle negative numbers. // This offset is applied to reset the lowest development version to 0 const offset = part => { // Not numeric, return as is if (isNaN(part)) { return part; } return 5 + Number(part); }; const parseSub = part => { // Missing, consider it zero if (typeof part === 'undefined') { return 0; } // Sort development versions switch (part.toLowerCase()) { case 'dev': return -5; case 'alpha': case 'a': return -4; case 'beta': case 'b': return -3; case 'rc': case 'c': return -2; case 'pre': return -1; default: } // Return as is, it’s either a plain number or text that will be sorted alphabetically return part; }; function compareSubs(a, b) { for (let i = 0; i < a.length || i < b.length; i++) { const ai = offset(parseSub(a[i])); const bi = offset(parseSub(b[i])); const sort = String(ai).localeCompare(bi, 'en', { numeric: true, }); // Once the difference is found, // stop comparing the rest of the parts if (sort !== 0) { return sort; } } return 0; } export default function compareVersions(a, b) { if (a === b) { return 0; } const [aMain, aDev] = splitDev(a).map(splitSub); const [bMain, bDev] = splitDev(b).map(splitSub); const mainSort = compareSubs(aMain, bMain); if (mainSort !== 0) { return mainSort; } if (aDev && !bDev) { return -1; } if (!aDev && bDev) { return 1; } if (aDev && bDev) { return compareSubs(aDev, bDev); } // No difference found return 0; }