verbal-expressions
Advanced tools
Comparing version 0.3.0 to 1.0.0
{ | ||
"name": "verbal-expressions", | ||
"description": "JavaScript Regular expressions made easy", | ||
"keywords": [ "regular expressions", "regex" ], | ||
"main": "VerbalExpressions.js", | ||
"license": "MIT", | ||
"ignore": [ | ||
"**/.*", | ||
"node_modules", | ||
"bower_components", | ||
"test", | ||
"tests", | ||
"Gruntfile.js", | ||
"package.json", | ||
"bower.json" | ||
] | ||
"name": "verbal-expressions", | ||
"description": "JavaScript Regular expressions made easy", | ||
"keywords": [ "regular expressions", "regex" ], | ||
"main": "dist/verbalexpressions.js", | ||
"license": "MIT", | ||
"ignore": [ | ||
"**/.*", | ||
"node_modules", | ||
"bower_components", | ||
"test", | ||
"tests", | ||
"Gruntfile.js", | ||
"package.json", | ||
"bower.json" | ||
] | ||
} |
@@ -1,305 +0,435 @@ | ||
/*! | ||
* VerbalExpressions JavaScript Library v0.3.0 | ||
* https://github.com/VerbalExpressions/JSVerbalExpressions | ||
(function (root, factory) { | ||
if (root === undefined && window !== undefined) root = window; | ||
if (typeof define === 'function' && define.amd) { | ||
// AMD. Register as an anonymous module unless amdModuleId is set | ||
define('VerEx', [], function () { | ||
return (root['VerEx'] = factory()); | ||
}); | ||
} else if (typeof module === 'object' && module.exports) { | ||
// Node. Does not work with strict CommonJS, but | ||
// only CommonJS-like environments that support module.exports, | ||
// like Node. | ||
module.exports = factory(); | ||
} else { | ||
root['VerEx'] = factory(); | ||
} | ||
}(this, function () { | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _extendableBuiltin(cls) { | ||
function ExtendableBuiltin() { | ||
var instance = Reflect.construct(cls, Array.from(arguments)); | ||
Object.setPrototypeOf(instance, Object.getPrototypeOf(this)); | ||
return instance; | ||
} | ||
ExtendableBuiltin.prototype = Object.create(cls.prototype, { | ||
constructor: { | ||
value: cls, | ||
enumerable: false, | ||
writable: true, | ||
configurable: true | ||
} | ||
}); | ||
if (Object.setPrototypeOf) { | ||
Object.setPrototypeOf(ExtendableBuiltin, cls); | ||
} else { | ||
ExtendableBuiltin.__proto__ = cls; | ||
} | ||
return ExtendableBuiltin; | ||
} | ||
/** | ||
* @file VerbalExpressions JavaScript Library | ||
* @version 0.3.0 | ||
* @license MIT | ||
* | ||
* | ||
* Released under the MIT license | ||
* http://opensource.org/licenses/MIT | ||
* @see https://github.com/VerbalExpressions/JSVerbalExpressions | ||
*/ | ||
/** | ||
* Define the VerbalExpression class. | ||
* @class | ||
*/ | ||
(function verbalExpressionIIFE(root) { | ||
// Constants | ||
var MODULE_NAME = 'VerEx'; | ||
* Define the VerbalExpression class | ||
* | ||
* @class VerbalExpression | ||
* @extends {RegExp} | ||
*/ | ||
var VerbalExpression = function (_extendableBuiltin2) { | ||
_inherits(VerbalExpression, _extendableBuiltin2); | ||
/** | ||
* I am the constructor function. | ||
* @constructor | ||
* @alias VerEx | ||
* @return {RegExp} A new instance of RegExp with injected methods | ||
*/ | ||
* Creates an instance of VerbalExpression. | ||
* @constructor | ||
* @alias VerEx | ||
* @memberof VerbalExpression | ||
*/ | ||
function VerbalExpression() { | ||
var verbalExpression = new RegExp(); | ||
_classCallCheck(this, VerbalExpression); | ||
// Add all the class methods | ||
VerbalExpression.injectClassMethods(verbalExpression); | ||
// Variables to hold the expression construction in order | ||
var _this = _possibleConstructorReturn(this, (VerbalExpression.__proto__ || Object.getPrototypeOf(VerbalExpression)).call(this, '', 'gm')); | ||
// Call the `RegExp` constructor so that `this` can be used | ||
// Return the new object. | ||
return verbalExpression; | ||
_this._prefixes = ''; | ||
_this._source = ''; | ||
_this._suffixes = ''; | ||
_this._modifiers = 'gm'; // 'global, multiline' matching by default | ||
return _this; | ||
} | ||
// Utility // | ||
/** | ||
* @param {RegExp} verbalExpression An instance of RegExp on which to add VerbalExpressions methods | ||
* @return {RegExp} A new instance of RegExp with injected methods | ||
*/ | ||
VerbalExpression.injectClassMethods = function injectClassMethods(verbalExpression) { | ||
var method; | ||
// Loop over all the prototype methods | ||
for (method in VerbalExpression.prototype) { | ||
// Make sure this is a local method. | ||
if (VerbalExpression.prototype.hasOwnProperty(method)) { | ||
// Add the method | ||
verbalExpression[method] = VerbalExpression.prototype[method]; | ||
} | ||
} | ||
* Escape meta-characters in the parameter and make it safe for adding to the expression | ||
* @static | ||
* @param {(string|RegExp|number)} value object to sanitize | ||
* @returns {string} sanitized value | ||
* @memberof VerbalExpression | ||
*/ | ||
return verbalExpression; | ||
}; | ||
/** | ||
* Define the class methods. | ||
*/ | ||
VerbalExpression.prototype = { | ||
// Variables to hold the whole | ||
// expression construction in order | ||
_prefixes: '', | ||
_source: '', | ||
_suffixes: '', | ||
_modifiers: 'gm', // default to global multiline matching | ||
_createClass(VerbalExpression, [{ | ||
key: 'add', | ||
/** | ||
* Sanitation function for adding anything safely to the expression | ||
* @param {String} value string to sanitize | ||
* @return {String} sanitized value | ||
*/ | ||
sanitize: function sanitize(value) { | ||
var reRegExpEscape; | ||
* Add stuff to the expression and compile the new expression so it's ready to be used. | ||
* @param {(string|number)} [value=''] stuff to add | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
value: function add() { | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
if (value.source) { | ||
return value.source; | ||
} | ||
this._source += value; | ||
var pattern = this._prefixes + this._source + this._suffixes; | ||
if (typeof value === 'number') { | ||
return value; | ||
} | ||
this.compile(pattern, this._modifiers); | ||
// Regular expression meta characters, URL: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp | ||
reRegExpEscape = /([\].|*?+(){}^$\\:=[])/g; | ||
return this; | ||
} | ||
// Escape RegExp special characters only | ||
// $& => Last match, URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch | ||
return value.replace(reRegExpEscape, '\\$&'); | ||
}, | ||
// Rules // | ||
/** | ||
* Function to add stuff to the expression. Also compiles the new expression so it's ready to be used. | ||
* @param {string} value literal expression, not sanitized | ||
* @return {VerbalExpression} Freshly recompiled instance of VerbalExpression | ||
*/ | ||
add: function add(value) { | ||
this._source += value || ''; | ||
this.compile(this._prefixes + this._source + this._suffixes, this._modifiers); | ||
* Control start-of-line matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
return this; | ||
}, | ||
}, { | ||
key: 'startOfLine', | ||
value: function startOfLine() { | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
/** | ||
* Control start-of-line matching | ||
* @param {Boolean} enable Control start-of-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
startOfLine: function startOfLine(enable) { | ||
enable = (enable !== false); | ||
this._prefixes = enable ? '^' : ''; | ||
return this.add(); | ||
}, | ||
} | ||
/** | ||
* Control end-of-line matching | ||
* @param {Boolean} enable Control end-of-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
endOfLine: function endOfLine(enable) { | ||
enable = (enable !== false); | ||
* Control end-of-line matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'endOfLine', | ||
value: function endOfLine() { | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
this._suffixes = enable ? '$' : ''; | ||
return this.add(); | ||
}, | ||
} | ||
/** | ||
* We try to keep the syntax as user-friendly as possible. So we can use the "normal" behaviour to split the "sentences" naturally. | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
then: function then(value) { | ||
value = this.sanitize(value); | ||
* Look for the value passed | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'then', | ||
value: function then(value) { | ||
value = VerbalExpression.sanitize(value); | ||
return this.add('(?:' + value + ')'); | ||
}, | ||
} | ||
/** | ||
* And because we can't start with "then" function, we create an alias to be used as the first function of the chain. | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
find: function find(value) { | ||
* Alias for then() to allow for readable syntax when then() is the first method in the chain. | ||
* @param {(string|RegExp|numer)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'find', | ||
value: function find(value) { | ||
return this.then(value); | ||
}, | ||
} | ||
/* | ||
* Maybe is used to add values with ? | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
maybe: function maybe(value) { | ||
value = this.sanitize(value); | ||
/** | ||
* Add optional values | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'maybe', | ||
value: function maybe(value) { | ||
value = VerbalExpression.sanitize(value); | ||
return this.add('(?:' + value + ')?'); | ||
}, | ||
} | ||
/** | ||
* Any character any number of times | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anything: function anything() { | ||
* Add alternative expressions | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'or', | ||
value: function or(value) { | ||
this._prefixes += '(?:'; | ||
this._suffixes = ')' + this._suffixes; | ||
this.add(')|(?:'); | ||
if (value) { | ||
this.then(value); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Any character any number of times | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'anything', | ||
value: function anything() { | ||
return this.add('(?:.*)'); | ||
}, | ||
} | ||
/** | ||
* Anything but these characters | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anythingBut: function anythingBut(value) { | ||
value = this.sanitize(value); | ||
* Anything but these characters | ||
* @param {(string|number|string[]|number[])} value characters to not match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'anythingBut', | ||
value: function anythingBut(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
value = VerbalExpression.sanitize(value); | ||
return this.add('(?:[^' + value + ']*)'); | ||
}, | ||
} | ||
/** | ||
* Any character at least one time | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
something: function something() { | ||
* Any character(s) at least once | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'something', | ||
value: function something() { | ||
return this.add('(?:.+)'); | ||
}, | ||
} | ||
/** | ||
* Any character at least one time except for these characters | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
somethingBut: function somethingBut(value) { | ||
value = this.sanitize(value); | ||
* Any character at least one time except for these characters | ||
* @param {(string|number|string[]|number[])} value characters to not match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'somethingBut', | ||
value: function somethingBut(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
value = VerbalExpression.sanitize(value); | ||
return this.add('(?:[^' + value + ']+)'); | ||
}, | ||
} | ||
/** | ||
* Shorthand function for the String.replace function to give more logical flow if, for example, we're doing multiple replacements on one regexp. | ||
* @param {String} source string to search for | ||
* @param {String} value value to replace with | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
replace: function replace(source, value) { | ||
source = source.toString(); | ||
return source.replace(this, value); | ||
}, | ||
* Match any of the given characters | ||
* @param {(string|number|string[]|number[])} value characters to match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/// Add regular expression special /// | ||
/// characters /// | ||
}, { | ||
key: 'anyOf', | ||
value: function anyOf(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
/** | ||
* Line break | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
lineBreak: function lineBreak() { | ||
return this.add('(?:\\r\\n|\\r|\\n)'); // Unix + Windows CRLF | ||
}, | ||
value = VerbalExpression.sanitize(value); | ||
return this.add('[' + value + ']'); | ||
} | ||
/** | ||
* And a shorthand for html-minded | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
br: function br() { | ||
return this.lineBreak(); | ||
}, | ||
* Shorthand for anyOf(value) | ||
* @param {string|number} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/** | ||
* Tab (duh?) | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
tab: function tab() { | ||
return this.add('\\t'); | ||
}, | ||
}, { | ||
key: 'any', | ||
value: function any(value) { | ||
return this.anyOf(value); | ||
} | ||
/** | ||
* Any alphanumeric | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
word: function word() { | ||
return this.add('\\w+'); | ||
}, | ||
* Ensure that the parameter does not follow | ||
* @param {string|number} value | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/** | ||
* Any digit | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
digit: function digit() { | ||
this.add('\\d'); | ||
}, { | ||
key: 'not', | ||
value: function not(value) { | ||
value = VerbalExpression.sanitize(value); | ||
this.add('(?!' + value + ')'); | ||
return this; | ||
}, | ||
} | ||
/** | ||
* Any whitespace | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
whitespace: function whitespace() { | ||
return this.add('\\s'); | ||
}, | ||
* Matching any character within a range of characters | ||
* Usage: .range( from, to [, from, to ... ] ) | ||
* @param {...string} ranges characters denoting beginning and ending of ranges | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/** | ||
* Any given character | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anyOf: function anyOf(value) { | ||
value = this.sanitize(value); | ||
}, { | ||
key: 'range', | ||
value: function range() { | ||
var value = ''; | ||
for (var i = 1; i < arguments.length; i += 2) { | ||
var from = VerbalExpression.sanitize(arguments.length <= i - 1 ? undefined : arguments[i - 1]); | ||
var to = VerbalExpression.sanitize(arguments.length <= i ? undefined : arguments[i]); | ||
value += from + '-' + to; | ||
} | ||
return this.add('[' + value + ']'); | ||
}, | ||
} | ||
// Special characters // | ||
/** | ||
* Shorthand | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
any: function any(value) { | ||
return this.anyOf(value); | ||
}, | ||
* Match a Line break | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'lineBreak', | ||
value: function lineBreak() { | ||
return this.add('(?:\\r\\n|\\r|\\n)'); // Unix(LF) + Windows(CRLF) | ||
} | ||
/** | ||
* Usage: .range( from, to [, from, to ... ] ) | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
range: function range() { | ||
var length = arguments.length; | ||
* A shorthand for lineBreak() for html-minded users | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
// Create a string buffer instead of concatenating on iteration | ||
var buffer = new Array(length / 2); | ||
var index = 0; | ||
var i = 0; | ||
var from; | ||
var to; | ||
}, { | ||
key: 'br', | ||
value: function br() { | ||
return this.lineBreak(); | ||
} | ||
buffer[index++] = '['; | ||
/** | ||
* Match a tab character | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
while (i < length) { | ||
from = this.sanitize(arguments[i++]); | ||
to = this.sanitize(arguments[i++]); | ||
buffer[index++] = from + '-' + to; | ||
} | ||
}, { | ||
key: 'tab', | ||
value: function tab() { | ||
return this.add('\\t'); | ||
} | ||
buffer[index++] = ']'; | ||
/** | ||
* Match any alphanumeric | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
return this.add(buffer.join('')); | ||
}, | ||
}, { | ||
key: 'word', | ||
value: function word() { | ||
return this.add('\\w+'); | ||
} | ||
/// Modifiers /// | ||
/** | ||
* Match a single digit | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'digit', | ||
value: function digit() { | ||
return this.add('\\d'); | ||
} | ||
/** | ||
* Modifier abstraction | ||
* @param {String} modifier modifier to add | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
addModifier: function addModifier(modifier) { | ||
if (this._modifiers.indexOf(modifier) === -1) { | ||
* Match a single whitespace | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'whitespace', | ||
value: function whitespace() { | ||
return this.add('\\s'); | ||
} | ||
// Modifiers // | ||
/** | ||
* Add a regex modifier/flag | ||
* @param {string} modifier modifier to add | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'addModifier', | ||
value: function addModifier(modifier) { | ||
if (!this._modifiers.includes(modifier)) { | ||
this._modifiers += modifier; | ||
@@ -309,166 +439,238 @@ } | ||
return this.add(); | ||
}, | ||
} | ||
/** | ||
* Remove modifier | ||
* @param {String} modifier modifier to remove | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
removeModifier: function removeModifier(modifier) { | ||
* Remove modifier | ||
* @param {string} modifier modifier to remove | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'removeModifier', | ||
value: function removeModifier(modifier) { | ||
this._modifiers = this._modifiers.replace(modifier, ''); | ||
return this.add(); | ||
}, | ||
} | ||
/** | ||
* Case-insensitivity modifier | ||
* @param {Boolean} enable Control case-insensitive matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
withAnyCase: function withAnyCase(enable) { | ||
return enable !== false ? this.addModifier('i') : this.removeModifier('i'); | ||
}, | ||
* Control case-insensitive matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/** | ||
* Default behaviour is with "g" modifier, so we can turn this another way around than other modifiers | ||
* @param {Boolean} enable Control global matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
stopAtFirst: function stopAtFirst(enable) { | ||
return enable !== false ? this.removeModifier('g') : this.addModifier('g'); | ||
}, | ||
}, { | ||
key: 'withAnyCase', | ||
value: function withAnyCase() { | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
return enable ? this.addModifier('i') : this.removeModifier('i'); | ||
} | ||
/** | ||
* Multiline, also reversed | ||
* @param {Boolean} enable Control multi-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
searchOneLine: function searchOneLine(enable) { | ||
return enable !== false ? this.removeModifier('m') : this.addModifier('m'); | ||
}, | ||
* Default behaviour is with "g" modifier, so we can turn this another way around than other modifiers | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'stopAtFirst', | ||
value: function stopAtFirst() { | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
return enable ? this.removeModifier('g') : this.addModifier('g'); | ||
} | ||
/** | ||
* Repeats the previous item exactly n times or between n and m times. | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
repeatPrevious: function repeatPrevious() { | ||
var value; | ||
var reIsInteger = /\d+/; | ||
var length = arguments.length; | ||
var values = new Array(length); | ||
var i = 0; | ||
var j = 0; | ||
for (i = 0; i < length; i++) { | ||
if (reIsInteger.test(arguments[i])) { | ||
values[j++] = arguments[i]; | ||
} | ||
} | ||
* Control the multiline modifier | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
if (j > 0) { | ||
// Set the new length of the array, thus reducing to the elements that have content | ||
values.length = j; | ||
value = '{' + values.join(',') + '}'; | ||
} | ||
}, { | ||
key: 'searchOneLine', | ||
value: function searchOneLine() { | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
return enable ? this.removeModifier('m') : this.addModifier('m'); | ||
} | ||
return this.add(value); | ||
}, | ||
// Loops // | ||
/** | ||
* Repeats the previous at least once | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
oneOrMore: function oneOrMore() { | ||
return this.add('+'); | ||
}, | ||
* Repeat the previous item exactly n times or between n and m times | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
/// Loops /// | ||
}, { | ||
key: 'repeatPrevious', | ||
value: function repeatPrevious() { | ||
var isInteger = /\d+/; | ||
/** | ||
* Matches the value zero or more times | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
multiple: function multiple(value) { | ||
// Use expression or string | ||
value = value.source || this.sanitize(value); | ||
if (arguments.length === 1) { | ||
this.add('(?:' + value + ')*'); | ||
for (var _len = arguments.length, quantity = Array(_len), _key = 0; _key < _len; _key++) { | ||
quantity[_key] = arguments[_key]; | ||
} | ||
if (arguments.length > 1) { | ||
this.add('(?:' + value + ')'); | ||
this.add('{' + arguments[1] + '}'); | ||
var values = quantity.filter(function (argument) { | ||
return isInteger.test(argument); | ||
}); | ||
if (values.length === 0 || values.length > 2) { | ||
return this; | ||
} | ||
this.add('{' + values.join(',') + '}'); | ||
return this; | ||
}, | ||
} | ||
/** | ||
* Adds alternative expressions | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
or: function or(value) { | ||
this._prefixes += '(?:'; | ||
this._suffixes = ')' + this._suffixes; | ||
* Repeat the previous at least once | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
this.add(')|(?:'); | ||
if (value) { | ||
this.then(value); | ||
}, { | ||
key: 'oneOrMore', | ||
value: function oneOrMore() { | ||
return this.add('+'); | ||
} | ||
/** | ||
* Match the value zero or more times | ||
* @param {string} value value to find | ||
* @param {integer} [lower] minimum number of times the value should be repeated | ||
* @param {integer} [upper] maximum number of times the value should be repeated | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'multiple', | ||
value: function multiple(value, lower, upper) { | ||
if (value !== undefined) { | ||
value = VerbalExpression.sanitize(value); | ||
this.add('(?:' + value + ')'); | ||
} | ||
if (lower === undefined && upper === undefined) { | ||
this.add('*'); // Any number of times | ||
} else if (lower !== undefined && upper === undefined) { | ||
this.add('{' + lower + ',}'); | ||
} else if (lower !== undefined && upper !== undefined) { | ||
this.add('{' + lower + ',' + upper + '}'); | ||
} | ||
return this; | ||
}, | ||
} | ||
// Capture groups // | ||
/** | ||
* Starts a capturing group | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
beginCapture: function beginCapture() { | ||
// Add the end of the capture group to the suffixes for now so compilation continues to work | ||
* Starts a capturing group | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'beginCapture', | ||
value: function beginCapture() { | ||
// Add the end of the capture group to the suffixes temporarily so that compilation continues to work | ||
this._suffixes += ')'; | ||
return this.add('('); | ||
}, | ||
} | ||
/** | ||
* Ends a capturing group | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
endCapture: function endCapture() { | ||
// Remove the last parentheses from the _suffixes and add to the regex itself | ||
this._suffixes = this._suffixes.substring(0, this._suffixes.length - 1); | ||
* Ends a capturing group | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'endCapture', | ||
value: function endCapture() { | ||
// Remove the last parenthesis from the _suffixes and add it to the regex | ||
this._suffixes = this._suffixes.slice(0, -1); | ||
return this.add(')'); | ||
}, | ||
} | ||
// Miscellaneous // | ||
/** | ||
* Convert to RegExp object | ||
* @return {RegExp} Converted RegExp instance | ||
*/ | ||
toRegExp: function toRegExp() { | ||
var array = this.toString().match(/\/(.*)\/([gimuy]+)?/); | ||
return new RegExp(array[1], array[2]); | ||
* Shorthand function for the string.replace function to allow for a more logical flow | ||
* @param {string} source string to search for | ||
* @param {string} value value to replace with | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
}, { | ||
key: 'replace', | ||
value: function replace(source, value) { | ||
source = source.toString(); | ||
return source.replace(this, value); | ||
} | ||
}; | ||
/** | ||
* @return {VerbalExpression} Returns a new instance of VerbalExpressions | ||
*/ | ||
function createVerbalExpression() { | ||
return new VerbalExpression(); | ||
} | ||
/** | ||
* Convert to RegExp object | ||
* @returns {RegExp} equivalent RegExp instance | ||
* @memberof VerbalExpression | ||
*/ | ||
// UMD (Universal Module Definition), URL: https://github.com/umdjs/umd | ||
// Supports AMD, CommonJS and the browser | ||
if (typeof module !== 'undefined' && module.exports) { | ||
// Node.js Module | ||
module.exports = createVerbalExpression; | ||
} else if (typeof define === 'function' && define.amd) { | ||
// AMD Module | ||
define(MODULE_NAME, [], function define() { | ||
return VerbalExpression; | ||
}); | ||
} else { | ||
// Browser | ||
root[MODULE_NAME] = createVerbalExpression; | ||
} | ||
}(this)); | ||
}, { | ||
key: 'toRegExp', | ||
value: function toRegExp() { | ||
var components = this.toString().match(/\/(.*)\/([gimuy]+)?/); | ||
var pattern = components[1]; | ||
var flags = components[2]; | ||
return new RegExp(pattern, flags); | ||
} | ||
}], [{ | ||
key: 'sanitize', | ||
value: function sanitize(value) { | ||
if (value.source) { | ||
return value.source; | ||
} | ||
if (typeof value === 'number') { | ||
return value; | ||
} | ||
// Regular expression to match meta characters | ||
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp | ||
var toEscape = /([\].|*?+(){}^$\\:=[])/g; | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch | ||
var lastMatch = '$&'; | ||
// Escape meta characters | ||
return value.replace(toEscape, '\\' + lastMatch); | ||
} | ||
}]); | ||
return VerbalExpression; | ||
}(_extendableBuiltin(RegExp)); | ||
/** | ||
* Return a new instance of `VerbalExpression` | ||
* @export | ||
* @returns {VerbalExpression} new instance | ||
*/ | ||
function VerEx() { | ||
// eslint-disable-line no-unused-vars | ||
var instance = new VerbalExpression(); | ||
instance.sanitize = VerbalExpression.sanitize; | ||
return instance; | ||
} | ||
//# sourceMappingURL=verbalexpressions.js.map | ||
return VerEx; | ||
})); |
@@ -5,10 +5,6 @@ /*! | ||
* | ||
* | ||
* Released under the MIT license | ||
* | ||
* Date: 2017-01-14 | ||
* | ||
*/ | ||
!function(a){function b(){var a=new RegExp;return b.injectClassMethods(a),a}function c(){return new b}var d="VerEx";b.injectClassMethods=function(a){var c;for(c in b.prototype)b.prototype.hasOwnProperty(c)&&(a[c]=b.prototype[c]);return a},b.prototype={_prefixes:"",_source:"",_suffixes:"",_modifiers:"gm",sanitize:function(a){var b;return a.source?a.source:"number"==typeof a?a:(b=/([\].|*?+(){}^$\\:=[])/g,a.replace(b,"\\$&"))},add:function(a){return this._source+=a||"",this.compile(this._prefixes+this._source+this._suffixes,this._modifiers),this},startOfLine:function(a){return a=a!==!1,this._prefixes=a?"^":"",this.add()},endOfLine:function(a){return a=a!==!1,this._suffixes=a?"$":"",this.add()},then:function(a){return a=this.sanitize(a),this.add("(?:"+a+")")},find:function(a){return this.then(a)},maybe:function(a){return a=this.sanitize(a),this.add("(?:"+a+")?")},anything:function(){return this.add("(?:.*)")},anythingBut:function(a){return a=this.sanitize(a),this.add("(?:[^"+a+"]*)")},something:function(){return this.add("(?:.+)")},somethingBut:function(a){return a=this.sanitize(a),this.add("(?:[^"+a+"]+)")},replace:function(a,b){return a=a.toString(),a.replace(this,b)},lineBreak:function(){return this.add("(?:\\r\\n|\\r|\\n)")},br:function(){return this.lineBreak()},tab:function(){return this.add("\\t")},word:function(){return this.add("\\w+")},digit:function(){return this.add("\\d"),this},whitespace:function(){return this.add("\\s")},anyOf:function(a){return a=this.sanitize(a),this.add("["+a+"]")},any:function(a){return this.anyOf(a)},range:function(){var a,b,c=arguments.length,d=new Array(c/2),e=0,f=0;for(d[e++]="[";f<c;)a=this.sanitize(arguments[f++]),b=this.sanitize(arguments[f++]),d[e++]=a+"-"+b;return d[e++]="]",this.add(d.join(""))},addModifier:function(a){return this._modifiers.indexOf(a)===-1&&(this._modifiers+=a),this.add()},removeModifier:function(a){return this._modifiers=this._modifiers.replace(a,""),this.add()},withAnyCase:function(a){return a!==!1?this.addModifier("i"):this.removeModifier("i")},stopAtFirst:function(a){return a!==!1?this.removeModifier("g"):this.addModifier("g")},searchOneLine:function(a){return a!==!1?this.removeModifier("m"):this.addModifier("m")},repeatPrevious:function(){var a,b=/\d+/,c=arguments.length,d=new Array(c),e=0,f=0;for(e=0;e<c;e++)b.test(arguments[e])&&(d[f++]=arguments[e]);return f>0&&(d.length=f,a="{"+d.join(",")+"}"),this.add(a)},oneOrMore:function(){return this.add("+")},multiple:function(a){return a=a.source||this.sanitize(a),1===arguments.length&&this.add("(?:"+a+")*"),arguments.length>1&&(this.add("(?:"+a+")"),this.add("{"+arguments[1]+"}")),this},or:function(a){return this._prefixes+="(?:",this._suffixes=")"+this._suffixes,this.add(")|(?:"),a&&this.then(a),this},beginCapture:function(){return this._suffixes+=")",this.add("(")},endCapture:function(){return this._suffixes=this._suffixes.substring(0,this._suffixes.length-1),this.add(")")},toRegExp:function(){var a=this.toString().match(/\/(.*)\/([gimuy]+)?/);return new RegExp(a[1],a[2])}},"undefined"!=typeof module&&module.exports?module.exports=c:"function"==typeof define&&define.amd?define(d,[],function(){return b}):a[d]=c}(this); | ||
!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define("VerEx",[],function(){return e.VerEx=t()}):"object"==typeof module&&module.exports?module.exports=t():e.VerEx=t()}(this,function(){var e=function(){function e(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,i,n){return i&&e(t.prototype,i),n&&e(t,n),t}}();function t(e){function t(){var t=Reflect.construct(e,Array.from(arguments));return Object.setPrototypeOf(t,Object.getPrototypeOf(this)),t}return t.prototype=Object.create(e.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e,t}var i=function(i){function n(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n);var e=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(n.__proto__||Object.getPrototypeOf(n)).call(this,"","gm"));return e._prefixes="",e._source="",e._suffixes="",e._modifiers="gm",e}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(n,t(RegExp)),e(n,[{key:"add",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";this._source+=e;var t=this._prefixes+this._source+this._suffixes;return this.compile(t,this._modifiers),this}},{key:"startOfLine",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return this._prefixes=e?"^":"",this.add()}},{key:"endOfLine",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return this._suffixes=e?"$":"",this.add()}},{key:"then",value:function(e){return e=n.sanitize(e),this.add("(?:"+e+")")}},{key:"find",value:function(e){return this.then(e)}},{key:"maybe",value:function(e){return e=n.sanitize(e),this.add("(?:"+e+")?")}},{key:"or",value:function(e){return this._prefixes+="(?:",this._suffixes=")"+this._suffixes,this.add(")|(?:"),e&&this.then(e),this}},{key:"anything",value:function(){return this.add("(?:.*)")}},{key:"anythingBut",value:function(e){return Array.isArray(e)&&(e=e.join("")),e=n.sanitize(e),this.add("(?:[^"+e+"]*)")}},{key:"something",value:function(){return this.add("(?:.+)")}},{key:"somethingBut",value:function(e){return Array.isArray(e)&&(e=e.join("")),e=n.sanitize(e),this.add("(?:[^"+e+"]+)")}},{key:"anyOf",value:function(e){return Array.isArray(e)&&(e=e.join("")),e=n.sanitize(e),this.add("["+e+"]")}},{key:"any",value:function(e){return this.anyOf(e)}},{key:"not",value:function(e){return e=n.sanitize(e),this.add("(?!"+e+")"),this}},{key:"range",value:function(){for(var e="",t=1;t<arguments.length;t+=2){e+=n.sanitize(arguments.length<=t-1?void 0:arguments[t-1])+"-"+n.sanitize(arguments.length<=t?void 0:arguments[t])}return this.add("["+e+"]")}},{key:"lineBreak",value:function(){return this.add("(?:\\r\\n|\\r|\\n)")}},{key:"br",value:function(){return this.lineBreak()}},{key:"tab",value:function(){return this.add("\\t")}},{key:"word",value:function(){return this.add("\\w+")}},{key:"digit",value:function(){return this.add("\\d")}},{key:"whitespace",value:function(){return this.add("\\s")}},{key:"addModifier",value:function(e){return this._modifiers.includes(e)||(this._modifiers+=e),this.add()}},{key:"removeModifier",value:function(e){return this._modifiers=this._modifiers.replace(e,""),this.add()}},{key:"withAnyCase",value:function(){return!(arguments.length>0&&void 0!==arguments[0])||arguments[0]?this.addModifier("i"):this.removeModifier("i")}},{key:"stopAtFirst",value:function(){return!(arguments.length>0&&void 0!==arguments[0])||arguments[0]?this.removeModifier("g"):this.addModifier("g")}},{key:"searchOneLine",value:function(){return!(arguments.length>0&&void 0!==arguments[0])||arguments[0]?this.removeModifier("m"):this.addModifier("m")}},{key:"repeatPrevious",value:function(){for(var e=/\d+/,t=arguments.length,i=Array(t),n=0;n<t;n++)i[n]=arguments[n];var r=i.filter(function(t){return e.test(t)});return 0===r.length||r.length>2?this:(this.add("{"+r.join(",")+"}"),this)}},{key:"oneOrMore",value:function(){return this.add("+")}},{key:"multiple",value:function(e,t,i){return void 0!==e&&(e=n.sanitize(e),this.add("(?:"+e+")")),void 0===t&&void 0===i?this.add("*"):void 0!==t&&void 0===i?this.add("{"+t+",}"):void 0!==t&&void 0!==i&&this.add("{"+t+","+i+"}"),this}},{key:"beginCapture",value:function(){return this._suffixes+=")",this.add("(")}},{key:"endCapture",value:function(){return this._suffixes=this._suffixes.slice(0,-1),this.add(")")}},{key:"replace",value:function(e,t){return(e=e.toString()).replace(this,t)}},{key:"toRegExp",value:function(){var e=this.toString().match(/\/(.*)\/([gimuy]+)?/),t=e[1],i=e[2];return new RegExp(t,i)}}],[{key:"sanitize",value:function(e){if(e.source)return e.source;if("number"==typeof e)return e;return e.replace(/([\].|*?+(){}^$\\:=[])/g,"\\$&")}}]),n}();return function(){var e=new i;return e.sanitize=i.sanitize,e}}); | ||
//# sourceMappingURL=verbalexpressions.min.js.map |
102
Gruntfile.js
@@ -9,28 +9,56 @@ module.exports = function gruntConfig(grunt) { | ||
}, | ||
target: ['VerbalExpressions.js', 'test/tests.js'], | ||
target: ['VerbalExpressions.js', 'test/tests.js', 'Gruntfile.js'], | ||
}, | ||
qunit: { | ||
files: ['test/index.html'], | ||
ava: { | ||
test: ['test/tests.js'], | ||
options: { | ||
nyc: true, | ||
}, | ||
verbose: { | ||
test: ['test/tests.js'], | ||
options: { | ||
verbose: true, | ||
nyc: true, | ||
}, | ||
}, | ||
}, | ||
copy: { | ||
build: { | ||
src: '<%= pkg.main %>', | ||
dest: 'dist/verbalexpressions.js', | ||
babel: { | ||
options: { | ||
sourceMap: true, | ||
presets: [ | ||
['env', { modules: false }], | ||
], | ||
plugins: [ | ||
['transform-builtin-extend', { globals: ['RegExp'] }], | ||
], | ||
}, | ||
dist: { | ||
files: { | ||
'dist/verbalexpressions.js': 'VerbalExpressions.js', | ||
}, | ||
}, | ||
}, | ||
umd: { | ||
all: { | ||
options: { | ||
src: 'dist/verbalexpressions.js', | ||
objectToExport: 'VerEx', | ||
amdModuleId: 'VerEx', | ||
globalAlias: 'VerEx', | ||
}, | ||
}, | ||
}, | ||
uglify: { | ||
options: { | ||
banner: '/*!\n' + | ||
'* <%= pkg.name %> JavaScript Library v<%= pkg.version %>\n' + | ||
'* <%= pkg.homepage %>\n' + | ||
'*\n' + | ||
'*\n' + | ||
'* Released under the <%= pkg.license %> license\n' + | ||
'*\n' + | ||
'* Date: <%= grunt.template.today("yyyy-mm-dd") %>\n' + | ||
'*\n' + | ||
'*/\n', | ||
banner: '/*!\n' | ||
+ '* <%= pkg.name %> JavaScript Library v<%= pkg.version %>\n' | ||
+ '* <%= pkg.homepage %>\n' | ||
+ '*\n' | ||
+ '* Released under the <%= pkg.license %> license\n' | ||
+ '*/\n', | ||
sourceMap: true, | ||
@@ -40,3 +68,3 @@ }, | ||
files: { | ||
'dist/verbalexpressions.min.js': ['<%= pkg.main %>'], | ||
'dist/verbalexpressions.min.js': ['dist/verbalexpressions.js'], | ||
}, | ||
@@ -57,35 +85,23 @@ }, | ||
jsdoc: { | ||
markdownlint: { | ||
options: { | ||
pedantic: true, | ||
verbose: true, | ||
readme: 'README.md', | ||
package: 'package.json', | ||
config: grunt.file.readJSON('.mdlintrc.json'), | ||
}, | ||
src: { | ||
options: { | ||
destination: 'docs', | ||
}, | ||
src: ['VerbalExpressions.js'], | ||
}, | ||
dist: { | ||
options: { | ||
destination: 'dist/docs', | ||
}, | ||
src: ['dist/verbalexpressions.js'], | ||
}, | ||
src: ['README.md', 'docs/*.md', 'docs/VerbalExpression/*.md'], | ||
}, | ||
}); | ||
grunt.loadNpmTasks('grunt-contrib-copy'); | ||
grunt.loadNpmTasks('grunt-contrib-qunit'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-eslint'); | ||
grunt.loadNpmTasks('grunt-jsdoc'); | ||
grunt.loadNpmTasks('grunt-ava'); | ||
grunt.loadNpmTasks('grunt-babel'); | ||
grunt.loadNpmTasks('grunt-umd'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify-es'); | ||
grunt.loadNpmTasks('grunt-sourcemap-localize'); | ||
grunt.loadNpmTasks('grunt-markdownlint'); | ||
grunt.registerTask('test', ['eslint', 'qunit']); | ||
grunt.registerTask('default', ['qunit']); | ||
grunt.registerTask('build', ['test', 'copy', 'uglify', 'sourcemap_localize', 'jsdoc:dist']); | ||
grunt.registerTask('docs', ['test', 'jsdoc:src']); | ||
grunt.registerTask('default', ['test']); | ||
grunt.registerTask('test', ['compile', 'eslint', 'markdownlint', 'ava:test']); | ||
grunt.registerTask('test:verbose', ['compile', 'eslint', 'ava:verbose']); | ||
grunt.registerTask('compile', ['babel', 'umd:all']); | ||
grunt.registerTask('build', ['compile', 'ava:test', 'uglify', 'sourcemap_localize']); | ||
}; |
{ | ||
"name": "verbal-expressions", | ||
"description": "JavaScript Regular expressions made easy", | ||
"version": "0.3.0", | ||
"version": "1.0.0", | ||
"keywords": [ | ||
@@ -11,12 +11,20 @@ "regular expressions", | ||
"devDependencies": { | ||
"eslint": "^2.5.1", | ||
"eslint-config-airbnb": "^6.2.0", | ||
"grunt": "^0.4.2", | ||
"grunt-cli": "^1.2.0", | ||
"grunt-contrib-copy": "^1.0.0", | ||
"grunt-contrib-qunit": "^1.0.1", | ||
"grunt-contrib-uglify": "^1.0.1", | ||
"grunt-eslint": "^18.0.0", | ||
"grunt-jsdoc": "^1.1.0", | ||
"grunt-sourcemap-localize": "^0.1.0" | ||
"ava": "^0.25.0", | ||
"babel-core": "^6.26.3", | ||
"babel-plugin-transform-builtin-extend": "^1.1.2", | ||
"babel-preset-env": "^1.7.0", | ||
"eslint": "^4.19.1", | ||
"eslint-config-airbnb": "^17.0.0", | ||
"eslint-plugin-import": "^2.13.0", | ||
"eslint-plugin-jsx-a11y": "^6.0.3", | ||
"eslint-plugin-react": "^7.10.0", | ||
"grunt": "^1.0.3", | ||
"grunt-ava": "^0.19.0", | ||
"grunt-babel": "^7.0.0", | ||
"grunt-contrib-uglify-es": "^3.3.0", | ||
"grunt-eslint": "^21.0.0", | ||
"grunt-markdownlint": "^2.1.0", | ||
"grunt-sourcemap-localize": "^0.1.0", | ||
"grunt-umd": "^3.0.0", | ||
"nyc": "^13.1.0" | ||
}, | ||
@@ -30,15 +38,17 @@ "repository": { | ||
}, | ||
"main": "VerbalExpressions.js", | ||
"main": "dist/verbalexpressions.js", | ||
"license": "MIT", | ||
"scripts": { | ||
"test": "grunt test", | ||
"test:verbose": "grunt test:verbose", | ||
"compile": "grunt compile", | ||
"grunt": "grunt", | ||
"test": "grunt test", | ||
"test:verbose": "grunt test --verbose", | ||
"build": "grunt build", | ||
"docs": "grunt docs" | ||
}, | ||
"types": "./typings/verbalexpression.d.ts", | ||
"types": "./typings/VerbalExpressions.d.ts", | ||
"engines": { | ||
"node": ">= 0.8.0" | ||
} | ||
"node": "^9.2.0" | ||
}, | ||
"dependencies": {} | ||
} |
@@ -1,3 +0,2 @@ | ||
VerbalExpressions v0.3.0 | ||
===================== | ||
# VerbalExpressions | ||
@@ -7,43 +6,70 @@ [](https://travis-ci.org/VerbalExpressions/JSVerbalExpressions) | ||
## JavaScript Regular Expressions made easy | ||
VerbalExpressions is a JavaScript library that helps to construct difficult regular expressions. | ||
## How to get started | ||
### In the browser | ||
```HTML | ||
```html | ||
<script src="VerbalExpressions.js"></script> | ||
``` | ||
Or use the [jsDelivr CDN](http://www.jsdelivr.com/projects/jsverbalexpressions). | ||
### On the server (node.js) | ||
Install: | ||
``` | ||
```sh | ||
npm install verbal-expressions | ||
``` | ||
Require: | ||
```javascript | ||
var VerEx = require('verbal-expressions'); | ||
```js | ||
const VerEx = require('verbal-expressions'); | ||
``` | ||
Or use ES6's `import`: | ||
```js | ||
import VerEx from 'verbal-expressions'; | ||
``` | ||
## Running tests | ||
$ npm run grunt | ||
(or) | ||
$ npm test | ||
```sh | ||
npm test | ||
``` | ||
(or) | ||
```sh | ||
npm run test:verbose | ||
``` | ||
## Creating a minified version | ||
This will generate a minified version of VerbalExpressions.js (aptly named VerbalExpressions.min.js) in a _dist_ folder. | ||
```sh | ||
npm run build | ||
``` | ||
$ npm run build | ||
This will run [Babel](https://babeljs.io) on `VerbalExpressions.js` and output the result to `dist/verbalexpressions.js`. A minified version of the same will also be written to `dist/verbalexpressions.min.js`. | ||
A source map will also be created in the same folder, so you can use the original unminified source file (copied to _dist_ as well) for debugging purposes. | ||
A source map will also be created in `dist`, so you can use the original "un-babelified", unminified source file for debugging purposes. | ||
## API documentation | ||
You can find the API documentation at [verbalexpressions.github.io/JSVerbalExpressions](https://verbalexpressions.github.io/JSVerbalExpressions). | ||
## Examples | ||
Here's a couple of simple examples to give an idea of how VerbalExpressions works: | ||
Here are some simple examples to give an idea of how VerbalExpressions works: | ||
### Testing if we have a valid URL | ||
```javascript | ||
```js | ||
// Create an example of how to test for correctly formed URLs | ||
var tester = VerEx() | ||
const tester = VerEx() | ||
.startOfLine() | ||
@@ -58,7 +84,7 @@ .then('http') | ||
// Create an example URL | ||
var testMe = 'https://www.google.com'; | ||
const testMe = 'https://www.google.com'; | ||
// Use RegExp object's native test() function | ||
if (tester.test(testMe)) { | ||
alert('We have a correct URL '); // This output will fire} | ||
alert('We have a correct URL'); // This output will fire | ||
} else { | ||
@@ -73,11 +99,11 @@ alert('The URL is incorrect'); | ||
```javascript | ||
```js | ||
// Create a test string | ||
var replaceMe = 'Replace bird with a duck'; | ||
const replaceMe = 'Replace bird with a duck'; | ||
// Create an expression that seeks for word "bird" | ||
var expression = VerEx().find('bird'); | ||
const expression = VerEx().find('bird'); | ||
// Execute the expression like a normal RegExp object | ||
var result = expression.replace(replaceMe, 'duck'); | ||
const result = expression.replace(replaceMe, 'duck'); | ||
@@ -88,6 +114,6 @@ // Outputs "Replace duck with a duck" | ||
### Shorthand for string replace: | ||
### Shorthand for string replace | ||
```javascript | ||
var result = VerEx().find('red').replace('We have a red house', 'blue'); | ||
```js | ||
const result = VerEx().find('red').replace('We have a red house', 'blue'); | ||
@@ -98,20 +124,22 @@ // Outputs "We have a blue house" | ||
## API documentation | ||
## A little word for a big help | ||
You can find the API documentation at the [wiki pages](https://github.com/VerbalExpressions/JSVerbalExpressions/wiki). | ||
## A little word for a big help | ||
I'd like to promote a special thank-you to [Ben Nadel][ben-nadel] for his [great article about extending native JS objects][extending] | ||
## Contributions | ||
Pull requests are warmly welcome! | ||
Clone the repo and fork: | ||
`git clone https://github.com/jehna/VerbalExpressions.git`. | ||
```sh | ||
git clone https://github.com/jehna/VerbalExpressions.git | ||
``` | ||
### Style guide | ||
The [Airbnb](https://github.com/airbnb/javascript) style guide is loosely used as a basis for creating clean and readable JavaScript code. | ||
The [Airbnb](https://github.com/airbnb/javascript) style guide is loosely used as a basis for creating clean and readable JavaScript code. Check [`.eslintrc`](.eslintrc). | ||
Pull requests are warmly welcome! | ||
Check out these slide decks for handy Github & git tips: | ||
Check out these slide decks for handy Github & git tips: | ||
- [Git and Github Secrets](http://zachholman.com/talk/git-github-secrets/) | ||
@@ -123,4 +151,9 @@ - [More Git and Github Secrets](http://zachholman.com/talk/more-git-and-github-secrets/) | ||
## Tools | ||
- https://verbalregex.com - it's a wrapper of JSVerbalExpressions; users can write down the code and compile to regex | ||
## Other Implementations | ||
You can see an up to date list of all ports on [VerbalExpressions.github.io](http://VerbalExpressions.github.io). | ||
- [Ruby](https://github.com/ryan-endacott/verbal_expressions) | ||
@@ -139,2 +172,2 @@ - [C#](https://github.com/VerbalExpressions/CSharpVerbalExpressions) | ||
If you would like to contribute another port (which would be awesome!), please open an issue specifying the language. A repo in the [VerbalExpressions organization](https://github.com/VerbalExpressions) will be created for it. Please don't open PRs for other languages against this repo. | ||
If you would like to contribute another port (which would be awesome!), please [open an issue](https://github.com/VerbalExpressions/implementation/issues/new) specifying the language in the [VerbalExpressions/implementation repo](https://github.com/VerbalExpressions/implementation/issues). Please don't open PRs for other languages against this repo. |
@@ -1,248 +0,553 @@ | ||
/* eslint-disable new-cap */ | ||
import test from 'ava'; | ||
import VerEx from '../dist/verbalexpressions'; | ||
test('something', function somethingTest() { | ||
var testRegex = VerEx().something(); | ||
var testString = ''; | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag | ||
function resetLastIndex(regex) { | ||
regex.lastIndex = 0; | ||
} | ||
ok(!testRegex.test(testString), 'Empty string doesn\'t have something'); | ||
test('constructor', (t) => { | ||
const testRegex = VerEx(); | ||
testRegex.lastIndex = 0; | ||
testString = 'a'; | ||
ok(testRegex.test(testString), 'a is something'); | ||
t.true(testRegex instanceof RegExp, 'Should extend RegExp'); | ||
t.is(testRegex.toString(), '/(?:)/gm', 'Should be empty regex with global, multiline matching'); | ||
}); | ||
test('anything', function anythingTest() { | ||
var testRegex = VerEx().startOfLine().anything(); | ||
var testString = 'what'; | ||
// Utility // | ||
ok(testRegex.test(testString), 'Contains anything'); | ||
}); | ||
test('sanitize', (t) => { | ||
const testString = '$a^b\\c|d(e)f[g]h{i}j.k*l+m?n:o=p'; | ||
const escaped = '\\$a\\^b\\\\c\\|d\\(e\\)f\\[g\\]h\\{i\\}j\\.k\\*l\\+m\\?n\\:o\\=p'; | ||
t.is(VerEx().sanitize(testString), escaped, 'Special characters should be sanitized'); | ||
test('anythingBut', function anythingButTest() { | ||
var testRegex = VerEx().startOfLine().anythingBut('w'); | ||
var testString = 'what'; | ||
ok(testRegex.test(testString), 'Starts with a w'); | ||
t.is(VerEx().sanitize(42), 42); | ||
t.is(VerEx().sanitize(/foo/), 'foo'); | ||
}); | ||
test('somethingBut', function somethingButTest() { | ||
var testRegex = VerEx().somethingBut('a'); | ||
var testString = ''; | ||
test('add', (t) => { | ||
let testRegex = VerEx().startOfLine().withAnyCase().endOfLine(); | ||
testRegex = testRegex.add('(?:foo)?'); | ||
ok(!testRegex.test(testString), 'Empty string doesn\'t have something'); | ||
t.true(testRegex.source.startsWith('^'), 'Should retain old prefixes'); | ||
t.true(testRegex.source.endsWith('$'), 'Should retain old suffixes'); | ||
testRegex.lastIndex = 0; | ||
testString = 'b'; | ||
ok(testRegex.test(testString), 'Doesn\'t start with an a'); | ||
t.true(testRegex.test('foo'), 'Should add new rules'); | ||
resetLastIndex(testRegex); | ||
t.true(testRegex.test(''), 'Should add new rules'); | ||
testRegex.lastIndex = 0; | ||
testString = 'a'; | ||
ok(!testRegex.test(testString), 'Starts with an a'); | ||
t.true(testRegex.flags.includes('i'), 'Should retain old modifiers'); | ||
}); | ||
test('startOfLine', function startOfLineTest() { | ||
var testRegex = VerEx().startOfLine().then('a'); | ||
var testString = 'a'; | ||
// Rules // | ||
ok(testRegex.test(testString), 'Starts with an a'); | ||
test('startOfLine', (t) => { | ||
let testRegex = VerEx().startOfLine().then('a'); | ||
let testString = 'a'; | ||
testRegex.lastIndex = 0; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'ba'; | ||
ok(!testRegex.test(testString), 'Doesn\'t start with an a'); | ||
t.false(testRegex.test(testString)); | ||
testRegex = testRegex.startOfLine(false); // start of line is no longer necessary | ||
testString = 'ba'; | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('endOfLine', function endOfLineTest() { | ||
var testRegex = VerEx().find('a').endOfLine(); | ||
var testString = 'a'; | ||
test('endOfLine', (t) => { | ||
let testRegex = VerEx().find('a').endOfLine(); | ||
let testString = 'a'; | ||
ok(testRegex.test(testString), 'Ends with an a'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'ab'; | ||
ok(!testRegex.test(testString), 'Doesn\'t end with an a'); | ||
t.false(testRegex.test(testString)); | ||
testRegex = testRegex.endOfLine(false); // end of line is no longer necessary | ||
testString = 'ab'; | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('maybe', function maybeTest() { | ||
var testRegex = VerEx().startOfLine().then('a').maybe('b'); | ||
var testString = 'acb'; | ||
function then(name, t) { | ||
let testRegex = VerEx()[name]('a'); | ||
let testString = 'a'; | ||
ok(testRegex.test(testString), 'Maybe has a b after an a'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
testString = 'abc'; | ||
ok(testRegex.test(testString), 'Maybe has a b after an a'); | ||
resetLastIndex(testRegex); | ||
testString = 'b'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = ''; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx()[name]('a')[name]('b'); | ||
testString = 'ab'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'ac'; | ||
t.false(testRegex.test(testString)); | ||
} | ||
test('then', (t) => { | ||
then('then', t); | ||
}); | ||
test('anyOf', function anyOfTest() { | ||
var testRegex = VerEx().startOfLine().then('a').anyOf('xyz'); | ||
var testString = 'ay'; | ||
test('find', (t) => { | ||
then('find', t); | ||
}); | ||
ok(testRegex.test(testString), 'Has an x, y, or z after an a'); | ||
test('maybe', (t) => { | ||
const testRegex = VerEx().startOfLine().then('a').maybe('b'); | ||
let testString = 'acb'; | ||
testRegex.lastIndex = 0; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'abc'; | ||
ok(!testRegex.test(testString), 'Doesn\'t have an x, y, or z after an a'); | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('or', function orTest() { | ||
var testRegex = VerEx().startOfLine().then('abc').or('def'); | ||
var testString = 'defzzz'; | ||
test('or', (t) => { | ||
let testRegex = VerEx().startOfLine().then('abc').or('def'); | ||
let testString = 'defzzz'; | ||
ok(testRegex.test(testString), 'Starts with an abc or a def'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'abczzz'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'xyzabc'; | ||
ok(!testRegex.test(testString), 'Doesn\'t start with an abc or a def'); | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('abc').or().then('def'); | ||
testString = 'defzzz'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'abczzz'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'xyzabc'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('lineBreak', function lineBreakTest() { | ||
var testRegex = VerEx().startOfLine().then('abc').lineBreak().then('def'); | ||
var testString = 'abc\r\ndef'; | ||
test('anything', (t) => { | ||
const testRegex = VerEx().startOfLine().anything(); | ||
let testString = 'foo'; | ||
ok(testRegex.test(testString), 'abc,then a line break and then def'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
testString = 'abc\ndef'; | ||
ok(testRegex.test(testString), 'abc, then a line break and then def'); | ||
resetLastIndex(testRegex); | ||
testString = ''; | ||
t.true(testRegex.test(testString), 'Should be able to match zero characters'); | ||
}); | ||
testRegex.lastIndex = 0; | ||
testString = 'abc\r\n def'; | ||
ok(!testRegex.test(testString), 'abc, then a line break, then a space and then def'); | ||
test('anythingBut', (t) => { | ||
let testRegex = VerEx().startOfLine().anythingBut('br').endOfLine(); | ||
let testString = 'foobar'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foo_a_'; | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().anythingBut('br'); | ||
testString = 'bar'; | ||
t.true(testRegex.test(testString), 'Should be able to match zero characters'); | ||
testRegex = VerEx().startOfLine().anythingBut(['b', 'r']).endOfLine(); | ||
testString = 'foobar'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foo_a_'; | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().anythingBut(['b', 'r']); | ||
testString = 'bar'; | ||
t.true(testRegex.test(testString), 'Should be able to match zero characters'); | ||
}); | ||
test('br', function brTest() { | ||
var testRegex = VerEx().startOfLine().then('abc').lineBreak().then('def'); | ||
var testString = 'abc\r\ndef'; | ||
test('something', (t) => { | ||
const testRegex = VerEx().something(); | ||
let testString = ''; | ||
ok(testRegex.test(testString), 'abc, then a line break and then def'); | ||
t.false(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'a'; | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('somethingBut', (t) => { | ||
let testRegex = VerEx().startOfLine().somethingBut('abc').endOfLine(); | ||
let testString = ''; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foo'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'fab'; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().somethingBut(['a', 'b', 'c']).endOfLine(); | ||
testString = ''; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foo'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'fab'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
function anyOf(name, t) { | ||
let testRegex = VerEx().startOfLine().then('a')[name]('xyz'); | ||
let testString = 'ay'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'ab'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'a'; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('a')[name](['x', 'y', 'z']); | ||
testString = 'ay'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'ab'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'a'; | ||
t.false(testRegex.test(testString)); | ||
} | ||
test('anyOf', (t) => { | ||
anyOf('anyOf', t); | ||
}); | ||
test('any', (t) => { | ||
anyOf('any', t); | ||
}); | ||
test('not', (t) => { | ||
const testRegex = VerEx().startOfLine().not('foo').anything().endOfLine(); | ||
let testString = 'foobar'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'bar'; | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('range', (t) => { | ||
let testRegex = VerEx().startOfLine().range('a', 'z', '0', '9').oneOrMore().endOfLine(); | ||
let testString = 'foobarbaz123'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'fooBarBaz_123'; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().range('a', 'z', '0').oneOrMore().endOfLine(); | ||
testString = 'foobarbaz'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foobarbaz123'; | ||
t.false(testRegex.test(testString), 'Should ignore extra parameters'); | ||
}); | ||
// Special characters // | ||
function lineBreak(name, t) { | ||
const testRegex = VerEx().startOfLine().then('abc')[name]().then('def'); | ||
let testString = 'abc\r\ndef'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'abc\ndef'; | ||
ok(testRegex.test(testString), 'abc, then a line break and then def'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
testString = 'abc\r\n def'; | ||
ok(!testRegex.test(testString), 'abc, then a line break, then a space and then def'); | ||
resetLastIndex(testRegex); | ||
testString = 'abc\rdef'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'abc\r\n\ndef'; | ||
t.false(testRegex.test(testString)); | ||
} | ||
test('lineBreak', (t) => { | ||
lineBreak('lineBreak', t); | ||
}); | ||
test('tab', function tabTest() { | ||
var testRegex = VerEx().startOfLine().tab().then('abc'); | ||
var testString = '\tabc'; | ||
test('br', (t) => { | ||
lineBreak('br', t); | ||
}); | ||
ok(testRegex.test(testString), 'tab then abc'); | ||
test('tab', (t) => { | ||
const testRegex = VerEx().startOfLine().tab().then('abc'); | ||
let testString = '\tabc'; | ||
testRegex.lastIndex = 0; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'abc'; | ||
ok(!testRegex.test(testString), 'No tab then abc'); | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('withAnyCase', function withAnyCaseTest() { | ||
var testRegex = VerEx().startOfLine().then('a'); | ||
var testString = 'A'; | ||
test('word', (t) => { | ||
let testRegex = VerEx().startOfLine().word().endOfLine(); | ||
let testString = 'azertyuiopqsdfghjklmwxcvbn0123456789_'; | ||
ok(!testRegex.test(testString), 'Not case-insensitive'); | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().word(); | ||
testString = '. @[]|,&~-'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('digit', (t) => { | ||
let testRegex = VerEx().startOfLine().digit().oneOrMore().endOfLine(); | ||
let testString = '0123456789'; | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().digit(); | ||
testString = '-.azertyuiopqsdfghjklmwxcvbn @[]|,_&~'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('whitespace', (t) => { | ||
const testRegex = VerEx().startOfLine().whitespace().oneOrMore().searchOneLine().endOfLine(); | ||
let testString = ' \t\r\n\v\f'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'a z'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
// Modifiers // | ||
test('addModifier', (t) => { | ||
let testRegex = VerEx().addModifier('y'); | ||
t.true(testRegex.flags.includes('y')); | ||
t.notThrows(() => { | ||
testRegex = VerEx().addModifier('g'); | ||
}, 'Should not add extra modifier if it already exists'); | ||
}); | ||
test('removeModifier', (t) => { | ||
const testRegex = VerEx().removeModifier('g'); | ||
t.false(testRegex.flags.includes('g')); | ||
}); | ||
test('withAnyCase', (t) => { | ||
let testRegex = VerEx().startOfLine().then('a'); | ||
let testString = 'A'; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('a').withAnyCase(); | ||
testString = 'A'; | ||
ok(testRegex.test(testString), 'Case-insensitive'); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'a'; | ||
ok(testRegex.test(testString), 'Case-insensitive'); | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('a').withAnyCase(false); | ||
testString = 'A'; | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('whitespace', function whitespaceTest() { | ||
var testRegex = VerEx().startOfLine().then('a').whitespace().then('z'); | ||
var testString = 'a z'; | ||
test('stopAtFirst', (t) => { | ||
let testRegex = VerEx().find('foo'); | ||
const testString = 'foofoofoo'; | ||
ok(testRegex.test(testString), 'a, then a space and then z'); | ||
t.is(testString.match(testRegex).length, 3, 'Should match all "foo"s'); | ||
testRegex.lastIndex = 0; | ||
testString = 'a_z'; | ||
ok(!testRegex.test(testString), 'a, then no whitespace and then z'); | ||
testRegex = VerEx().find('foo').stopAtFirst(); | ||
t.is(testString.match(testRegex).length, 1, 'Should match one "foo"'); | ||
testRegex = VerEx().find('foo').stopAtFirst(false); | ||
t.is(testString.match(testRegex).length, 3, 'Should match all "foo"s'); | ||
}); | ||
test('searchOneLine', function searchOneLineTest() { | ||
var testRegex = VerEx().startOfLine().then('a').br().then('b').endOfLine(); | ||
var testString = 'a\nb'; | ||
test('searchOneLine', (t) => { | ||
let testRegex = VerEx().startOfLine().then('b').endOfLine(); | ||
const testString = 'a\nb\nc'; | ||
ok(testRegex.test(testString), 'b is on the second line'); | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('a').br().then('b').endOfLine().searchOneLine(); | ||
testString = 'a\nb'; | ||
ok(testRegex.test(testString), 'b is on the second line, but we are only searching the first'); | ||
testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine(); | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine(false); | ||
t.true(testRegex.test(testString)); | ||
}); | ||
test('sanitize', function sanitizeTest() { | ||
var testRegex = VerEx().startOfLine().then('$a^b\\c|d(e)f[g]h{i}j.k*l+m?').endOfLine(); | ||
var testString = '$a^b\\c|d(e)f[g]h{i}j.k*l+m?'; | ||
// Loops // | ||
ok(testRegex.test(testString), 'Special character sanitization'); | ||
test('repeatPrevious', (t) => { | ||
let testRegex = VerEx().startOfLine().find('foo').repeatPrevious(3).endOfLine(); | ||
let testString = 'foofoofoo'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foofoo'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foofoofoofoo'; | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'bar'; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 3).endOfLine(); | ||
for (let i = 0; i <= 4; i++) { | ||
resetLastIndex(testRegex); | ||
testString = 'foo'.repeat(i); | ||
if (i < 1 || i > 3) { | ||
t.false(testRegex.test(testString)); | ||
} else { | ||
t.true(testRegex.test(testString)); | ||
} | ||
} | ||
testRegex = VerEx().startOfLine().find('foo').repeatPrevious().endOfLine(); | ||
testString = 'foofoo'; | ||
t.false(testRegex.test(testString), 'Should silently fail on edge cases'); | ||
testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 2, 3).endOfLine(); | ||
testString = 'foofoo'; | ||
t.false(testRegex.test(testString), 'Should silently fail on edge cases'); | ||
}); | ||
test('oneOrMore', function oneOrMoreTest() { | ||
var testRegex = VerEx().startOfLine().then('foo').oneOrMore(); | ||
var testString = 'foo'; | ||
test('oneOrMore', (t) => { | ||
const testRegex = VerEx().startOfLine().then('foo').oneOrMore().endOfLine(); | ||
let testString = 'foo'; | ||
ok(testRegex.test(testString), 'Contains \'foo\' at least once '); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'foofoo'; | ||
ok(testRegex.test(testString), 'Contains \'foo\' at least once in \'foofoo\''); | ||
t.true(testRegex.test(testString)); | ||
testRegex.lastIndex = 0; | ||
resetLastIndex(testRegex); | ||
testString = 'bar'; | ||
ok(!testRegex.test(testString), 'Contains \'foo\' at least once'); | ||
t.false(testRegex.test(testString)); | ||
}); | ||
test('multiple', function multipleTest() { | ||
var testRegex = VerEx().startOfLine().multiple('foo'); | ||
var testString = 'foo'; | ||
test('multiple', (t) => { | ||
let testRegex = VerEx().startOfLine().find(' ').multiple().endOfLine(); | ||
let testString = ' '; | ||
t.true(testRegex.test(testString)); | ||
ok(testRegex.test(testString), 'Contains \'foo\' at least once'); | ||
resetLastIndex(testRegex); | ||
testString = ' a '; | ||
t.false(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2); | ||
testRegex = VerEx().startOfLine().multiple('foo').endOfLine(); | ||
testString = 'foo'; | ||
ok(!testRegex.test(testString), 'Should contain \'foo\' at least twice'); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2); | ||
testString = 'foofoo'; | ||
ok(testRegex.test(testString), 'Should contain \'foo\' at least twice'); | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2, 5); | ||
testString = 'foofoofoofoo'; | ||
ok(testRegex.test(testString), 'Should be \'foo\' repeated two to five times'); | ||
resetLastIndex(testRegex); | ||
testString = 'foofoofoo'; | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2, 5); | ||
resetLastIndex(testRegex); | ||
testString = ''; | ||
t.true(testRegex.test(testString)); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine(); | ||
testString = 'foo'; | ||
ok(!testRegex.test(testString), 'Should be \'foo\' repeated two to five times'); | ||
}); | ||
t.false(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
testString = 'foofoo'; | ||
t.true(testRegex.test(testString)); | ||
test('word', function multipleTest() { | ||
var testRegex = VerEx().word(); | ||
var testString = 'azertyuiopqsdfghjklmwxcvbn0123456789_'; | ||
var i; | ||
var len; | ||
resetLastIndex(testRegex); | ||
testString = 'foofoofoo'; | ||
t.true(testRegex.test(testString)); | ||
ok(testRegex.test(testString), 'Should match word'); | ||
testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine(); | ||
testString = '. @[]|,&~-'; | ||
for (i = 0, len = testString.length; i < len; i++) { | ||
ok(!testRegex.test(testString[i]), 'Should not match word (' + testString[i] + ')'); | ||
for (let i = 0; i <= 6; i++) { | ||
resetLastIndex(testRegex); | ||
testString = 'foo'.repeat(i); | ||
if (i < 2 || i > 5) { | ||
t.false(testRegex.test(testString)); | ||
} else { | ||
t.true(testRegex.test(testString)); | ||
} | ||
} | ||
}); | ||
test('digit', function multipleTest() { | ||
var testRegex = VerEx().digit(); | ||
var testString = '0123456789'; | ||
var i; | ||
var len; | ||
// Capture groups // | ||
ok(testRegex.test(testString), 'Should match digit'); | ||
test('capture groups', (t) => { | ||
let testRegex = VerEx().find('foo').beginCapture().then('bar'); | ||
let testString = 'foobar'; | ||
testString = '-.azertyuiopqsdfghjklmwxcvbn @[]|,_&~'; | ||
for (i = 0, len = testString.length; i < len; i++) { | ||
ok(!testRegex.test(testString[i]), 'Should not match digit (' + testString[i] + ')'); | ||
} | ||
t.true(testRegex.test(testString), 'Expressions with incomplete capture groups should work'); | ||
testRegex = testRegex.endCapture().then('baz'); | ||
testString = 'foobarbaz'; | ||
t.true(testRegex.test(testString)); | ||
resetLastIndex(testRegex); | ||
const matches = testRegex.exec(testString); | ||
t.is(matches[1], 'bar'); | ||
}); | ||
// Miscellaneous // | ||
test('replace', (t) => { | ||
const testRegex = VerEx().find(' '); | ||
const testString = 'foo bar baz'; | ||
t.is(testRegex.replace(testString, '_'), 'foo_bar_baz'); | ||
}); | ||
test('toRegExp', (t) => { | ||
const testRegex = VerEx().anything(); | ||
const converted = testRegex.toRegExp(); | ||
t.is(converted.toString(), testRegex.toString(), 'Converted regex should have same behaviour'); | ||
}); |
@@ -1,473 +0,486 @@ | ||
/*! | ||
* VerbalExpressions JavaScript Library v0.3.0 | ||
* https://github.com/VerbalExpressions/JSVerbalExpressions | ||
/** | ||
* @file VerbalExpressions JavaScript Library | ||
* @version 0.3.0 | ||
* @license MIT | ||
* | ||
* | ||
* Released under the MIT license | ||
* http://opensource.org/licenses/MIT | ||
* @see https://github.com/VerbalExpressions/JSVerbalExpressions | ||
*/ | ||
/** | ||
* Define the VerbalExpression class. | ||
* @class | ||
*/ | ||
(function verbalExpressionIIFE(root) { | ||
// Constants | ||
var MODULE_NAME = 'VerEx'; | ||
* Define the VerbalExpression class | ||
* | ||
* @class VerbalExpression | ||
* @extends {RegExp} | ||
*/ | ||
class VerbalExpression extends RegExp { | ||
/** | ||
* I am the constructor function. | ||
* @constructor | ||
* @alias VerEx | ||
* @return {RegExp} A new instance of RegExp with injected methods | ||
*/ | ||
function VerbalExpression() { | ||
var verbalExpression = new RegExp(); | ||
* Creates an instance of VerbalExpression. | ||
* @constructor | ||
* @alias VerEx | ||
* @memberof VerbalExpression | ||
*/ | ||
constructor() { | ||
// Call the `RegExp` constructor so that `this` can be used | ||
super('', 'gm'); | ||
// Add all the class methods | ||
VerbalExpression.injectClassMethods(verbalExpression); | ||
// Return the new object. | ||
return verbalExpression; | ||
// Variables to hold the expression construction in order | ||
this._prefixes = ''; | ||
this._source = ''; | ||
this._suffixes = ''; | ||
this._modifiers = 'gm'; // 'global, multiline' matching by default | ||
} | ||
// Utility // | ||
/** | ||
* @param {RegExp} verbalExpression An instance of RegExp on which to add VerbalExpressions methods | ||
* @return {RegExp} A new instance of RegExp with injected methods | ||
*/ | ||
VerbalExpression.injectClassMethods = function injectClassMethods(verbalExpression) { | ||
var method; | ||
// Loop over all the prototype methods | ||
for (method in VerbalExpression.prototype) { | ||
// Make sure this is a local method. | ||
if (VerbalExpression.prototype.hasOwnProperty(method)) { | ||
// Add the method | ||
verbalExpression[method] = VerbalExpression.prototype[method]; | ||
} | ||
* Escape meta-characters in the parameter and make it safe for adding to the expression | ||
* @static | ||
* @param {(string|RegExp|number)} value object to sanitize | ||
* @returns {string} sanitized value | ||
* @memberof VerbalExpression | ||
*/ | ||
static sanitize(value) { | ||
if (value.source) { | ||
return value.source; | ||
} | ||
return verbalExpression; | ||
}; | ||
if (typeof value === 'number') { | ||
return value; | ||
} | ||
// Regular expression to match meta characters | ||
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp | ||
const toEscape = /([\].|*?+(){}^$\\:=[])/g; | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch | ||
const lastMatch = '$&'; | ||
// Escape meta characters | ||
return value.replace(toEscape, `\\${lastMatch}`); | ||
} | ||
/** | ||
* Define the class methods. | ||
*/ | ||
VerbalExpression.prototype = { | ||
// Variables to hold the whole | ||
// expression construction in order | ||
_prefixes: '', | ||
_source: '', | ||
_suffixes: '', | ||
_modifiers: 'gm', // default to global multiline matching | ||
* Add stuff to the expression and compile the new expression so it's ready to be used. | ||
* @param {(string|number)} [value=''] stuff to add | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
add(value = '') { | ||
this._source += value; | ||
const pattern = this._prefixes + this._source + this._suffixes; | ||
/** | ||
* Sanitation function for adding anything safely to the expression | ||
* @param {String} value string to sanitize | ||
* @return {String} sanitized value | ||
*/ | ||
sanitize: function sanitize(value) { | ||
var reRegExpEscape; | ||
this.compile(pattern, this._modifiers); | ||
if (value.source) { | ||
return value.source; | ||
} | ||
return this; | ||
} | ||
if (typeof value === 'number') { | ||
return value; | ||
} | ||
// Rules // | ||
// Regular expression meta characters, URL: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp | ||
reRegExpEscape = /([\].|*?+(){}^$\\:=[])/g; | ||
/** | ||
* Control start-of-line matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
startOfLine(enable = true) { | ||
this._prefixes = enable ? '^' : ''; | ||
return this.add(); | ||
} | ||
// Escape RegExp special characters only | ||
// $& => Last match, URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch | ||
return value.replace(reRegExpEscape, '\\$&'); | ||
}, | ||
/** | ||
* Control end-of-line matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
endOfLine(enable = true) { | ||
this._suffixes = enable ? '$' : ''; | ||
return this.add(); | ||
} | ||
/** | ||
* Function to add stuff to the expression. Also compiles the new expression so it's ready to be used. | ||
* @param {string} value literal expression, not sanitized | ||
* @return {VerbalExpression} Freshly recompiled instance of VerbalExpression | ||
*/ | ||
add: function add(value) { | ||
this._source += value || ''; | ||
this.compile(this._prefixes + this._source + this._suffixes, this._modifiers); | ||
/** | ||
* Look for the value passed | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
then(value) { | ||
value = VerbalExpression.sanitize(value); | ||
return this.add(`(?:${value})`); | ||
} | ||
return this; | ||
}, | ||
/** | ||
* Alias for then() to allow for readable syntax when then() is the first method in the chain. | ||
* @param {(string|RegExp|numer)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
find(value) { | ||
return this.then(value); | ||
} | ||
/** | ||
* Control start-of-line matching | ||
* @param {Boolean} enable Control start-of-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
startOfLine: function startOfLine(enable) { | ||
enable = (enable !== false); | ||
this._prefixes = enable ? '^' : ''; | ||
return this.add(); | ||
}, | ||
/** | ||
* Add optional values | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
maybe(value) { | ||
value = VerbalExpression.sanitize(value); | ||
return this.add(`(?:${value})?`); | ||
} | ||
/** | ||
* Control end-of-line matching | ||
* @param {Boolean} enable Control end-of-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
endOfLine: function endOfLine(enable) { | ||
enable = (enable !== false); | ||
this._suffixes = enable ? '$' : ''; | ||
return this.add(); | ||
}, | ||
/** | ||
* Add alternative expressions | ||
* @param {(string|RegExp|number)} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
or(value) { | ||
this._prefixes += '(?:'; | ||
this._suffixes = `)${this._suffixes}`; | ||
/** | ||
* We try to keep the syntax as user-friendly as possible. So we can use the "normal" behaviour to split the "sentences" naturally. | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
then: function then(value) { | ||
value = this.sanitize(value); | ||
return this.add('(?:' + value + ')'); | ||
}, | ||
this.add(')|(?:'); | ||
/** | ||
* And because we can't start with "then" function, we create an alias to be used as the first function of the chain. | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
find: function find(value) { | ||
return this.then(value); | ||
}, | ||
if (value) { | ||
this.then(value); | ||
} | ||
/* | ||
* Maybe is used to add values with ? | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
maybe: function maybe(value) { | ||
value = this.sanitize(value); | ||
return this.add('(?:' + value + ')?'); | ||
}, | ||
return this; | ||
} | ||
/** | ||
* Any character any number of times | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anything: function anything() { | ||
return this.add('(?:.*)'); | ||
}, | ||
/** | ||
* Any character any number of times | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
anything() { | ||
return this.add('(?:.*)'); | ||
} | ||
/** | ||
* Anything but these characters | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anythingBut: function anythingBut(value) { | ||
value = this.sanitize(value); | ||
return this.add('(?:[^' + value + ']*)'); | ||
}, | ||
/** | ||
* Anything but these characters | ||
* @param {(string|number|string[]|number[])} value characters to not match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
anythingBut(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
/** | ||
* Any character at least one time | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
something: function something() { | ||
return this.add('(?:.+)'); | ||
}, | ||
value = VerbalExpression.sanitize(value); | ||
return this.add(`(?:[^${value}]*)`); | ||
} | ||
/** | ||
* Any character at least one time except for these characters | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
somethingBut: function somethingBut(value) { | ||
value = this.sanitize(value); | ||
return this.add('(?:[^' + value + ']+)'); | ||
}, | ||
/** | ||
* Any character(s) at least once | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
something() { | ||
return this.add('(?:.+)'); | ||
} | ||
/** | ||
* Shorthand function for the String.replace function to give more logical flow if, for example, we're doing multiple replacements on one regexp. | ||
* @param {String} source string to search for | ||
* @param {String} value value to replace with | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
replace: function replace(source, value) { | ||
source = source.toString(); | ||
return source.replace(this, value); | ||
}, | ||
/** | ||
* Any character at least one time except for these characters | ||
* @param {(string|number|string[]|number[])} value characters to not match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
somethingBut(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
/// Add regular expression special /// | ||
/// characters /// | ||
value = VerbalExpression.sanitize(value); | ||
return this.add(`(?:[^${value}]+)`); | ||
} | ||
/** | ||
* Line break | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
lineBreak: function lineBreak() { | ||
return this.add('(?:\\r\\n|\\r|\\n)'); // Unix + Windows CRLF | ||
}, | ||
/** | ||
* Match any of the given characters | ||
* @param {(string|number|string[]|number[])} value characters to match | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
anyOf(value) { | ||
if (Array.isArray(value)) { | ||
value = value.join(''); | ||
} | ||
/** | ||
* And a shorthand for html-minded | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
br: function br() { | ||
return this.lineBreak(); | ||
}, | ||
value = VerbalExpression.sanitize(value); | ||
return this.add(`[${value}]`); | ||
} | ||
/** | ||
* Tab (duh?) | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
tab: function tab() { | ||
return this.add('\\t'); | ||
}, | ||
/** | ||
* Shorthand for anyOf(value) | ||
* @param {string|number} value value to find | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
any(value) { | ||
return this.anyOf(value); | ||
} | ||
/** | ||
* Any alphanumeric | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
word: function word() { | ||
return this.add('\\w+'); | ||
}, | ||
/** | ||
* Ensure that the parameter does not follow | ||
* @param {string|number} value | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
not(value) { | ||
value = VerbalExpression.sanitize(value); | ||
this.add(`(?!${value})`); | ||
/** | ||
* Any digit | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
digit: function digit() { | ||
this.add('\\d'); | ||
return this; | ||
}, | ||
return this; | ||
} | ||
/** | ||
* Any whitespace | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
whitespace: function whitespace() { | ||
return this.add('\\s'); | ||
}, | ||
/** | ||
* Matching any character within a range of characters | ||
* Usage: .range( from, to [, from, to ... ] ) | ||
* @param {...string} ranges characters denoting beginning and ending of ranges | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
range(...ranges) { | ||
let value = ''; | ||
/** | ||
* Any given character | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
anyOf: function anyOf(value) { | ||
value = this.sanitize(value); | ||
return this.add('[' + value + ']'); | ||
}, | ||
for (let i = 1; i < ranges.length; i += 2) { | ||
const from = VerbalExpression.sanitize(ranges[i - 1]); | ||
const to = VerbalExpression.sanitize(ranges[i]); | ||
/** | ||
* Shorthand | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
any: function any(value) { | ||
return this.anyOf(value); | ||
}, | ||
value += `${from}-${to}`; | ||
} | ||
/** | ||
* Usage: .range( from, to [, from, to ... ] ) | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
range: function range() { | ||
var length = arguments.length; | ||
return this.add(`[${value}]`); | ||
} | ||
// Create a string buffer instead of concatenating on iteration | ||
var buffer = new Array(length / 2); | ||
var index = 0; | ||
var i = 0; | ||
var from; | ||
var to; | ||
// Special characters // | ||
buffer[index++] = '['; | ||
/** | ||
* Match a Line break | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
lineBreak() { | ||
return this.add('(?:\\r\\n|\\r|\\n)'); // Unix(LF) + Windows(CRLF) | ||
} | ||
while (i < length) { | ||
from = this.sanitize(arguments[i++]); | ||
to = this.sanitize(arguments[i++]); | ||
buffer[index++] = from + '-' + to; | ||
} | ||
/** | ||
* A shorthand for lineBreak() for html-minded users | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
br() { | ||
return this.lineBreak(); | ||
} | ||
buffer[index++] = ']'; | ||
/** | ||
* Match a tab character | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
tab() { | ||
return this.add('\\t'); | ||
} | ||
return this.add(buffer.join('')); | ||
}, | ||
/** | ||
* Match any alphanumeric | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
word() { | ||
return this.add('\\w+'); | ||
} | ||
/// Modifiers /// | ||
/** | ||
* Match a single digit | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
digit() { | ||
return this.add('\\d'); | ||
} | ||
/** | ||
* Modifier abstraction | ||
* @param {String} modifier modifier to add | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
addModifier: function addModifier(modifier) { | ||
if (this._modifiers.indexOf(modifier) === -1) { | ||
this._modifiers += modifier; | ||
} | ||
/** | ||
* Match a single whitespace | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
whitespace() { | ||
return this.add('\\s'); | ||
} | ||
return this.add(); | ||
}, | ||
// Modifiers // | ||
/** | ||
* Remove modifier | ||
* @param {String} modifier modifier to remove | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
removeModifier: function removeModifier(modifier) { | ||
this._modifiers = this._modifiers.replace(modifier, ''); | ||
return this.add(); | ||
}, | ||
/** | ||
* Add a regex modifier/flag | ||
* @param {string} modifier modifier to add | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
addModifier(modifier) { | ||
if (!this._modifiers.includes(modifier)) { | ||
this._modifiers += modifier; | ||
} | ||
/** | ||
* Case-insensitivity modifier | ||
* @param {Boolean} enable Control case-insensitive matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
withAnyCase: function withAnyCase(enable) { | ||
return enable !== false ? this.addModifier('i') : this.removeModifier('i'); | ||
}, | ||
return this.add(); | ||
} | ||
/** | ||
* Default behaviour is with "g" modifier, so we can turn this another way around than other modifiers | ||
* @param {Boolean} enable Control global matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
stopAtFirst: function stopAtFirst(enable) { | ||
return enable !== false ? this.removeModifier('g') : this.addModifier('g'); | ||
}, | ||
/** | ||
* Remove modifier | ||
* @param {string} modifier modifier to remove | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
removeModifier(modifier) { | ||
this._modifiers = this._modifiers.replace(modifier, ''); | ||
return this.add(); | ||
} | ||
/** | ||
* Multiline, also reversed | ||
* @param {Boolean} enable Control multi-line matching | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
searchOneLine: function searchOneLine(enable) { | ||
return enable !== false ? this.removeModifier('m') : this.addModifier('m'); | ||
}, | ||
/** | ||
* Control case-insensitive matching | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
withAnyCase(enable = true) { | ||
return enable ? this.addModifier('i') : this.removeModifier('i'); | ||
} | ||
/** | ||
* Repeats the previous item exactly n times or between n and m times. | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
repeatPrevious: function repeatPrevious() { | ||
var value; | ||
var reIsInteger = /\d+/; | ||
var length = arguments.length; | ||
var values = new Array(length); | ||
var i = 0; | ||
var j = 0; | ||
for (i = 0; i < length; i++) { | ||
if (reIsInteger.test(arguments[i])) { | ||
values[j++] = arguments[i]; | ||
} | ||
} | ||
/** | ||
* Default behaviour is with "g" modifier, so we can turn this another way around than other modifiers | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
stopAtFirst(enable = true) { | ||
return enable ? this.removeModifier('g') : this.addModifier('g'); | ||
} | ||
if (j > 0) { | ||
// Set the new length of the array, thus reducing to the elements that have content | ||
values.length = j; | ||
value = '{' + values.join(',') + '}'; | ||
} | ||
/** | ||
* Control the multiline modifier | ||
* @param {boolean} [enable=true] whether to enable this behaviour | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
searchOneLine(enable = true) { | ||
return enable ? this.removeModifier('m') : this.addModifier('m'); | ||
} | ||
// Loops // | ||
return this.add(value); | ||
}, | ||
/** | ||
* Repeat the previous item exactly n times or between n and m times | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
repeatPrevious(...quantity) { | ||
const isInteger = /\d+/; | ||
const values = quantity.filter(argument => isInteger.test(argument)); | ||
/** | ||
* Repeats the previous at least once | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
oneOrMore: function oneOrMore() { | ||
return this.add('+'); | ||
}, | ||
if (values.length === 0 || values.length > 2) { | ||
return this; | ||
} | ||
/// Loops /// | ||
this.add(`{${values.join(',')}}`); | ||
/** | ||
* Matches the value zero or more times | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
multiple: function multiple(value) { | ||
// Use expression or string | ||
value = value.source || this.sanitize(value); | ||
if (arguments.length === 1) { | ||
this.add('(?:' + value + ')*'); | ||
} | ||
return this; | ||
} | ||
if (arguments.length > 1) { | ||
this.add('(?:' + value + ')'); | ||
this.add('{' + arguments[1] + '}'); | ||
} | ||
/** | ||
* Repeat the previous at least once | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
oneOrMore() { | ||
return this.add('+'); | ||
} | ||
return this; | ||
}, | ||
/** | ||
* Match the value zero or more times | ||
* @param {string} value value to find | ||
* @param {integer} [lower] minimum number of times the value should be repeated | ||
* @param {integer} [upper] maximum number of times the value should be repeated | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
multiple(value, lower, upper) { | ||
if (value !== undefined) { | ||
value = VerbalExpression.sanitize(value); | ||
this.add(`(?:${value})`); | ||
} | ||
/** | ||
* Adds alternative expressions | ||
* @param {String} value value to find | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
or: function or(value) { | ||
this._prefixes += '(?:'; | ||
this._suffixes = ')' + this._suffixes; | ||
if (lower === undefined && upper === undefined) { | ||
this.add('*'); // Any number of times | ||
} else if (lower !== undefined && upper === undefined) { | ||
this.add(`{${lower},}`); | ||
} else if (lower !== undefined && upper !== undefined) { | ||
this.add(`{${lower},${upper}}`); | ||
} | ||
this.add(')|(?:'); | ||
if (value) { | ||
this.then(value); | ||
} | ||
return this; | ||
} | ||
return this; | ||
}, | ||
// Capture groups // | ||
/** | ||
* Starts a capturing group | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
beginCapture: function beginCapture() { | ||
// Add the end of the capture group to the suffixes for now so compilation continues to work | ||
this._suffixes += ')'; | ||
return this.add('('); | ||
}, | ||
/** | ||
* Starts a capturing group | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
beginCapture() { | ||
// Add the end of the capture group to the suffixes temporarily so that compilation continues to work | ||
this._suffixes += ')'; | ||
return this.add('('); | ||
} | ||
/** | ||
* Ends a capturing group | ||
* @return {VerbalExpression} Same instance of VerbalExpression to allow method chaining | ||
*/ | ||
endCapture: function endCapture() { | ||
// Remove the last parentheses from the _suffixes and add to the regex itself | ||
this._suffixes = this._suffixes.substring(0, this._suffixes.length - 1); | ||
return this.add(')'); | ||
}, | ||
/** | ||
* Ends a capturing group | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
endCapture() { | ||
// Remove the last parenthesis from the _suffixes and add it to the regex | ||
this._suffixes = this._suffixes.slice(0, -1); | ||
return this.add(')'); | ||
} | ||
/** | ||
* Convert to RegExp object | ||
* @return {RegExp} Converted RegExp instance | ||
*/ | ||
toRegExp: function toRegExp() { | ||
var array = this.toString().match(/\/(.*)\/([gimuy]+)?/); | ||
return new RegExp(array[1], array[2]); | ||
} | ||
}; | ||
// Miscellaneous // | ||
/** | ||
* @return {VerbalExpression} Returns a new instance of VerbalExpressions | ||
*/ | ||
function createVerbalExpression() { | ||
return new VerbalExpression(); | ||
* Shorthand function for the string.replace function to allow for a more logical flow | ||
* @param {string} source string to search for | ||
* @param {string} value value to replace with | ||
* @returns {VerbalExpression} recompiled instance of VerbalExpression | ||
* @memberof VerbalExpression | ||
*/ | ||
replace(source, value) { | ||
source = source.toString(); | ||
return source.replace(this, value); | ||
} | ||
// UMD (Universal Module Definition), URL: https://github.com/umdjs/umd | ||
// Supports AMD, CommonJS and the browser | ||
if (typeof module !== 'undefined' && module.exports) { | ||
// Node.js Module | ||
module.exports = createVerbalExpression; | ||
} else if (typeof define === 'function' && define.amd) { | ||
// AMD Module | ||
define(MODULE_NAME, [], function define() { | ||
return VerbalExpression; | ||
}); | ||
} else { | ||
// Browser | ||
root[MODULE_NAME] = createVerbalExpression; | ||
/** | ||
* Convert to RegExp object | ||
* @returns {RegExp} equivalent RegExp instance | ||
* @memberof VerbalExpression | ||
*/ | ||
toRegExp() { | ||
const components = this.toString().match(/\/(.*)\/([gimuy]+)?/); | ||
const pattern = components[1]; | ||
const flags = components[2]; | ||
return new RegExp(pattern, flags); | ||
} | ||
}(this)); | ||
} | ||
/** | ||
* Return a new instance of `VerbalExpression` | ||
* @export | ||
* @returns {VerbalExpression} new instance | ||
*/ | ||
function VerEx() { // eslint-disable-line no-unused-vars | ||
const instance = new VerbalExpression(); | ||
instance.sanitize = VerbalExpression.sanitize; | ||
return instance; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
82
0
0
167
782573
18
1804
1