Alex Rudenko | d04dd45 | 2024-02-27 08:25:35 | [diff] [blame] | 1 | const SemVer = require('../classes/semver') |
| 2 | const parse = require('./parse') |
| 3 | const { safeRe: re, t } = require('../internal/re') |
| 4 | |
| 5 | const coerce = (version, options) => { |
| 6 | if (version instanceof SemVer) { |
| 7 | return version |
| 8 | } |
| 9 | |
| 10 | if (typeof version === 'number') { |
| 11 | version = String(version) |
| 12 | } |
| 13 | |
| 14 | if (typeof version !== 'string') { |
| 15 | return null |
| 16 | } |
| 17 | |
| 18 | options = options || {} |
| 19 | |
| 20 | let match = null |
| 21 | if (!options.rtl) { |
| 22 | match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]) |
| 23 | } else { |
| 24 | // Find the right-most coercible string that does not share |
| 25 | // a terminus with a more left-ward coercible string. |
| 26 | // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' |
| 27 | // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4' |
| 28 | // |
| 29 | // Walk through the string checking with a /g regexp |
| 30 | // Manually set the index so as to pick up overlapping matches. |
| 31 | // Stop when we get a match that ends at the string end, since no |
| 32 | // coercible string can be more right-ward without the same terminus. |
| 33 | const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL] |
| 34 | let next |
| 35 | while ((next = coerceRtlRegex.exec(version)) && |
| 36 | (!match || match.index + match[0].length !== version.length) |
| 37 | ) { |
| 38 | if (!match || |
| 39 | next.index + next[0].length !== match.index + match[0].length) { |
| 40 | match = next |
| 41 | } |
| 42 | coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length |
| 43 | } |
| 44 | // leave it in a clean state |
| 45 | coerceRtlRegex.lastIndex = -1 |
| 46 | } |
| 47 | |
| 48 | if (match === null) { |
| 49 | return null |
| 50 | } |
| 51 | |
| 52 | const major = match[2] |
| 53 | const minor = match[3] || '0' |
| 54 | const patch = match[4] || '0' |
| 55 | const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : '' |
| 56 | const build = options.includePrerelease && match[6] ? `+${match[6]}` : '' |
| 57 | |
| 58 | return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options) |
| 59 | } |
| 60 | module.exports = coerce |