semver 6.1.1 → 6.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # changes log
2
2
 
3
+ ## 6.2.0
4
+
5
+ * Coerce numbers to strings when passed to semver.coerce()
6
+ * Add `rtl` option to coerce from right to left
7
+
8
+ ## 6.1.3
9
+
10
+ * Handle X-ranges properly in includePrerelease mode
11
+
12
+ ## 6.1.2
13
+
14
+ * Do not throw when testing invalid version strings
15
+
16
+ ## 6.1.1
17
+
18
+ * Add options support for semver.coerce()
19
+ * Handle undefined version passed to Range.test
20
+
21
+ ## 6.1.0
22
+
23
+ * Add semver.compareBuild function
24
+ * Support `*` in semver.intersects
25
+
3
26
  ## 6.0
4
27
 
5
28
  * Fix `intersects` logic.
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,19 +405,26 @@ 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.
415
428
 
416
429
  ### Clean
417
430
 
@@ -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.1",
3
+ "version": "6.3.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
@@ -29,75 +29,80 @@ var MAX_SAFE_COMPONENT_LENGTH = 16
29
29
  // The actual regexps go on exports.re
30
30
  var re = exports.re = []
31
31
  var src = exports.src = []
32
+ var t = exports.tokens = {}
32
33
  var R = 0
33
34
 
35
+ function tok (n) {
36
+ t[n] = R++
37
+ }
38
+
34
39
  // The following Regular Expressions can be used for tokenizing,
35
40
  // validating, and parsing SemVer version strings.
36
41
 
37
42
  // ## Numeric Identifier
38
43
  // A single `0`, or a non-zero digit followed by zero or more digits.
39
44
 
40
- var NUMERICIDENTIFIER = R++
41
- src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'
42
- var NUMERICIDENTIFIERLOOSE = R++
43
- src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'
45
+ tok('NUMERICIDENTIFIER')
46
+ src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*'
47
+ tok('NUMERICIDENTIFIERLOOSE')
48
+ src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+'
44
49
 
45
50
  // ## Non-numeric Identifier
46
51
  // Zero or more digits, followed by a letter or hyphen, and then zero or
47
52
  // more letters, digits, or hyphens.
48
53
 
49
- var NONNUMERICIDENTIFIER = R++
50
- src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'
54
+ tok('NONNUMERICIDENTIFIER')
55
+ src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'
51
56
 
52
57
  // ## Main Version
53
58
  // Three dot-separated numeric identifiers.
54
59
 
55
- var MAINVERSION = R++
56
- src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
57
- '(' + src[NUMERICIDENTIFIER] + ')\\.' +
58
- '(' + src[NUMERICIDENTIFIER] + ')'
60
+ tok('MAINVERSION')
61
+ src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' +
62
+ '(' + src[t.NUMERICIDENTIFIER] + ')\\.' +
63
+ '(' + src[t.NUMERICIDENTIFIER] + ')'
59
64
 
60
- var MAINVERSIONLOOSE = R++
61
- src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
62
- '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
63
- '(' + src[NUMERICIDENTIFIERLOOSE] + ')'
65
+ tok('MAINVERSIONLOOSE')
66
+ src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' +
67
+ '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' +
68
+ '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')'
64
69
 
65
70
  // ## Pre-release Version Identifier
66
71
  // A numeric identifier, or a non-numeric identifier.
67
72
 
68
- var PRERELEASEIDENTIFIER = R++
69
- src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
70
- '|' + src[NONNUMERICIDENTIFIER] + ')'
73
+ tok('PRERELEASEIDENTIFIER')
74
+ src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] +
75
+ '|' + src[t.NONNUMERICIDENTIFIER] + ')'
71
76
 
72
- var PRERELEASEIDENTIFIERLOOSE = R++
73
- src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
74
- '|' + src[NONNUMERICIDENTIFIER] + ')'
77
+ tok('PRERELEASEIDENTIFIERLOOSE')
78
+ src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] +
79
+ '|' + src[t.NONNUMERICIDENTIFIER] + ')'
75
80
 
76
81
  // ## Pre-release Version
77
82
  // Hyphen, followed by one or more dot-separated pre-release version
78
83
  // identifiers.
79
84
 
80
- var PRERELEASE = R++
81
- src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
82
- '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'
85
+ tok('PRERELEASE')
86
+ src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] +
87
+ '(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))'
83
88
 
