fill-range
Advanced tools
Comparing version 2.2.3 to 3.0.0
449
index.js
@@ -10,19 +10,13 @@ /*! | ||
var isObject = require('isobject'); | ||
var util = require('util'); | ||
var isNumber = require('is-number'); | ||
var randomize = require('randomatic'); | ||
var repeatStr = require('repeat-string'); | ||
var repeat = require('repeat-element'); | ||
var extend = require('extend-shallow'); | ||
var repeat = require('repeat-string'); | ||
var toRegex = require('to-regex-range'); | ||
/** | ||
* Expose `fillRange` | ||
*/ | ||
module.exports = fillRange; | ||
/** | ||
* Return a range of numbers or letters. | ||
* | ||
* @param {String} `a` Start of the range | ||
* @param {String} `b` End of the range | ||
* @param {String} `start` Start of the range | ||
* @param {String} `stop` End of the range | ||
* @param {String} `step` Increment or decrement to use. | ||
@@ -33,378 +27,175 @@ * @param {Function} `fn` Custom function to modify each element in the range. | ||
function fillRange(a, b, step, options, fn) { | ||
if (a == null || b == null) { | ||
throw new Error('fill-range expects the first and second args to be strings.'); | ||
function fillRange(start, stop, step, options) { | ||
if (typeof start === 'undefined') { | ||
return []; | ||
} | ||
if (typeof step === 'function') { | ||
fn = step; options = {}; step = null; | ||
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 options === 'function') { | ||
fn = options; options = {}; | ||
if (typeof step !== 'number' && typeof step !== 'string') { | ||
options = step; | ||
step = null; | ||
} | ||
if (isObject(step)) { | ||
options = step; step = ''; | ||
if (typeof options === 'function') { | ||
options = { transform: options }; | ||
} | ||
var expand, regex = false, sep = ''; | ||
var opts = options || {}; | ||
if (typeof opts.silent === 'undefined') { | ||
opts.silent = true; | ||
} | ||
step = step || opts.step; | ||
// store a ref to unmodified arg | ||
var origA = a, origB = b; | ||
b = (b.toString() === '-0') ? 0 : b; | ||
if (opts.optimize || opts.makeRe) { | ||
step = step ? (step += '~') : step; | ||
expand = true; | ||
regex = true; | ||
sep = '~'; | ||
} | ||
// handle special step characters | ||
if (typeof step === 'string') { | ||
var match = stepRe().exec(step); | ||
if (match) { | ||
var i = match.index; | ||
var m = match[0]; | ||
// repeat string | ||
if (m === '+') { | ||
return repeat(a, b); | ||
// randomize a, `b` times | ||
} else if (m === '?') { | ||
return [randomize(a, b)]; | ||
// expand right, no regex reduction | ||
} else if (m === '>') { | ||
step = step.substr(0, i) + step.substr(i + 1); | ||
expand = true; | ||
// expand to an array, or if valid create a reduced | ||
// string for a regex logic `or` | ||
} else if (m === '|') { | ||
step = step.substr(0, i) + step.substr(i + 1); | ||
expand = true; | ||
regex = true; | ||
sep = m; | ||
// expand to an array, or if valid create a reduced | ||
// string for a regex range | ||
} else if (m === '~') { | ||
step = step.substr(0, i) + step.substr(i + 1); | ||
expand = true; | ||
regex = true; | ||
sep = m; | ||
} | ||
} else if (!isNumber(step)) { | ||
if (!opts.silent) { | ||
throw new TypeError('fill-range: invalid step.'); | ||
} | ||
return null; | ||
var opts = extend({step: step}, options); | ||
if (opts.step && !isValidNumber(opts.step)) { | ||
if (opts.strict === true) { | ||
throw new TypeError('expected options.step to be a number'); | ||
} | ||
return []; | ||
} | ||
if (/[.&*()[\]^%$#@!]/.test(a) || /[.&*()[\]^%$#@!]/.test(b)) { | ||
if (!opts.silent) { | ||
throw new RangeError('fill-range: invalid range arguments.'); | ||
opts.isNumber = isValidNumber(start) && isValidNumber(stop); | ||
if (!opts.isNumber && !isValid(start, stop)) { | ||
if (opts.strict === true) { | ||
throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); | ||
} | ||
return null; | ||
return []; | ||
} | ||
// has neither a letter nor number, or has both letters and numbers | ||
// this needs to be after the step logic | ||
if (!noAlphaNum(a) || !noAlphaNum(b) || hasBoth(a) || hasBoth(b)) { | ||
if (!opts.silent) { | ||
throw new RangeError('fill-range: invalid range arguments.'); | ||
} | ||
return null; | ||
} | ||
opts.isPadded = isPadded(start) || isPadded(stop); | ||
opts.toString = opts.stringify | ||
|| typeof opts.step === 'string' | ||
|| typeof start === 'string' | ||
|| typeof stop === 'string' | ||
|| !opts.isNumber; | ||
// validate arguments | ||
var isNumA = isNumber(zeros(a)); | ||
var isNumB = isNumber(zeros(b)); | ||
if ((!isNumA && isNumB) || (isNumA && !isNumB)) { | ||
if (!opts.silent) { | ||
throw new TypeError('fill-range: first range argument is incompatible with second.'); | ||
} | ||
return null; | ||
if (opts.isPadded) { | ||
opts.maxLength = Math.max(String(start).length, String(stop).length); | ||
} | ||
// by this point both are the same, so we | ||
// can use A to check going forward. | ||
var isNum = isNumA; | ||
var num = formatStep(step); | ||
// 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); | ||
} | ||
// is the range alphabetical? or numeric? | ||
if (isNum) { | ||
// if numeric, coerce to an integer | ||
a = +a; b = +b; | ||
} else { | ||
// otherwise, get the charCode to expand alpha ranges | ||
a = a.charCodeAt(0); | ||
b = b.charCodeAt(0); | ||
} | ||
function expand(start, stop, options) { | ||
var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); | ||
var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); | ||
// is the pattern descending? | ||
var isDescending = a > b; | ||
// don't create a character class if the args are < 0 | ||
if (a < 0 || b < 0) { | ||
expand = false; | ||
regex = false; | ||
var step = Math.abs(toNumber(options.step)) || 1; | ||
if (options.toRegex && step === 1) { | ||
return toRange(a, b, options); | ||
} | ||
// detect padding | ||
var padding = isPadded(origA, origB); | ||
var res, pad, arr = []; | ||
var ii = 0; | ||
var zero = {greater: [], lesser: []}; | ||
var asc = a < b; | ||
var arr = new Array(Math.round((asc ? b - a : a - b) / step)); | ||
var idx = 0; | ||
// character classes, ranges and logical `or` | ||
if (regex) { | ||
if (shouldExpand(a, b, num, isNum, padding, opts)) { | ||
// make sure the correct separator is used | ||
if (sep === '|' || sep === '~') { | ||
sep = detectSeparator(a, b, num, isNum, isDescending); | ||
} | ||
return wrap([origA, origB], sep, opts); | ||
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)); | ||
} | ||
} | ||
while (isDescending ? (a >= b) : (a <= b)) { | ||
if (padding && isNum) { | ||
pad = padding(a); | ||
if (options.isPadded) { | ||
val = zeros(val, options); | ||
} | ||
// custom function | ||
if (typeof fn === 'function') { | ||
res = fn(a, isNum, pad, ii++); | ||
if (options.toString) { | ||
val = String(val); | ||
} | ||
// letters | ||
} else if (!isNum) { | ||
if (regex && isInvalidChar(a)) { | ||
res = null; | ||
} else { | ||
res = String.fromCharCode(a); | ||
} | ||
// numbers | ||
if (typeof options.transform === 'function') { | ||
arr[idx++] = options.transform(val, a, b, step, idx, arr, options); | ||
} else { | ||
res = formatPadding(a, pad); | ||
arr[idx++] = val; | ||
} | ||
// add result to the array, filtering any nulled values | ||
if (res !== null) arr.push(res); | ||
// increment or decrement | ||
if (isDescending) { | ||
a -= num; | ||
if (asc) { | ||
a += step; | ||
} else { | ||
a += num; | ||
a -= step; | ||
} | ||
} | ||
// now that the array is expanded, we need to handle regex | ||
// character classes, ranges or logical `or` that wasn't | ||
// already handled before the loop | ||
if ((regex || expand) && !opts.noexpand) { | ||
// make sure the correct separator is used | ||
if (sep === '|' || sep === '~') { | ||
sep = detectSeparator(a, b, num, isNum, isDescending); | ||
} | ||
if (arr.length === 1 || a < 0 || b < 0) { return arr; } | ||
return wrap(arr, sep, opts); | ||
if (options.toRegex === true) { | ||
return toSequence(arr, zero); | ||
} | ||
return arr; | ||
} | ||
/** | ||
* Wrap the string with the correct regex | ||
* syntax. | ||
*/ | ||
function wrap(arr, sep, opts) { | ||
if (sep === '~') { sep = '-'; } | ||
var str = arr.join(sep); | ||
var pre = opts && opts.regexPrefix; | ||
// regex logical `or` | ||
if (sep === '|') { | ||
str = pre ? pre + str : str; | ||
str = '(' + str + ')'; | ||
function toRange(a, b, options) { | ||
if (options.isNumber) { | ||
return toRegex(a, b); | ||
} | ||
// regex character class | ||
if (sep === '-') { | ||
str = (pre && pre === '^') | ||
? pre + str | ||
: str; | ||
str = '[' + str + ']'; | ||
} | ||
return [str]; | ||
var start = String.fromCharCode(Math.min(a, b)); | ||
var stop = String.fromCharCode(Math.max(a, b)); | ||
return '[' + start + '-' + stop + ']'; | ||
} | ||
/** | ||
* Check for invalid characters | ||
*/ | ||
function isCharClass(a, b, step, isNum, isDescending) { | ||
if (isDescending) { return false; } | ||
if (isNum) { return a <= 9 && b <= 9; } | ||
if (a < b) { return step === 1; } | ||
return false; | ||
} | ||
/** | ||
* Detect the correct separator to use | ||
*/ | ||
function shouldExpand(a, b, num, isNum, padding, opts) { | ||
if (isNum && (a > 9 || b > 9)) { return false; } | ||
return !padding && num === 1 && a < b; | ||
} | ||
/** | ||
* Detect the correct separator to use | ||
*/ | ||
function detectSeparator(a, b, step, isNum, isDescending) { | ||
var isChar = isCharClass(a, b, step, isNum, isDescending); | ||
if (!isChar) { | ||
return '|'; | ||
function toSequence(arr, zeros) { | ||
var greater = '', lesser = ''; | ||
if (zeros.greater.length) { | ||
greater = zeros.greater.join('|'); | ||
} | ||
return '~'; | ||
if (zeros.lesser.length) { | ||
lesser = '-(' + zeros.lesser.join('|') + ')'; | ||
} | ||
if (greater && lesser) { | ||
return greater + '|' + lesser; | ||
} | ||
return greater || lesser; | ||
} | ||
/** | ||
* Correctly format the step based on type | ||
*/ | ||
function formatStep(step) { | ||
return Math.abs(step >> 0) || 1; | ||
} | ||
/** | ||
* Format padding, taking leading `-` into account | ||
*/ | ||
function formatPadding(ch, pad) { | ||
var res = pad ? pad + ch : ch; | ||
if (pad && ch.toString().charAt(0) === '-') { | ||
res = '-' + pad + ch.toString().substr(1); | ||
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); | ||
} | ||
return res.toString(); | ||
if (options.stringify) { | ||
return String(val); | ||
} | ||
return val; | ||
} | ||
/** | ||
* Check for invalid characters | ||
*/ | ||
function isInvalidChar(str) { | ||
var ch = toStr(str); | ||
return ch === '\\' | ||
|| ch === '[' | ||
|| ch === ']' | ||
|| ch === '^' | ||
|| ch === '(' | ||
|| ch === ')' | ||
|| ch === '`'; | ||
function toNumber(val) { | ||
return val >> 0; | ||
} | ||
/** | ||
* Convert to a string from a charCode | ||
*/ | ||
function toStr(ch) { | ||
return String.fromCharCode(ch); | ||
function isPadded(str) { | ||
return /^-*0\d+/.test(str); | ||
} | ||
/** | ||
* Step regex | ||
*/ | ||
function stepRe() { | ||
return /\?|>|\||\+|\~/g; | ||
function isValid(min, max) { | ||
return (isValidNumber(min) || isValidLetter(min)) | ||
&& (isValidNumber(max) || isValidLetter(max)); | ||
} | ||
/** | ||
* Return true if `val` has either a letter | ||
* or a number | ||
*/ | ||
function noAlphaNum(val) { | ||
return /[a-z0-9]/i.test(val); | ||
function isValidLetter(ch) { | ||
return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); | ||
} | ||
/** | ||
* Return true if `val` has both a letter and | ||
* a number (invalid) | ||
*/ | ||
function hasBoth(val) { | ||
return /[a-z][0-9]|[0-9][a-z]/i.test(val); | ||
function isValidNumber(n) { | ||
return isNumber(n) && !/\./.test(n); | ||
} | ||
/** | ||
* Normalize zeros for checks | ||
* Expose `fillRange` | ||
* @type {Function} | ||
*/ | ||
function zeros(val) { | ||
if (/^-*0+$/.test(val.toString())) { | ||
return '0'; | ||
} | ||
return val; | ||
} | ||
/** | ||
* Return true if `val` has leading zeros, | ||
* or a similar valid pattern. | ||
*/ | ||
function hasZeros(val) { | ||
return /[^.]\.|^-*0+[0-9]/.test(val); | ||
} | ||
/** | ||
* If the string is padded, returns a curried function with | ||
* the a cached padding string, or `false` if no padding. | ||
* | ||
* @param {*} `origA` String or number. | ||
* @return {String|Boolean} | ||
*/ | ||
function isPadded(origA, origB) { | ||
if (hasZeros(origA) || hasZeros(origB)) { | ||
var alen = length(origA); | ||
var blen = length(origB); | ||
var len = alen >= blen | ||
? alen | ||
: blen; | ||
return function (a) { | ||
return repeatStr('0', len - length(a)); | ||
}; | ||
} | ||
return false; | ||
} | ||
/** | ||
* Get the string length of `val` | ||
*/ | ||
function length(val) { | ||
return val.toString().length; | ||
} | ||
module.exports = fillRange; |
{ | ||
"name": "fill-range", | ||
"description": "Fill in a range of numbers or letters, optionally passing an increment or multiplier to use.", | ||
"version": "2.2.3", | ||
"description": "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`", | ||
"version": "3.0.0", | ||
"homepage": "https://github.com/jonschlinkert/fill-range", | ||
"author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"contributors": [ | ||
"Jon Schlinkert <jon.schlinkert@sellside.com> (http://twitter.com/jonschlinkert)", | ||
"Paul Miller <paul+gh@paulmillr.com> (paulmillr.com)" | ||
], | ||
"repository": "jonschlinkert/fill-range", | ||
@@ -23,14 +27,13 @@ "bugs": { | ||
"dependencies": { | ||
"is-number": "^2.1.0", | ||
"isobject": "^2.0.0", | ||
"randomatic": "^1.1.3", | ||
"repeat-element": "^1.1.2", | ||
"repeat-string": "^1.5.2" | ||
"extend-shallow": "^2.0.1", | ||
"is-number": "^3.0.0", | ||
"repeat-string": "^1.5.4", | ||
"to-regex-range": "^0.2.0" | ||
}, | ||
"devDependencies": { | ||
"benchmarked": "^0.1.3", | ||
"chalk": "^0.5.1", | ||
"should": "*" | ||
"gulp-format-md": "^0.1.10", | ||
"mocha": "^3.0.2" | ||
}, | ||
"keywords": [ | ||
"array", | ||
"alpha", | ||
@@ -42,2 +45,3 @@ "alphabetical", | ||
"expansion", | ||
"fill", | ||
"glob", | ||
@@ -49,2 +53,3 @@ "match", | ||
"numerical", | ||
"regex", | ||
"range", | ||
@@ -57,9 +62,24 @@ "ranges", | ||
"list": [ | ||
"micromatch", | ||
"braces", | ||
"to-regex-range", | ||
"expand-range", | ||
"braces", | ||
"is-glob" | ||
"micromatch" | ||
] | ||
} | ||
}, | ||
"toc": true, | ||
"layout": "default", | ||
"tasks": [ | ||
"readme" | ||
], | ||
"plugins": [ | ||
"gulp-format-md" | ||
], | ||
"lint": { | ||
"reflinks": true | ||
}, | ||
"reflinks": [ | ||
"verb", | ||
"verb-generate-readme" | ||
] | ||
} | ||
} |
297
README.md
@@ -1,84 +0,108 @@ | ||
# fill-range [![NPM version](https://badge.fury.io/js/fill-range.svg)](http://badge.fury.io/js/fill-range) [![Build Status](https://travis-ci.org/jonschlinkert/fill-range.svg)](https://travis-ci.org/jonschlinkert/fill-range) | ||
# fill-range [![NPM version](https://img.shields.io/npm/v/fill-range.svg?style=flat)](https://www.npmjs.com/package/fill-range) [![NPM downloads](https://img.shields.io/npm/dm/fill-range.svg?style=flat)](https://npmjs.org/package/fill-range) [![Build Status](https://img.shields.io/travis/jonschlinkert/fill-range.svg?style=flat)](https://travis-ci.org/jonschlinkert/fill-range) | ||
> Fill in a range of numbers or letters, optionally passing an increment or multiplier to use. | ||
> Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex` | ||
## Install with [npm](npmjs.org) | ||
## Table of Contents | ||
```bash | ||
npm i fill-range --save | ||
``` | ||
<!-- toc --> | ||
- [Install](#install) | ||
- [Usage](#usage) | ||
* [Invalid ranges](#invalid-ranges) | ||
* [Custom function](#custom-function) | ||
* [Special characters](#special-characters) | ||
+ [plus](#plus) | ||
+ [pipe and tilde](#pipe-and-tilde) | ||
+ [angle bracket](#angle-bracket) | ||
+ [question mark](#question-mark) | ||
- [Other useful libs](#other-useful-libs) | ||
- [Running tests](#running-tests) | ||
- [Contributing](#contributing) | ||
- [Author](#author) | ||
- [License](#license) | ||
- [About](#about) | ||
* [Related projects](#related-projects) | ||
* [Contributing](#contributing) | ||
* [Building docs](#building-docs) | ||
* [Running tests](#running-tests) | ||
* [Author](#author) | ||
* [License](#license) | ||
_(Table of contents generated by [verb])_ | ||
_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_ | ||
<!-- tocstop --> | ||
## Install | ||
Install with [npm](https://www.npmjs.com/): | ||
```sh | ||
$ npm install --save fill-range | ||
``` | ||
## Usage | ||
Expands numbers and letters, optionally using a `step` as the last argument. _(Numbers may be defined as JavaScript numbers or strings)_. | ||
```js | ||
var range = require('fill-range'); | ||
var fill = require('fill-range'); | ||
range('a', 'e'); | ||
console.log(fill('a', 'e')); | ||
//=> ['a', 'b', 'c', 'd', 'e'] | ||
console.log(fill(0, 25, 5)); | ||
//=> [ 0, 5, 10, 15, 20, 25 ] | ||
console.log(fill('a', 'e', {toRegex: true})); | ||
//=> '[a-e]' | ||
console.log(fill('a', 'z', 3, {toRegex: true})); | ||
//=> 'a|d|g|j|m|p|s|v|y' | ||
console.log(fill('1', '100', {toRegex: true})); | ||
//=> '[1-9]|[1-9][0-9]|100' | ||
``` | ||
Create regex-compatible ranges (returns a string, which can be used however you need to create a regex): | ||
```js | ||
console.log(fill('a', 'e', {toRegex: true})); | ||
//=> '[a-e]' | ||
console.log(fill('a', 'z', 3, {toRegex: true})); | ||
//=> 'a|d|g|j|m|p|s|v|y' | ||
console.log(fill('1', '100', {toRegex: true})); | ||
//=> '[1-9]|[1-9][0-9]|100' | ||
``` | ||
**Params** | ||
```js | ||
range(start, stop, step, options, fn); | ||
fill(start, stop, step, options, fn); | ||
``` | ||
- `start`: **{String|Number}** the number or letter to start with | ||
- `end`: **{String|Number}** the number or letter to end with | ||
- `step`: **{String|Number}** optionally pass the step to use. works for letters or numbers. | ||
- `options`: **{Object}**: | ||
+ `makeRe`: return a regex-compatible string (still returned as an array for consistency) | ||
+ `step`: pass the step on the options as an alternative to passing it as an argument | ||
+ `silent`: `true` by default, set to false to throw errors for invalid ranges. | ||
- `fn`: **{Function}** optionally [pass a function](#custom-function) to modify each character | ||
* `start`: **{String|Number}** the number or letter to start with | ||
* `end`: **{String|Number}** the number or letter to end with | ||
* `step`: **{String|Number}** optionally pass the step to use. works for letters or numbers. | ||
* `options`: **{Object}**: | ||
- `toRegex`: return a regex-compatible string (still returned as an array for consistency) | ||
- `step`: pass the step on the options as an alternative to passing it as an argument | ||
- `strict`: `undefined` by default, set to true to throw errors on invalid ranges. | ||
* `fn`: **{Function}** optionally [pass a function](#custom-function) to modify each character. This can also be defined as `options.transform` | ||
**Examples** | ||
```js | ||
range(1, 3) | ||
fill(1, 3) | ||
//=> ['1', '2', '3'] | ||
range('1', '3') | ||
fill('1', '3') | ||
//=> ['1', '2', '3'] | ||
range('0', '-5') | ||
fill('0', '-5') | ||
//=> [ '0', '-1', '-2', '-3', '-4', '-5' ] | ||
range(-9, 9, 3) | ||
fill(-9, 9, 3) | ||
//=> [ '-9', '-6', '-3', '0', '3', '6', '9' ]) | ||
range('-1', '-10', '-2') | ||
fill('-1', '-10', '-2') | ||
//=> [ '-1', '-3', '-5', '-7', '-9' ] | ||
range('1', '10', '2') | ||
fill('1', '10', '2') | ||
//=> [ '1', '3', '5', '7', '9' ] | ||
range('a', 'e') | ||
fill('a', 'e') | ||
//=> ['a', 'b', 'c', 'd', 'e'] | ||
range('a', 'e', 2) | ||
fill('a', 'e', 2) | ||
//=> ['a', 'c', 'e'] | ||
range('A', 'E', 2) | ||
fill('A', 'E', 2) | ||
//=> ['A', 'C', 'E'] | ||
@@ -89,24 +113,23 @@ ``` | ||
When an invalid range is passed, `null` is returned. | ||
When an invalid range is passed, `null` is returned. | ||
```js | ||
range('1.1', '2'); | ||
fill('1.1', '2'); // decimals not supported in ranges | ||
//=> null | ||
range('a', '2'); | ||
fill('a', '2'); // unmatched values | ||
//=> null | ||
range(1, 10, 'foo'); | ||
fill(1, 10, 'foo'); // invalid step | ||
//=> null | ||
``` | ||
If you want errors to be throw, pass `silent: false` on the options: | ||
If you want errors to be throw, set `options.strict` to true. | ||
### Custom function | ||
Optionally pass a custom function as the third or fourth argument: | ||
Optionally pass a custom function as the third or fourth argument or on `options.transform`. | ||
```js | ||
range('a', 'e', function (val, isNumber, pad, i) { | ||
fill('a', 'e', function (val, isNumber, pad, i) { | ||
if (!isNumber) { | ||
@@ -120,173 +143,47 @@ return String.fromCharCode(val) + i; | ||
### Special characters | ||
## About | ||
A special character may be passed as the third arg instead of a step increment. These characters can be pretty useful for brace expansion, creating file paths, test fixtures and similar use case. | ||
### Related projects | ||
```js | ||
range('a', 'z', SPECIAL_CHARACTER_HERE); | ||
``` | ||
* [braces](https://www.npmjs.com/package/braces): Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces… [more](https://github.com/jonschlinkert/braces) | [homepage](https://github.com/jonschlinkert/braces "Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces specification.") | ||
* [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See… [more](https://github.com/jonschlinkert/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range "Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See the benchmarks. Used by micromatch.") | ||
* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") | ||
* [to-regex-range](https://www.npmjs.com/package/to-regex-range): Returns a regex-compatible range from two numbers, min and max, with 855,412 generated unit tests… [more](https://github.com/jonschlinkert/to-regex-range) | [homepage](https://github.com/jonschlinkert/to-regex-range "Returns a regex-compatible range from two numbers, min and max, with 855,412 generated unit tests to validate it's accuracy! Useful for creating regular expressions to validate numbers, ranges, years, etc. Returns a string, allowing the returned value to ") | ||
**Supported characters** | ||
### Contributing | ||
- `+`: repeat the given string `n` times | ||
- `|`: create a regex-ready string, instead of an array | ||
- `>`: join values to single array element | ||
- `?`: randomize the given pattern using [randomatic] | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). | ||
#### plus | ||
### Building docs | ||
Character: _(`+`)_ | ||
_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ | ||
Repeat the first argument the number of times passed on the second argument. | ||
To generate the readme and API documentation with [verb](https://github.com/verbose/verb): | ||
**Examples:** | ||
```js | ||
range('a', 3, '+'); | ||
//=> ['a', 'a', 'a'] | ||
range('abc', 2, '+'); | ||
//=> ['abc', 'abc'] | ||
```sh | ||
$ npm install -g verb verb-generate-readme && verb | ||
``` | ||
#### pipe and tilde | ||
### Running tests | ||
Characters: _(`|` and `~`)_ | ||
Creates a regex-capable string (either a logical `or` or a character class) from the expanded arguments. | ||
**Examples:** | ||
```js | ||
range('a', 'c', '|'); | ||
//=> ['(a|b|c)' | ||
range('a', 'c', '~'); | ||
//=> ['[a-c]' | ||
range('a', 'z', '|5'); | ||
//=> ['(a|f|k|p|u|z)' | ||
``` | ||
**Automatic separator correction** | ||
To avoid this error: | ||
> `Range out of order in character class` | ||
Fill-range detects invalid sequences and uses the correct syntax. For example: | ||
**invalid** (regex) | ||
If you pass these: | ||
```js | ||
range('a', 'z', '~5'); | ||
// which would result in this | ||
//=> ['[a-f-k-p-u-z]'] | ||
range('10', '20', '~'); | ||
// which would result in this | ||
//=> ['[10-20]'] | ||
``` | ||
**valid** (regex) | ||
fill-range corrects them to this: | ||
```js | ||
range('a', 'z', '~5'); | ||
//=> ['(a|f|k|p|u|z)' | ||
range('10', '20', '~'); | ||
//=> ['(10-20)' | ||
``` | ||
#### angle bracket | ||
Character: _(`>`)_ | ||
Joins all values in the returned array to a single value. | ||
**Examples:** | ||
```js | ||
range('a', 'e', '>'); | ||
//=> ['abcde'] | ||
range('5', '8', '>'); | ||
//=> ['5678'] | ||
range('2', '20', '2>'); | ||
//=> ['2468101214161820'] | ||
``` | ||
#### question mark | ||
Character: _(`?`)_ | ||
Uses [randomatic] to generate randomized alpha, numeric, or alpha-numeric patterns based on the provided arguments. | ||
**Examples:** | ||
_(actual results would obviously be randomized)_ | ||
Generate a 5-character, uppercase, alphabetical string: | ||
```js | ||
range('A', 5, '?'); | ||
//=> ['NSHAK'] | ||
``` | ||
Generate a 5-digit random number: | ||
```js | ||
range('0', 5, '?'); | ||
//=> ['36583'] | ||
``` | ||
Generate a 10-character alpha-numeric string: | ||
```js | ||
range('A0', 10, '?'); | ||
//=> ['5YJD60VQNN'] | ||
``` | ||
See the [randomatic] repo for all available options and or to create issues or feature requests related to randomization. | ||
## Other useful libs | ||
* [micromatch](https://github.com/jonschlinkert/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. Just use `micromatch.isMatch()` instead of `minimatch()`, or use `micromatch()` instead of `multimatch()`. | ||
* [expand-range](https://github.com/jonschlinkert/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See the benchmarks. Used by micromatch. | ||
* [braces](https://github.com/jonschlinkert/braces): Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces specification. | ||
* [is-glob](https://github.com/jonschlinkert/is-glob): Returns `true` if the given string looks like a glob pattern. | ||
## Running tests | ||
Install dev dependencies: | ||
```bash | ||
npm i -d && npm test | ||
```sh | ||
$ npm install -d && npm test | ||
``` | ||
## Contributing | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/fill-range/issues) | ||
### Author | ||
## Author | ||
**Jon Schlinkert** | ||
+ [github/jonschlinkert](https://github.com/jonschlinkert) | ||
+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
* [github/jonschlinkert](https://github.com/jonschlinkert) | ||
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
## License | ||
Copyright (c) 2014-2015 Jon Schlinkert | ||
Released under the MIT license | ||
### License | ||
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). | ||
Released under the [MIT license](https://github.com/jonschlinkert/fill-range/blob/master/LICENSE). | ||
*** | ||
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on April 07, 2015._ | ||
[randomatic]: https://github.com/jonschlinkert/randomatic | ||
[expand-range]: https://github.com/jonschlinkert/expand-range | ||
[micromatch]: https://github.com/jonschlinkert/micromatch | ||
[braces]: https://github.com/jonschlinkert/braces | ||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.30, on September 15, 2016._ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4
2
14171
168
187
1
+ Addedextend-shallow@^2.0.1
+ Addedto-regex-range@^0.2.0
+ Addedextend-shallow@2.0.1(transitive)
+ Addedis-extendable@0.1.1(transitive)
+ Addedto-regex-range@0.2.0(transitive)
- Removedisobject@^2.0.0
- Removedrandomatic@^1.1.3
- Removedrepeat-element@^1.1.2
- Removedisarray@1.0.0(transitive)
- Removedisobject@2.1.0(transitive)
- Removedkind-of@4.0.0(transitive)
- Removedrandomatic@1.1.7(transitive)
- Removedrepeat-element@1.1.4(transitive)
Updatedis-number@^3.0.0
Updatedrepeat-string@^1.5.4