| | |
| | | // First, split based on boolean or || |
| | | this.raw = range |
| | | this.set = range |
| | | .split(/\s*\|\|\s*/) |
| | | .split('||') |
| | | // map the range to a 2d array of comparators |
| | | .map(range => this.parseRange(range.trim())) |
| | | .map(r => this.parseRange(r.trim())) |
| | | // throw out any comparator lists that are empty |
| | | // this generally means that it was not a valid range, which is allowed |
| | | // in loose mode, but will still throw if the WHOLE range is invalid. |
| | |
| | | // keep the first one, in case they're all null sets |
| | | const first = this.set[0] |
| | | this.set = this.set.filter(c => !isNullSet(c[0])) |
| | | if (this.set.length === 0) |
| | | if (this.set.length === 0) { |
| | | this.set = [first] |
| | | else if (this.set.length > 1) { |
| | | } else if (this.set.length > 1) { |
| | | // if we have any that are *, then the range is just * |
| | | for (const c of this.set) { |
| | | if (c.length === 1 && isAny(c[0])) { |
| | |
| | | const memoOpts = Object.keys(this.options).join(',') |
| | | const memoKey = `parseRange:${memoOpts}:${range}` |
| | | const cached = cache.get(memoKey) |
| | | if (cached) |
| | | if (cached) { |
| | | return cached |
| | | } |
| | | |
| | | const loose = this.options.loose |
| | | // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` |
| | |
| | | debug('hyphen replace', range) |
| | | // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` |
| | | range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) |
| | | debug('comparator trim', range, re[t.COMPARATORTRIM]) |
| | | debug('comparator trim', range) |
| | | |
| | | // `~ 1.2.3` => `~1.2.3` |
| | | range = range.replace(re[t.TILDETRIM], tildeTrimReplace) |
| | |
| | | // At this point, the range is completely trimmed and |
| | | // ready to be split into comparators. |
| | | |
| | | const compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] |
| | | const rangeList = range |
| | | let rangeList = range |
| | | .split(' ') |
| | | .map(comp => parseComparator(comp, this.options)) |
| | | .join(' ') |
| | | .split(/\s+/) |
| | | // >=0.0.0 is equivalent to * |
| | | .map(comp => replaceGTE0(comp, this.options)) |
| | | |
| | | if (loose) { |
| | | // in loose mode, throw out any that are not valid comparators |
| | | .filter(this.options.loose ? comp => !!comp.match(compRe) : () => true) |
| | | .map(comp => new Comparator(comp, this.options)) |
| | | rangeList = rangeList.filter(comp => { |
| | | debug('loose invalid filter', comp, this.options) |
| | | return !!comp.match(re[t.COMPARATORLOOSE]) |
| | | }) |
| | | } |
| | | debug('range list', rangeList) |
| | | |
| | | // if any comparators are the null set, then replace with JUST null set |
| | | // if more than one comparator, remove any * comparators |
| | | // also, don't include the same comparator more than once |
| | | const l = rangeList.length |
| | | const rangeMap = new Map() |
| | | for (const comp of rangeList) { |
| | | if (isNullSet(comp)) |
| | | const comparators = rangeList.map(comp => new Comparator(comp, this.options)) |
| | | for (const comp of comparators) { |
| | | if (isNullSet(comp)) { |
| | | return [comp] |
| | | } |
| | | rangeMap.set(comp.value, comp) |
| | | } |
| | | if (rangeMap.size > 1 && rangeMap.has('')) |
| | | if (rangeMap.size > 1 && rangeMap.has('')) { |
| | | rangeMap.delete('') |
| | | } |
| | | |
| | | const result = [...rangeMap.values()] |
| | | cache.set(memoKey, result) |
| | |
| | | t, |
| | | comparatorTrimReplace, |
| | | tildeTrimReplace, |
| | | caretTrimReplace |
| | | caretTrimReplace, |
| | | } = require('../internal/re') |
| | | |
| | | const isNullSet = c => c.value === '<0.0.0-0' |
| | |
| | | // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 |
| | | // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 |
| | | const replaceTildes = (comp, options) => |
| | | comp.trim().split(/\s+/).map((comp) => { |
| | | return replaceTilde(comp, options) |
| | | comp.trim().split(/\s+/).map((c) => { |
| | | return replaceTilde(c, options) |
| | | }).join(' ') |
| | | |
| | | const replaceTilde = (comp, options) => { |
| | |
| | | // ^1.2.3 --> >=1.2.3 <2.0.0-0 |
| | | // ^1.2.0 --> >=1.2.0 <2.0.0-0 |
| | | const replaceCarets = (comp, options) => |
| | | comp.trim().split(/\s+/).map((comp) => { |
| | | return replaceCaret(comp, options) |
| | | comp.trim().split(/\s+/).map((c) => { |
| | | return replaceCaret(c, options) |
| | | }).join(' ') |
| | | |
| | | const replaceCaret = (comp, options) => { |
| | |
| | | |
| | | const replaceXRanges = (comp, options) => { |
| | | debug('replaceXRanges', comp, options) |
| | | return comp.split(/\s+/).map((comp) => { |
| | | return replaceXRange(comp, options) |
| | | return comp.split(/\s+/).map((c) => { |
| | | return replaceXRange(c, options) |
| | | }).join(' ') |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | if (gtlt === '<') |
| | | if (gtlt === '<') { |
| | | pr = '-0' |
| | | } |
| | | |
| | | ret = `${gtlt + M}.${m}.${p}${pr}` |
| | | } else if (xm) { |