84
- var PRERELEASELOOSE = R++
85
- src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
86
- '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'
89
+ tok('PRERELEASELOOSE')
90
+ src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] +
91
+ '(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))'
87
92
 
88
93
  // ## Build Metadata Identifier
89
94
  // Any combination of digits, letters, or hyphens.
90
95
 
91
- var BUILDIDENTIFIER = R++
92
- src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'
96
+ tok('BUILDIDENTIFIER')
97
+ src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+'
93
98
 
94
99
  // ## Build Metadata
95
100
  // Plus sign, followed by one or more period-separated build metadata
96
101
  // identifiers.
97
102
 
98
- var BUILD = R++
99
- src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
100
- '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'
103
+ tok('BUILD')
104
+ src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] +
105
+ '(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))'
101
106
 
102
107
  // ## Full Version String
103
108
  // A main version, followed optionally by a pre-release version and
@@ -108,129 +113,133 @@ src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
108
113
  // capturing group, because it should not ever be used in version
109
114
  // comparison.
110
115
 
111
- var FULL = R++
112
- var FULLPLAIN = 'v?' + src[MAINVERSION] +
113
- src[PRERELEASE] + '?' +
114
- src[BUILD] + '?'
116
+ tok('FULL')
117
+ tok('FULLPLAIN')
118
+ src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] +
119
+ src[t.PRERELEASE] + '?' +
120
+ src[t.BUILD] + '?'
115
121
 
116
- src[FULL] = '^' + FULLPLAIN + '$'
122
+ src[t.FULL] = '^' + src[t.FULLPLAIN] + '$'
117
123
 
118
124
  // like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
119
125
  // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
120
126
  // common in the npm registry.
121
- var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
122
- src[PRERELEASELOOSE] + '?' +
123
- src[BUILD] + '?'
127
+ tok('LOOSEPLAIN')
128
+ src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] +
129
+ src[t.PRERELEASELOOSE] + '?' +
130
+ src[t.BUILD] + '?'
124
131
 
125
- var LOOSE = R++
126
- src[LOOSE] = '^' + LOOSEPLAIN + '$'
132
+ tok('LOOSE')
133
+ src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$'
127
134
 
128
- var GTLT = R++
129
- src[GTLT] = '((?:<|>)?=?)'
135
+ tok('GTLT')
136
+ src[t.GTLT] = '((?:<|>)?=?)'
130
137
 
131
138
  // Something like "2.*" or "1.2.x".
132
139
  // Note that "x.x" is a valid xRange identifer, meaning "any version"
133
140
  // Only the first item is strictly required.
134
- var XRANGEIDENTIFIERLOOSE = R++
135
- src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'
136
- var XRANGEIDENTIFIER = R++
137
- src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'
138
-
139
- var XRANGEPLAIN = R++
140
- src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
141
- '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
142
- '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
143
- '(?:' + src[PRERELEASE] + ')?' +
144
- src[BUILD] + '?' +
141
+ tok('XRANGEIDENTIFIERLOOSE')
142
+ src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'
143
+ tok('XRANGEIDENTIFIER')
144
+ src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*'
145
+
146
+ tok('XRANGEPLAIN')
147
+ src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' +
148
+ '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' +
149
+ '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' +
150
+ '(?:' + src[t.PRERELEASE] + ')?' +
151
+ src[t.BUILD] + '?' +
145
152
  ')?)?'
146
153
 
147
- var XRANGEPLAINLOOSE = R++
148
- src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
149
- '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
150
- '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
151
- '(?:' + src[PRERELEASELOOSE] + ')?' +
152
- src[BUILD] + '?' +
154
+ tok('XRANGEPLAINLOOSE')
155
+ src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
156
+ '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
157
+ '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
158
+ '(?:' + src[t.PRERELEASELOOSE] + ')?' +
159
+ src[t.BUILD] + '?' +
153
160
  ')?)?'
154
161
 
155
- var XRANGE = R++
156
- src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'
157
- var XRANGELOOSE = R++
158
- src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'
162
+ tok('XRANGE')
163
+ src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$'
164
+ tok('XRANGELOOSE')
165
+ src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$'
159
166
 
160
167
  // Coercion.
161
168
  // Extract anything that could conceivably be a part of a valid semver
