6.7.0 - Alpha5 - 修复版本比较时 Canary 后缀的权重错误

This commit is contained in:
SuperMonster003
2025-09-12 13:56:05 +08:00
parent 685fc46850
commit c5d02b399f
4 changed files with 361 additions and 203 deletions

View File

@@ -1,6 +1,57 @@
// utils/versioning.mjs
const SUFFIX_PRIORITY = { '': 10, 'alpha': 1, 'beta': 2, 'canary': 3, 'rc': 5 };
const SUFFIX_PRIORITY = {
// 预发布 (越小越靠前)
'canary': 1, 'nightly': 1, 'snapshot': 1, 'dev': 1,
'pre-alpha': 2, 'prealpha': 2, 'preview': 2, 'eap': 2, 'milestone': 2,
'alpha': 3,
'beta': 4,
'rc': 5,
// 正式/稳定
'': 10, 'stable': 10, 'ga': 10, 'final': 10, 'release': 10, 'lts': 10,
};
/**
* 统一后缀别名到规范键.
*
* @param {string} nameRaw
* @return {string}
*/
function normalizeSuffixName(nameRaw) {
const n = String(nameRaw || '').toLowerCase();
switch (n) {
case 'a':
return 'alpha';
case 'b':
return 'beta';
case 'cr':
return 'rc';
case 'm':
return 'milestone';
case 'pre':
return 'preview';
case 'canary':
case 'nightly':
case 'snapshot':
case 'dev':
case 'pre-alpha':
case 'prealpha':
case 'preview':
case 'eap':
case 'milestone':
case 'alpha':
case 'beta':
case 'rc':
case 'stable':
case 'ga':
case 'final':
case 'release':
case 'lts':
return n;
default:
return n; // 未知后缀维持原样, 优先级将落在默认分支
}
}
/**
* @param {string} version
@@ -16,15 +67,18 @@ export function toVersionParts(version) {
return num;
});
// 解析后缀, 如 Alpha2 / Beta / RC1 等; 默认数字为 1
const suffixPattern = /([A-Za-z]+)\s*(\d*)|([A-Za-z]*)\s*(\d+)/;
// 解析后缀, 支持 rc1 / rc 1 / rc.1 / RC1 等; 默认数字为 1
const suffixPattern = /([A-Za-z]+)[\s._-]*(\d*)|([A-Za-z]*)[\s._-]*(\d+)/;
const suffixStr = parts[1] || '';
const m = suffixStr.match(suffixPattern);
if (!m) return [ numberParts, [ '', 0 ] ];
const suffixName = m[1] || '';
const suffixNumber = parseInt(m[2] || '1', 10);
return [ numberParts, [ suffixName, Number.isNaN(suffixNumber) ? 1 : suffixNumber ] ];
const rawName = (m[1] ?? m[3] ?? '');
const rawNum = (m[2] ?? m[4] ?? '');
const suffixName = normalizeSuffixName(rawName);
const suffixNumberParsed = parseInt(rawNum || '1', 10);
const suffixNumber = Number.isNaN(suffixNumberParsed) ? 1 : suffixNumberParsed;
return [ numberParts, [ suffixName, suffixNumber ] ];
}
/**
@@ -50,8 +104,8 @@ export function compareVersionParts(a, b) {
export function compareVersionSuffix(s1, s2) {
const [ name1Raw, num1 ] = s1;
const [ name2Raw, num2 ] = s2;
const name1 = name1Raw.toLowerCase();
const name2 = name2Raw.toLowerCase();
const name1 = normalizeSuffixName(name1Raw);
const name2 = normalizeSuffixName(name2Raw);
const p1 = SUFFIX_PRIORITY[name1] ?? Number.MAX_SAFE_INTEGER;
const p2 = SUFFIX_PRIORITY[name2] ?? Number.MAX_SAFE_INTEGER;
if (p1 !== p2) return p1 > p2 ? 1 : -1;
@@ -83,6 +137,16 @@ export function compareVersionStringsDescending(v1, v2) {
return cmp !== 0 ? cmp : compareVersionSuffix(s2, s1);
}
/**
* @param {string} v
* @return {boolean}
*/
export function isVersionStable(v) {
const [ _, [ suffixName ] ] = toVersionParts(v);
const normalizedName = normalizeSuffixName(suffixName);
return (SUFFIX_PRIORITY[normalizedName] ?? Number.MAX_SAFE_INTEGER) === 10;
}
/**
* @param {string} v
* @param {Object} options
@@ -91,7 +155,6 @@ export function compareVersionStringsDescending(v1, v2) {
* @return {boolean}
*/
export function isVersionInRange(v, { min, max } = {}) {
return (min !== null && compareVersionStrings(v, min) >= 0)
&& (max !== null && compareVersionStrings(v, max) <= 0);
}
return (min == null || compareVersionStrings(v, min) >= 0)
&& (max == null || compareVersionStrings(v, max) <= 0);
}