You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							223 lines
						
					
					
						
							8.0 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							223 lines
						
					
					
						
							8.0 KiB
						
					
					
				
								'use strict'
							 | 
						|
								
							 | 
						|
								const {
							 | 
						|
								  MAX_SAFE_COMPONENT_LENGTH,
							 | 
						|
								  MAX_SAFE_BUILD_LENGTH,
							 | 
						|
								  MAX_LENGTH,
							 | 
						|
								} = require('./constants')
							 | 
						|
								const debug = require('./debug')
							 | 
						|
								exports = module.exports = {}
							 | 
						|
								
							 | 
						|
								// The actual regexps go on exports.re
							 | 
						|
								const re = exports.re = []
							 | 
						|
								const safeRe = exports.safeRe = []
							 | 
						|
								const src = exports.src = []
							 | 
						|
								const safeSrc = exports.safeSrc = []
							 | 
						|
								const t = exports.t = {}
							 | 
						|
								let R = 0
							 | 
						|
								
							 | 
						|
								const LETTERDASHNUMBER = '[a-zA-Z0-9-]'
							 | 
						|
								
							 | 
						|
								// Replace some greedy regex tokens to prevent regex dos issues. These regex are
							 | 
						|
								// used internally via the safeRe object since all inputs in this library get
							 | 
						|
								// normalized first to trim and collapse all extra whitespace. The original
							 | 
						|
								// regexes are exported for userland consumption and lower level usage. A
							 | 
						|
								// future breaking change could export the safer regex only with a note that
							 | 
						|
								// all input should have extra whitespace removed.
							 | 
						|
								const safeRegexReplacements = [
							 | 
						|
								  ['\\s', 1],
							 | 
						|
								  ['\\d', MAX_LENGTH],
							 | 
						|
								  [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
							 | 
						|
								]
							 | 
						|
								
							 | 
						|
								const makeSafeRegex = (value) => {
							 | 
						|
								  for (const [token, max] of safeRegexReplacements) {
							 | 
						|
								    value = value
							 | 
						|
								      .split(`${token}*`).join(`${token}{0,${max}}`)
							 | 
						|
								      .split(`${token}+`).join(`${token}{1,${max}}`)
							 | 
						|
								  }
							 | 
						|
								  return value
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								const createToken = (name, value, isGlobal) => {
							 | 
						|
								  const safe = makeSafeRegex(value)
							 | 
						|
								  const index = R++
							 | 
						|
								  debug(name, index, value)
							 | 
						|
								  t[name] = index
							 | 
						|
								  src[index] = value
							 | 
						|
								  safeSrc[index] = safe
							 | 
						|
								  re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
							 | 
						|
								  safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// The following Regular Expressions can be used for tokenizing,
							 | 
						|
								// validating, and parsing SemVer version strings.
							 | 
						|
								
							 | 
						|
								// ## Numeric Identifier
							 | 
						|
								// A single `0`, or a non-zero digit followed by zero or more digits.
							 | 
						|
								
							 | 
						|
								createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
							 | 
						|
								createToken('NUMERICIDENTIFIERLOOSE', '\\d+')
							 | 
						|
								
							 | 
						|
								// ## Non-numeric Identifier
							 | 
						|
								// Zero or more digits, followed by a letter or hyphen, and then zero or
							 | 
						|
								// more letters, digits, or hyphens.
							 | 
						|
								
							 | 
						|
								createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)
							 | 
						|
								
							 | 
						|
								// ## Main Version
							 | 
						|
								// Three dot-separated numeric identifiers.
							 | 
						|
								
							 | 
						|
								createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
							 | 
						|
								                   `(${src[t.NUMERICIDENTIFIER]})\\.` +
							 | 
						|
								                   `(${src[t.NUMERICIDENTIFIER]})`)
							 | 
						|
								
							 | 
						|
								createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
							 | 
						|
								                        `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
							 | 
						|
								                        `(${src[t.NUMERICIDENTIFIERLOOSE]})`)
							 | 
						|
								
							 | 
						|
								// ## Pre-release Version Identifier
							 | 
						|
								// A numeric identifier, or a non-numeric identifier.
							 | 
						|
								// Non-numberic identifiers include numberic identifiers but can be longer.
							 | 
						|
								// Therefore non-numberic identifiers must go first.
							 | 
						|
								
							 | 
						|
								createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
							 | 
						|
								}|${src[t.NUMERICIDENTIFIER]})`)
							 | 
						|
								
							 | 
						|
								createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]
							 | 
						|
								}|${src[t.NUMERICIDENTIFIERLOOSE]})`)
							 | 
						|
								
							 | 
						|
								// ## Pre-release Version
							 | 
						|
								// Hyphen, followed by one or more dot-separated pre-release version
							 | 
						|
								// identifiers.
							 | 
						|
								
							 | 
						|
								createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
							 | 
						|
								}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)
							 | 
						|
								
							 | 
						|
								createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
							 | 
						|
								}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)
							 | 
						|
								
							 | 
						|
								// ## Build Metadata Identifier
							 | 
						|
								// Any combination of digits, letters, or hyphens.
							 | 
						|
								
							 | 
						|
								createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)
							 | 
						|
								
							 | 
						|
								// ## Build Metadata
							 | 
						|
								// Plus sign, followed by one or more period-separated build metadata
							 | 
						|
								// identifiers.
							 | 
						|
								
							 | 
						|
								createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
							 | 
						|
								}(?:\\.${src[t.BUILDIDENTIFIER]})*))`)
							 | 
						|
								
							 | 
						|
								// ## Full Version String
							 | 
						|
								// A main version, followed optionally by a pre-release version and
							 | 
						|
								// build metadata.
							 | 
						|
								
							 | 
						|
								// Note that the only major, minor, patch, and pre-release sections of
							 | 
						|
								// the version string are capturing groups.  The build metadata is not a
							 | 
						|
								// capturing group, because it should not ever be used in version
							 | 
						|
								// comparison.
							 | 
						|
								
							 | 
						|
								createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
							 | 
						|
								}${src[t.PRERELEASE]}?${
							 | 
						|
								  src[t.BUILD]}?`)
							 | 
						|
								
							 | 
						|
								createToken('FULL', `^${src[t.FULLPLAIN]}$`)
							 | 
						|
								
							 | 
						|
								// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
							 | 
						|
								// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
							 | 
						|
								// common in the npm registry.
							 | 
						|
								createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
							 | 
						|
								}${src[t.PRERELEASELOOSE]}?${
							 | 
						|
								  src[t.BUILD]}?`)
							 | 
						|
								
							 | 
						|
								createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)
							 | 
						|
								
							 | 
						|
								createToken('GTLT', '((?:<|>)?=?)')
							 | 
						|
								
							 | 
						|
								// Something like "2.*" or "1.2.x".
							 | 
						|
								// Note that "x.x" is a valid xRange identifer, meaning "any version"
							 | 
						|
								// Only the first item is strictly required.
							 | 
						|
								createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
							 | 
						|
								createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)
							 | 
						|
								
							 | 
						|
								createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
							 | 
						|
								                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
							 | 
						|
								                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
							 | 
						|
								                   `(?:${src[t.PRERELEASE]})?${
							 | 
						|
								                     src[t.BUILD]}?` +
							 | 
						|
								                   `)?)?`)
							 | 
						|
								
							 | 
						|
								createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
							 | 
						|
								                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
							 | 
						|
								                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
							 | 
						|
								                        `(?:${src[t.PRERELEASELOOSE]})?${
							 | 
						|
								                          src[t.BUILD]}?` +
							 | 
						|
								                        `)?)?`)
							 | 
						|
								
							 | 
						|
								createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
							 | 
						|
								createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)
							 | 
						|
								
							 | 
						|
								// Coercion.
							 | 
						|
								// Extract anything that could conceivably be a part of a valid semver
							 | 
						|
								createToken('COERCEPLAIN', `${'(^|[^\\d])' +
							 | 
						|
								              '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
							 | 
						|
								              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
							 | 
						|
								              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
							 | 
						|
								createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
							 | 
						|
								createToken('COERCEFULL', src[t.COERCEPLAIN] +
							 | 
						|
								              `(?:${src[t.PRERELEASE]})?` +
							 | 
						|
								              `(?:${src[t.BUILD]})?` +
							 | 
						|
								              `(?:$|[^\\d])`)
							 | 
						|
								createToken('COERCERTL', src[t.COERCE], true)
							 | 
						|
								createToken('COERCERTLFULL', src[t.COERCEFULL], true)
							 | 
						|
								
							 | 
						|
								// Tilde ranges.
							 | 
						|
								// Meaning is "reasonably at or greater than"
							 | 
						|
								createToken('LONETILDE', '(?:~>?)')
							 | 
						|
								
							 | 
						|
								createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
							 | 
						|
								exports.tildeTrimReplace = '$1~'
							 | 
						|
								
							 | 
						|
								createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
							 | 
						|
								createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)
							 | 
						|
								
							 | 
						|
								// Caret ranges.
							 | 
						|
								// Meaning is "at least and backwards compatible with"
							 | 
						|
								createToken('LONECARET', '(?:\\^)')
							 | 
						|
								
							 | 
						|
								createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
							 | 
						|
								exports.caretTrimReplace = '$1^'
							 | 
						|
								
							 | 
						|
								createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
							 | 
						|
								createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)
							 | 
						|
								
							 | 
						|
								// A simple gt/lt/eq thing, or just "" to indicate "any version"
							 | 
						|
								createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
							 | 
						|
								createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)
							 | 
						|
								
							 | 
						|
								// An expression to strip any whitespace between the gtlt and the thing
							 | 
						|
								// it modifies, so that `> 1.2.3` ==> `>1.2.3`
							 | 
						|
								createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
							 | 
						|
								}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
							 | 
						|
								exports.comparatorTrimReplace = '$1$2$3'
							 | 
						|
								
							 | 
						|
								// Something like `1.2.3 - 1.2.4`
							 | 
						|
								// Note that these all use the loose form, because they'll be
							 | 
						|
								// checked against either the strict or loose comparator form
							 | 
						|
								// later.
							 | 
						|
								createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
							 | 
						|
								                   `\\s+-\\s+` +
							 | 
						|
								                   `(${src[t.XRANGEPLAIN]})` +
							 | 
						|
								                   `\\s*$`)
							 | 
						|
								
							 | 
						|
								createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
							 | 
						|
								                        `\\s+-\\s+` +
							 | 
						|
								                        `(${src[t.XRANGEPLAINLOOSE]})` +
							 | 
						|
								                        `\\s*$`)
							 | 
						|
								
							 | 
						|
								// Star ranges basically just allow anything at all.
							 | 
						|
								createToken('STAR', '(<|>)?=?\\s*\\*')
							 | 
						|
								// >=0.0.0 is like a star
							 | 
						|
								createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
							 | 
						|
								createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
							 | 
						|
								
							 |