semver 6.1.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -60,6 +60,12 @@ Options:
60
60
  Coerce a string into SemVer if possible
61
61
  (does not imply --loose)
62
62
 
63
+ --rtl
64
+ Coerce version strings right to left
65
+
66
+ --ltr
67
+ Coerce version strings left to right (default)
68
+
63
69
  Program exits successfully if any valid version satisfies
64
70
  all supplied ranges, and prints all satisfying versions.
65
71
 
@@ -399,16 +405,39 @@ range, use the `satisfies(version, range)` function.
399
405
 
400
406
  ### Coercion
401
407
 
402
- * `coerce(version)`: Coerces a string to semver if possible
403
-
404
- This aims to provide a very forgiving translation of a non-semver
405
- string to semver. It looks for the first digit in a string, and
406
- consumes all remaining characters which satisfy at least a partial semver
407
- (e.g., `1`, `1.2`, `1.2.3`) up to the max permitted length (256 characters).
408
- Longer versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`).
409
- All surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes `3.4.0`).
410
- Only text which lacks digits will fail coercion (`version one` is not valid).
411
- The maximum length for any semver component considered for coercion is 16 characters;
412
- longer components will be ignored (`10000000000000000.4.7.4` becomes `4.7.4`).
413
- The maximum value for any semver component is `Integer.MAX_SAFE_INTEGER || (2**53 - 1)`;
414
- higher value components are invalid (`9999999999999999.4.7.4` is likely invalid).
408
+ * `coerce(version, options)`: Coerces a string to semver if possible
409
+
410
+ This aims to provide a very forgiving translation of a non-semver string to
411
+ semver. It looks for the first digit in a string, and consumes all
412
+ remaining characters which satisfy at least a partial semver (e.g., `1`,
413
+ `1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
414
+ versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
415
+ surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
416
+ `3.4.0`). Only text which lacks digits will fail coercion (`version one`
417
+ is not valid). The maximum length for any semver component considered for
418
+ coercion is 16 characters; longer components will be ignored
419
+ (`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
420
+ semver component is `Integer.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
421
+ components are invalid (`9999999999999999.4.7.4` is likely invalid).
422
+
423
+ If the `options.rtl` flag is set, then `coerce` will return the right-most
424
+ coercible tuple that does not share an ending index with a longer coercible
425
+ tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not
426
+ `4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of
427
+ any other overlapping SemVer tuple.
428
+
429
+ ### Clean
430
+
431
+ * `clean(version)`: Clean a string to be a valid semver if possible
432
+
433
+ This will return a cleaned and trimmed semver version. If the provided version is not valid a null will be returned. This does not work for ranges.
434
+
435
+ ex.
436
+ * `s.clean(' = v 2.1.5foo')`: `null`
437
+ * `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'`
438
+ * `s.clean(' = v 2.1.5-foo')`: `null`
439
+ * `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'`
440
+ * `s.clean('=v2.1.5')`: `'2.1.5'`
441
+ * `s.clean(' =v2.1.5')`: `2.1.5`
442
+ * `s.clean(' 2.1.5 ')`: `'2.1.5'`
443
+ * `s.clean('~1.0.0')`: `null`
Binary file
@@ -19,6 +19,8 @@ var includePrerelease = false
19
19
 
20
20
  var coerce = false
21
21
 
22
+ var rtl = false
23
+
22
24
  var identifier
23
25
 
24
26
  var semver = require('../semver')
@@ -71,6 +73,12 @@ function main () {
71
73
  case '-c': case '--coerce':
72
74
  coerce = true
73
75
  break
76
+ case '--rtl':
77
+ rtl = true
78
+ break
79
+ case '--ltr':
80
+ rtl = false
81
+ break
74
82
  case '-h': case '--help': case '-?':
75
83
  return help()
76
84
  default:
@@ -79,10 +87,10 @@ function main () {
79
87
  }
80
88
  }
81
89
 
82
- var options = { loose: loose, includePrerelease: includePrerelease }
90
+ var options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl }
83
91
 
84
92
  versions = versions.map(function (v) {
85
- return coerce ? (semver.coerce(v) || { version: v }).version : v
93
+ return coerce ? (semver.coerce(v, options) || { version: v }).version : v
86
94
  }).filter(function (v) {
87
95
  return semver.valid(v)
88
96
  })
