From a7f3fea96df381a4b2b2672a97847d8f69614733 Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Tue, 11 Feb 2020 08:12:07 +0200 Subject: [PATCH 1/5] feat: add isSemVer validator to check for Semantic Versioning --- README.md | 1 + index.js | 3 ++ lib/isSemVer.js | 41 +++++++++++++++++++++++++ src/index.js | 2 ++ src/lib/isSemVer.js | 33 ++++++++++++++++++++ test/validators.js | 73 +++++++++++++++++++++++++++++++++++++++++++++ validator.js | 29 ++++++++++++++++++ validator.min.js | 2 +- 8 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 lib/isSemVer.js create mode 100644 src/lib/isSemVer.js diff --git a/README.md b/README.md index 490d4a245..b6ccdf579 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ Validator | Description **isOctal(str)** | check if the string is a valid octal number. **isPort(str)** | check if the string is a valid port number. **isPostalCode(str, locale)** | check if the string is a postal code,

(locale is one of `[ 'AD', 'AT', 'AU', 'BE', 'BG', 'BR', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'ID', 'IE' 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MT', 'MX', 'NL', 'NO', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM' ]` OR 'any'. If 'any' is used, function will check if any of the locals match. Locale list is `validator.isPostalCodeLocales`.). +**isSemVer(str)** | check if the string is a Semantic Versioning Specification (SemVer). **isSurrogatePair(str)** | check if the string contains any surrogate pairs chars. **isURL(str [, options])** | check if the string is an URL.

`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, disallow_auth: false }`.

