diff --git a/VerbalExpressions.js b/VerbalExpressions.js index c3630a0c..fd8c6910 100644 --- a/VerbalExpressions.js +++ b/VerbalExpressions.js @@ -54,13 +54,15 @@ class VerbalExpression extends RegExp { // Regular expression to match meta characters // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp - const toEscape = /([\].|*?+(){}^$\\:=[])/g; + 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}`); + return value + .replace(toEscape, `\\${lastMatch}`) + .replace(/-/g, '\\x2d'); } /** diff --git a/dist/verbalexpressions.js b/dist/verbalexpressions.js index 3309b9b8..c15f5818 100644 --- a/dist/verbalexpressions.js +++ b/dist/verbalexpressions.js @@ -15,37 +15,51 @@ } }(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 _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 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 _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); } } -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 _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } -function _extendableBuiltin(cls) { - function ExtendableBuiltin() { - var instance = Reflect.construct(cls, Array.from(arguments)); - Object.setPrototypeOf(instance, Object.getPrototypeOf(this)); - return instance; - } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } - ExtendableBuiltin.prototype = Object.create(cls.prototype, { - constructor: { - value: cls, - enumerable: false, - writable: true, - configurable: true - } - }); +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } - if (Object.setPrototypeOf) { - Object.setPrototypeOf(ExtendableBuiltin, cls); - } else { - ExtendableBuiltin.__proto__ = cls; +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +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 } + }); - return ExtendableBuiltin; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(ExtendableBuiltin, cls); + } else { + ExtendableBuiltin.__proto__ = cls; + } + + return ExtendableBuiltin; } /** @@ -62,603 +76,549 @@ function _extendableBuiltin(cls) { * @class VerbalExpression * @extends {RegExp} */ -var VerbalExpression = function (_extendableBuiltin2) { - _inherits(VerbalExpression, _extendableBuiltin2); +var VerbalExpression = /*#__PURE__*/function (_extendableBuiltin2) { + _inherits(VerbalExpression, _extendableBuiltin2); + + var _super = _createSuper(VerbalExpression); + + /** + * Creates an instance of VerbalExpression. + * @constructor + * @alias VerEx + * @memberof VerbalExpression + */ + function VerbalExpression() { + var _this; + + _classCallCheck(this, VerbalExpression); + + // Call the `RegExp` constructor so that `this` can be used + _this = _super.call(this, '', 'gm'); // Variables to hold the expression construction in order + + _this._prefixes = ''; + _this._source = ''; + _this._suffixes = ''; + _this._modifiers = 'gm'; // 'global, multiline' matching by default + + return _this; + } // Utility // + + /** + * 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 + */ + + + _createClass(VerbalExpression, [{ + key: "add", + value: + /** + * 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 + */ + function add() { + var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + this._source += value; + var pattern = this._prefixes + this._source + this._suffixes; + this.compile(pattern, this._modifiers); + return this; + } // Rules // /** - * Creates an instance of VerbalExpression. - * @constructor - * @alias VerEx + * Control start-of-line matching + * @param {boolean} [enable=true] whether to enable this behaviour + * @returns {VerbalExpression} recompiled instance of VerbalExpression * @memberof VerbalExpression */ - function VerbalExpression() { - _classCallCheck(this, 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 + }, { + key: "startOfLine", + value: function startOfLine() { + var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + this._prefixes = enable ? '^' : ''; + return this.add(); + } + /** + * 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(); + } + /** + * Look for the value passed + * @param {(string|RegExp|number)} value value to find + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ - _this._prefixes = ''; - _this._source = ''; - _this._suffixes = ''; - _this._modifiers = 'gm'; // 'global, multiline' matching by default - return _this; + }, { + key: "then", + value: function then(value) { + value = VerbalExpression.sanitize(value); + return this.add("(?:".concat(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 + */ - // Utility // + }, { + key: "find", + value: function find(value) { + return this.then(value); + } + /** + * Add optional values + * @param {(string|RegExp|number)} value value to find + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ - /** - * 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 - */ - - - _createClass(VerbalExpression, [{ - key: 'add', - - - /** - * 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] : ''; - - this._source += value; - var pattern = this._prefixes + this._source + this._suffixes; - - this.compile(pattern, this._modifiers); - - return this; - } - - // Rules // - - /** - * Control start-of-line matching - * @param {boolean} [enable=true] whether to enable this behaviour - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'startOfLine', - value: function startOfLine() { - var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; - - this._prefixes = enable ? '^' : ''; - return this.add(); - } - - /** - * 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(); - } - - /** - * 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 + ')'); - } - - /** - * 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); - } - - /** - * 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 + ')?'); - } - - /** - * 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|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(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|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 + ']+)'); - } - - /** - * Match any of the given characters - * @param {(string|number|string[]|number[])} value characters to match - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'anyOf', - value: function anyOf(value) { - if (Array.isArray(value)) { - value = value.join(''); - } - - value = VerbalExpression.sanitize(value); - return this.add('[' + value + ']'); - } - - /** - * Shorthand for anyOf(value) - * @param {string|number} value value to find - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'any', - value: function any(value) { - return this.anyOf(value); - } - - /** - * Ensure that the parameter does not follow - * @param {string|number} value - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'not', - value: function not(value) { - value = VerbalExpression.sanitize(value); - this.add('(?!' + value + ')'); - - return this; - } - - /** - * 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 - */ - - }, { - 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 // - - /** - * 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) - } - - /** - * A shorthand for lineBreak() for html-minded users - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'br', - value: function br() { - return this.lineBreak(); - } - - /** - * Match a tab character - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'tab', - value: function tab() { - return this.add('\\t'); - } - - /** - * Match any alphanumeric - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'word', - value: function word() { - return this.add('\\w+'); - } - - /** - * Match a single digit - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'digit', - value: function digit() { - return this.add('\\d'); - } - - /** - * 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; - } - - return this.add(); - } - - /** - * 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(); - } - - /** - * Control case-insensitive matching - * @param {boolean} [enable=true] whether to enable this behaviour - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'withAnyCase', - value: function withAnyCase() { - var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; - - return enable ? this.addModifier('i') : this.removeModifier('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 - */ - - }, { - key: 'stopAtFirst', - value: function stopAtFirst() { - var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; - - return enable ? this.removeModifier('g') : this.addModifier('g'); - } - - /** - * Control the multiline modifier - * @param {boolean} [enable=true] whether to enable this behaviour - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'searchOneLine', - value: function searchOneLine() { - var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; - - return enable ? this.removeModifier('m') : this.addModifier('m'); - } - - // Loops // - - /** - * Repeat the previous item exactly n times or between n and m times - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - key: 'repeatPrevious', - value: function repeatPrevious() { - var isInteger = /\d+/; - - for (var _len = arguments.length, quantity = Array(_len), _key = 0; _key < _len; _key++) { - quantity[_key] = arguments[_key]; - } - - 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; - } - - /** - * Repeat the previous at least once - * @returns {VerbalExpression} recompiled instance of VerbalExpression - * @memberof VerbalExpression - */ - - }, { - 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 - * @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 - * @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 // - - /** - * 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); - } - - /** - * Convert to RegExp object - * @returns {RegExp} equivalent RegExp instance - * @memberof VerbalExpression - */ - - }, { - 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 instanceof RegExp) { - return value.source; - } - - if (typeof value === 'number') { - return value; - } - - if (typeof value !== 'string') { - return ''; - } - - // 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)); + }, { + key: "maybe", + value: function maybe(value) { + value = VerbalExpression.sanitize(value); + return this.add("(?:".concat(value, ")?")); + } + /** + * 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 = ")".concat(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|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("(?:[^".concat(value, "]*)")); + } + /** + * 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|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("(?:[^".concat(value, "]+)")); + } + /** + * Match any of the given characters + * @param {(string|number|string[]|number[])} value characters to match + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "anyOf", + value: function anyOf(value) { + if (Array.isArray(value)) { + value = value.join(''); + } + + value = VerbalExpression.sanitize(value); + return this.add("[".concat(value, "]")); + } + /** + * Shorthand for anyOf(value) + * @param {string|number} value value to find + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "any", + value: function any(value) { + return this.anyOf(value); + } + /** + * Ensure that the parameter does not follow + * @param {string|number} value + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "not", + value: function not(value) { + value = VerbalExpression.sanitize(value); + this.add("(?!".concat(value, ")")); + return this; + } + /** + * 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 + */ + + }, { + key: "range", + value: function range() { + var value = ''; + + for (var i = 1; i < arguments.length; i += 2) { + var from = VerbalExpression.sanitize(i - 1 < 0 || arguments.length <= i - 1 ? undefined : arguments[i - 1]); + var to = VerbalExpression.sanitize(i < 0 || arguments.length <= i ? undefined : arguments[i]); + value += "".concat(from, "-").concat(to); + } + + return this.add("[".concat(value, "]")); + } // Special characters // + + /** + * 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) + } + /** + * A shorthand for lineBreak() for html-minded users + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "br", + value: function br() { + return this.lineBreak(); + } + /** + * Match a tab character + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "tab", + value: function tab() { + return this.add('\\t'); + } + /** + * Match any alphanumeric + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "word", + value: function word() { + return this.add('\\w+'); + } + /** + * Match a single digit + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "digit", + value: function digit() { + return this.add('\\d'); + } + /** + * 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; + } + + return this.add(); + } + /** + * 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(); + } + /** + * Control case-insensitive matching + * @param {boolean} [enable=true] whether to enable this behaviour + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "withAnyCase", + value: function withAnyCase() { + var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + return enable ? this.addModifier('i') : this.removeModifier('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 + */ + + }, { + key: "stopAtFirst", + value: function stopAtFirst() { + var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + return enable ? this.removeModifier('g') : this.addModifier('g'); + } + /** + * Control the multiline modifier + * @param {boolean} [enable=true] whether to enable this behaviour + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + }, { + key: "searchOneLine", + value: function searchOneLine() { + var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + return enable ? this.removeModifier('m') : this.addModifier('m'); + } // Loops // + + /** + * Repeat the previous item exactly n times or between n and m times + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + key: "repeatPrevious", + value: function repeatPrevious() { + var isInteger = /\d+/; + + for (var _len = arguments.length, quantity = new Array(_len), _key = 0; _key < _len; _key++) { + quantity[_key] = arguments[_key]; + } + + var values = quantity.filter(function (argument) { + return isInteger.test(argument); + }); + + if (values.length === 0 || values.length > 2) { + return this; + } + + this.add("{".concat(values.join(','), "}")); + return this; + } + /** + * Repeat the previous at least once + * @returns {VerbalExpression} recompiled instance of VerbalExpression + * @memberof VerbalExpression + */ + + }, { + 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("(?:".concat(value, ")")); + } + + if (lower === undefined && upper === undefined) { + this.add('*'); // Any number of times + } else if (lower !== undefined && upper === undefined) { + this.add("{".concat(lower, ",}")); + } else if (lower !== undefined && upper !== undefined) { + this.add("{".concat(lower, ",").concat(upper, "}")); + } + + return this; + } // Capture groups // + + /** + * 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 + * @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 // + + /** + * 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); + } + /** + * Convert to RegExp object + * @returns {RegExp} equivalent RegExp instance + * @memberof VerbalExpression + */ + + }, { + 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 instanceof RegExp) { + return value.source; + } + + if (typeof value === 'number') { + return value; + } + + if (typeof value !== 'string') { + return ''; + } // 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, "\\".concat(lastMatch)).replace(/-/g, '\\x2d'); + } + }]); + + return VerbalExpression; +}(_extendableBuiltin(RegExp)); /** * Return a new instance of `VerbalExpression` * @export @@ -667,10 +627,10 @@ var VerbalExpression = function (_extendableBuiltin2) { function VerEx() { - // eslint-disable-line no-unused-vars - var instance = new VerbalExpression(); - instance.sanitize = VerbalExpression.sanitize; - return instance; + // eslint-disable-line no-unused-vars + var instance = new VerbalExpression(); + instance.sanitize = VerbalExpression.sanitize; + return instance; } //# sourceMappingURL=verbalexpressions.js.map diff --git a/dist/verbalexpressions.js.map b/dist/verbalexpressions.js.map index 189df829..e4691a78 100644 --- a/dist/verbalexpressions.js.map +++ b/dist/verbalexpressions.js.map @@ -1 +1 @@ -{"version":3,"sources":["../VerbalExpressions.js"],"names":["VerbalExpression","_prefixes","_source","_suffixes","_modifiers","value","pattern","compile","enable","add","sanitize","then","Array","isArray","join","anyOf","i","length","from","to","lineBreak","modifier","includes","replace","addModifier","removeModifier","isInteger","quantity","values","filter","test","argument","lower","upper","undefined","slice","source","toString","components","match","flags","RegExp","toEscape","lastMatch","VerEx","instance"],"mappings":"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","file":"verbalexpressions.js","sourcesContent":["/**\r\n * @file VerbalExpressions JavaScript Library\r\n * @version 0.3.0\r\n * @license MIT\r\n *\r\n * @see https://github.com/VerbalExpressions/JSVerbalExpressions\r\n */\r\n\r\n/**\r\n * Define the VerbalExpression class\r\n *\r\n * @class VerbalExpression\r\n * @extends {RegExp}\r\n */\r\nclass VerbalExpression extends RegExp {\r\n /**\r\n * Creates an instance of VerbalExpression.\r\n * @constructor\r\n * @alias VerEx\r\n * @memberof VerbalExpression\r\n */\r\n constructor() {\r\n // Call the `RegExp` constructor so that `this` can be used\r\n super('', 'gm');\r\n\r\n // Variables to hold the expression construction in order\r\n this._prefixes = '';\r\n this._source = '';\r\n this._suffixes = '';\r\n this._modifiers = 'gm'; // 'global, multiline' matching by default\r\n }\r\n\r\n // Utility //\r\n\r\n /**\r\n * Escape meta-characters in the parameter and make it safe for adding to the expression\r\n * @static\r\n * @param {(string|RegExp|number)} value object to sanitize\r\n * @returns {string} sanitized value\r\n * @memberof VerbalExpression\r\n */\r\n static sanitize(value) {\r\n if (value instanceof RegExp) {\r\n return value.source;\r\n }\r\n\r\n if (typeof value === 'number') {\r\n return value;\r\n }\r\n\r\n if (typeof value !== 'string') {\r\n return '';\r\n }\r\n\r\n // Regular expression to match meta characters\r\n // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp\r\n const toEscape = /([\\].|*?+(){}^$\\\\:=[])/g;\r\n\r\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch\r\n const lastMatch = '$&';\r\n\r\n // Escape meta characters\r\n return value.replace(toEscape, `\\\\${lastMatch}`);\r\n }\r\n\r\n /**\r\n * Add stuff to the expression and compile the new expression so it's ready to be used.\r\n * @param {(string|number)} [value=''] stuff to add\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n add(value = '') {\r\n this._source += value;\r\n const pattern = this._prefixes + this._source + this._suffixes;\r\n\r\n this.compile(pattern, this._modifiers);\r\n\r\n return this;\r\n }\r\n\r\n // Rules //\r\n\r\n /**\r\n * Control start-of-line matching\r\n * @param {boolean} [enable=true] whether to enable this behaviour\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n startOfLine(enable = true) {\r\n this._prefixes = enable ? '^' : '';\r\n return this.add();\r\n }\r\n\r\n /**\r\n * Control end-of-line matching\r\n * @param {boolean} [enable=true] whether to enable this behaviour\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n endOfLine(enable = true) {\r\n this._suffixes = enable ? '$' : '';\r\n return this.add();\r\n }\r\n\r\n /**\r\n * Look for the value passed\r\n * @param {(string|RegExp|number)} value value to find\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n then(value) {\r\n value = VerbalExpression.sanitize(value);\r\n return this.add(`(?:${value})`);\r\n }\r\n\r\n /**\r\n * Alias for then() to allow for readable syntax when then() is the first method in the chain.\r\n * @param {(string|RegExp|numer)} value value to find\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n find(value) {\r\n return this.then(value);\r\n }\r\n\r\n /**\r\n * Add optional values\r\n * @param {(string|RegExp|number)} value value to find\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n maybe(value) {\r\n value = VerbalExpression.sanitize(value);\r\n return this.add(`(?:${value})?`);\r\n }\r\n\r\n /**\r\n * Add alternative expressions\r\n * @param {(string|RegExp|number)} value value to find\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n or(value) {\r\n this._prefixes += '(?:';\r\n this._suffixes = `)${this._suffixes}`;\r\n\r\n this.add(')|(?:');\r\n\r\n if (value) {\r\n this.then(value);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Any character any number of times\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n anything() {\r\n return this.add('(?:.*)');\r\n }\r\n\r\n /**\r\n * Anything but these characters\r\n * @param {(string|number|string[]|number[])} value characters to not match\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n anythingBut(value) {\r\n if (Array.isArray(value)) {\r\n value = value.join('');\r\n }\r\n\r\n value = VerbalExpression.sanitize(value);\r\n return this.add(`(?:[^${value}]*)`);\r\n }\r\n\r\n /**\r\n * Any character(s) at least once\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n something() {\r\n return this.add('(?:.+)');\r\n }\r\n\r\n /**\r\n * Any character at least one time except for these characters\r\n * @param {(string|number|string[]|number[])} value characters to not match\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n somethingBut(value) {\r\n if (Array.isArray(value)) {\r\n value = value.join('');\r\n }\r\n\r\n value = VerbalExpression.sanitize(value);\r\n return this.add(`(?:[^${value}]+)`);\r\n }\r\n\r\n /**\r\n * Match any of the given characters\r\n * @param {(string|number|string[]|number[])} value characters to match\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n anyOf(value) {\r\n if (Array.isArray(value)) {\r\n value = value.join('');\r\n }\r\n\r\n value = VerbalExpression.sanitize(value);\r\n return this.add(`[${value}]`);\r\n }\r\n\r\n /**\r\n * Shorthand for anyOf(value)\r\n * @param {string|number} value value to find\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n any(value) {\r\n return this.anyOf(value);\r\n }\r\n\r\n /**\r\n * Ensure that the parameter does not follow\r\n * @param {string|number} value\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n not(value) {\r\n value = VerbalExpression.sanitize(value);\r\n this.add(`(?!${value})`);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Matching any character within a range of characters\r\n * Usage: .range( from, to [, from, to ... ] )\r\n * @param {...string} ranges characters denoting beginning and ending of ranges\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n range(...ranges) {\r\n let value = '';\r\n\r\n for (let i = 1; i < ranges.length; i += 2) {\r\n const from = VerbalExpression.sanitize(ranges[i - 1]);\r\n const to = VerbalExpression.sanitize(ranges[i]);\r\n\r\n value += `${from}-${to}`;\r\n }\r\n\r\n return this.add(`[${value}]`);\r\n }\r\n\r\n // Special characters //\r\n\r\n /**\r\n * Match a Line break\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n lineBreak() {\r\n return this.add('(?:\\\\r\\\\n|\\\\r|\\\\n)'); // Unix(LF) + Windows(CRLF)\r\n }\r\n\r\n /**\r\n * A shorthand for lineBreak() for html-minded users\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n br() {\r\n return this.lineBreak();\r\n }\r\n\r\n /**\r\n * Match a tab character\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n tab() {\r\n return this.add('\\\\t');\r\n }\r\n\r\n /**\r\n * Match any alphanumeric\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n word() {\r\n return this.add('\\\\w+');\r\n }\r\n\r\n /**\r\n * Match a single digit\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n digit() {\r\n return this.add('\\\\d');\r\n }\r\n\r\n /**\r\n * Match a single whitespace\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n whitespace() {\r\n return this.add('\\\\s');\r\n }\r\n\r\n // Modifiers //\r\n\r\n /**\r\n * Add a regex modifier/flag\r\n * @param {string} modifier modifier to add\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n addModifier(modifier) {\r\n if (!this._modifiers.includes(modifier)) {\r\n this._modifiers += modifier;\r\n }\r\n\r\n return this.add();\r\n }\r\n\r\n /**\r\n * Remove modifier\r\n * @param {string} modifier modifier to remove\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n removeModifier(modifier) {\r\n this._modifiers = this._modifiers.replace(modifier, '');\r\n return this.add();\r\n }\r\n\r\n /**\r\n * Control case-insensitive matching\r\n * @param {boolean} [enable=true] whether to enable this behaviour\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n withAnyCase(enable = true) {\r\n return enable ? this.addModifier('i') : this.removeModifier('i');\r\n }\r\n\r\n /**\r\n * Default behaviour is with \"g\" modifier, so we can turn this another way around than other modifiers\r\n * @param {boolean} [enable=true] whether to enable this behaviour\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n stopAtFirst(enable = true) {\r\n return enable ? this.removeModifier('g') : this.addModifier('g');\r\n }\r\n\r\n /**\r\n * Control the multiline modifier\r\n * @param {boolean} [enable=true] whether to enable this behaviour\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n searchOneLine(enable = true) {\r\n return enable ? this.removeModifier('m') : this.addModifier('m');\r\n }\r\n\r\n // Loops //\r\n\r\n /**\r\n * Repeat the previous item exactly n times or between n and m times\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n repeatPrevious(...quantity) {\r\n const isInteger = /\\d+/;\r\n const values = quantity.filter(argument => isInteger.test(argument));\r\n\r\n if (values.length === 0 || values.length > 2) {\r\n return this;\r\n }\r\n\r\n this.add(`{${values.join(',')}}`);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Repeat the previous at least once\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n oneOrMore() {\r\n return this.add('+');\r\n }\r\n\r\n /**\r\n * Match the value zero or more times\r\n * @param {string} value value to find\r\n * @param {integer} [lower] minimum number of times the value should be repeated\r\n * @param {integer} [upper] maximum number of times the value should be repeated\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n multiple(value, lower, upper) {\r\n if (value !== undefined) {\r\n value = VerbalExpression.sanitize(value);\r\n this.add(`(?:${value})`);\r\n }\r\n\r\n if (lower === undefined && upper === undefined) {\r\n this.add('*'); // Any number of times\r\n } else if (lower !== undefined && upper === undefined) {\r\n this.add(`{${lower},}`);\r\n } else if (lower !== undefined && upper !== undefined) {\r\n this.add(`{${lower},${upper}}`);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n // Capture groups //\r\n\r\n /**\r\n * Starts a capturing group\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n beginCapture() {\r\n // Add the end of the capture group to the suffixes temporarily so that compilation continues to work\r\n this._suffixes += ')';\r\n return this.add('(');\r\n }\r\n\r\n /**\r\n * Ends a capturing group\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n endCapture() {\r\n // Remove the last parenthesis from the _suffixes and add it to the regex\r\n this._suffixes = this._suffixes.slice(0, -1);\r\n return this.add(')');\r\n }\r\n\r\n // Miscellaneous //\r\n\r\n /**\r\n * Shorthand function for the string.replace function to allow for a more logical flow\r\n * @param {string} source string to search for\r\n * @param {string} value value to replace with\r\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\r\n * @memberof VerbalExpression\r\n */\r\n replace(source, value) {\r\n source = source.toString();\r\n return source.replace(this, value);\r\n }\r\n\r\n /**\r\n * Convert to RegExp object\r\n * @returns {RegExp} equivalent RegExp instance\r\n * @memberof VerbalExpression\r\n */\r\n toRegExp() {\r\n const components = this.toString().match(/\\/(.*)\\/([gimuy]+)?/);\r\n const pattern = components[1];\r\n const flags = components[2];\r\n\r\n return new RegExp(pattern, flags);\r\n }\r\n}\r\n\r\n/**\r\n * Return a new instance of `VerbalExpression`\r\n * @export\r\n * @returns {VerbalExpression} new instance\r\n */\r\nfunction VerEx() { // eslint-disable-line no-unused-vars\r\n const instance = new VerbalExpression();\r\n instance.sanitize = VerbalExpression.sanitize;\r\n return instance;\r\n}\r\n"]} \ No newline at end of file +{"version":3,"sources":["../VerbalExpressions.js"],"names":["VerbalExpression","_prefixes","_source","_suffixes","_modifiers","value","pattern","compile","enable","add","sanitize","then","Array","isArray","join","anyOf","i","length","from","to","lineBreak","modifier","includes","replace","addModifier","removeModifier","isInteger","quantity","values","filter","argument","test","lower","upper","undefined","slice","source","toString","components","match","flags","RegExp","toEscape","lastMatch","VerEx","instance"],"mappings":"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","sourcesContent":["/**\n * @file VerbalExpressions JavaScript Library\n * @version 0.3.0\n * @license MIT\n *\n * @see https://github.com/VerbalExpressions/JSVerbalExpressions\n */\n\n/**\n * Define the VerbalExpression class\n *\n * @class VerbalExpression\n * @extends {RegExp}\n */\nclass VerbalExpression extends RegExp {\n /**\n * Creates an instance of VerbalExpression.\n * @constructor\n * @alias VerEx\n * @memberof VerbalExpression\n */\n constructor() {\n // Call the `RegExp` constructor so that `this` can be used\n super('', 'gm');\n\n // Variables to hold the expression construction in order\n this._prefixes = '';\n this._source = '';\n this._suffixes = '';\n this._modifiers = 'gm'; // 'global, multiline' matching by default\n }\n\n // Utility //\n\n /**\n * Escape meta-characters in the parameter and make it safe for adding to the expression\n * @static\n * @param {(string|RegExp|number)} value object to sanitize\n * @returns {string} sanitized value\n * @memberof VerbalExpression\n */\n static sanitize(value) {\n if (value instanceof RegExp) {\n return value.source;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n if (typeof value !== 'string') {\n return '';\n }\n\n // Regular expression to match meta characters\n // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp\n const toEscape = /[|\\\\{}()[\\]^$+*?.]/g;\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch\n const lastMatch = '$&';\n\n // Escape meta characters\n return value\n .replace(toEscape, `\\\\${lastMatch}`)\n .replace(/-/g, '\\\\x2d');\n }\n\n /**\n * Add stuff to the expression and compile the new expression so it's ready to be used.\n * @param {(string|number)} [value=''] stuff to add\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n add(value = '') {\n this._source += value;\n const pattern = this._prefixes + this._source + this._suffixes;\n\n this.compile(pattern, this._modifiers);\n\n return this;\n }\n\n // Rules //\n\n /**\n * Control start-of-line matching\n * @param {boolean} [enable=true] whether to enable this behaviour\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n startOfLine(enable = true) {\n this._prefixes = enable ? '^' : '';\n return this.add();\n }\n\n /**\n * Control end-of-line matching\n * @param {boolean} [enable=true] whether to enable this behaviour\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n endOfLine(enable = true) {\n this._suffixes = enable ? '$' : '';\n return this.add();\n }\n\n /**\n * Look for the value passed\n * @param {(string|RegExp|number)} value value to find\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n then(value) {\n value = VerbalExpression.sanitize(value);\n return this.add(`(?:${value})`);\n }\n\n /**\n * Alias for then() to allow for readable syntax when then() is the first method in the chain.\n * @param {(string|RegExp|numer)} value value to find\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n find(value) {\n return this.then(value);\n }\n\n /**\n * Add optional values\n * @param {(string|RegExp|number)} value value to find\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n maybe(value) {\n value = VerbalExpression.sanitize(value);\n return this.add(`(?:${value})?`);\n }\n\n /**\n * Add alternative expressions\n * @param {(string|RegExp|number)} value value to find\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n or(value) {\n this._prefixes += '(?:';\n this._suffixes = `)${this._suffixes}`;\n\n this.add(')|(?:');\n\n if (value) {\n this.then(value);\n }\n\n return this;\n }\n\n /**\n * Any character any number of times\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n anything() {\n return this.add('(?:.*)');\n }\n\n /**\n * Anything but these characters\n * @param {(string|number|string[]|number[])} value characters to not match\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n anythingBut(value) {\n if (Array.isArray(value)) {\n value = value.join('');\n }\n\n value = VerbalExpression.sanitize(value);\n return this.add(`(?:[^${value}]*)`);\n }\n\n /**\n * Any character(s) at least once\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n something() {\n return this.add('(?:.+)');\n }\n\n /**\n * Any character at least one time except for these characters\n * @param {(string|number|string[]|number[])} value characters to not match\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n somethingBut(value) {\n if (Array.isArray(value)) {\n value = value.join('');\n }\n\n value = VerbalExpression.sanitize(value);\n return this.add(`(?:[^${value}]+)`);\n }\n\n /**\n * Match any of the given characters\n * @param {(string|number|string[]|number[])} value characters to match\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n anyOf(value) {\n if (Array.isArray(value)) {\n value = value.join('');\n }\n\n value = VerbalExpression.sanitize(value);\n return this.add(`[${value}]`);\n }\n\n /**\n * Shorthand for anyOf(value)\n * @param {string|number} value value to find\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n any(value) {\n return this.anyOf(value);\n }\n\n /**\n * Ensure that the parameter does not follow\n * @param {string|number} value\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n not(value) {\n value = VerbalExpression.sanitize(value);\n this.add(`(?!${value})`);\n\n return this;\n }\n\n /**\n * Matching any character within a range of characters\n * Usage: .range( from, to [, from, to ... ] )\n * @param {...string} ranges characters denoting beginning and ending of ranges\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n range(...ranges) {\n let value = '';\n\n for (let i = 1; i < ranges.length; i += 2) {\n const from = VerbalExpression.sanitize(ranges[i - 1]);\n const to = VerbalExpression.sanitize(ranges[i]);\n\n value += `${from}-${to}`;\n }\n\n return this.add(`[${value}]`);\n }\n\n // Special characters //\n\n /**\n * Match a Line break\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n lineBreak() {\n return this.add('(?:\\\\r\\\\n|\\\\r|\\\\n)'); // Unix(LF) + Windows(CRLF)\n }\n\n /**\n * A shorthand for lineBreak() for html-minded users\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n br() {\n return this.lineBreak();\n }\n\n /**\n * Match a tab character\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n tab() {\n return this.add('\\\\t');\n }\n\n /**\n * Match any alphanumeric\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n word() {\n return this.add('\\\\w+');\n }\n\n /**\n * Match a single digit\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n digit() {\n return this.add('\\\\d');\n }\n\n /**\n * Match a single whitespace\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n whitespace() {\n return this.add('\\\\s');\n }\n\n // Modifiers //\n\n /**\n * Add a regex modifier/flag\n * @param {string} modifier modifier to add\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n addModifier(modifier) {\n if (!this._modifiers.includes(modifier)) {\n this._modifiers += modifier;\n }\n\n return this.add();\n }\n\n /**\n * Remove modifier\n * @param {string} modifier modifier to remove\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n removeModifier(modifier) {\n this._modifiers = this._modifiers.replace(modifier, '');\n return this.add();\n }\n\n /**\n * Control case-insensitive matching\n * @param {boolean} [enable=true] whether to enable this behaviour\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n withAnyCase(enable = true) {\n return enable ? this.addModifier('i') : this.removeModifier('i');\n }\n\n /**\n * Default behaviour is with \"g\" modifier, so we can turn this another way around than other modifiers\n * @param {boolean} [enable=true] whether to enable this behaviour\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n stopAtFirst(enable = true) {\n return enable ? this.removeModifier('g') : this.addModifier('g');\n }\n\n /**\n * Control the multiline modifier\n * @param {boolean} [enable=true] whether to enable this behaviour\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n searchOneLine(enable = true) {\n return enable ? this.removeModifier('m') : this.addModifier('m');\n }\n\n // Loops //\n\n /**\n * Repeat the previous item exactly n times or between n and m times\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n repeatPrevious(...quantity) {\n const isInteger = /\\d+/;\n const values = quantity.filter((argument) => isInteger.test(argument));\n\n if (values.length === 0 || values.length > 2) {\n return this;\n }\n\n this.add(`{${values.join(',')}}`);\n\n return this;\n }\n\n /**\n * Repeat the previous at least once\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n oneOrMore() {\n return this.add('+');\n }\n\n /**\n * Match the value zero or more times\n * @param {string} value value to find\n * @param {integer} [lower] minimum number of times the value should be repeated\n * @param {integer} [upper] maximum number of times the value should be repeated\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n multiple(value, lower, upper) {\n if (value !== undefined) {\n value = VerbalExpression.sanitize(value);\n this.add(`(?:${value})`);\n }\n\n if (lower === undefined && upper === undefined) {\n this.add('*'); // Any number of times\n } else if (lower !== undefined && upper === undefined) {\n this.add(`{${lower},}`);\n } else if (lower !== undefined && upper !== undefined) {\n this.add(`{${lower},${upper}}`);\n }\n\n return this;\n }\n\n // Capture groups //\n\n /**\n * Starts a capturing group\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n beginCapture() {\n // Add the end of the capture group to the suffixes temporarily so that compilation continues to work\n this._suffixes += ')';\n return this.add('(');\n }\n\n /**\n * Ends a capturing group\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n endCapture() {\n // Remove the last parenthesis from the _suffixes and add it to the regex\n this._suffixes = this._suffixes.slice(0, -1);\n return this.add(')');\n }\n\n // Miscellaneous //\n\n /**\n * Shorthand function for the string.replace function to allow for a more logical flow\n * @param {string} source string to search for\n * @param {string} value value to replace with\n * @returns {VerbalExpression} recompiled instance of VerbalExpression\n * @memberof VerbalExpression\n */\n replace(source, value) {\n source = source.toString();\n return source.replace(this, value);\n }\n\n /**\n * Convert to RegExp object\n * @returns {RegExp} equivalent RegExp instance\n * @memberof VerbalExpression\n */\n toRegExp() {\n const components = this.toString().match(/\\/(.*)\\/([gimuy]+)?/);\n const pattern = components[1];\n const flags = components[2];\n\n return new RegExp(pattern, flags);\n }\n}\n\n/**\n * Return a new instance of `VerbalExpression`\n * @export\n * @returns {VerbalExpression} new instance\n */\nfunction VerEx() { // eslint-disable-line no-unused-vars\n const instance = new VerbalExpression();\n instance.sanitize = VerbalExpression.sanitize;\n return instance;\n}\n"],"file":"verbalexpressions.js"} \ No newline at end of file diff --git a/test/tests.js b/test/tests.js index 9c646c03..7db8d451 100644 --- a/test/tests.js +++ b/test/tests.js @@ -17,7 +17,7 @@ test('constructor', (t) => { 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'; + 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');