From 53c71614fcd383e357444cfe73cdd3de527a8f83 Mon Sep 17 00:00:00 2001 From: tophf Date: Fri, 26 Feb 2021 10:02:21 +0300 Subject: [PATCH] relaxed parsing of usercss @version fixes #821 --- _locales/de/messages.json | 7 +---- _locales/en/messages.json | 7 +---- _locales/es/messages.json | 7 +---- _locales/fr/messages.json | 7 +---- _locales/hu/messages.json | 7 +---- _locales/ja/messages.json | 7 +---- _locales/ko/messages.json | 7 +---- _locales/nl/messages.json | 7 +---- _locales/pl/messages.json | 7 +---- _locales/ru/messages.json | 7 +---- _locales/sv/messages.json | 7 +---- _locales/zh/messages.json | 7 +---- _locales/zh_CN/messages.json | 7 +---- _locales/zh_TW/messages.json | 7 +---- background/update-manager.js | 19 +++++--------- install-usercss/install-usercss.js | 6 ++--- js/cmpver.js | 42 ++++++++++++++++++++++++++++++ js/meta-parser.js | 15 +++++++++++ manifest.json | 1 + package-lock.json | 34 ++++++++++++------------ package.json | 1 - tools/build-vendor.js | 3 --- vendor/semver-bundle/LICENSE | 15 ----------- vendor/semver-bundle/README.md | 5 ---- vendor/semver-bundle/semver.js | 1 - 25 files changed, 98 insertions(+), 142 deletions(-) create mode 100644 js/cmpver.js delete mode 100644 vendor/semver-bundle/LICENSE delete mode 100644 vendor/semver-bundle/README.md delete mode 100644 vendor/semver-bundle/semver.js diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 4ce69ddf..adeb617b 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -672,12 +672,7 @@ } }, "meta_invalidVersion": { - "message": "Ungültige Versionsnummer: Der Wert entspricht nicht dem SemVer Schema: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Ungültige Versionsnummer" }, "meta_invalidWord": { "message": "Erwarte ein Wort" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 86919510..79aeef9e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -916,12 +916,7 @@ "description": "Error displayed when the protocol of the URL is invalid" }, "meta_invalidVersion": { - "message": "Invalid version number. The value doesn't match SemVer pattern: $version$", - "placeholders": { - "version": { - "content": "$1" - } - }, + "message": "Invalid version number", "description": "Error displayed when @version is invalid" }, "meta_invalidWord": { diff --git a/_locales/es/messages.json b/_locales/es/messages.json index f3837958..7dab8338 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -662,12 +662,7 @@ } }, "meta_invalidVersion": { - "message": "Número de versión no válido. El valor no coincide con el patrón SemVer: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Número de versión no válido" }, "meta_invalidWord": { "message": "Se espera una palabra" diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index fad3df8f..c81c44ff 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -669,12 +669,7 @@ } }, "meta_invalidVersion": { - "message": "Numéro de version invalide. La valeur ne correspond pas au motif SemVer : $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Numéro de version invalide" }, "meta_invalidWord": { "message": "Mot attendu" diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json index f5741c6a..294acdf3 100644 --- a/_locales/hu/messages.json +++ b/_locales/hu/messages.json @@ -654,12 +654,7 @@ } }, "meta_invalidVersion": { - "message": "Érvénytelen verziószám. Az érték nem illeszkedik a SemVer mintájához: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Érvénytelen verziószám" }, "meta_invalidWord": { "message": "Várt elem: szó" diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index db8a916a..647b083c 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -684,12 +684,7 @@ } }, "meta_invalidVersion": { - "message": "不正なバージョン番号。値がバージョン番号のパターンに合っていません: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "不正なバージョン番号" }, "meta_invalidWord": { "message": "単語を入力してください" diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index d80ea710..ad336f5f 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -672,12 +672,7 @@ } }, "meta_invalidVersion": { - "message": "유효하지 않은 버전 숫자입니다. $version$은(는) 유의적 버전 패턴과 일치하지 않습니다.", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "유효하지 않은 버전 숫자입니다" }, "meta_invalidWord": { "message": "단어를 입력하세요" diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index fdaf5b15..06d4921f 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -691,12 +691,7 @@ } }, "meta_invalidVersion": { - "message": "Ongeldig versienummer. De waarde komt niet overeen met het SemVer-patroon:$version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Ongeldig versienummer" }, "meta_invalidWord": { "message": "Woord verwacht" diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index cc1e76de..f2348466 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -719,12 +719,7 @@ } }, "meta_invalidVersion": { - "message": "Nieprawidłowy numer wersji. Wartość nie pasuje do wzorca SemVer: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Nieprawidłowy numer wersji" }, "meta_invalidWord": { "message": "Spodziewane słowo" diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index e4d2b1de..630971d8 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -675,12 +675,7 @@ } }, "meta_invalidVersion": { - "message": "Неверный номер версии. Значение не соответствует шаблону SemVer: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Неверный номер версии" }, "meta_invalidWord": { "message": "Ожидание слова" diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index 048e7b90..524fa83e 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -648,12 +648,7 @@ } }, "meta_invalidVersion": { - "message": "Ogiltigt versionsnummer. Värdet matchar inte SemVer-mönstret: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "Ogiltigt versionsnummer" }, "meta_invalidWord": { "message": "Förvänta dig ett ord" diff --git a/_locales/zh/messages.json b/_locales/zh/messages.json index 64873312..d0417726 100644 --- a/_locales/zh/messages.json +++ b/_locales/zh/messages.json @@ -725,12 +725,7 @@ } }, "meta_invalidVersion": { - "message": "无效的版本号. 值与 SemVer 规则不匹配: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "无效的版本号" }, "meta_invalidWord": { "message": "需要一个单词" diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 1c9da6e6..05670a48 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -719,12 +719,7 @@ } }, "meta_invalidVersion": { - "message": "无效的版本号. 值与 SemVer 规则不匹配: $version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "无效的版本号" }, "meta_invalidWord": { "message": "需要一个单词" diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index faf85f41..0de3b2bd 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -719,12 +719,7 @@ } }, "meta_invalidVersion": { - "message": "無效的版本號。值不符合 SemVer 模式:$version$", - "placeholders": { - "version": { - "content": "$1" - } - } + "message": "無效的版本號" }, "meta_invalidWord": { "message": "預期為單字" diff --git a/background/update-manager.js b/background/update-manager.js index 05f48486..2ef3a357 100644 --- a/background/update-manager.js +++ b/background/update-manager.js @@ -2,6 +2,7 @@ /* global RX_META URLS debounce download ignoreChromeError */// toolbox.js /* global calcStyleDigest styleJSONseemsValid styleSectionsEqual */ // sections-util.js /* global chromeLocal */// storage-util.js +/* global compareVersion */// cmpver.js /* global db */ /* global prefs */ 'use strict'; @@ -25,10 +26,10 @@ const updateMan = (() => { const RH_ETAG = {responseHeaders: ['etag']}; // a hashsum of file contents const RX_DATE2VER = new RegExp([ /^(\d{4})/, - /(1(?:0|[12](?=\d\d))?|[2-9])/, // in ambiguous cases like yyyy123 the month will be 1 - /([1-2][0-9]?|3[0-1]?|[4-9])/, - /\.(0|1[0-9]?|2[0-3]?|[3-9])/, - /\.(0|[1-5][0-9]?|[6-9])$/, + /(0[1-9]|1(?:0|[12](?=\d\d))?|[2-9])/, // in ambiguous cases like yyyy123 the month will be 1 + /(0[1-9]|[1-2][0-9]?|3[0-1]?|[4-9])/, + /\.([01][0-9]?|2[0-3]?|[3-9])/, + /\.([0-5][0-9]?|[6-9])$/, ].map(rx => rx.source).join('')); const ALARM_NAME = 'scheduledUpdate'; const MIN_INTERVAL_MS = 60e3; @@ -213,14 +214,8 @@ const updateMan = (() => { } // TODO: when sourceCode is > 100kB use http range request(s) for version check const {headers: {etag}, response} = await tryDownload(style.updateUrl, RH_ETAG); - /* There's a bug? in Chrome which occurs only in a packaged crx: - * DOM script for semver fires 'load' event before the script actually runs. - * Since the conditions for the bug are rare we'll simply load in parallel */ - const [json] = await Promise.all([ - API.usercss.buildMeta({sourceCode: response, etag}), - require(['/vendor/semver-bundle/semver']), /* global semverCompare */ - ]); - const delta = semverCompare(json.usercssData.version, ucd.version); + const json = await API.usercss.buildMeta({sourceCode: response, etag}); + const delta = compareVersion(json.usercssData.version, ucd.version); let err; if (!delta && !ignoreDigest) { // re-install is invalid in a soft upgrade diff --git a/install-usercss/install-usercss.js b/install-usercss/install-usercss.js index eb6f9b5a..1befaff4 100644 --- a/install-usercss/install-usercss.js +++ b/install-usercss/install-usercss.js @@ -56,7 +56,7 @@ setTimeout(() => { '/vendor/codemirror/addon/selection/active-line', '/vendor/codemirror/lib/codemirror.css', '/vendor/codemirror/addon/fold/foldgutter.css', - '/vendor/semver-bundle/semver', /* global semverCompare */ + '/js/cmpver', /* global compareVersion */ '/js/sections-util', /* global styleCodeEmpty */ '/js/color/color-converter', '/edit/codemirror-default.css', @@ -89,7 +89,7 @@ setTimeout(() => { } const data = style.usercssData; const dupData = dup && dup.usercssData; - const versionTest = dup && semverCompare(data.version, dupData.version); + const versionTest = dup && compareVersion(data.version, dupData.version); updateMeta(style, dup); @@ -144,7 +144,7 @@ function updateMeta(style, dup = installedDup) { installedDup = dup; const data = style.usercssData; const dupData = dup && dup.usercssData; - const versionTest = dup && semverCompare(data.version, dupData.version); + const versionTest = dup && compareVersion(data.version, dupData.version); cm.setPreprocessor(data.preprocessor); diff --git a/js/cmpver.js b/js/cmpver.js new file mode 100644 index 00000000..170e2f6f --- /dev/null +++ b/js/cmpver.js @@ -0,0 +1,42 @@ +'use strict'; + +/** + Copied from https://github.com/violentmonkey/violentmonkey/blob/master/src/common/util.js + A couple of trivial changes: switched to Math.sign, removed the default radix from parseInt + */ + +/* exported compareVersion */ + +const VERSION_RE = /^(.*?)-([-.0-9a-z]+)|$/i; +const DIGITS_RE = /^\d+$/; // using regexp to avoid +'1e2' being parsed as 100 + +/** @return -1 | 0 | 1 */ +function compareVersion(ver1, ver2) { + const [, main1 = ver1 || '', pre1] = VERSION_RE.exec(ver1); + const [, main2 = ver2 || '', pre2] = VERSION_RE.exec(ver2); + const delta = compareVersionChunk(main1, main2) + || !pre1 - !pre2 // 1.2.3-pre-release is less than 1.2.3 + || pre1 && compareVersionChunk(pre1, pre2, true); // if pre1 is present, pre2 is too + return Math.sign(delta); +} + +function compareVersionChunk(ver1, ver2, isSemverMode) { + const parts1 = ver1.split('.'); + const parts2 = ver2.split('.'); + const len1 = parts1.length; + const len2 = parts2.length; + const len = (isSemverMode ? Math.min : Math.max)(len1, len2); + let delta; + for (let i = 0; !delta && i < len; i += 1) { + const a = parts1[i]; + const b = parts2[i]; + if (isSemverMode) { + delta = DIGITS_RE.test(a) && DIGITS_RE.test(b) + ? a - b + : a > b || a < b && -1; + } else { + delta = (parseInt(a) || 0) - (parseInt(b) || 0); + } + } + return delta || isSemverMode && (len1 - len2); +} diff --git a/js/meta-parser.js b/js/meta-parser.js index 10058ceb..5a0aa734 100644 --- a/js/meta-parser.js +++ b/js/meta-parser.js @@ -5,6 +5,12 @@ const metaParser = (() => { require(['/vendor/usercss-meta/usercss-meta.min']); /* global usercssMeta */ const {createParser, ParseError} = usercssMeta; const PREPROCESSORS = new Set(['default', 'uso', 'stylus', 'less']); + /** Relaxed semver: + * dot-separated digits sequence e.g. 1 or 1.2 or 1.2.3.4.5 + * optional pre-release chunk: "-" followed by dot-separated word characters, "-" + * optional build chunk: "+" followed by dot-separated word characters, "-" + */ + const RX_VER = /^\d+(\.\d+)*(?:-(\w[-\w]*(\.[-\w]+)*))?(?:\+(\w[-\w]*(\.[-\w]+)*))?$/; const options = { validateKey: { preprocessor: state => { @@ -16,6 +22,15 @@ const metaParser = (() => { }); } }, + version: state => { + if (!RX_VER.test(state.value)) { + throw new ParseError({ + code: 'invalidVersion', + message: 'Invalid @version', + index: state.valueIndex, + }); + } + }, }, validateVar: { select: state => { diff --git a/manifest.json b/manifest.json index f8807935..aafb0dcc 100644 --- a/manifest.json +++ b/manifest.json @@ -32,6 +32,7 @@ "js/storage-util.js", "js/sections-util.js", "js/worker-util.js", + "js/cmpver.js", "background/common.js", diff --git a/package-lock.json b/package-lock.json index d3ce4aaa..6693b7ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "jsonlint": "^1.6.3", "less-bundle": "github:openstyles/less-bundle#v0.1.0", "lz-string-unsafe": "^1.4.4-fork-1", - "semver-bundle": "^0.1.1", "stylelint-bundle": "^13.8.0", "stylus-lang-bundle": "github:openstyles/stylus-lang-bundle#v0.54.7", "usercss-meta": "^0.10.0", @@ -644,6 +643,7 @@ "espree": "7.3.0", "esprima": "4.0.1", "fluent-syntax": "0.13.0", + "fsevents": "2.2.1", "glob": "7.1.6", "is-mergeable-object": "1.1.1", "jed": "1.1.1", @@ -1853,6 +1853,12 @@ "engines": [ "node >=0.10.0" ], + "dependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + }, "bin": { "bunyan": "bin/bunyan" }, @@ -2136,6 +2142,7 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -4570,6 +4577,9 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7009,6 +7019,7 @@ "integrity": "sha512-ssHt0dkljEDaKmTgQ04DQgx2ag6G2gMPxA5hpcsoeTbfDgRf2fC2gNSRc6kISjD7ckCpHwwQvXxuTBK8402fXg==", "dev": true, "dependencies": { + "encoding": "^0.1.12", "minipass": "^3.1.0", "minipass-pipeline": "^1.2.2", "minipass-sized": "^1.0.3", @@ -9110,14 +9121,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, - "node_modules/semver-bundle": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/semver-bundle/-/semver-bundle-0.1.1.tgz", - "integrity": "sha512-AXZEjNFlP6BzqRlWQNF3NBGsDw/clPcuUAk1mUl+ypnSplG20CDLQj5ofmaj40vlUHt40duxH3d/x/RXItLAHA==", - "dependencies": { - "semver": "^5.5.0" - } - }, "node_modules/semver-diff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", @@ -11267,8 +11270,10 @@ "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", "dev": true, "dependencies": { + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" }, "optionalDependencies": { "chokidar": "^3.4.1", @@ -11352,6 +11357,7 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -19458,14 +19464,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, - "semver-bundle": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/semver-bundle/-/semver-bundle-0.1.1.tgz", - "integrity": "sha512-AXZEjNFlP6BzqRlWQNF3NBGsDw/clPcuUAk1mUl+ypnSplG20CDLQj5ofmaj40vlUHt40duxH3d/x/RXItLAHA==", - "requires": { - "semver": "^5.5.0" - } - }, "semver-diff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", diff --git a/package.json b/package.json index 06b19406..3053651d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "jsonlint": "^1.6.3", "less-bundle": "github:openstyles/less-bundle#v0.1.0", "lz-string-unsafe": "^1.4.4-fork-1", - "semver-bundle": "^0.1.1", "stylelint-bundle": "^13.8.0", "stylus-lang-bundle": "github:openstyles/stylus-lang-bundle#v0.54.7", "usercss-meta": "^0.10.0", diff --git a/tools/build-vendor.js b/tools/build-vendor.js index befa0018..fa6c5c37 100644 --- a/tools/build-vendor.js +++ b/tools/build-vendor.js @@ -44,9 +44,6 @@ const files = { 'lz-string-unsafe': [ 'lz-string-unsafe.min.js', ], - 'semver-bundle': [ - 'dist/semver.js → semver.js', - ], 'stylelint-bundle': [ 'dist/stylelint-bundle.min.js → stylelint-bundle.min.js', 'https://github.com/stylelint/stylelint/raw/{VERSION}/LICENSE → LICENSE', diff --git a/vendor/semver-bundle/LICENSE b/vendor/semver-bundle/LICENSE deleted file mode 100644 index 19129e31..00000000 --- a/vendor/semver-bundle/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/semver-bundle/README.md b/vendor/semver-bundle/README.md deleted file mode 100644 index 92441f95..00000000 --- a/vendor/semver-bundle/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## semver-bundle v0.1.1 - -Following files are copied from npm (node_modules): - -* semver.js: dist\semver.js diff --git a/vendor/semver-bundle/semver.js b/vendor/semver-bundle/semver.js deleted file mode 100644 index 4c72e092..00000000 --- a/vendor/semver-bundle/semver.js +++ /dev/null @@ -1 +0,0 @@ -var semverCompare=function(){"use strict";var s=256,i=Number.MAX_SAFE_INTEGER||9007199254740991,a=[],e=[],r=0,t=r++;e[t]="0|[1-9]\\d*";var n=r++;e[n]="[0-9]+";var h=r++;e[h]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var o=r++;e[o]="("+e[t]+")\\.("+e[t]+")\\.("+e[t]+")";var p=r++;e[p]="("+e[n]+")\\.("+e[n]+")\\.("+e[n]+")";var l=r++;e[l]="(?:"+e[t]+"|"+e[h]+")";var c=r++;e[c]="(?:"+e[n]+"|"+e[h]+")";var v=r++;e[v]="(?:-("+e[l]+"(?:\\."+e[l]+")*))";var f=r++;e[f]="(?:-?("+e[c]+"(?:\\."+e[c]+")*))";var m=r++;e[m]="[0-9A-Za-z-]+";var u=r++;e[u]="(?:\\+("+e[m]+"(?:\\."+e[m]+")*))";var g=r++,w="v?"+e[o]+e[v]+"?"+e[u]+"?";e[g]="^"+w+"$";var d="[v=\\s]*"+e[p]+e[f]+"?"+e[u]+"?",$=r++;e[$]="^"+d+"$";var y=r++;e[y]="((?:<|>)?=?)";var E=r++;e[E]=e[n]+"|x|X|\\*";var j=r++;e[j]=e[t]+"|x|X|\\*";var b=r++;e[b]="[v=\\s]*("+e[j]+")(?:\\.("+e[j]+")(?:\\.("+e[j]+")(?:"+e[v]+")?"+e[u]+"?)?)?";var k=r++;e[k]="[v=\\s]*("+e[E]+")(?:\\.("+e[E]+")(?:\\.("+e[E]+")(?:"+e[f]+")?"+e[u]+"?)?)?",e[r++]="^"+e[y]+"\\s*"+e[b]+"$",e[r++]="^"+e[y]+"\\s*"+e[k]+"$",e[r++]="(?:^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])";var T=r++;e[T]="(?:~>?)";var x=r++;e[x]="(\\s*)"+e[T]+"\\s+",a[x]=new RegExp(e[x],"g"),e[r++]="^"+e[T]+e[b]+"$",e[r++]="^"+e[T]+e[k]+"$";var I=r++;e[I]="(?:\\^)";var A=r++;e[A]="(\\s*)"+e[I]+"\\s+",a[A]=new RegExp(e[A],"g"),e[r++]="^"+e[I]+e[b]+"$",e[r++]="^"+e[I]+e[k]+"$",e[r++]="^"+e[y]+"\\s*("+d+")$|^$",e[r++]="^"+e[y]+"\\s*("+w+")$|^$";var R=r++;e[R]="(\\s*)"+e[y]+"\\s*("+d+"|"+e[b]+")",a[R]=new RegExp(e[R],"g"),e[r++]="^\\s*("+e[b]+")\\s+-\\s+("+e[b]+")\\s*$",e[r++]="^\\s*("+e[k]+")\\s+-\\s+("+e[k]+")\\s*$",e[r++]="(<|>)?=?\\s*\\*";for(var N=0;N<35;N++)a[N]||(a[N]=new RegExp(e[N]));function z(e,r){if(e instanceof z){if(e.loose===r)return e;e=e.version}else if("string"!=typeof e)throw new TypeError("Invalid Version: "+e);if(e.length>s)throw new TypeError("version is longer than "+s+" characters");if(!(this instanceof z))return new z(e,r);this.loose=r;var t=e.trim().match(r?a[$]:a[g]);if(!t)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+t[1],this.minor=+t[2],this.patch=+t[3],this.major>i||this.major<0)throw new TypeError("Invalid major version");if(this.minor>i||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>i||this.patch<0)throw new TypeError("Invalid patch version");t[4]?this.prerelease=t[4].split(".").map(function(e){if(/^[0-9]+$/.test(e)){var r=+e;if(0<=r&&r