|
66 | 66 | const activePath = ref<string | null>(null) |
67 | 67 | const pendingPath = ref<string | null>(null) |
68 | 68 |
|
| 69 | + function compareSemver (a: string, b: string): number { |
| 70 | + const [aMain, aPre] = a.split('-', 2) |
| 71 | + const [bMain, bPre] = b.split('-', 2) |
| 72 | + const aParts = aMain.split('.').map(Number) |
| 73 | + const bParts = bMain.split('.').map(Number) |
| 74 | +
|
| 75 | + for (let i = 0; i < 3; i++) { |
| 76 | + if (aParts[i] !== bParts[i]) return (aParts[i] ?? 0) - (bParts[i] ?? 0) |
| 77 | + } |
| 78 | + if (aPre === bPre) return 0 |
| 79 | + if (aPre === undefined) return 1 |
| 80 | + if (bPre === undefined) return -1 |
| 81 | + return aPre < bPre ? -1 : 1 |
| 82 | + } |
| 83 | +
|
| 84 | + const isPrerelease = (v: string): boolean => v.includes('-') |
| 85 | + const baseVersion = (v: string): string => v.split('-', 1)[0] |
| 86 | +
|
| 87 | + async function resolvePrevVersion (name: string, anchorVersion: string): Promise<string> { |
| 88 | + const [{ versions }, { version }] = await Promise.all([ |
| 89 | + listVersions(name), |
| 90 | + resolveTarball(name, anchorVersion), |
| 91 | + ]) |
| 92 | +
|
| 93 | + const anchorIsPrerelease = isPrerelease(version) |
| 94 | + const prereleaseAllowed = (v: string) => anchorIsPrerelease && baseVersion(v) === baseVersion(version) |
| 95 | + const candidates = versions.filter(v => |
| 96 | + (!isPrerelease(v) || prereleaseAllowed(v)) && compareSemver(v, version) < 0, |
| 97 | + ) |
| 98 | +
|
| 99 | + return candidates.toSorted(compareSemver).at(-1) ?? 'latest' |
| 100 | + } |
| 101 | +
|
69 | 102 | // ---- URL params (?a=&b=, optional &av=&bv=&path=) — read on load, write on compare. |
70 | | - function readUrl () { |
| 103 | + async function readUrl () { |
71 | 104 | const p = new URLSearchParams(globalThis.location.search) |
72 | 105 | if (p.get('a')) a.name = p.get('a')! |
73 | 106 | if (p.get('b')) b.name = p.get('b')! |
74 | | - if (p.get('av')) a.version = p.get('av')! |
75 | 107 | if (p.get('bv')) b.version = p.get('bv')! |
| 108 | + const av = p.get('av') |
| 109 | + if (av === 'prev') { |
| 110 | + a.version = a.name === b.name ? await resolvePrevVersion(a.name, b.version).catch(() => 'latest') : 'latest' |
| 111 | + } else if (av) { |
| 112 | + a.version = av |
| 113 | + } |
76 | 114 | pendingPath.value = p.get('path') |
77 | 115 | } |
78 | 116 |
|
|
0 commit comments