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.
		
		
		
		
		
			
		
			
				
					
					
						
							208 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							208 lines
						
					
					
						
							4.9 KiB
						
					
					
				/*! | 
						|
 * fill-range <https://github.com/jonschlinkert/fill-range> | 
						|
 * | 
						|
 * Copyright (c) 2014-2015, 2017, Jon Schlinkert. | 
						|
 * Released under the MIT License. | 
						|
 */ | 
						|
 | 
						|
'use strict'; | 
						|
 | 
						|
var util = require('util'); | 
						|
var isNumber = require('is-number'); | 
						|
var extend = require('extend-shallow'); | 
						|
var repeat = require('repeat-string'); | 
						|
var toRegex = require('to-regex-range'); | 
						|
 | 
						|
/** | 
						|
 * Return a range of numbers or letters. | 
						|
 * | 
						|
 * @param  {String} `start` Start of the range | 
						|
 * @param  {String} `stop` End of the range | 
						|
 * @param  {String} `step` Increment or decrement to use. | 
						|
 * @param  {Function} `fn` Custom function to modify each element in the range. | 
						|
 * @return {Array} | 
						|
 */ | 
						|
 | 
						|
function fillRange(start, stop, step, options) { | 
						|
  if (typeof start === 'undefined') { | 
						|
    return []; | 
						|
  } | 
						|
 | 
						|
  if (typeof stop === 'undefined' || start === stop) { | 
						|
    // special case, for handling negative zero | 
						|
    var isString = typeof start === 'string'; | 
						|
    if (isNumber(start) && !toNumber(start)) { | 
						|
      return [isString ? '0' : 0]; | 
						|
    } | 
						|
    return [start]; | 
						|
  } | 
						|
 | 
						|
  if (typeof step !== 'number' && typeof step !== 'string') { | 
						|
    options = step; | 
						|
    step = undefined; | 
						|
  } | 
						|
 | 
						|
  if (typeof options === 'function') { | 
						|
    options = { transform: options }; | 
						|
  } | 
						|
 | 
						|
  var opts = extend({step: step}, options); | 
						|
  if (opts.step && !isValidNumber(opts.step)) { | 
						|
    if (opts.strictRanges === true) { | 
						|
      throw new TypeError('expected options.step to be a number'); | 
						|
    } | 
						|
    return []; | 
						|
  } | 
						|
 | 
						|
  opts.isNumber = isValidNumber(start) && isValidNumber(stop); | 
						|
  if (!opts.isNumber && !isValid(start, stop)) { | 
						|
    if (opts.strictRanges === true) { | 
						|
      throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); | 
						|
    } | 
						|
    return []; | 
						|
  } | 
						|
 | 
						|
  opts.isPadded = isPadded(start) || isPadded(stop); | 
						|
  opts.toString = opts.stringify | 
						|
    || typeof opts.step === 'string' | 
						|
    || typeof start === 'string' | 
						|
    || typeof stop === 'string' | 
						|
    || !opts.isNumber; | 
						|
 | 
						|
  if (opts.isPadded) { | 
						|
    opts.maxLength = Math.max(String(start).length, String(stop).length); | 
						|
  } | 
						|
 | 
						|
  // support legacy minimatch/fill-range options | 
						|
  if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; | 
						|
  if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; | 
						|
  return expand(start, stop, opts); | 
						|
} | 
						|
 | 
						|
