Comparing version 0.3.0 to 0.3.1
@@ -24,10 +24,46 @@ var ret = require('ret') | ||
// returns true if all properties of a are equal to b | ||
// a and b are arrays of objects | ||
var deepEqual = function(a, b) { | ||
var i, l, key, obj; | ||
if ((l = a.length) !== b.length) return false; | ||
for (i = 0; i < l; i++) { | ||
obj = a[i]; | ||
for (key in obj) { | ||
if (obj.hasOwnProperty(key) && obj[key] !== b[i][key]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
// returns true if negated needle set is inside of sets array | ||
// using deepEqual as comparator | ||
var findNotSet = function(sets, needle) { | ||
for (var i = 0, l = sets.length; i < l; i++) { | ||
var cset = sets[i]; | ||
if (cset.not !== needle.not && deepEqual(cset.set, needle.set)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
// returns true if character is in class set | ||
var inClass = function(set, code, ignoreCase) { | ||
var token | ||
, v | ||
, sets = [] | ||
, infLoop = false | ||
for (var i = 0, l = set.length; i < l; i++) { | ||
var token = set[i]; | ||
token = set[i] | ||
switch (token.type) { | ||
case types.CHAR: | ||
var v = token.value; | ||
v = token.value; | ||
if (v === code || (ignoreCase && toOtherCase(v) === code)) { | ||
@@ -39,8 +75,9 @@ return true; | ||
case types.RANGE: | ||
var r; | ||
// if ignoreCase is on, and alphabetic character ranges fall | ||
// inside this range, check against both cases | ||
if (token.from <= code && code <= token.to || (ignoreCase && | ||
(((r = range(97, 122, token.from, token.to)) !== false && | ||
r.from <= code && code <= r.to) || | ||
((r = range(65, 90, token.from, token.to)) !== false && | ||
r.from <= code && code <= r.to)))) { | ||
(((v = range(97, 122, token.from, token.to)) !== false && | ||
v.from <= code && code <= v.to) || | ||
((v = range(65, 90, token.from, token.to)) !== false && | ||
v.from <= code && code <= v.to)))) { | ||
return true; | ||
@@ -50,4 +87,13 @@ } | ||
case types.CLASS: | ||
if (inClass(token.set, code, ignoreCase)) { | ||
case types.SET: | ||
// use these to detect an infinite loop with 2 sets | ||
// that cancel out each other | ||
if (sets.length > 0 && findNotSet(sets, token)) { | ||
infLoop = true; | ||
} else { | ||
sets.push(token); | ||
} | ||
if (!infLoop && | ||
!inClass(token.set, code, ignoreCase) !== !token.not) { | ||
return true; | ||
@@ -70,3 +116,3 @@ } | ||
// generate random string modeled after given tokens | ||
var gen = function(token, groups) { | ||
var gen = function(token, groups, negate) { | ||
switch (token.type) { | ||
@@ -103,3 +149,3 @@ | ||
case types.CLASS: | ||
case types.SET: | ||
@@ -109,3 +155,4 @@ // if this class is an except class i.e. [^abc] | ||
// is found | ||
if (token.not) { | ||
var not = !negate !== !token.not; | ||
if (not) { | ||
while (true) { | ||
@@ -122,3 +169,4 @@ var c = this.anyRandChar() | ||
return gen.call(this, | ||
token.set[Math.floor(Math.random() * token.set.length)]); | ||
token.set[Math.floor(Math.random() * token.set.length)], | ||
groups, not); | ||
} | ||
@@ -226,7 +274,1 @@ | ||
}; | ||
// export to browser | ||
if (typeof window !== 'undefined') { | ||
window.RandExp = RandExp; | ||
} |
@@ -5,3 +5,3 @@ { | ||
"keywords": ["regex", "regexp", "regular expression", "random"], | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"homepage": "http://fent.github.com/randexp.js/", | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -14,7 +14,7 @@ # randexp.js [![Build Status](https://secure.travis-ci.org/fent/randexp.js.png)](http://travis-ci.org/fent/randexp.js) | ||
// classes and ranges and references | ||
// sets and ranges and references | ||
new RandExp(/<([a-z]\w{0,20})>foo<\1>/).gen(); | ||
// => <m5xhdg>foo<m5xhdg> | ||
// wildcard class | ||
// wildcard | ||
new RandExp(/random stuff: .+/).gen(); | ||
@@ -54,17 +54,9 @@ // => random stuff: 湐箻ໜ䫴㳸長���邓蕲뤀쑡篷皇硬剈궦佔칗븛뀃匫鴔事좍ﯣ⭼ꝏ䭍詳蒂䥂뽭 | ||
Thanks to [String-Random](http://search.cpan.org/~steve/String-Random-0.22/lib/String/Random.pm) for giving me the idea to make this in the first place and [randexp](https://github.com/benburkert/randexp) for the nifty little `.gen` syntax. | ||
Thanks to [String-Random](http://search.cpan.org/~steve/String-Random-0.22/lib/String/Random.pm) for giving me the idea to make this in the first place and [randexp](https://github.com/benburkert/randexp) for the sweet `.gen()` syntax. | ||
# Limitations | ||
I wish I could say randexp is guaranteed to generate a string that will always match the given regex. But ONE limitation prevents me. Positionals. You can make a regex object that is guaranteed to never match any string. Such as | ||
# Negated Character Sets | ||
Sets like the `.` character will match anything except a new line. In this case, a character with a random char code between 0 and 65535 will be generated. If you want to overwrite this function you can change the `anyRandChar` function in the randexp object. | ||
```js | ||
/a^b/m | ||
``` | ||
That will never match any string because it will never be next to the beginning of the expression or a new line character. For now, positionals (`^$\\b\\B`) are ignored. In the above case, randexp will generate the string `ab`. | ||
Classes like the `.` character will match anything except a new line. In this case, a character with a random char code between 0 and 65535 will be generated. If you want to overwrite this function you can change the `anyRandChar` function in the randexp object. | ||
```js | ||
var randexp = new RandExp(/./); | ||
@@ -85,4 +77,6 @@ randexp.anyRandChar = function() { | ||
Repetitionals such as `*`, `+`, and `{3,}` have an infinite max range. In this case, randexp looks at its min and adds 100 to it to get a useable max value. If you want to use another int other than 100 you can change the `max` property in the randexp object. | ||
# Infinite Repetitionals | ||
Repetitional tokens such as `*`, `+`, and `{3,}` have an infinite max range. In this case, randexp looks at its min and adds 100 to it to get a useable max value. If you want to use another int other than 100 you can change the `max` property in the randexp object. | ||
```js | ||
@@ -100,3 +94,12 @@ var randexp = new RandExp(/no{1,}/); | ||
# Bad Regular Expressions | ||
There are some regular expressions which can never match any string. | ||
* Ones with badly placed positionals such as `/a^/` and `/$c/m`. Randexp will ignore positional tokens. | ||
* Custom negated character sets with two sets inside that cancel each other out. Example: `/[^\w\W]/`. If you give this to randexp, it will ignore both set tokens. | ||
Other cancelling out character sets like `/[^\D]/` are bad too. These are the same as `/[\d]/`. Except it will be slow in generating a matching string because it will first generate a random character and then check if it's in the set inside. It will take a while to randomly generate an integer out of 65535 characters. | ||
# Install | ||
@@ -103,0 +106,0 @@ ### Node.js |
var tests = require('./tests.js') | ||
, assert = require('assert') | ||
, RandExp = require('..') | ||
, randexp = require('..').randexp | ||
var match = function(regexp, str, bad) { | ||
var err = 'Generated string \'' + str + '\' ' + | ||
(bad ? 'matches' : 'does not match') + ' ' + | ||
'regexp \'' + regexp.source + '\''; | ||
var t = regexp.test(str); | ||
assert.ok(!bad !== !t, err); | ||
}; | ||
for (var type in tests) { | ||
@@ -15,6 +24,17 @@ if (tests.hasOwnProperty(type)) { | ||
it(test.desc, function() { | ||
var randexp = new RandExp(test.regexp); | ||
var regs = test.regexp; | ||
if (!Array.isArray(regs)) { regs = [regs]; } | ||
assert.equal(true, test.regexp.test(randexp.gen())); | ||
assert.equal(true, test.regexp.test(randexp.gen())); | ||
for (var i = 0, l = regs.length; i < l; i++) { | ||
var reg = regs[i]; | ||
var rand = new RandExp(reg); | ||
var s, err; | ||
// generate several times | ||
for ( var k = 0; k < 5; k++) { | ||
match(reg, rand.gen(), test.bad); | ||
match(reg, randexp(reg), test.bad); | ||
} | ||
} | ||
}); | ||
@@ -21,0 +41,0 @@ |
@@ -34,2 +34,8 @@ module.exports = { | ||
desc: 'Matches any non-word boundary.' | ||
}, | ||
'Bad Regexp': { | ||
regexp: [/a^/m, /b^/, /$c/m, /$d/, /e\bf/, /\Bg/], | ||
desc: 'A string that matches these regular expressions does not exist.', | ||
bad: true | ||
} | ||
@@ -97,5 +103,5 @@ }, | ||
'Character Classes': { | ||
'Character Sets': { | ||
'[xyz]': { | ||
regexp: /[abc] [a-z] [0-4] [a-zA-Z0-9]/, | ||
regexp: [/[abc]/, /[a-z]/, /[0-4]/, /[a-zA-Z0-9]/, /[\w]/, /[\d]/, /[\s]/, /[\W]/, /[\D]/, /[\S]/], | ||
desc: 'Matches any one character enclosed in the character set. You may use a hyphen to denote range.' | ||
@@ -105,6 +111,12 @@ }, | ||
'[^xyz]': { | ||
regexp: /[^AN]BC/, | ||
regexp: [/[^AN]BC/, /[^\w]/, /[^\d]/, /[^\s]/, /[^\W]/, /[^\D]/, /[^\S]/], | ||
desc: 'Matches any one characer not enclosed in the character set.' | ||
}, | ||
'Bad Custom Sets': { | ||
regexp: [/[^\W\w]/, /[^\D\d]/, /[^\S\s]/], | ||
desc: 'A string that matches these regular expressions does not exist', | ||
bad: true | ||
}, | ||
'. (Dot)': { | ||
@@ -111,0 +123,0 @@ regexp: /b.t/, |
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
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
20429
450
121
0
0
10