@@ -149,6 +157,12 @@ function help () {
149
157
  ' Coerce a string into SemVer if possible',
150
158
  ' (does not imply --loose)',
151
159
  '',
160
+ '--rtl',
161
+ ' Coerce version strings right to left',
162
+ '',
163
+ '--ltr',
164
+ ' Coerce version strings left to right (default)',
165
+ '',
152
166
  'Program exits successfully if any valid version satisfies',
153
167
  'all supplied ranges, and prints all satisfying versions.',
154
168
  '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semver",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "The semantic version parser used by npm.",
5
5
  "main": "semver.js",
6
6
  "scripts": {
@@ -10,12 +10,12 @@
10
10
  "postpublish": "git push origin --follow-tags"
11
11
  },
12
12
  "devDependencies": {
13
- "tap": "^14.1.6"
13
+ "tap": "^14.3.1"
14
14
  },
15
15
  "license": "ISC",
16
16
  "repository": "https://github.com/npm/node-semver",
17
17
  "bin": {
18
- "semver": "./bin/semver"
18
+ "semver": "./bin/semver.js"
19
19
  },
20
20
  "files": [
21
21
  "bin",
package/semver.js CHANGED
@@ -160,11 +160,13 @@ src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'
160
160
  // Coercion.
161
161
  // Extract anything that could conceivably be a part of a valid semver
162
162
  var COERCE = R++
163
- src[COERCE] = '(?:^|[^\\d])' +
163
+ src[COERCE] = '(^|[^\\d])' +
164
164
  '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
165
165
  '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
166
166
  '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
167
167
  '(?:$|[^\\d])'
168
+ var COERCERTL = R++
169
+ re[COERCERTL] = new RegExp(src[COERCE], 'g')
168
170
 
169
171
  // Tilde ranges.
170
172
  // Meaning is "reasonably at or greater than"
@@ -810,7 +812,11 @@ Comparator.prototype.test = function (version) {
810
812
  }
811
813
 
812
814
  if (typeof version === 'string') {
813
- version = new SemVer(version, this.options)
815
+ try {
816
+ version = new SemVer(version, this.options)
817
+ } catch (er) {
818
+ return false
819
+ }
814
820
  }
815
821
 
816
822
  return cmp(version, this.operator, this.semver, this.options)
@@ -1160,10 +1166,14 @@ function replaceXRange (comp, options) {
1160
1166
  gtlt = ''
1161
1167
  }
1162
1168
 
1169
+ // if we're including prereleases in the match, then we need
1170
+ // to fix this to -0, the lowest possible prerelease value
1171
+ pr = options.includePrerelease ? '-0' : ''
1172
+
1163
1173
  if (xM) {
1164
1174
  if (gtlt === '>' || gtlt === '<') {
1165
1175
  // nothing is allowed
1166
- ret = '<0.0.0'
1176
+ ret = '<0.0.0-0'
1167
1177
  } else {
1168
1178
  // nothing is forbidden
1169
1179
  ret = '*'
@@ -1200,11 +1210,12 @@ function replaceXRange (comp, options) {
1200
1210
  }
1201
1211
  }
1202
1212
 
1203
- ret = gtlt + M + '.' + m + '.' + p
1213
+ ret = gtlt + M + '.' + m + '.' + p + pr
1204
1214
  } else if (xm) {
1205
- ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
1215
+ ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr
1206
1216
  } else if (xp) {
1207
- ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
1217
+ ret = '>=' + M + '.' + m + '.0' + pr +
1218
+ ' <' + M + '.' + (+m + 1) + '.0' + pr
1208
1219
  }
1209
1220
 
1210
1221
  debug('xRange return', ret)
@@ -1256,8 +1267,16 @@ function hyphenReplace ($0,
1256
1267
 
1257
1268
  // if ANY of the sets match ALL of its comparators, then pass
1258
1269
  Range.prototype.test = function (version) {
1270
+ if (!version) {
1271
+ return false
1272
+ }
1273
+
1259
1274
  if (typeof version === 'string') {
1260
- version = new SemVer(version, this.options)
1275
+ try {
1276
+ version = new SemVer(version, this.options)
1277
+ } catch (er) {
1278
+ return false
1279
+ }
1261
1280
  }
1262
1281
 
1263
1282
  for (var i = 0; i < this.set.length; i++) {
@@ -1519,22 +1538,52 @@ function intersects (r1, r2, options) {
1519
1538
  }
1520
1539
 
1521
1540
  exports.coerce = coerce
1522
- function coerce (version) {
1541
+ function coerce (version, options) {
1523
1542
  if (version instanceof SemVer) {
1524
1543
  return version
1525
1544
  }
1526
1545
 
1546
+ if (typeof version === 'number') {
1547
+ version = String(version)
1548
+ }
1549
+
1527
1550
  if (typeof version !== 'string') {
1528
1551
  return null
1529
1552
  }
1530
1553
 
1531
- var match = version.match(re[COERCE])
1554
+ options = options || {}
1555
+
1556
+ var match = null
1557
+ if (!options.rtl) {
1558
+ match = version.match(re[COERCE])
1559
+ } else {
1560
+ // Find the right-most coercible string that does not share
1561
+ // a terminus with a more left-ward coercible string.
1562
+ // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
1563
+ //
1564
+ // Walk through the string checking with a /g regexp
1565
+ // Manually set the index so as to pick up overlapping matches.
1566
+ // Stop when we get a match that ends at the string end, since no
1567
+ // coercible string can be more right-ward without the same terminus.
1568
+ var next
1569
+ while ((next = re[COERCERTL].exec(version)) &&
1570
+ (!match || match.index + match[0].length !== version.length)
1571
+ ) {
1572
+ if (!match ||
1573
+ next.index + next[0].length !== match.index + match[0].length) {
1574
+ match = next
1575
+ }
1576
+ re[COERCERTL].lastIndex = next.index + next[1].length + next[2].length
1577
+ }
1578
+ // leave it in a clean state
1579
+ re[COERCERTL].lastIndex = -1
1580
+ }
1532
1581
 
1533
- if (match == null) {
1582
+ if (match === null) {
1534
1583
  return null
1535
1584
  }
1536
1585
 
1537
- return parse(match[1] +
1538
- '.' + (match[2] || '0') +
1539
- '.' + (match[3] || '0'))
1586
+ return parse(match[2] +
1587
+ '.' + (match[3] || '0') +
1588
+ '.' + (match[4] || '0'), options)
1540
1589
  }