coerce.js 1.5 KB

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