162
- var COERCE = R++
163
- src[COERCE] = '(?:^|[^\\d])' +
169
+ tok('COERCE')
170
+ src[t.COERCE] = '(^|[^\\d])' +
164
171
  '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
165
172
  '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
166
173
  '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
167
174
  '(?:$|[^\\d])'
175
+ tok('COERCERTL')
176
+ re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g')
168
177
 
169
178
  // Tilde ranges.
170
179
  // Meaning is "reasonably at or greater than"
171
- var LONETILDE = R++
172
- src[LONETILDE] = '(?:~>?)'
180
+ tok('LONETILDE')
181
+ src[t.LONETILDE] = '(?:~>?)'
173
182
 
174
- var TILDETRIM = R++
175
- src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'
176
- re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g')
183
+ tok('TILDETRIM')
184
+ src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+'
185
+ re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g')
177
186
  var tildeTrimReplace = '$1~'
178
187
 
179
- var TILDE = R++
180
- src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'
181
- var TILDELOOSE = R++
182
- src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'
188
+ tok('TILDE')
189
+ src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$'
190
+ tok('TILDELOOSE')
191
+ src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$'
183
192
 
184
193
  // Caret ranges.
185
194
  // Meaning is "at least and backwards compatible with"
186
- var LONECARET = R++
187
- src[LONECARET] = '(?:\\^)'
195
+ tok('LONECARET')
196
+ src[t.LONECARET] = '(?:\\^)'
188
197
 
189
- var CARETTRIM = R++
190
- src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'
191
- re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g')
198
+ tok('CARETTRIM')
199
+ src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+'
200
+ re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g')
192
201
  var caretTrimReplace = '$1^'
193
202
 
194
- var CARET = R++
195
- src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'
196
- var CARETLOOSE = R++
197
- src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'
203
+ tok('CARET')
204
+ src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$'
205
+ tok('CARETLOOSE')
206
+ src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$'
198
207
 
199
208
  // A simple gt/lt/eq thing, or just "" to indicate "any version"
200
- var COMPARATORLOOSE = R++
201
- src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'
202
- var COMPARATOR = R++
203
- src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'
209
+ tok('COMPARATORLOOSE')
210
+ src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$'
211
+ tok('COMPARATOR')
212
+ src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$'
204
213
 
205
214
  // An expression to strip any whitespace between the gtlt and the thing
206
215
  // it modifies, so that `> 1.2.3` ==> `>1.2.3`
207
- var COMPARATORTRIM = R++
208
- src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
209
- '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'
216
+ tok('COMPARATORTRIM')
217
+ src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] +
218
+ '\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')'
210
219
 
211
220
  // this one has to use the /g flag
212
- re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g')
221
+ re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g')
213
222
  var comparatorTrimReplace = '$1$2$3'
214
223
 
215
224
  // Something like `1.2.3 - 1.2.4`
216
225
  // Note that these all use the loose form, because they'll be
217
226
  // checked against either the strict or loose comparator form
218
227
  // later.
219
- var HYPHENRANGE = R++
220
- src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
228
+ tok('HYPHENRANGE')
229
+ src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' +
221
230
  '\\s+-\\s+' +
222
- '(' + src[XRANGEPLAIN] + ')' +
231
+ '(' + src[t.XRANGEPLAIN] + ')' +
223
232
  '\\s*$'
224
233
 
225
- var HYPHENRANGELOOSE = R++
226
- src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
234
+ tok('HYPHENRANGELOOSE')
235
+ src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' +
227
236
  '\\s+-\\s+' +
228
- '(' + src[XRANGEPLAINLOOSE] + ')' +
237
+ '(' + src[t.XRANGEPLAINLOOSE] + ')' +
229
238
  '\\s*$'
230
239
 
231
240
  // Star ranges basically just allow anything at all.
232
- var STAR = R++
233
- src[STAR] = '(<|>)?=?\\s*\\*'
241
+ tok('STAR')
242
+ src[t.STAR] = '(<|>)?=?\\s*\\*'
234
243
 
235
244
  // Compile to actual regexp objects.
236
245
  // All are flag-free, unless they were created above with a flag.
@@ -262,7 +271,7 @@ function parse (version, options) {
262
271
  return null
263
272
  }
264
273
 