function expand(start, stop, options) { | 
						|
  var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); | 
						|
  var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); | 
						|
 | 
						|
  var step = Math.abs(toNumber(options.step)) || 1; | 
						|
  if (options.toRegex && step === 1) { | 
						|
    return toRange(a, b, start, stop, options); | 
						|
  } | 
						|
 | 
						|
  var zero = {greater: [], lesser: []}; | 
						|
  var asc = a < b; | 
						|
  var arr = new Array(Math.round((asc ? b - a : a - b) / step)); | 
						|
  var idx = 0; | 
						|
 | 
						|
  while (asc ? a <= b : a >= b) { | 
						|
    var val = options.isNumber ? a : String.fromCharCode(a); | 
						|
    if (options.toRegex && (val >= 0 || !options.isNumber)) { | 
						|
      zero.greater.push(val); | 
						|
    } else { | 
						|
      zero.lesser.push(Math.abs(val)); | 
						|
    } | 
						|
 | 
						|
    if (options.isPadded) { | 
						|
      val = zeros(val, options); | 
						|
    } | 
						|
 | 
						|
    if (options.toString) { | 
						|
      val = String(val); | 
						|
    } | 
						|
 | 
						|
    if (typeof options.transform === 'function') { | 
						|
      arr[idx++] = options.transform(val, a, b, step, idx, arr, options); | 
						|
    } else { | 
						|
      arr[idx++] = val; | 
						|
    } | 
						|
 | 
						|
    if (asc) { | 
						|
      a += step; | 
						|
    } else { | 
						|
      a -= step; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  if (options.toRegex === true) { | 
						|
    return toSequence(arr, zero, options); | 
						|
  } | 
						|
  return arr; | 
						|
} | 
						|
 | 
						|
function toRange(a, b, start, stop, options) { | 
						|
  if (options.isPadded) { | 
						|
    return toRegex(start, stop, options); | 
						|
  } | 
						|
 | 
						|
  if (options.isNumber) { | 
						|
    return toRegex(Math.min(a, b), Math.max(a, b), options); | 
						|
  } | 
						|
 | 
						|
  var start = String.fromCharCode(Math.min(a, b)); | 
						|
  var stop = String.fromCharCode(Math.max(a, b)); | 
						|
  return '[' + start + '-' + stop + ']'; | 
						|
} | 
						|
 | 
						|
function toSequence(arr, zeros, options) { | 
						|
  var greater = '', lesser = ''; | 
						|
  if (zeros.greater.length) { | 
						|
    greater = zeros.greater.join('|'); | 
						|
  } | 
						|
  if (zeros.lesser.length) { | 
						|
    lesser = '-(' + zeros.lesser.join('|') + ')'; | 
						|
  } | 
						|
  var res = greater && lesser | 
						|
    ? greater + '|' + lesser | 
						|
    : greater || lesser; | 
						|
 | 
						|
  if (options.capture) { | 
						|
    return '(' + res + ')'; | 
						|
  } | 
						|
  return res; | 
						|
} | 
						|
 | 
						|
function zeros(val, options) { | 
						|
  if (options.isPadded) { | 
						|
    var str = String(val); | 
						|
    var len = str.length; | 
						|
    var dash = ''; | 
						|
    if (str.charAt(0) === '-') { | 
						|
      dash = '-'; | 
						|
      str = str.slice(1); | 
						|
    } | 
						|
    var diff = options.maxLength - len; | 
						|
    var pad = repeat('0', diff); | 
						|
    val = (dash + pad + str); | 
						|
  } | 
						|
  if (options.stringify) { | 
						|
    return String(val); | 
						|
  } | 
						|
  return val; | 
						|
} | 
						|
 | 
						|
function toNumber(val) { | 
						|
  return Number(val) || 0; | 
						|
} | 
						|
 | 
						|
function isPadded(str) { | 
						|
  return /^-?0\d/.test(str); | 
						|
} | 
						|
 | 
						|
function isValid(min, max) { | 
						|
  return (isValidNumber(min) || isValidLetter(min)) | 
						|
      && (isValidNumber(max) || isValidLetter(max)); | 
						|
} | 
						|
 | 
						|
function isValidLetter(ch) { | 
						|
  return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); | 
						|
} | 
						|
 | 
						|
function isValidNumber(n) { | 
						|
  return isNumber(n) && !/\./.test(n); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Expose `fillRange` | 
						|
 * @type {Function} | 
						|
 */ | 
						|
 | 
						|
module.exports = fillRange;
 | 
						|
 |