require_protocol - if set as true isURL will return false if protocol is not present in the URL.
require_valid_protocol - isURL will check if the URL's protocol is present in the protocols option.
protocols - valid protocols can be modified with this option.
require_host - if set as false isURL will not check if host is present in the URL.
allow_protocol_relative_urls - if set as true protocol relative URLs will be allowed. **isUppercase(str)** | check if the string is uppercase. diff --git a/index.js b/index.js index 0ee550633..fdff26e2d 100644 --- a/index.js +++ b/index.js @@ -57,6 +57,8 @@ var _isVariableWidth = _interopRequireDefault(require("./lib/isVariableWidth")); var _isMultibyte = _interopRequireDefault(require("./lib/isMultibyte")); +var _isSemVer = _interopRequireDefault(require("./lib/isSemVer")); + var _isSurrogatePair = _interopRequireDefault(require("./lib/isSurrogatePair")); var _isInt = _interopRequireDefault(require("./lib/isInt")); @@ -203,6 +205,7 @@ var validator = { isHalfWidth: _isHalfWidth.default, isVariableWidth: _isVariableWidth.default, isMultibyte: _isMultibyte.default, + isSemVer: _isSemVer.default, isSurrogatePair: _isSurrogatePair.default, isInt: _isInt.default, isFloat: _isFloat.default, diff --git a/lib/isSemVer.js b/lib/isSemVer.js new file mode 100644 index 000000000..222dec546 --- /dev/null +++ b/lib/isSemVer.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = isSemVer; + +var _assertString = _interopRequireDefault(require("./util/assertString")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Build RegExp object from an array + * of multiple/multi-line RegExp objects + * + * @param {string[]} parts + * @param {string} flags + * @return {object} - RegExp object + */ +function buildMultiLineRegexp(parts) { + var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var regexpAsStringLiteral = parts.join(''); + return new RegExp(regexpAsStringLiteral, flags); +} +/** + * Regular Expression to match + * semantic versioning (SemVer) + * built from multi-line, multi-parts regexp + * Reference: https://semver.org/ + */ + + +var semanticVersioningRegex = buildMultiLineRegexp(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); + +function isSemVer(str) { + (0, _assertString.default)(str); + return semanticVersioningRegex.test(str); +} + +module.exports = exports.default; +module.exports.default = exports.default; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 7b46f359a..ada97c215 100644 --- a/src/index.js +++ b/src/index.js @@ -27,6 +27,7 @@ import isFullWidth from './lib/isFullWidth'; import isHalfWidth from './lib/isHalfWidth'; import isVariableWidth from './lib/isVariableWidth'; import isMultibyte from './lib/isMultibyte'; +import isSemVer from './lib/isSemVer'; import isSurrogatePair from './lib/isSurrogatePair'; import isInt from './lib/isInt'; @@ -137,6 +138,7 @@ const validator = { isHalfWidth, isVariableWidth, isMultibyte, + isSemVer, isSurrogatePair, isInt, isFloat, diff --git a/src/lib/isSemVer.js b/src/lib/isSemVer.js new file mode 100644 index 000000000..53fa97283 --- /dev/null +++ b/src/lib/isSemVer.js @@ -0,0 +1,33 @@ +import assertString from './util/assertString'; + +/** + * Build RegExp object from an array + * of multiple/multi-line RegExp objects + * + * @param {string[]} parts + * @param {string} flags + * @return {object} - RegExp object + */ +function buildMultiLineRegexp(parts, flags = '') { + const regexpAsStringLiteral = parts.join(''); + + return new RegExp(regexpAsStringLiteral, flags); +} + +/** + * Regular Expression to match + * semantic versioning (SemVer) + * built from multi-line, multi-parts regexp + * Reference: https://semver.org/ + */ +const semanticVersioningRegex = buildMultiLineRegexp([ + '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', + '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', + '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$', +]); + +export default function isSemVer(str) { + assertString(str); + + return semanticVersioningRegex.test(str); +} diff --git a/test/validators.js b/test/validators.js index f660f0f28..e270420cf 100644 --- a/test/validators.js +++ b/test/validators.js @@ -3685,6 +3685,79 @@ describe('Validators', () => { }); }); + it('should validate Semantic Versioning Specification (SemVer) strings', () => { + test({ + validator: 'isSemVer', + valid: [ + '0.0.4', + '1.2.3', + '10.20.30', + '1.1.2-prerelease+meta', + '1.1.2+meta', + '1.1.2+meta-valid', + '1.0.0-alpha', + '1.0.0-beta', + '1.0.0-alpha.beta', + '1.0.0-alpha.beta.1', + '1.0.0-alpha.1', + '1.0.0-alpha0.valid', + '1.0.0-alpha.0valid', + '1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay', + '1.0.0-rc.1+build.1', + '2.0.0-rc.1+build.123', + '1.2.3-beta', + '10.2.3-DEV-SNAPSHOT', + '1.2.3-SNAPSHOT-123', + '1.0.0', + '2.0.0', + '1.1.7', + '2.0.0+build.1848', + '2.0.1-alpha.1227', + '1.0.0-alpha+beta', + '1.2.3----RC-SNAPSHOT.12.9.1--.12+788', + '1.2.3----R-S.12.9.1--.12+meta', + '1.2.3----RC-SNAPSHOT.12.9.1--.12', + '1.0.0+0.build.1-rc.10000aaa-kk-0.1', + '99999999999999999999999.999999999999999999.99999999999999999', + '1.0.0-0A.is.legal', + ], + invalid: [ + '-invalid+invalid', + '-invalid.01', + 'alpha', + 'alpha.beta', + 'alpha.beta.1', + 'alpha.1', + 'alpha+beta', + 'alpha_beta', + 'alpha.', + 'alpha..', + 'beta', + '1.0.0-alpha_beta', + '-alpha.', + '1.0.0-alpha..', + '1.0.0-alpha..1', + '1.0.0-alpha...1', + '1.0.0-alpha....1', + '1.0.0-alpha.....1', + '1.0.0-alpha......1', + '1.0.0-alpha.......1', + '01.1.1', + '1.01.1', + '1.1.01', + '1.2', + '1.2.3.DEV', + '1.2-SNAPSHOT', + '1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788', + '1.2-RC-SNAPSHOT', + '-1.0.3-gamma+b7718', + '+justmeta', + '9.8.7+meta+meta', + '9.8.7-whatever+meta+meta', + ], + }); + }); + it('should validate base32 strings', () => { test({ validator: 'isBase32', diff --git a/validator.js b/validator.js index 926d1ce13..6c0920809 100644 --- a/validator.js +++ b/validator.js @@ -954,6 +954,34 @@ function isMultibyte(str) { return multibyte.test(str); } +/** + * Build RegExp object from an array + * of multiple/multi-line RegExp objects + * + * @param {string[]} parts + * @param {string} flags + * @return {object} - RegExp object + */ + +function buildMultiLineRegexp(parts) { + var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var regexpAsStringLiteral = parts.join(''); + return new RegExp(regexpAsStringLiteral, flags); +} +/** + * Regular Expression to match + * semantic versioning (SemVer) + * built from multi-line, multi-parts regexp + * Reference: https://semver.org/ + */ + + +var semanticVersioningRegex = buildMultiLineRegexp(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); +function isSemVer(str) { + assertString(str); + return semanticVersioningRegex.test(str); +} + var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; function isSurrogatePair(str) { assertString(str); @@ -2354,6 +2382,7 @@ var validator = { isHalfWidth: isHalfWidth, isVariableWidth: isVariableWidth, isMultibyte: isMultibyte, + isSemVer: isSemVer, isSurrogatePair: isSurrogatePair, isInt: isInt, isFloat: isFloat, diff --git a/validator.min.js b/validator.min.js index 2848ef130..779dc568f 100644 --- a/validator.min.js +++ b/validator.min.js @@ -20,4 +20,4 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.validator=e()}(this,function(){"use strict";function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function h(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if(!(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t)))return;var r=[],n=!0,o=!1,i=void 0;try{for(var a,s=t[Symbol.iterator]();!(n=(a=s.next()).done)&&(r.push(a.value),!e||r.length!==e);n=!0);}catch(t){o=!0,i=t}finally{try{n||null==s.return||s.return()}finally{if(o)throw i}}return r}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function g(t){var e;if(!("string"==typeof t||t instanceof String))throw e=null===t?"null":"object"===(e=a(t))&&t.constructor&&t.constructor.hasOwnProperty("name")?t.constructor.name:"a ".concat(e),new TypeError("Expected string but received ".concat(e,"."))}function o(t){return g(t),t=Date.parse(t),isNaN(t)?null:new Date(t)}for(var t,r={"en-US":/^[A-Z]+$/i,"bg-BG":/^[А-Я]+$/i,"cs-CZ":/^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,"da-DK":/^[A-ZÆØÅ]+$/i,"de-DE":/^[A-ZÄÖÜß]+$/i,"el-GR":/^[Α-ώ]+$/i,"es-ES":/^[A-ZÁÉÍÑÓÚÜ]+$/i,"fr-FR":/^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,"it-IT":/^[A-ZÀÉÈÌÎÓÒÙ]+$/i,"nb-NO":/^[A-ZÆØÅ]+$/i,"nl-NL":/^[A-ZÁÉËÏÓÖÜÚ]+$/i,"nn-NO":/^[A-ZÆØÅ]+$/i,"hu-HU":/^[A-ZÁÉÍÓÖŐÚÜŰ]+$/i,"pl-PL":/^[A-ZĄĆĘŚŁŃÓŻŹ]+$/i,"pt-PT":/^[A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,"ru-RU":/^[А-ЯЁ]+$/i,"sl-SI":/^[A-ZČĆĐŠŽ]+$/i,"sk-SK":/^[A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,"sr-RS@latin":/^[A-ZČĆŽŠĐ]+$/i,"sr-RS":/^[А-ЯЂЈЉЊЋЏ]+$/i,"sv-SE":/^[A-ZÅÄÖ]+$/i,"tr-TR":/^[A-ZÇĞİıÖŞÜ]+$/i,"uk-UA":/^[А-ЩЬЮЯЄIЇҐі]+$/i,"ku-IQ":/^[ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,ar:/^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,he:/^[א-ת]+$/,"fa-IR":/^['آابپتثجچهخدذرزژسشصضطظعغفقکگلمنوهی']+$/i},n={"en-US":/^[0-9A-Z]+$/i,"bg-BG":/^[0-9А-Я]+$/i,"cs-CZ":/^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,"da-DK":/^[0-9A-ZÆØÅ]+$/i,"de-DE":/^[0-9A-ZÄÖÜß]+$/i,"el-GR":/^[0-9Α-ω]+$/i,"es-ES":/^[0-9A-ZÁÉÍÑÓÚÜ]+$/i,"fr-FR":/^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,"it-IT":/^[0-9A-ZÀÉÈÌÎÓÒÙ]+$/i,"hu-HU":/^[0-9A-ZÁÉÍÓÖŐÚÜŰ]+$/i,"nb-NO":/^[0-9A-ZÆØÅ]+$/i,"nl-NL":/^[0-9A-ZÁÉËÏÓÖÜÚ]+$/i,"nn-NO":/^[0-9A-ZÆØÅ]+$/i,"pl-PL":/^[0-9A-ZĄĆĘŚŁŃÓŻŹ]+$/i,"pt-PT":/^[0-9A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,"ru-RU":/^[0-9А-ЯЁ]+$/i,"sl-SI":/^[0-9A-ZČĆĐŠŽ]+$/i,"sk-SK":/^[0-9A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,"sr-RS@latin":/^[0-9A-ZČĆŽŠĐ]+$/i,"sr-RS":/^[0-9А-ЯЂЈЉЊЋЏ]+$/i,"sv-SE":/^[0-9A-ZÅÄÖ]+$/i,"tr-TR":/^[0-9A-ZÇĞİıÖŞÜ]+$/i,"uk-UA":/^[0-9А-ЩЬЮЯЄIЇҐі]+$/i,"ku-IQ":/^[٠١٢٣٤٥٦٧٨٩0-9ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,ar:/^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,he:/^[0-9א-ת]+$/,"fa-IR":/^['0-9آابپتثجچهخدذرزژسشصضطظعغفقکگلمنوهی۱۲۳۴۵۶۷۸۹۰']+$/i},i={"en-US":".",ar:"٫"},e=["AU","GB","HK","IN","NZ","ZA","ZM"],s=0;s=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)}r["pt-BR"]=r["pt-PT"],n["pt-BR"]=n["pt-PT"],i["pt-BR"]=i["pt-PT"],r["pl-Pl"]=r["pl-PL"],n["pl-Pl"]=n["pl-PL"],i["pl-Pl"]=i["pl-PL"];var m=Object.keys(i);function v(t){return p(t)?parseFloat(t):NaN}function _(t){return"object"===a(t)&&null!==t?t="function"==typeof t.toString?t.toString():"[object Object]":(null==t||isNaN(t)&&!t.length)&&(t=""),String(t)}function S(t,e){var r=0a)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(n.shift(),n.shift(),o=!0):"::"===t.substr(t.length-2)&&(n.pop(),n.pop(),o=!0);for(var s=0;s$/i,N=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,T=/^[a-z\d]+$/,B=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,x=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,w=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*$/i;var G={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},O=/^\[([^\]]+)\](?::([0-9]+))?$/;function b(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var J=/^[\x00-\x7F]+$/;var Q=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var q=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var X=/[^\x00-\x7F]/;var tt=/[\uD800-\uDBFF][\uDC00-\uDFFF]/;function et(t,e){return t.some(function(t){return e===t})}var rt={force_decimal:!1,decimal_digits:"1,",locale:"en-US"},nt=["","-","+"];var ot=/^(0x|0h)?[0-9A-F]+$/i;function it(t){return g(t),ot.test(t)}var at=/^(0o)?[0-7]+$/i;var st=/^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i;var lt=/^[A-Z]{2}[0-9A-Z]{3}\d{2}\d{5}$/;var ut={AD:/^(AD[0-9]{2})\d{8}[A-Z0-9]{12}$/,AE:/^(AE[0-9]{2})\d{3}\d{16}$/,AL:/^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/,AT:/^(AT[0-9]{2})\d{16}$/,AZ:/^(AZ[0-9]{2})[A-Z0-9]{4}\d{20}$/,BA:/^(BA[0-9]{2})\d{16}$/,BE:/^(BE[0-9]{2})\d{12}$/,BG:/^(BG[0-9]{2})[A-Z]{4}\d{6}[A-Z0-9]{8}$/,BH:/^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/,BR:/^(BR[0-9]{2})\d{23}[A-Z]{1}[A-Z0-9]{1}$/,BY:/^(BY[0-9]{2})[A-Z0-9]{4}\d{20}$/,CH:/^(CH[0-9]{2})\d{5}[A-Z0-9]{12}$/,CR:/^(CR[0-9]{2})\d{18}$/,CY:/^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/,CZ:/^(CZ[0-9]{2})\d{20}$/,DE:/^(DE[0-9]{2})\d{18}$/,DK:/^(DK[0-9]{2})\d{14}$/,DO:/^(DO[0-9]{2})[A-Z]{4}\d{20}$/,EE:/^(EE[0-9]{2})\d{16}$/,ES:/^(ES[0-9]{2})\d{20}$/,FI:/^(FI[0-9]{2})\d{14}$/,FO:/^(FO[0-9]{2})\d{14}$/,FR:/^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,GB:/^(GB[0-9]{2})[A-Z]{4}\d{14}$/,GE:/^(GE[0-9]{2})[A-Z0-9]{2}\d{16}$/,GI:/^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/,GL:/^(GL[0-9]{2})\d{14}$/,GR:/^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/,GT:/^(GT[0-9]{2})[A-Z0-9]{4}[A-Z0-9]{20}$/,HR:/^(HR[0-9]{2})\d{17}$/,HU:/^(HU[0-9]{2})\d{24}$/,IE:/^(IE[0-9]{2})[A-Z0-9]{4}\d{14}$/,IL:/^(IL[0-9]{2})\d{19}$/,IQ:/^(IQ[0-9]{2})[A-Z]{4}\d{15}$/,IS:/^(IS[0-9]{2})\d{22}$/,IT:/^(IT[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,JO:/^(JO[0-9]{2})[A-Z]{4}\d{22}$/,KW:/^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/,KZ:/^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/,LB:/^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/,LC:/^(LC[0-9]{2})[A-Z]{4}[A-Z0-9]{24}$/,LI:/^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/,LT:/^(LT[0-9]{2})\d{16}$/,LU:/^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/,LV:/^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,MC:/^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,MD:/^(MD[0-9]{2})[A-Z0-9]{20}$/,ME:/^(ME[0-9]{2})\d{18}$/,MK:/^(MK[0-9]{2})\d{3}[A-Z0-9]{10}\d{2}$/,MR:/^(MR[0-9]{2})\d{23}$/,MT:/^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/,MU:/^(MU[0-9]{2})[A-Z]{4}\d{19}[A-Z]{3}$/,NL:/^(NL[0-9]{2})[A-Z]{4}\d{10}$/,NO:/^(NO[0-9]{2})\d{11}$/,PK:/^(PK[0-9]{2})[A-Z0-9]{4}\d{16}$/,PL:/^(PL[0-9]{2})\d{24}$/,PS:/^(PS[0-9]{2})[A-Z0-9]{4}\d{21}$/,PT:/^(PT[0-9]{2})\d{21}$/,QA:/^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,RO:/^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/,RS:/^(RS[0-9]{2})\d{18}$/,SA:/^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/,SC:/^(SC[0-9]{2})[A-Z]{4}\d{20}[A-Z]{3}$/,SE:/^(SE[0-9]{2})\d{20}$/,SI:/^(SI[0-9]{2})\d{15}$/,SK:/^(SK[0-9]{2})\d{20}$/,SM:/^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,TL:/^(TL[0-9]{2})\d{19}$/,TN:/^(TN[0-9]{2})\d{20}$/,TR:/^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/,UA:/^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/,VA:/^(VA[0-9]{2})\d{18}$/,VG:/^(VG[0-9]{2})[A-Z0-9]{4}\d{16}$/,XK:/^(XK[0-9]{2})\d{16}$/};var ct=/^[A-z]{4}[A-z]{2}\w{2}(\w{3})?$/;var dt=/^[a-f0-9]{32}$/;var ft={md5:32,md4:32,sha1:40,sha256:64,sha384:96,sha512:128,ripemd128:32,ripemd160:40,tiger128:32,tiger160:40,tiger192:48,crc32:8,crc32b:8};var At=/^([A-Za-z0-9\-_~+\/]+[=]{0,2})\.([A-Za-z0-9\-_~+\/]+[=]{0,2})(?:\.([A-Za-z0-9\-_~+\/]+[=]{0,2}))?$/;var $t={ignore_whitespace:!1};var pt={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};var ht=/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11}|6[27][0-9]{14})$/;var gt={ES:function(t){g(t);var e={X:0,Y:1,Z:2},r=t.trim().toUpperCase();if(!/^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/.test(r))return!1;var n=r.slice(0,-1).replace(/[X,Y,Z]/g,function(t){return e[t]});return r.endsWith(["T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E"][n%23])},"he-IL":function(t){var e=t.trim();if(!/^\d{9}$/.test(e))return!1;for(var r,n=e,o=0,i=0;i]/.test(r)){if(!e)return;if(!(r.split('"').length===r.split('\\"').length))return}return 1}}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,s,l,u;if(e=S(e,G),1<(l=(t=(l=(t=(l=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=l.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;l[0]=t.substr(2)}}if(""===(t=l.join("://")))return!1;if(""===(t=(l=t.split("/")).shift())&&!e.require_host)return!0;if(1<(l=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=l.shift()).indexOf(":")&&2/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return g(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return g(t),oe(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return g(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:oe,isWhitelisted:function(t,e){g(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=S(e,ie);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,ce)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=ae.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=se.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=le.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)}r["pt-BR"]=r["pt-PT"],n["pt-BR"]=n["pt-PT"],i["pt-BR"]=i["pt-PT"],r["pl-Pl"]=r["pl-PL"],n["pl-Pl"]=n["pl-PL"],i["pl-Pl"]=i["pl-PL"];var m=Object.keys(i);function v(t){return p(t)?parseFloat(t):NaN}function Z(t){return"object"===a(t)&&null!==t?t="function"==typeof t.toString?t.toString():"[object Object]":(null==t||isNaN(t)&&!t.length)&&(t=""),String(t)}function _(t,e){var r=0a)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(n.shift(),n.shift(),o=!0):"::"===t.substr(t.length-2)&&(n.pop(),n.pop(),o=!0);for(var s=0;s$/i,N=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,T=/^[a-z\d]+$/,x=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,B=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,w=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*$/i;var G={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},O=/^\[([^\]]+)\](?::([0-9]+))?$/;function b(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var J=/^[\x00-\x7F]+$/;var Q=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var q=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var X=/[^\x00-\x7F]/;var tt=function(t,e){var r=1]/.test(r)){if(!e)return;if(!(r.split('"').length===r.split('\\"').length))return}return 1}}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,s,l,u;if(e=_(e,G),1<(l=(t=(l=(t=(l=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=l.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;l[0]=t.substr(2)}}if(""===(t=l.join("://")))return!1;if(""===(t=(l=t.split("/")).shift())&&!e.require_host)return!0;if(1<(l=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=l.shift()).indexOf(":")&&2/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return g(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return g(t),ie(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return g(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:ie,isWhitelisted:function(t,e){g(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=_(e,ae);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,de)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=se.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=le.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=ue.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1 Date: Tue, 11 Feb 2020 08:14:07 +0200 Subject: [PATCH 2/5] style: modify function docs --- src/lib/isSemVer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/isSemVer.js b/src/lib/isSemVer.js index 53fa97283..cd84c679a 100644 --- a/src/lib/isSemVer.js +++ b/src/lib/isSemVer.js @@ -2,7 +2,7 @@ import assertString from './util/assertString'; /** * Build RegExp object from an array - * of multiple/multi-line RegExp objects + * of multiple/multi-line regexp parts * * @param {string[]} parts * @param {string} flags From c11f7d15f77cc0e927f61a6ffa20a45d4e4163e8 Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Tue, 11 Feb 2020 08:15:40 +0200 Subject: [PATCH 3/5] push compiled modules after function docs change --- lib/isSemVer.js | 2 +- validator.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/isSemVer.js b/lib/isSemVer.js index 222dec546..1b2aa2b74 100644 --- a/lib/isSemVer.js +++ b/lib/isSemVer.js @@ -11,7 +11,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de /** * Build RegExp object from an array - * of multiple/multi-line RegExp objects + * of multiple/multi-line regexp parts * * @param {string[]} parts * @param {string} flags diff --git a/validator.js b/validator.js index 6c0920809..a11316ea6 100644 --- a/validator.js +++ b/validator.js @@ -956,7 +956,7 @@ function isMultibyte(str) { /** * Build RegExp object from an array - * of multiple/multi-line RegExp objects + * of multiple/multi-line regexp parts * * @param {string[]} parts * @param {string} flags From bb152f933c668f7efec3366057ed2f885180588f Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Tue, 11 Feb 2020 11:13:31 +0200 Subject: [PATCH 4/5] moe multilineRegexp function to util for re-usability --- lib/isSemVer.js | 19 +++---------------- lib/util/multilineRegex.js | 23 +++++++++++++++++++++++ src/lib/isSemVer.js | 17 ++--------------- src/lib/util/multilineRegex.js | 13 +++++++++++++ validator.js | 7 +++---- 5 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 lib/util/multilineRegex.js create mode 100644 src/lib/util/multilineRegex.js diff --git a/lib/isSemVer.js b/lib/isSemVer.js index 1b2aa2b74..23cb2a70d 100644 --- a/lib/isSemVer.js +++ b/lib/isSemVer.js @@ -7,30 +7,17 @@ exports.default = isSemVer; var _assertString = _interopRequireDefault(require("./util/assertString")); +var _multilineRegex = _interopRequireDefault(require("./util/multilineRegex")); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -/** - * Build RegExp object from an array - * of multiple/multi-line regexp parts - * - * @param {string[]} parts - * @param {string} flags - * @return {object} - RegExp object - */ -function buildMultiLineRegexp(parts) { - var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var regexpAsStringLiteral = parts.join(''); - return new RegExp(regexpAsStringLiteral, flags); -} /** * Regular Expression to match * semantic versioning (SemVer) * built from multi-line, multi-parts regexp * Reference: https://semver.org/ */ - - -var semanticVersioningRegex = buildMultiLineRegexp(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); +var semanticVersioningRegex = (0, _multilineRegex.default)(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); function isSemVer(str) { (0, _assertString.default)(str); diff --git a/lib/util/multilineRegex.js b/lib/util/multilineRegex.js new file mode 100644 index 000000000..0879ca905 --- /dev/null +++ b/lib/util/multilineRegex.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = multilineRegexp; + +/** + * Build RegExp object from an array + * of multiple/multi-line regexp parts + * + * @param {string[]} parts + * @param {string} flags + * @return {object} - RegExp object + */ +function multilineRegexp(parts) { + var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var regexpAsStringLiteral = parts.join(''); + return new RegExp(regexpAsStringLiteral, flags); +} + +module.exports = exports.default; +module.exports.default = exports.default; \ No newline at end of file diff --git a/src/lib/isSemVer.js b/src/lib/isSemVer.js index cd84c679a..f685771db 100644 --- a/src/lib/isSemVer.js +++ b/src/lib/isSemVer.js @@ -1,18 +1,5 @@ import assertString from './util/assertString'; - -/** - * Build RegExp object from an array - * of multiple/multi-line regexp parts - * - * @param {string[]} parts - * @param {string} flags - * @return {object} - RegExp object - */ -function buildMultiLineRegexp(parts, flags = '') { - const regexpAsStringLiteral = parts.join(''); - - return new RegExp(regexpAsStringLiteral, flags); -} +import multilineRegexp from './util/multilineRegex'; /** * Regular Expression to match @@ -20,7 +7,7 @@ function buildMultiLineRegexp(parts, flags = '') { * built from multi-line, multi-parts regexp * Reference: https://semver.org/ */ -const semanticVersioningRegex = buildMultiLineRegexp([ +const semanticVersioningRegex = multilineRegexp([ '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$', diff --git a/src/lib/util/multilineRegex.js b/src/lib/util/multilineRegex.js new file mode 100644 index 000000000..e8d21229d --- /dev/null +++ b/src/lib/util/multilineRegex.js @@ -0,0 +1,13 @@ +/** + * Build RegExp object from an array + * of multiple/multi-line regexp parts + * + * @param {string[]} parts + * @param {string} flags + * @return {object} - RegExp object + */ +export default function multilineRegexp(parts, flags = '') { + const regexpAsStringLiteral = parts.join(''); + + return new RegExp(regexpAsStringLiteral, flags); +} diff --git a/validator.js b/validator.js index a11316ea6..eec0f6de2 100644 --- a/validator.js +++ b/validator.js @@ -962,12 +962,12 @@ function isMultibyte(str) { * @param {string} flags * @return {object} - RegExp object */ - -function buildMultiLineRegexp(parts) { +function multilineRegexp(parts) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var regexpAsStringLiteral = parts.join(''); return new RegExp(regexpAsStringLiteral, flags); } + /** * Regular Expression to match * semantic versioning (SemVer) @@ -975,8 +975,7 @@ function buildMultiLineRegexp(parts) { * Reference: https://semver.org/ */ - -var semanticVersioningRegex = buildMultiLineRegexp(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); +var semanticVersioningRegex = multilineRegexp(['^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)', '(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))', '?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$']); function isSemVer(str) { assertString(str); return semanticVersioningRegex.test(str); From c71cfdffa103c6c09c800b00e21ec5b2f2653649 Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Tue, 11 Feb 2020 11:16:42 +0200 Subject: [PATCH 5/5] add more invalid/bad testcases --- test/validators.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/validators.js b/test/validators.js index e270420cf..22b7fb19d 100644 --- a/test/validators.js +++ b/test/validators.js @@ -3754,6 +3754,8 @@ describe('Validators', () => { '+justmeta', '9.8.7+meta+meta', '9.8.7-whatever+meta+meta', + '99999999999999999999999.999999999999999999.99999999999999999-', + '---RC-SNAPSHOT.12.09.1--------------------------------..12', ], }); });