265
- var r = options.loose ? re[LOOSE] : re[FULL]
274
+ var r = options.loose ? re[t.LOOSE] : re[t.FULL]
266
275
  if (!r.test(version)) {
267
276
  return null
268
277
  }
@@ -317,7 +326,7 @@ function SemVer (version, options) {
317
326
  this.options = options
318
327
  this.loose = !!options.loose
319
328
 
320
- var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL])
329
+ var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])
321
330
 
322
331
  if (!m) {
323
332
  throw new TypeError('Invalid Version: ' + version)
@@ -778,7 +787,7 @@ function Comparator (comp, options) {
778
787
 
779
788
  var ANY = {}
780
789
  Comparator.prototype.parse = function (comp) {
781
- var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]
790
+ var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
782
791
  var m = comp.match(r)
783
792
 
784
793
  if (!m) {
@@ -810,7 +819,11 @@ Comparator.prototype.test = function (version) {
810
819
  }
811
820
 
812
821
  if (typeof version === 'string') {
813
- version = new SemVer(version, this.options)
822
+ try {
823
+ version = new SemVer(version, this.options)
824
+ } catch (er) {
825
+ return false
826
+ }
814
827
  }
815
828
 
816
829
  return cmp(version, this.operator, this.semver, this.options)
@@ -929,18 +942,18 @@ Range.prototype.parseRange = function (range) {
929
942
  var loose = this.options.loose
930
943
  range = range.trim()
931
944
  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
932
- var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]
945
+ var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
933
946
  range = range.replace(hr, hyphenReplace)
934
947
  debug('hyphen replace', range)
935
948
  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
936
- range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace)
937
- debug('comparator trim', range, re[COMPARATORTRIM])
949
+ range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
950
+ debug('comparator trim', range, re[t.COMPARATORTRIM])
938
951
 
939
952
  // `~ 1.2.3` => `~1.2.3`
940
- range = range.replace(re[TILDETRIM], tildeTrimReplace)
953
+ range = range.replace(re[t.TILDETRIM], tildeTrimReplace)
941
954
 
942
955
  // `^ 1.2.3` => `^1.2.3`
943
- range = range.replace(re[CARETTRIM], caretTrimReplace)
956
+ range = range.replace(re[t.CARETTRIM], caretTrimReplace)
944
957
 
945
958
  // normalize spaces
946
959
  range = range.split(/\s+/).join(' ')
@@ -948,7 +961,7 @@ Range.prototype.parseRange = function (range) {
948
961
  // At this point, the range is completely trimmed and
949
962
  // ready to be split into comparators.
950
963
 
951
- var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]
964
+ var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
952
965
  var set = range.split(' ').map(function (comp) {
953
966
  return parseComparator(comp, this.options)
954
967
  }, this).join(' ').split(/\s+/)
@@ -1048,7 +1061,7 @@ function replaceTildes (comp, options) {
1048
1061
  }
1049
1062
 
1050
1063
  function replaceTilde (comp, options) {
1051
- var r = options.loose ? re[TILDELOOSE] : re[TILDE]
1064
+ var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
1052
1065
  return comp.replace(r, function (_, M, m, p, pr) {
1053
1066
  debug('tilde', comp, _, M, m, p, pr)
1054
1067
  var ret
@@ -1089,7 +1102,7 @@ function replaceCarets (comp, options) {
1089
1102
 
1090
1103
  function replaceCaret (comp, options) {
1091
1104
  debug('caret', comp, options)
1092
- var r = options.loose ? re[CARETLOOSE] : re[CARET]
1105
+ var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]
1093
1106
  return comp.replace(r, function (_, M, m, p, pr) {
1094
1107
  debug('caret', comp, _, M, m, p, pr)
1095
1108
  var ret
@@ -1148,7 +1161,7 @@ function replaceXRanges (comp, options) {
1148
1161
 
1149
1162
  function replaceXRange (comp, options) {
1150
1163
  comp = comp.trim()
1151
- var r = options.loose ? re[XRANGELOOSE] : re[XRANGE]
1164
+ var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]
1152
1165
  return comp.replace(r, function (ret, gtlt, M, m, p, pr) {
1153
1166
  debug('xRange', comp, ret, gtlt, M, m, p, pr)
1154
1167
  var xM = isX(M)
@@ -1160,10 +1173,14 @@ function replaceXRange (comp, options) {
1160
1173
  gtlt = ''
1161
1174
  }
1162
1175
 
1176
+ // if we're including prereleases in the match, then we need
1177
+ // to fix this to -0, the lowest possible prerelease value
1178
+ pr = options.includePrerelease ? '-0' : ''
1179
+
1163
1180
  if (xM) {
1164
1181
  if (gtlt === '>' || gtlt === '<') {
1165
1182
  // nothing is allowed
1166
- ret = '<0.0.0'
1183
+ ret = '<0.0.0-0'
1167
1184
  } else {
1168
1185
  // nothing is forbidden
1169
1186
  ret = '*'
@@ -1200,11 +1217,12 @@ function replaceXRange (comp, options) {
1200
1217
  }
1201
1218
  }
1202
1219
 
1203
- ret = gtlt + M + '.' + m + '.' + p
1220
+ ret = gtlt + M + '.' + m + '.' + p + pr
1204
1221
  } else if (xm) {
1205
- ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
1222
+ ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr
1206
1223
  } else if (xp) {
1207
- ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
1224
+ ret = '>=' + M + '.' + m + '.0' + pr +
1225
+ ' <' + M + '.' + (+m + 1) + '.0' + pr
1208
1226
  }
1209
1227
 
1210
1228
  debug('xRange return', ret)
@@ -1218,10 +1236,10 @@ function replaceXRange (comp, options) {
1218
1236
  function replaceStars (comp, options) {
1219
1237
  debug('replaceStars', comp, options)
1220
1238
  // Looseness is ignored here. star is always as loose as it gets!
1221
- return comp.trim().replace(re[STAR], '')
1239
+ return comp.trim().replace(re[t.STAR], '')
1222
1240
  }
1223
1241
 
1224
- // This function is passed to string.replace(re[HYPHENRANGE])
1242
+ // This function is passed to string.replace(re[t.HYPHENRANGE])
1225
1243
  // M, m, patch, prerelease, build
1226
1244
  // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
1227
1245
  // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
@@ -1261,7 +1279,11 @@ Range.prototype.test = function (version) {
1261
1279
  }
1262
1280
 
1263
1281
  if (typeof version === 'string') {
1264
- version = new SemVer(version, this.options)
1282
+ try {
1283
+ version = new SemVer(version, this.options)
1284
+ } catch (er) {
1285
+ return false
1286
+ }
1265
1287
  }
1266
1288
 
1267
1289
  for (var i = 0; i < this.set.length; i++) {
@@ -1528,17 +1550,47 @@ function coerce (version, options) {
1528
1550
  return version
1529
1551
  }
1530
1552
 
1553
+ if (typeof version === 'number') {
1554
+ version = String(version)
1555
+ }
1556
+
1531
1557
  if (typeof version !== 'string') {
1532
1558
  return null
1533
1559
  }
1534
1560
 
1535
- var match = version.match(re[COERCE])
1561
+ options = options || {}
1562
+
1563
+ var match = null
1564
+ if (!options.rtl) {
1565
+ match = version.match(re[t.COERCE])
1566
+ } else {
1567
+ // Find the right-most coercible string that does not share
1568
+ // a terminus with a more left-ward coercible string.
1569
+ // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
1570
+ //
1571
+ // Walk through the string checking with a /g regexp
1572
+ // Manually set the index so as to pick up overlapping matches.
1573
+ // Stop when we get a match that ends at the string end, since no
1574
+ // coercible string can be more right-ward without the same terminus.
1575
+ var next
1576
+ while ((next = re[t.COERCERTL].exec(version)) &&
1577
+ (!match || match.index + match[0].length !== version.length)
1578
+ ) {
1579
+ if (!match ||
1580
+ next.index + next[0].length !== match.index + match[0].length) {
1581
+ match = next
1582
+ }
1583
+ re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
1584
+ }
1585
+ // leave it in a clean state
1586
+ re[t.COERCERTL].lastIndex = -1
1587
+ }
1536
1588
 
1537
- if (match == null) {
1589
+ if (match === null) {
1538
1590
  return null
1539
1591
  }
1540
1592
 
1541
- return parse(match[1] +
1542
- '.' + (match[2] || '0') +
1543
- '.' + (match[3] || '0'), options)
1593
+ return parse(match[2] +
1594
+ '.' + (match[3] || '0') +
1595
+ '.' + (match[4] || '0'), options)
1544
1596
  }