diff --git a/.editorconfig b/.editorconfig index 49c154d..2895e47 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*] indent_style = space -indent_size = 2 +indent_size = 4 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true diff --git a/.eslintrc.js b/.eslintrc.js index 34a4590..cb826f2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,37 +1,40 @@ module.exports = { - "root": true, - "env": { - "browser": true, - "es6": true, - "greasemonkey": true, - "jquery": true - }, - "extends": "airbnb", - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly", - "lscache": "readonly", - "dateFns": "readonly", - "eus": "readonly", - "_": "readonly", - "hljs": "readonly", - "jsyaml": "readonly" - }, - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "script" - }, - "rules": { - // Tech debt. Remove or reconsider one day: - "no-unused-vars": ["error", { "args": "none" }], - "func-names": 0, - "no-use-before-define": ["error", "nofunc"], - "max-len": 0, - "no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"], - "strict": 0, - "require-await": "error", - "require-yield": "error", - "linebreak-style": 0, - "arrow-parens": 0, - } + "root": true, + "env": { + "browser": true, + "es6": true, + "greasemonkey": true, + "jquery": true + }, + "extends": "@ni", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly", + "lscache": "readonly", + "dateFns": "readonly", + "eus": "readonly", + "_": "readonly", + "hljs": "readonly", + "jsyaml": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "script" + }, + "rules": { + // Tech debt. Remove or reconsider one day: + "no-unused-vars": ["error", { "args": "none" }], + "func-names": "off", + "no-use-before-define": ["error", "nofunc"], + "max-len": "off", + "no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"], + "strict": "off" + }, + "overrides": [{ + "files": [".*.js"], + "rules": { + "quote-props": "off", + "quotes": "off" + } + }], }; diff --git a/package-lock.json b/package-lock.json index eb61f24..aa9f684 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,42 +3,51 @@ "lockfileVersion": 1, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.10.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, - "@babel/runtime": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", - "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.5.tgz", - "integrity": "sha512-RMafpmrNB5E/bwdSphLr8a8++9TosnyJp98RZzI6VOx2R2CCMpsXXXRvmI700O9oEKpXdZat6oEK68/F0zjd4A==", + "@ni/eslint-config": { + "version": "1.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@ni/eslint-config/-/eslint-config-1.0.0-alpha.2.tgz", + "integrity": "sha512-/6flevI4RbZzxUig0nTjyvmx50wXXPUgVCBbNzuiCfyeLRMZzS2/z9o9rttUXZWYNHbb23nfojST3FdtGfLezQ==", "dev": true, "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" + "eslint-config-airbnb-base": "~14.2.0" } }, "@types/json5": { @@ -48,39 +57,39 @@ "dev": true }, "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -101,16 +110,6 @@ "sprintf-js": "~1.0.2" } }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, "array-includes": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", @@ -123,61 +122,23 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, @@ -192,158 +153,32 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - } - } - }, - "array.prototype.flatmap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", - "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, - "axe-core": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", - "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -367,37 +202,56 @@ "dev": true }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -431,38 +285,24 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, - "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true - }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "damerau-levenshtein": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", - "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", - "dev": true - }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "deep-is": { @@ -495,6 +335,15 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -505,27 +354,29 @@ } }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -540,69 +391,58 @@ "dev": true }, "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.6.0.tgz", + "integrity": "sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", + "levn": "^0.4.1", + "lodash": "^4.17.19", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", - "text-table": "^0.2.0" - } - }, - "eslint-config-airbnb": { - "version": "17.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.1.tgz", - "integrity": "sha512-xCu//8a/aWqagKljt+1/qAM62BYZeNq04HmdevG5yUGWpja0I/xhqd6GdLRch5oetEGFiJAnvtGuTEAese53Qg==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^13.2.0", - "object.assign": "^4.1.0", - "object.entries": "^1.1.0" + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" } }, "eslint-config-airbnb-base": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.2.0.tgz", - "integrity": "sha512-1mg/7eoB4AUeB0X1c/ho4vb2gYkNH8Trr/EgCT/aGmKhhG+F6vF5s8+iRBlWAzFIAphxIdp3YfEKgEl0f9Xg+w==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", + "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", "dev": true, "requires": { - "confusing-browser-globals": "^1.0.5", + "confusing-browser-globals": "^1.0.9", "object.assign": "^4.1.0", - "object.entries": "^1.1.0" + "object.entries": "^1.1.2" } }, "eslint-import-resolver-node": { @@ -707,165 +547,40 @@ } } }, - "eslint-plugin-jsx-a11y": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz", - "integrity": "sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "aria-query": "^4.2.2", - "array-includes": "^3.1.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^3.5.4", - "axobject-query": "^2.1.2", - "damerau-levenshtein": "^1.0.6", - "emoji-regex": "^9.0.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "language-tags": "^1.0.5" - }, - "dependencies": { - "emoji-regex": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.0.0.tgz", - "integrity": "sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==", - "dev": true - } - } - }, - "eslint-plugin-react": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.2.tgz", - "integrity": "sha512-j3XKvrK3rpBzveKFbgAeGsWb9uz6iUOrR0jixRfjwdFeGSRsXvVTFtHDQYCjsd1/6Z/xvb8Vy3LiI5Reo7fDrg==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.17.0", - "string.prototype.matchall": "^4.0.2" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - } - } - } - }, "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "esrecurse": "^4.1.0", + "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" } }, "esprima": { @@ -875,21 +590,37 @@ "dev": true }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "estraverse": { @@ -904,27 +635,16 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { @@ -933,15 +653,6 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -972,9 +683,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "fs.realpath": { @@ -996,9 +707,9 @@ "dev": true }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1009,11 +720,23 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "graceful-fs": { "version": "4.2.4", @@ -1037,9 +760,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, "hosted-git-info": { @@ -1048,15 +771,6 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -1064,9 +778,9 @@ "dev": true }, "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -1095,114 +809,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - } - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1210,15 +816,21 @@ "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { @@ -1227,25 +839,28 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", "dev": true }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.1" + "has-symbols": "^1.0.1" } }, "is-string": { @@ -1255,12 +870,12 @@ "dev": true }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "isarray": { @@ -1282,9 +897,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -1310,49 +925,16 @@ "dev": true, "requires": { "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } - } - }, - "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "language-subtag-registry": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", - "integrity": "sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "load-json-file": { @@ -1378,24 +960,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, "minimatch": { @@ -1408,18 +975,18 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "ms": { @@ -1428,24 +995,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -1456,18 +1011,20 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -1477,97 +1034,46 @@ "dev": true }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", + "es-abstract": "^1.17.5", "has": "^1.0.3" }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, @@ -1584,61 +1090,23 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, @@ -1651,35 +1119,20 @@ "wrappy": "1" } }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -1734,16 +1187,10 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { @@ -1777,9 +1224,9 @@ } }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "progress": { @@ -1788,29 +1235,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -1832,85 +1262,10 @@ "read-pkg": "^2.0.0" } }, - "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", - "dev": true - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - } - } - }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, "resolve": { @@ -1928,16 +1283,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -1947,125 +1292,25 @@ "glob": "^7.1.3" } }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rxjs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", - "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", - "dev": true, - "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - } - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "slice-ansi": { @@ -2106,9 +1351,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, "sprintf-js": { @@ -2118,85 +1363,30 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.matchall": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", - "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2" + "strip-ansi": "^5.1.0" }, "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "ansi-regex": "^4.1.0" } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, @@ -2211,84 +1401,26 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, - "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, "string.prototype.trimstart": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", @@ -2300,71 +1432,33 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { @@ -2374,9 +1468,9 @@ "dev": true }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { @@ -2398,34 +1492,6 @@ "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "text-table": { @@ -2434,21 +1500,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -2459,40 +1510,38 @@ "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" } }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -2504,18 +1553,18 @@ } }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, "wrappy": { diff --git a/package.json b/package.json index edb6269..9aa97ff 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,14 @@ { - "private": true, - "dependencies": {}, - "devDependencies": { - "eslint": "^5.3.0", - "eslint-config-airbnb": "^17.1.0", - "eslint-plugin-import": "^2.22.0", - "eslint-plugin-jsx-a11y": "^6.3.1", - "eslint-plugin-react": "^7.21.2" - }, - "scripts": { - "build": "npm run lint", - "lint": "eslint --ignore-path .gitignore .", - "lint-fix": "eslint --fix --ignore-path .gitignore ." - } + "private": true, + "dependencies": {}, + "devDependencies": { + "@ni/eslint-config": "^1.0.0-alpha.2", + "eslint": "^7.6.0", + "eslint-plugin-import": "^2.22.0" + }, + "scripts": { + "build": "npm run lint", + "lint": "eslint --ignore-path .gitignore .", + "lint-fix": "eslint --fix --ignore-path .gitignore ." + } } diff --git a/src/azdo-pr-dashboard.user.js b/src/azdo-pr-dashboard.user.js index 84b15b4..966db94 100644 --- a/src/azdo-pr-dashboard.user.js +++ b/src/azdo-pr-dashboard.user.js @@ -32,1395 +32,1403 @@ // ==/UserScript== -(function () { - 'use strict'; - - // All REST API calls should fail after a timeout, instead of going on forever. - $.ajaxSetup({ timeout: 5000 }); - - lscache.setBucket('acb-azdo/'); - - let currentUser; - let azdoApiBaseUrl; - - // Throttle page update events to avoid using up CPU when AzDO is adding a lot of elements during a short time (like on page load). - const onPageUpdatedThrottled = _.throttle(onPageUpdated, 400, { leading: false, trailing: true }); - - // Some features only apply at National Instruments. - const atNI = /^ni\./i.test(window.location.hostname) || /^\/ni\//i.test(window.location.pathname); - - function onReady() { - // Find out who is our current user. In general, we should avoid using pageData because it doesn't always get updated when moving between page-to-page in AzDO's single-page application flow. Instead, rely on the AzDO REST APIs to get information from stuff you find on the page or the URL. Some things are OK to get from pageData; e.g. stuff like the user which is available on all pages. - const pageData = JSON.parse(document.getElementById('dataProviders').innerHTML).data; - currentUser = pageData['ms.vss-web.page-data'].user; - - const theme = pageData['ms.vss-web.theme-data'].requestedThemeId; - const isDarkTheme = /(dark|night|neptune)/i.test(theme); - - // Because of CORS, we need to make sure we're querying the same hostname for our AzDO APIs. - azdoApiBaseUrl = `${window.location.origin}${pageData['ms.vss-tfs-web.header-action-data'].suiteHomeUrl}`; - - // Invoke our new eus-style features. - watchPullRequestDashboard(); - watchForNewLabels(); - watchForWorkItemForms(); - watchForNewDiffs(isDarkTheme); - watchForShowMoreButtons(); - - // Handle any existing elements, flushing it to execute immediately. - onPageUpdatedThrottled(); - onPageUpdatedThrottled.flush(); - - // Call our event handler if we notice new elements being inserted into the DOM. This happens as the page is loading or updating dynamically based on user activity. - $('body > div.full-size')[0].addEventListener('DOMNodeInserted', onPageUpdatedThrottled); - } - - // This is "main()" for this script. Runs periodically when the page updates. - function onPageUpdated() { - try { - // The page may not have refreshed when moving between URLs--sometimes AzDO acts as a single-page application. So we must always check where we are and act accordingly. - if (/\/(pullrequest)\//i.test(window.location.pathname)) { - addBaseUpdateSelector(); - makePullRequestDiffEasierToScroll(); - applyStickyPullRequestComments(); - highlightAwaitComments(); - addAccessKeysToPullRequestTabs(); - if (atNI) { - addOwnersInfoToFiles(); - conditionallyAddBypassReminderAsync(); - } - addTrophiesToPullRequest(); - if (atNI && /\/DevCentral\/_git\/ASW\//i.test(window.location.pathname)) { - addNICodeOfDayToggle(); - } - } - - if (atNI) { - styleLabels(); - } - - if (/\/(pullrequests)/i.test(window.location.pathname)) { - addOrgPRLink(); - } - } catch (e) { - eus.toast.fire({ - title: 'AzDO userscript error', - text: 'See JS console for more info.', - icon: 'error', - showConfirmButton: true, - confirmButtonColor: '#d43', - confirmButtonText: ' Get Help!', - }).then((result) => { - if (result.value) { - window.open(GM_info.script.supportURL, '_blank'); - } - }); - throw e; - } - } - - enhanceOverallUX(); - - addStyleOnce('labels', /* css */ ` - /* Known bug severities we should style. */ - .pr-bug-severity-1 { - background: #a008 !important; - } - .pr-bug-severity-2 { - background: #fd38 !important; - } - /* Align labels to the right and give them a nice border. */ - .repos-pr-list .bolt-pill-group { - flex-grow: 1; - justify-content: flex-end; - } - .bolt-pill { - border: 1px solid #0001; - } - /* Known labels we should style. */ - .pr-annotation:not([title=""]) { - cursor: help !important; - } - .pr-annotation.file-count, - .pr-annotation.build-status { - background: #fff4 !important; - min-width: 8ex; - }`); - - if (atNI) { - addStyleOnce('ni-labels', /* css */ ` - /* Known labels we should style. */ - .label--owners { - } - .label--draft { - background: #8808 !important; - } - .label--tiny { - background: #0a08 !important; - } - .label--bypassowners { - }`); - } - - addStyleOnce('bypassOwnersPrompt', /* css */ ` - .bypass-reminder { - display: inline; - position: absolute; - top: 38px; - left: -450px; - z-index: 1000; - background-color: #E6B307; - padding: 6px 12px; - border-radius: 6px; - box-shadow: 4px 4px 4px #18181888; - opacity: 0; - transition: 0.3s; - } - .bypass-reminder-container { - position: relative; - display: inline-flex; - flex-direction: column; - } - .vote-button-wrapper { - border: 3px solid transparent; - border-radius: 4px; - transition: 0.3s; - } - .vote-button-wrapper:hover { - border-color: #E6B307; - } - .vote-button-wrapper:hover ~ .bypass-reminder { - opacity: 1; - }`); - - function styleLabels() { - // Give all tags a CSS class based on their name. - $('.tag-box').once('labels').each(function () { - const tagBox = $(this); - const subClass = stringToCssIdentifier(tagBox.text()); - tagBox.addClass(`label--${subClass}`); - }); - } - - function watchForNewLabels() { - // Give all tags a CSS class based on their name. - eus.globalSession.onEveryNew(document, '.bolt-pill', label => { - if (!label.ariaLabel) return; - const subClass = stringToCssIdentifier(label.ariaLabel); - label.classList.add(`label--${subClass}`); - }); - } - - function watchForWorkItemForms() { - // Annotate work items (under the comment box) with who is following it. - eus.globalSession.onEveryNew(document, '.discussion-messages-right', async commentEditor => { - const workItemId = commentEditor.closest('.witform-layout').querySelector('.work-item-form-id > span').innerText; - const queryResponse = await fetch(`${azdoApiBaseUrl}/_apis/notification/subscriptionquery?api-version=6.0`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - conditions: [ - { - filter: { - type: 'Artifact', - eventType: '', - artifactId: workItemId, - artifactType: 'WorkItem', - }, - }, - ], - }), - }); +(function() { + 'use strict'; - const followers = [...(await queryResponse.json()).value].sort((a, b) => a.subscriber.displayName.localeCompare(b.subscriber.displayName)); + // All REST API calls should fail after a timeout, instead of going on forever. + $.ajaxSetup({ timeout: 5000 }); - const commentFollowers = followers - .filter(workItemSubscriptionFollowsEverything) - .map(s => `${s.subscriber.displayName}`) - .join(', ') - || 'Nobody'; + lscache.setBucket('acb-azdo/'); - const fieldFollowerCount = followers.filter(s => !workItemSubscriptionFollowsEverything(s)).length; - const fieldFollowers = fieldFollowerCount ? `(and ${fieldFollowerCount} field follower${fieldFollowerCount > 1 ? 's' : ''})` : ''; + let currentUser; + let azdoApiBaseUrl; - const annotation = `
${commentFollowers} ${fieldFollowers}
`; - commentEditor.insertAdjacentHTML('BeforeEnd', annotation); + // Throttle page update events to avoid using up CPU when AzDO is adding a lot of elements during a short time (like on page load). + const onPageUpdatedThrottled = _.throttle(onPageUpdated, 400, { + leading: false, + trailing: true }); - } - function workItemSubscriptionFollowsEverything(subscription) { - return subscription.description.startsWith("Following 'WorkItem' artifact"); - } + // Some features only apply at National Instruments. + const atNI = /^ni\./i.test(window.location.hostname) || /^\/ni\//i.test(window.location.pathname); - function watchForShowMoreButtons() { - // Auto-click Show More buttons on work item forms, until they disappear or until we've pressed it 10 times (a reasonable limit which will still bring in 60 more items into view). - eus.globalSession.onEveryNew(document, 'div[role="button"].la-show-more', async showMoreButton => { - if (eus.seen(showMoreButton)) return; + function onReady() { + // Find out who is our current user. In general, we should avoid using pageData because it doesn't always get updated when moving between page-to-page in AzDO's single-page application flow. Instead, rely on the AzDO REST APIs to get information from stuff you find on the page or the URL. Some things are OK to get from pageData; e.g. stuff like the user which is available on all pages. + const pageData = JSON.parse(document.getElementById('dataProviders').innerHTML).data; + currentUser = pageData['ms.vss-web.page-data'].user; - let clicks = 0; - while (document.body.contains(showMoreButton)) { - showMoreButton.click(); + const theme = pageData['ms.vss-web.theme-data'].requestedThemeId; + const isDarkTheme = /(dark|night|neptune)/i.test(theme); - clicks += 1; - if (clicks >= 10) break; + // Because of CORS, we need to make sure we're querying the same hostname for our AzDO APIs. + azdoApiBaseUrl = `${window.location.origin}${pageData['ms.vss-tfs-web.header-action-data'].suiteHomeUrl}`; - // eslint-disable-next-line no-await-in-loop - await sleep(100); - } - }); - - // Auto-click Show More buttons on Kanban boards, until they disappear, are hidden, or until we've pressed it 5 times (a reasonable limit which will still bring in hundreds of items into view). - eus.globalSession.onEveryNew(document, 'a[role="button"].see-more-items', async showMoreButton => { - if (eus.seen(showMoreButton)) return; + // Invoke our new eus-style features. + watchPullRequestDashboard(); + watchForNewLabels(); + watchForWorkItemForms(); + watchForNewDiffs(isDarkTheme); + watchForShowMoreButtons(); - const container = showMoreButton.closest('.page-items-container'); - let clicks = 0; + // Handle any existing elements, flushing it to execute immediately. + onPageUpdatedThrottled(); + onPageUpdatedThrottled.flush(); - while (document.body.contains(showMoreButton) && container.style.display !== 'none') { - if (showMoreButton.style.display !== 'none') { - showMoreButton.click(); + // Call our event handler if we notice new elements being inserted into the DOM. This happens as the page is loading or updating dynamically based on user activity. + $('body > div.full-size')[0].addEventListener('DOMNodeInserted', onPageUpdatedThrottled); + } - clicks += 1; - if (clicks >= 5) break; - } + // This is "main()" for this script. Runs periodically when the page updates. + function onPageUpdated() { + try { + // The page may not have refreshed when moving between URLs--sometimes AzDO acts as a single-page application. So we must always check where we are and act accordingly. + if (/\/(pullrequest)\//i.test(window.location.pathname)) { + addBaseUpdateSelector(); + makePullRequestDiffEasierToScroll(); + applyStickyPullRequestComments(); + highlightAwaitComments(); + addAccessKeysToPullRequestTabs(); + if (atNI) { + addOwnersInfoToFiles(); + conditionallyAddBypassReminderAsync(); + } + addTrophiesToPullRequest(); + if (atNI && /\/DevCentral\/_git\/ASW\//i.test(window.location.pathname)) { + addNICodeOfDayToggle(); + } + } - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - }); - } - - function stringToCssIdentifier(text) { - return encodeURIComponent(text.toLowerCase()).replace(/%[0-9A-F]{2}/gi, ''); - } - - function getRepoNameFromUrl(url) { - const repoName = url.match(/_git\/(.+)\/pullrequests/)[1]; - return repoName || ''; - } - - function addOrgPRLink() { - $('.bolt-header-title.title-m.l').once('decorate-with-org-pr-link').each(function () { - const titleElement = this; - titleElement.innerText = `${getRepoNameFromUrl(window.location.pathname)} ${titleElement.innerText}`; - const orgPRLink = document.createElement('a'); - orgPRLink.href = `${azdoApiBaseUrl}_pulls`; - orgPRLink.text = '→ View global PR dashboard'; - orgPRLink.style = 'margin: 15px; font-size: 80%; text-decoration: none; color: var(--communication-foreground,rgba(0, 90, 158, 1)); font-weight: normal'; - titleElement.insertAdjacentElement('beforeend', orgPRLink); - }); - } - - function highlightAwaitComments() { - // Comments that start with this string are highlighted. No other behavior is given to them. - const lowerCasePrefix = 'await:'; - - addStyleOnce('highlight-await-comments', /* css */ ` - .vc-discussion-thread-box .vc-discussion-thread-comment .vc-discussion-thread-renderparent[content^="${lowerCasePrefix}" i] { - border: 2px solid rgb(var(--palette-accent3)); - border-radius: 5px; - margin: 7px 0px; - padding: 10px 15px; - }`); - } - - function applyStickyPullRequestComments() { - // Comments that start with this string become sticky. Only the first comment of the thread counts. - const lowerCasePrefix = 'note:'; - - addStyleOnce('sticky-comments', /* css */ ` - .vc-discussion-thread-box .vc-discussion-thread-comment:first-of-type .vc-discussion-thread-renderparent[content^="${lowerCasePrefix}" i] { - border: 2px solid var(--palette-black-alpha-20); - border-radius: 5px; - margin: 7px 0px; - padding: 10px 15px; - }`); - - // Expand threads that have the sticky prefix. - const lowerCasePrefixCssSelector = CSS.escape(`: "${lowerCasePrefix}`); - $('.discussion-thread-host').once('expand-sticky-threads-on-load').each(async function () { - await sleep(100); - const button = this.querySelector(`button.ms-Button.expand-button[aria-label*="${lowerCasePrefixCssSelector}" i]`); - if (button) { - button.click(); - } - }); - } + if (atNI) { + styleLabels(); + } - function addAccessKeysToPullRequestTabs() { - // Give all the tabs an access key equal to their numeric position on screen. - $('ul.vc-pullrequest-tabs a').once('add-accesskeys').each(function () { - $(this).attr('accesskey', $(this).attr('aria-posinset')); - }); - } - - function enhanceOverallUX() { - addStyleOnce('enhance-overall-ux', /* css */ ` - /* Colored scrollbars */ - ::-webkit-scrollbar { - width: 15px; - height: 15px; - } - ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { - background: rgb(var(--palette-neutral-4)); - } - ::-webkit-scrollbar-thumb { - background: rgb(var(--palette-neutral-20)); - } - /* Bigger dropdown menus */ - .identity-picker-dropdown ul.items, .scroll-tree-overflow-box, .ui-autocomplete, .vss-PickList--items { - max-height: 50vh !important; - } - /* Prompts to add links to work items are much less prominent, unless hovered over */ - .zero-data-action, .deployments-zero-data { - opacity: 0.2; - } - .zero-data-action img, .deployments-zero-data img, - .zero-data-action i, .deployments-zero-data i { - display: none; - } - .zero-data-action:hover, .deployments-zero-data:hover { - opacity: 1; - }`); - } - - // Adds a bypass suggestion message that pops up when the user mouses over the Approve button. - async function conditionallyAddBypassReminderAsync() { - // Only add it if the target branch requires owner approval - if (!(await pullRequestHasRequiredOwnersPolicyAsync())) { - return; + if (/\/(pullrequests)/i.test(window.location.pathname)) { + addOrgPRLink(); + } + } catch (e) { + eus.toast.fire({ + title: 'AzDO userscript error', + text: 'See JS console for more info.', + icon: 'error', + showConfirmButton: true, + confirmButtonColor: '#d43', + confirmButtonText: ' Get Help!', + }).then(result => { + if (result.value) { + window.open(GM_info.script.supportURL, '_blank'); + } + }); + throw e; + } } - if ($('.bypass-reminder-container').length > 0) { - return; - } + enhanceOverallUX(); - const container = document.createElement('div'); - container.classList.add('bypass-reminder-container'); - - const banner = document.createElement('div'); - banner.classList.add('bypass-reminder'); - banner.appendChild(document.createTextNode('If you are confident the change needs no further review by others, please bypass owners.')); - - if ($('.repos-pr-header-vote-button').length === 0) { - // "old" PR experience - $('#pull-request-vote-button') - .parent() - .parent() - .addClass('vote-button-wrapper') - .appendTo(container); - container.appendChild(banner); - $('.vote-control-container').append(container); - } else { - // "new" PR experience - const voteButton = document.getElementsByClassName('repos-pr-header-vote-button')[0]; - // We cannot change the parent of voteButton, or we get an error when pressing the approve button. - // Instead, we'll wedge our "container" div between the voteButton and its children. - // Because the voteButton's children will be moved under our container, we'll need to create a new wrapping element (by cloning the old parent) to keep them laid-out properly. - const buttonLayoutWrapper = voteButton.cloneNode(false); - buttonLayoutWrapper.classList.add('vote-button-wrapper'); - buttonLayoutWrapper.append(voteButton.children[0]); - buttonLayoutWrapper.append(voteButton.children[0]); - buttonLayoutWrapper.append(voteButton.children[0]); - - container.append(buttonLayoutWrapper); - container.append(banner); - - voteButton.append(container); - } - } - - // Adds a "Trophies" section to the Overview tab of a PR for a qualifying PR number - function addTrophiesToPullRequest() { - // Pull request author is sometimes undefined on first call. Only add trophies if we can get the author name. - const pullRequestAuthor = $('div.ms-TooltipHost.host_e6f6b93f.created-by-label').children('span').text(); - - // Only create the trophies section once. - if ($('#trophies-section').length === 0 && pullRequestAuthor.length !== 0) { - const pullRequestId = getCurrentPullRequestId(); - let trophyAwarded = false; - - const trophiesLeftPaneSection = $('
').addClass('vc-pullrequest-leftpane-section').attr('id', 'trophies-section'); - - const sectionTitle = $('
').addClass('vc-pullrequest-leftpane-section-title').append('Trophies'); - const divider = $('
').addClass('divider'); - const sectionContent = $('
').addClass('policies-section'); - - trophiesLeftPaneSection - .append(sectionTitle) - .append(divider) - .append(sectionContent); - - // Milestone trophy: Awarded if pull request ID is greater than 1000 and is a non-zero digit followed by only zeroes (e.g. 1000, 5000, 10000). - if (pullRequestId >= 1000 && pullRequestId.match('^[1-9]0+$')) { - const milestoneTrophyMessage = $('
)').text(`${pullRequestAuthor} got pull request #${pullRequestId}!`); - sectionContent.append(milestoneTrophyMessage.prepend(' 🏆 ')); - trophyAwarded = true; - } - - // Fish trophy: Give a man a fish, he'll waste hours trying to figure out why. (Awarded if the ID is a palindrome.) - if (pullRequestId === pullRequestId.split('').reverse().join('')) { - const fishTrophyMessage = $('
)').text(`${pullRequestAuthor} got a fish trophy!`); - sectionContent.append(fishTrophyMessage.prepend(' 🐠 ')); - trophyAwarded = true; - } - - // Add the trophy section to the Overview tab pane only if a trophy has been awarded. - if (trophyAwarded) { - $('div.overview-tab-pane').append(trophiesLeftPaneSection); - } - } - } - - function makePullRequestDiffEasierToScroll() { - addStyleOnce('pr-diff-improvements', /* css */ ` - .vc-change-summary-files .file-container { - /* Make the divs float but clear them so they get stacked on top of each other. We float so that the divs expand to take up the width of the text in it. Finally, we remove the overflow property so that they don't have scrollbars and also such that we can have sticky elements (apparently, sticky elements don't work if the div has overflow). */ - float: left; - clear: both; - min-width: 95%; - overflow: initial; - } - .vc-change-summary-files .file-row { - /* Let the file name section of each diff stick to the top of the page if we're scrolling. */ - position: sticky; - top: 0; - z-index: 100000; - padding-bottom: 10px; - background: var(--background-color,rgba(255, 255, 255, 1)); - } - .vc-change-summary-files .vc-diff-viewer { - /* We borrowed padding from the diff to give to the bottom of the file row. So adjust accordingly (this value was originally 20px). */ - padding-top: 10px; - }`); - } - - // The func we'll call to continuously add checkboxes to the PR file listing, once initialization is over. - let annotateFilesTreeFunc = () => { }; - - // If we're on specific PR, add checkboxes to the file listing. - function addOwnersInfoToFiles() { - $('.vc-pullrequest-leftpane-section.files-tab').once('annotate-with-owners-info').each(async () => { - annotateFilesTreeFunc = () => { }; - - addStyleOnce('pr-file-tree-annotations-css', /* css */ ` - :root { - /* Set some constants for our CSS. */ - --file-to-review-color: var(--communication-foreground); + addStyleOnce('labels', /* css */ ` + /* Known bug severities we should style. */ + .pr-bug-severity-1 { + background: #a008 !important; } - .vc-sparse-files-tree .tree-row.file-to-review-row, - .vc-sparse-files-tree .tree-row.file-to-review-row .file-name { - /* Highlight files I need to review. */ - color: var(--file-to-review-color); - transition-duration: 0.2s; + .pr-bug-severity-2 { + background: #fd38 !important; } - .vc-sparse-files-tree .tree-row.folder-to-review-row[aria-expanded='false'], - .vc-sparse-files-tree .tree-row.folder-to-review-row[aria-expanded='false'] .file-name { - /* Highlight folders that have files I need to review, but only when files are hidden cause the folder is collapsed. */ - color: var(--file-to-review-color); - transition-duration: 0.2s; + /* Align labels to the right and give them a nice border. */ + .repos-pr-list .bolt-pill-group { + flex-grow: 1; + justify-content: flex-end; } - .vc-sparse-files-tree .tree-row.file-to-review-row .file-owners-role { - /* Style the role of the user in the files table. */ - font-weight: bold; - padding: 7px 10px; - position: absolute; - z-index: 100; - float: right; + .bolt-pill { + border: 1px solid #0001; } - .file-to-review-diff { - /* Highlight files I need to review. */ - border-left: 3px solid var(--file-to-review-color) !important; - padding-left: 7px; + /* Known labels we should style. */ + .pr-annotation:not([title=""]) { + cursor: help !important; } - .files-container.hide-files-not-to-review .file-container:not(.file-to-review-diff) { - /* Fade the header for files I don't have to review. */ - opacity: 0.2; + .pr-annotation.file-count, + .pr-annotation.build-status { + background: #fff4 !important; + min-width: 8ex; + }`); + + if (atNI) { + addStyleOnce('ni-labels', /* css */ ` + /* Known labels we should style. */ + .label--owners { + } + .label--draft { + background: #8808 !important; + } + .label--tiny { + background: #0a08 !important; + } + .label--bypassowners { + }`); + } + + addStyleOnce('bypassOwnersPrompt', /* css */ ` + .bypass-reminder { + display: inline; + position: absolute; + top: 38px; + left: -450px; + z-index: 1000; + background-color: #E6B307; + padding: 6px 12px; + border-radius: 6px; + box-shadow: 4px 4px 4px #18181888; + opacity: 0; + transition: 0.3s; } - .files-container.hide-files-not-to-review .file-container:not(.file-to-review-diff) .item-details-body { - /* Hide the diff for files I don't have to review. */ - display: none; + .bypass-reminder-container { + position: relative; + display: inline-flex; + flex-direction: column; } - .toolbar-button { - background: transparent; - color: var(--text-primary-color); - border: 1px solid transparent; - border-radius: 3px; - margin: 0px 2px; + .vote-button-wrapper { + border: 3px solid transparent; + border-radius: 4px; + transition: 0.3s; } - .toolbar-button:hover { - border: 1px solid var(--palette-black-alpha-20); + .vote-button-wrapper:hover { + border-color: #E6B307; } - .toolbar-button.active { - color: var(--communication-foreground); + .vote-button-wrapper:hover ~ .bypass-reminder { + opacity: 1; }`); - // Get the current iteration of the PR. - const prUrl = await getCurrentPullRequestUrlAsync(); - - // Get owners info for this PR. - const ownersInfo = await getNationalInstrumentsPullRequestOwnersInfo(prUrl); - const hasOwnersInfo = ownersInfo && ownersInfo.currentUserFileCount > 0; - - // If we have owners info, add a button to filter out diffs that we don't need to review. - if (hasOwnersInfo) { - $('.changed-files-summary-toolbar').once('add-other-files-button').each(function () { - $(this) - .find('ul') - .prepend('') - .click(event => { - $('.files-container').toggleClass('hide-files-not-to-review'); - }); + function styleLabels() { + // Give all tags a CSS class based on their name. + $('.tag-box').once('labels').each(function() { + const tagBox = $(this); + const subClass = stringToCssIdentifier(tagBox.text()); + tagBox.addClass(`label--${subClass}`); }); - } - - // If the user presses this button, it will auto-collapse folders in the files tree. Useful for large reviews. - let collapseFolderButtonClicks = 0; - const collapseFoldersButton = $(''); - updateButtonForCurrentState(button, isFlagged); - button.prependTo(this); - button.click(async function (event) { - const isNowFlagged = await toggleThreadFlaggedForNICodeOfTheDay(await getCurrentPullRequestUrlAsync(), { - flaggedDate: new Date().toISOString(), - flaggedBy: currentUser.uniqueName, - pullRequestId: getCurrentPullRequestId(), - threadId: thread.id, - file: thread.itemPath, - threadAuthor: thread.comments[0].author.displayName, - threadContentShort: truncate(thread.comments[0].content || thread.comments[0].newContent, 100), - }); + function getRepoNameFromUrl(url) { + const repoName = url.match(/_git\/(.+)\/pullrequests/)[1]; + return repoName || ''; + } - // Update the button visuals in this thread - updateButtonForCurrentState($(this).parents('.vc-discussion-comments').find('.cod-toggle'), isNowFlagged); - }); - }); - } + function addOrgPRLink() { + $('.bolt-header-title.title-m.l').once('decorate-with-org-pr-link').each(function() { + const titleElement = this; + titleElement.innerText = `${getRepoNameFromUrl(window.location.pathname)} ${titleElement.innerText}`; + const orgPRLink = document.createElement('a'); + orgPRLink.href = `${azdoApiBaseUrl}_pulls`; + orgPRLink.text = '→ View global PR dashboard'; + orgPRLink.style = 'margin: 15px; font-size: 80%; text-decoration: none; color: var(--communication-foreground,rgba(0, 90, 158, 1)); font-weight: normal'; + titleElement.insertAdjacentElement('beforeend', orgPRLink); + }); + } - addStyleOnce('pr-dashboard-css', /* css */ ` - table.repos-pr-list tbody > a { - transition: 0.2s; + function highlightAwaitComments() { + // Comments that start with this string are highlighted. No other behavior is given to them. + const lowerCasePrefix = 'await:'; + + addStyleOnce('highlight-await-comments', /* css */ ` + .vc-discussion-thread-box .vc-discussion-thread-comment .vc-discussion-thread-renderparent[content^="${lowerCasePrefix}" i] { + border: 2px solid rgb(var(--palette-accent3)); + border-radius: 5px; + margin: 7px 0px; + padding: 10px 15px; + }`); } - table.repos-pr-list tbody > a.voted-waiting > td > * { - opacity: 0.15; + + function applyStickyPullRequestComments() { + // Comments that start with this string become sticky. Only the first comment of the thread counts. + const lowerCasePrefix = 'note:'; + + addStyleOnce('sticky-comments', /* css */ ` + .vc-discussion-thread-box .vc-discussion-thread-comment:first-of-type .vc-discussion-thread-renderparent[content^="${lowerCasePrefix}" i] { + border: 2px solid var(--palette-black-alpha-20); + border-radius: 5px; + margin: 7px 0px; + padding: 10px 15px; + }`); + + // Expand threads that have the sticky prefix. + const lowerCasePrefixCssSelector = CSS.escape(`: "${lowerCasePrefix}`); + $('.discussion-thread-host').once('expand-sticky-threads-on-load').each(async function() { + await sleep(100); + const button = this.querySelector(`button.ms-Button.expand-button[aria-label*="${lowerCasePrefixCssSelector}" i]`); + if (button) { + button.click(); + } + }); } - .repos-pr-list-late-review-pill.outlined { - border-color: #f00; - border-color: var(--status-error-text,rgba(177, 133, 37, 1)); - color: #f00; - color: var(--status-error-text,rgba(177, 133, 37, 1)); - background: var(--status-error-background,rgba(177, 133, 37, 1)); - cursor: help; - }`); - - function watchPullRequestDashboard() { - eus.onUrl(/\/(_pulls|pullrequests)/gi, (session, urlMatch) => { - session.onEveryNew(document, '.repos-pr-section-card', section => { - const sectionTitle = section.querySelector('.repos-pr-section-header-title > span').innerText; - if (sectionTitle !== 'Assigned to me' && sectionTitle !== 'Created by me') return; - - session.onEveryNew(section, 'a[role="row"]', (row, addedDynamically) => { - // AzDO re-adds PR rows when it updates them with in JS. That's the one we want to enhance. - if (!addedDynamically) return; - - enhancePullRequestRow(row, sectionTitle); - - // React will re-use this DOM element, so we need to re-enhance. - session.onAnyChangeTo(row, () => enhancePullRequestRow(row, sectionTitle)); + + function addAccessKeysToPullRequestTabs() { + // Give all the tabs an access key equal to their numeric position on screen. + $('ul.vc-pullrequest-tabs a').once('add-accesskeys').each(function() { + $(this).attr('accesskey', $(this).attr('aria-posinset')); }); - }); - }); - } + } - async function enhancePullRequestRow(row, sectionTitle) { - const pullRequestUrl = new URL(row.href, window.location.origin); - const pullRequestId = parseInt(pullRequestUrl.pathname.substring(pullRequestUrl.pathname.lastIndexOf('/') + 1), 10); + function enhanceOverallUX() { + addStyleOnce('enhance-overall-ux', /* css */ ` + /* Colored scrollbars */ + ::-webkit-scrollbar { + width: 15px; + height: 15px; + } + ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { + background: rgb(var(--palette-neutral-4)); + } + ::-webkit-scrollbar-thumb { + background: rgb(var(--palette-neutral-20)); + } + /* Bigger dropdown menus */ + .identity-picker-dropdown ul.items, .scroll-tree-overflow-box, .ui-autocomplete, .vss-PickList--items { + max-height: 50vh !important; + } + /* Prompts to add links to work items are much less prominent, unless hovered over */ + .zero-data-action, .deployments-zero-data { + opacity: 0.2; + } + .zero-data-action img, .deployments-zero-data img, + .zero-data-action i, .deployments-zero-data i { + display: none; + } + .zero-data-action:hover, .deployments-zero-data:hover { + opacity: 1; + }`); + } - // Skip if we've already processed this PR. - if (row.dataset.pullRequestId === pullRequestId.toString()) return; - // eslint-disable-next-line no-param-reassign - row.dataset.pullRequestId = pullRequestId; + // Adds a bypass suggestion message that pops up when the user mouses over the Approve button. + async function conditionallyAddBypassReminderAsync() { + // Only add it if the target branch requires owner approval + if (!(await pullRequestHasRequiredOwnersPolicyAsync())) { + return; + } - // TODO: If you switch between Active and Reviewed too fast, you may get duplicate annotations. + if ($('.bypass-reminder-container').length > 0) { + return; + } - // Remove annotations a previous PR may have had. Recall that React reuses DOM elements. - row.classList.remove('voted-waiting'); - for (const element of row.querySelectorAll('.repos-pr-list-late-review-pill')) { - element.remove(); - } - for (const element of row.querySelectorAll('.userscript-bolt-pill-group')) { - element.remove(); - } - for (const element of row.querySelectorAll('.pr-annotation')) { - element.remove(); + const container = document.createElement('div'); + container.classList.add('bypass-reminder-container'); + + const banner = document.createElement('div'); + banner.classList.add('bypass-reminder'); + banner.appendChild(document.createTextNode('If you are confident the change needs no further review by others, please bypass owners.')); + + if ($('.repos-pr-header-vote-button').length === 0) { + // "old" PR experience + $('#pull-request-vote-button') + .parent() + .parent() + .addClass('vote-button-wrapper') + .appendTo(container); + container.appendChild(banner); + $('.vote-control-container').append(container); + } else { + // "new" PR experience + const voteButton = document.getElementsByClassName('repos-pr-header-vote-button')[0]; + + // We cannot change the parent of voteButton, or we get an error when pressing the approve button. + // Instead, we'll wedge our "container" div between the voteButton and its children. + // Because the voteButton's children will be moved under our container, we'll need to create a new wrapping element (by cloning the old parent) to keep them laid-out properly. + const buttonLayoutWrapper = voteButton.cloneNode(false); + buttonLayoutWrapper.classList.add('vote-button-wrapper'); + buttonLayoutWrapper.append(voteButton.children[0]); + buttonLayoutWrapper.append(voteButton.children[0]); + buttonLayoutWrapper.append(voteButton.children[0]); + + container.append(buttonLayoutWrapper); + container.append(banner); + + voteButton.append(container); + } } - const pr = await getPullRequestAsync(pullRequestId); + // Adds a "Trophies" section to the Overview tab of a PR for a qualifying PR number + function addTrophiesToPullRequest() { + // Pull request author is sometimes undefined on first call. Only add trophies if we can get the author name. + const pullRequestAuthor = $('div.ms-TooltipHost.host_e6f6b93f.created-by-label').children('span').text(); - // Sometimes, PRs lose their styling shortly after the page loads. A slight delay makes this problem go away, 99% of the time. Sucks -- but works and better to have this than not. - await sleep(333); + // Only create the trophies section once. + if ($('#trophies-section').length === 0 && pullRequestAuthor.length !== 0) { + const pullRequestId = getCurrentPullRequestId(); + let trophyAwarded = false; - if (sectionTitle === 'Assigned to me') { - const votes = countVotes(pr); + const trophiesLeftPaneSection = $('
').addClass('vc-pullrequest-leftpane-section').attr('id', 'trophies-section'); - // TODO: If you press the PR menu button, the PR loses it's styling. - row.classList.toggle('voted-waiting', votes.userVote === -5); + const sectionTitle = $('
').addClass('vc-pullrequest-leftpane-section-title').append('Trophies'); + const divider = $('
').addClass('divider'); + const sectionContent = $('
').addClass('policies-section'); - await annotateBugsOnPullRequestRow(row, pr); - await annotateFileCountOnPullRequestRow(row, pr); - await annotateBuildStatusOnPullRequestRow(row, pr); + trophiesLeftPaneSection + .append(sectionTitle) + .append(divider) + .append(sectionContent); - if (votes.userVote === 0 && votes.missingVotes === 1) { - annotatePullRequestTitle(row, 'repos-pr-list-late-review-pill', 'Last Reviewer', 'Everyone is waiting on you!'); - } + // Milestone trophy: Awarded if pull request ID is greater than 1000 and is a non-zero digit followed by only zeroes (e.g. 1000, 5000, 10000). + if (pullRequestId >= 1000 && pullRequestId.match('^[1-9]0+$')) { + const milestoneTrophyMessage = $('
)').text(`${pullRequestAuthor} got pull request #${pullRequestId}!`); + sectionContent.append(milestoneTrophyMessage.prepend(' 🏆 ')); + trophyAwarded = true; + } - if (atNI && votes.userVote === 0) { - const prThreadsNewestFirst = (await $.get(`${pr.url}/threads?api-version=5.0`)).value.filter(x => !x.isDeleted).reverse(); - const dateAdded = getReviewerAddedOrResetTime(prThreadsNewestFirst, currentUser.uniqueName) || pr.createdDate; - const weekDays = differenceInWeekDays(new Date(dateAdded), new Date()); - if (weekDays >= 1) { - const lastInteraction = getReviewerLastInteractionTime(prThreadsNewestFirst, currentUser.uniqueName); - if (!lastInteraction || new Date(dateAdded) > new Date(lastInteraction)) { - annotatePullRequestTitle(row, 'repos-pr-list-late-review-pill', `${weekDays} days old`, "# of week days since you've been added or reset. Reviewers are expected to comment or vote within 1 business day."); - } - } - } - } else { - await annotateBugsOnPullRequestRow(row, pr); - await annotateFileCountOnPullRequestRow(row, pr); - await annotateBuildStatusOnPullRequestRow(row, pr); - } - } - - function differenceInWeekDays(startDate, endDate) { - let days = (endDate - startDate) / (1000.0 * 60 * 60 * 24); - const date = new Date(startDate); - while (date <= endDate) { - if (date.getDay() === 0 || date.getDay() === 6) { - days -= 1.0; - } - date.setDate(date.getDate() + 1); - } - return days < 0 ? 0 : days.toFixed(1); - } - - function getReviewerAddedOrResetTime(prThreadsNewestFirst, reviewerUniqueName) { - for (const thread of prThreadsNewestFirst) { - if (thread.properties) { - if (Object.prototype.hasOwnProperty.call(thread.properties, 'CodeReviewReviewersUpdatedAddedIdentity')) { - const addedReviewer = thread.identities[thread.properties.CodeReviewReviewersUpdatedAddedIdentity.$value]; - if (addedReviewer.uniqueName === reviewerUniqueName) { - return thread.publishedDate; - } - } else if (Object.prototype.hasOwnProperty.call(thread.properties, 'CodeReviewResetMultipleVotesExampleVoterIdentities')) { - if (Object.keys(thread.identities).filter(x => thread.identities[x].uniqueName === reviewerUniqueName)) { - return thread.publishedDate; - } - } - } - } - return null; - } - - function getReviewerLastInteractionTime(prThreadsNewestFirst, reviewerUniqueName) { - for (const thread of prThreadsNewestFirst) { - // This includes both user comments, threads, and votes (since votes post comments). - for (const comment of thread.comments) { - if (comment.author.uniqueName === reviewerUniqueName) { - return comment.publishedDate; + // Fish trophy: Give a man a fish, he'll waste hours trying to figure out why. (Awarded if the ID is a palindrome.) + if (pullRequestId === pullRequestId.split('').reverse().join('')) { + const fishTrophyMessage = $('
)').text(`${pullRequestAuthor} got a fish trophy!`); + sectionContent.append(fishTrophyMessage.prepend(' 🐠 ')); + trophyAwarded = true; + } + + // Add the trophy section to the Overview tab pane only if a trophy has been awarded. + if (trophyAwarded) { + $('div.overview-tab-pane').append(trophiesLeftPaneSection); + } } - } - } - return null; - } - - function countVotes(pr) { - const votes = { - missingVotes: 0, - waitingOrRejectedVotes: 0, - userVote: 0, - }; - - for (const reviewer of pr.reviewers) { - if (reviewer.uniqueName === currentUser.uniqueName) { - votes.userVote = reviewer.vote; - } - if (reviewer.vote === 0) { - votes.missingVotes += 1; - } else if (reviewer.vote < 0) { - votes.waitingOrRejectedVotes += 1; - } } - return votes; - } - - async function annotateBugsOnPullRequestRow(row, pr) { - const workItemRefs = (await $.get(`${pr.url}/workitems?api-version=5.1`)).value; - let highestSeverityBug = null; - let highestSeverity = 100; // highest sev is lowest number - let otherHighestSeverityBugsCount = 0; - - for (const workItemRef of workItemRefs) { - // eslint-disable-next-line no-await-in-loop - const workItem = await $.get(`${workItemRef.url}?api-version=5.1`); - if (workItem.fields['System.WorkItemType'] === 'Bug') { - const severityString = workItem.fields['Microsoft.VSTS.Common.Severity']; - if (severityString) { - const severity = parseInt(severityString.replace(/ - .*$/, ''), 10); - if (severity < highestSeverity) { // lower severity value is higher severity - highestSeverity = severity; - highestSeverityBug = workItem; - otherHighestSeverityBugsCount = 0; - } else if (severity === highestSeverity) { - otherHighestSeverityBugsCount += 1; - } - } - } + function makePullRequestDiffEasierToScroll() { + addStyleOnce('pr-diff-improvements', /* css */ ` + .vc-change-summary-files .file-container { + /* Make the divs float but clear them so they get stacked on top of each other. We float so that the divs expand to take up the width of the text in it. Finally, we remove the overflow property so that they don't have scrollbars and also such that we can have sticky elements (apparently, sticky elements don't work if the div has overflow). */ + float: left; + clear: both; + min-width: 95%; + overflow: initial; + } + .vc-change-summary-files .file-row { + /* Let the file name section of each diff stick to the top of the page if we're scrolling. */ + position: sticky; + top: 0; + z-index: 100000; + padding-bottom: 10px; + background: var(--background-color,rgba(255, 255, 255, 1)); + } + .vc-change-summary-files .vc-diff-viewer { + /* We borrowed padding from the diff to give to the bottom of the file row. So adjust accordingly (this value was originally 20px). */ + padding-top: 10px; + }`); } - if (highestSeverityBug && highestSeverity <= 2) { - let title = highestSeverityBug.fields['System.Title']; - if (otherHighestSeverityBugsCount) { - title += ` (and ${otherHighestSeverityBugsCount} other)`; - } + // The func we'll call to continuously add checkboxes to the PR file listing, once initialization is over. + let annotateFilesTreeFunc = () => {}; + + // If we're on specific PR, add checkboxes to the file listing. + function addOwnersInfoToFiles() { + $('.vc-pullrequest-leftpane-section.files-tab').once('annotate-with-owners-info').each(async() => { + annotateFilesTreeFunc = () => {}; + + addStyleOnce('pr-file-tree-annotations-css', /* css */ ` + :root { + /* Set some constants for our CSS. */ + --file-to-review-color: var(--communication-foreground); + } + .vc-sparse-files-tree .tree-row.file-to-review-row, + .vc-sparse-files-tree .tree-row.file-to-review-row .file-name { + /* Highlight files I need to review. */ + color: var(--file-to-review-color); + transition-duration: 0.2s; + } + .vc-sparse-files-tree .tree-row.folder-to-review-row[aria-expanded='false'], + .vc-sparse-files-tree .tree-row.folder-to-review-row[aria-expanded='false'] .file-name { + /* Highlight folders that have files I need to review, but only when files are hidden cause the folder is collapsed. */ + color: var(--file-to-review-color); + transition-duration: 0.2s; + } + .vc-sparse-files-tree .tree-row.file-to-review-row .file-owners-role { + /* Style the role of the user in the files table. */ + font-weight: bold; + padding: 7px 10px; + position: absolute; + z-index: 100; + float: right; + } + .file-to-review-diff { + /* Highlight files I need to review. */ + border-left: 3px solid var(--file-to-review-color) !important; + padding-left: 7px; + } + .files-container.hide-files-not-to-review .file-container:not(.file-to-review-diff) { + /* Fade the header for files I don't have to review. */ + opacity: 0.2; + } + .files-container.hide-files-not-to-review .file-container:not(.file-to-review-diff) .item-details-body { + /* Hide the diff for files I don't have to review. */ + display: none; + } + .toolbar-button { + background: transparent; + color: var(--text-primary-color); + border: 1px solid transparent; + border-radius: 3px; + margin: 0px 2px; + } + .toolbar-button:hover { + border: 1px solid var(--palette-black-alpha-20); + } + .toolbar-button.active { + color: var(--communication-foreground); + }`); + + // Get the current iteration of the PR. + const prUrl = await getCurrentPullRequestUrlAsync(); + + // Get owners info for this PR. + const ownersInfo = await getNationalInstrumentsPullRequestOwnersInfo(prUrl); + const hasOwnersInfo = ownersInfo && ownersInfo.currentUserFileCount > 0; + + // If we have owners info, add a button to filter out diffs that we don't need to review. + if (hasOwnersInfo) { + $('.changed-files-summary-toolbar').once('add-other-files-button').each(function() { + $(this) + .find('ul') + .prepend('') + .click(_event => { + $('.files-container').toggleClass('hide-files-not-to-review'); + }); + }); + } - annotatePullRequestLabel(row, `pr-bug-severity-${highestSeverity}`, title, `SEV${highestSeverity}`); - } - } - - async function annotateFileCountOnPullRequestRow(row, pr) { - let fileCount; - - if (pr.lastMergeCommit) { - fileCount = 0; - - // See if this PR has owners info and count the files listed for the current user. - const ownersInfo = await getNationalInstrumentsPullRequestOwnersInfo(pr.url); - if (ownersInfo) { - fileCount = ownersInfo.currentUserFileCount; - } - - // If there is no owner info or if it returns zero files to review (since we may not be on the review explicitly), then count the number of files in the merge commit. - if (fileCount === 0) { - const mergeCommitInfo = await $.get(`${pr.lastMergeCommit.url}/changes?api-version=5.0`); - const files = _(mergeCommitInfo.changes).filter(item => !item.item.isFolder); - fileCount = files.size(); - } - } else { - fileCount = '⛔'; + // If the user presses this button, it will auto-collapse folders in the files tree. Useful for large reviews. + let collapseFolderButtonClicks = 0; + const collapseFoldersButton = $(''); + updateButtonForCurrentState(button, isFlagged); + button.prependTo(this); + button.click(async function(_event) { + const isNowFlagged = await toggleThreadFlaggedForNICodeOfTheDay(await getCurrentPullRequestUrlAsync(), { + flaggedDate: new Date().toISOString(), + flaggedBy: currentUser.uniqueName, + pullRequestId: getCurrentPullRequestId(), + threadId: thread.id, + file: thread.itemPath, + threadAuthor: thread.comments[0].author.displayName, + threadContentShort: truncate(thread.comments[0].content || thread.comments[0].newContent, 100), + }); + + // Update the button visuals in this thread + updateButtonForCurrentState($(this).parents('.vc-discussion-comments').find('.cod-toggle'), isNowFlagged); + }); + }); + } - .hljs-built_in, - .hljs-type { - color: #4ec9b0; + addStyleOnce('pr-dashboard-css', /* css */ ` + table.repos-pr-list tbody > a { + transition: 0.2s; } - - .hljs-class, - .hljs-number { - color: #b8d7a3; + table.repos-pr-list tbody > a.voted-waiting > td > * { + opacity: 0.15; } + .repos-pr-list-late-review-pill.outlined { + border-color: #f00; + border-color: var(--status-error-text,rgba(177, 133, 37, 1)); + color: #f00; + color: var(--status-error-text,rgba(177, 133, 37, 1)); + background: var(--status-error-background,rgba(177, 133, 37, 1)); + cursor: help; + }`); - .hljs-meta-string, - .hljs-string { - color: #d69d85; - } + function watchPullRequestDashboard() { + eus.onUrl(/\/(_pulls|pullrequests)/gi, (session, _urlMatch) => { + session.onEveryNew(document, '.repos-pr-section-card', section => { + const sectionTitle = section.querySelector('.repos-pr-section-header-title > span').innerText; + if (sectionTitle !== 'Assigned to me' && sectionTitle !== 'Created by me') return; - .hljs-regexp, - .hljs-template-tag { - color: #9a5334; - } + session.onEveryNew(section, 'a[role="row"]', (row, addedDynamically) => { + // AzDO re-adds PR rows when it updates them with in JS. That's the one we want to enhance. + if (!addedDynamically) return; - .hljs-formula, - .hljs-function, - .hljs-params, - .hljs-subst, - .hljs-title { - color: var(--text-primary-color, rgba(0, 0, 0, .7)); - } + enhancePullRequestRow(row, sectionTitle); - .hljs-comment, - .hljs-quote { - color: #57a64a; - font-style: italic; - } + // React will re-use this DOM element, so we need to re-enhance. + session.onAnyChangeTo(row, () => enhancePullRequestRow(row, sectionTitle)); + }); + }); + }); + } - .hljs-doctag { - color: #608b4e; - } + async function enhancePullRequestRow(row, sectionTitle) { + const pullRequestUrl = new URL(row.href, window.location.origin); + const pullRequestId = parseInt(pullRequestUrl.pathname.substring(pullRequestUrl.pathname.lastIndexOf('/') + 1), 10); + + // Skip if we've already processed this PR. + if (row.dataset.pullRequestId === pullRequestId.toString()) return; + // eslint-disable-next-line no-param-reassign + row.dataset.pullRequestId = pullRequestId; - .hljs-meta, - .hljs-meta-keyword, - .hljs-tag { - color: #9b9b9b; + // TODO: If you switch between Active and Reviewed too fast, you may get duplicate annotations. + + // Remove annotations a previous PR may have had. Recall that React reuses DOM elements. + row.classList.remove('voted-waiting'); + for (const element of row.querySelectorAll('.repos-pr-list-late-review-pill')) { + element.remove(); } - .hljs-meta-keyword { - font-weight: bold; + for (const element of row.querySelectorAll('.userscript-bolt-pill-group')) { + element.remove(); } - - .hljs-template-variable, - .hljs-variable { - color: #bd63c5; + for (const element of row.querySelectorAll('.pr-annotation')) { + element.remove(); } - .hljs-attr, - .hljs-attribute, - .hljs-builtin-name { - color: #9cdcfe; - } + const pr = await getPullRequestAsync(pullRequestId); + + // Sometimes, PRs lose their styling shortly after the page loads. A slight delay makes this problem go away, 99% of the time. Sucks -- but works and better to have this than not. + await sleep(333); + + if (sectionTitle === 'Assigned to me') { + const votes = countVotes(pr); + + // TODO: If you press the PR menu button, the PR loses it's styling. + row.classList.toggle('voted-waiting', votes.userVote === -5); + + await annotateBugsOnPullRequestRow(row, pr); + await annotateFileCountOnPullRequestRow(row, pr); + await annotateBuildStatusOnPullRequestRow(row, pr); - .hljs-section { - color: gold; + if (votes.userVote === 0 && votes.missingVotes === 1) { + annotatePullRequestTitle(row, 'repos-pr-list-late-review-pill', 'Last Reviewer', 'Everyone is waiting on you!'); + } + + if (atNI && votes.userVote === 0) { + const prThreadsNewestFirst = (await $.get(`${pr.url}/threads?api-version=5.0`)).value.filter(x => !x.isDeleted).reverse(); + const dateAdded = getReviewerAddedOrResetTime(prThreadsNewestFirst, currentUser.uniqueName) || pr.createdDate; + const weekDays = differenceInWeekDays(new Date(dateAdded), new Date()); + if (weekDays >= 1) { + const lastInteraction = getReviewerLastInteractionTime(prThreadsNewestFirst, currentUser.uniqueName); + if (!lastInteraction || new Date(dateAdded) > new Date(lastInteraction)) { + annotatePullRequestTitle(row, 'repos-pr-list-late-review-pill', `${weekDays} days old`, "# of week days since you've been added or reset. Reviewers are expected to comment or vote within 1 business day."); + } + } + } + } else { + await annotateBugsOnPullRequestRow(row, pr); + await annotateFileCountOnPullRequestRow(row, pr); + await annotateBuildStatusOnPullRequestRow(row, pr); } + } - .hljs-emphasis { - font-style: italic; + function differenceInWeekDays(startDate, endDate) { + let days = (endDate - startDate) / (1000.0 * 60 * 60 * 24); + const date = new Date(startDate); + while (date <= endDate) { + if (date.getDay() === 0 || date.getDay() === 6) { + days -= 1.0; + } + date.setDate(date.getDate() + 1); } + return days < 0 ? 0 : days.toFixed(1); + } - .hljs-strong { - font-weight: 700; + function getReviewerAddedOrResetTime(prThreadsNewestFirst, reviewerUniqueName) { + for (const thread of prThreadsNewestFirst) { + if (thread.properties) { + if (Object.prototype.hasOwnProperty.call(thread.properties, 'CodeReviewReviewersUpdatedAddedIdentity')) { + const addedReviewer = thread.identities[thread.properties.CodeReviewReviewersUpdatedAddedIdentity.$value]; + if (addedReviewer.uniqueName === reviewerUniqueName) { + return thread.publishedDate; + } + } else if (Object.prototype.hasOwnProperty.call(thread.properties, 'CodeReviewResetMultipleVotesExampleVoterIdentities')) { + if (Object.keys(thread.identities).filter(x => thread.identities[x].uniqueName === reviewerUniqueName)) { + return thread.publishedDate; + } + } + } } + return null; + } - .hljs-bullet, - .hljs-selector-attr, - .hljs-selector-class, - .hljs-selector-id, - .hljs-selector-pseudo, - .hljs-selector-tag { - color: #d7ba7d; + function getReviewerLastInteractionTime(prThreadsNewestFirst, reviewerUniqueName) { + for (const thread of prThreadsNewestFirst) { + // This includes both user comments, threads, and votes (since votes post comments). + for (const comment of thread.comments) { + if (comment.author.uniqueName === reviewerUniqueName) { + return comment.publishedDate; + } + } } + return null; + } + + function countVotes(pr) { + const votes = { + missingVotes: 0, + waitingOrRejectedVotes: 0, + userVote: 0, + }; - .hljs-addition { - background-color: #144212; - display: inline-block; - width: 100%; + for (const reviewer of pr.reviewers) { + if (reviewer.uniqueName === currentUser.uniqueName) { + votes.userVote = reviewer.vote; + } + if (reviewer.vote === 0) { + votes.missingVotes += 1; + } else if (reviewer.vote < 0) { + votes.waitingOrRejectedVotes += 1; + } } - .hljs-deletion { - background-color: #600; - display: inline-block; - width: 100%; - }`); - } else { - addStyleOnce('highlight', ` - .hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-comment,.hljs-quote,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag{color:#00f}.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type{color:#a31515}.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo{color:#2b91af}.hljs-doctag{color:grey}.hljs-attr{color:red}.hljs-bullet,.hljs-link,.hljs-symbol{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} - `); + return votes; } - eus.onUrl(/\/pullrequest\//gi, (session, urlMatch) => { - let languageDefinitions = null; - session.onEveryNew(document, '.text-diff-container', diff => { - if (eus.seen(diff)) return; - - if (!languageDefinitions) { - languageDefinitions = parseLanguageDefinitions(); + async function annotateBugsOnPullRequestRow(row, pr) { + const workItemRefs = (await $.get(`${pr.url}/workitems?api-version=5.1`)).value; + let highestSeverityBug = null; + let highestSeverity = 100; // highest sev is lowest number + let otherHighestSeverityBugsCount = 0; + + for (const workItemRef of workItemRefs) { + // eslint-disable-next-line no-await-in-loop + const workItem = await $.get(`${workItemRef.url}?api-version=5.1`); + if (workItem.fields['System.WorkItemType'] === 'Bug') { + const severityString = workItem.fields['Microsoft.VSTS.Common.Severity']; + if (severityString) { + const severity = parseInt(severityString.replace(/ - .*$/, ''), 10); + if (severity < highestSeverity) { // lower severity value is higher severity + highestSeverity = severity; + highestSeverityBug = workItem; + otherHighestSeverityBugsCount = 0; + } else if (severity === highestSeverity) { + otherHighestSeverityBugsCount += 1; + } + } + } } - // TODO: Handle new PR experience. + if (highestSeverityBug && highestSeverity <= 2) { + let title = highestSeverityBug.fields['System.Title']; + if (otherHighestSeverityBugsCount) { + title += ` (and ${otherHighestSeverityBugsCount} other)`; + } + + annotatePullRequestLabel(row, `pr-bug-severity-${highestSeverity}`, title, `SEV${highestSeverity}`); + } + } - session.onFirst(diff.closest('.file-container'), '.file-cell .file-name-link', fileNameLink => { - const fileName = fileNameLink.innerText.toLowerCase(); - const extension = getFileExt(fileName); + async function annotateFileCountOnPullRequestRow(row, pr) { + let fileCount; - const leftPane = diff.querySelector('.leftPane > div > .side-by-side-diff-container'); - const rightOrUnifiedPane = diff.querySelector('.rightPane > div > .side-by-side-diff-container') || diff; + if (pr.lastMergeCommit) { + fileCount = 0; - // Guess our language based on our file extension. The GitHub language definition keywords and the highlight.js language keywords are different, and may not match. This loop is a heuristic to find a language match. - // Supports languages listed here, without plugins: https://github.com/highlightjs/highlight.js/blob/master/SUPPORTED_LANGUAGES.md - let language = null; - for (const mode of [extension].concat(languageDefinitions.extensionToMode[extension]).concat(languageDefinitions.fileToMode[fileName])) { - if (hljs.getLanguage(mode)) { - language = mode; - break; + // See if this PR has owners info and count the files listed for the current user. + const ownersInfo = await getNationalInstrumentsPullRequestOwnersInfo(pr.url); + if (ownersInfo) { + fileCount = ownersInfo.currentUserFileCount; } - } - // If we still don't have a language, try to guess it based on the code. - if (!language) { - let code = ''; - for (const line of rightOrUnifiedPane.querySelectorAll('.code-line:not(.deleted-content)')) { - code += `${line.innerText}\n`; + // If there is no owner info or if it returns zero files to review (since we may not be on the review explicitly), then count the number of files in the merge commit. + if (fileCount === 0) { + const mergeCommitInfo = await $.get(`${pr.lastMergeCommit.url}/changes?api-version=5.0`); + const files = _(mergeCommitInfo.changes).filter(item => !item.item.isFolder); + fileCount = files.size(); } - // eslint-disable-next-line prefer-destructuring - language = hljs.highlightAuto(code).language; - } - - // If we have a language, highlight it :) - if (language) { - highlightDiff(language, fileName, 'left', leftPane, '.code-line'); - highlightDiff(language, fileName, 'right/unified', rightOrUnifiedPane, '.code-line:not(.deleted-content)'); - } - }); - }); - }); - } - - // Gets GitHub language definitions to parse extensions and filenames to a "mode" that we can try with highlight.js. - function parseLanguageDefinitions() { - const languages = jsyaml.load(GM_getResourceText('linguistLanguagesYml')); - const extensionToMode = {}; - const fileToMode = {}; - - for (const language of Object.values(languages)) { - const mode = [getFileExt(language.tm_scope), language.ace_mode]; - if (language.extensions) { - for (const extension of language.extensions) { - extensionToMode[extension.substring(1)] = mode; + } else { + fileCount = '⛔'; } - } - if (language.filenames) { - for (const filename of language.filenames) { - fileToMode[filename.toLowerCase()] = mode; + + const label = ` ${fileCount}`; + annotatePullRequestLabel(row, 'file-count', '# of files you need to review', label); + } + + async function annotateBuildStatusOnPullRequestRow(row, pr) { + if (!pr.lastMergeCommit) return; + + const builds = (await $.get(`${pr.lastMergeCommit.url}/statuses?api-version=5.1&latestOnly=true`)).value; + if (!builds) return; + + let state; + if (builds.every(b => b.state === 'succeeded' || b.description.includes('partially succeeded'))) { + state = '✔️'; + } else if (builds.some(b => b.state === 'pending')) { + state = '▶️'; + } else { + state = '❌'; } - } + + const tooltip = _.map(builds, 'description').join('\n'); + const label = ` ${state}`; + annotatePullRequestLabel(row, 'build-status', tooltip, label); } - // For debugging: console.debug(`Supporting ${Object.keys(extensionToMode).length} extensions and ${Object.keys(fileToMode).length} special filenames`); - return { extensionToMode, fileToMode }; - } + function annotatePullRequestTitle(row, cssClass, message, tooltip) { + const blockingAnnotation = ` + `; + const title = row.querySelector('.body-l'); + title.insertAdjacentHTML('afterend', blockingAnnotation); + } - function highlightDiff(language, fileName, part, diffContainer, selector) { - if (!diffContainer) return; + function annotatePullRequestLabel(pullRequestRow, cssClass, title, html) { + let labels = pullRequestRow.querySelector('.bolt-pill-group-inner'); + + // The PR may not have any labels to begin with, so we have to construct the label container. + if (!labels) { + const labelContainer = $(` +
+
+
+
+
+
+
`)[0]; + pullRequestRow.querySelector('.body-l').insertAdjacentElement('afterend', labelContainer); + labels = pullRequestRow.querySelector('.bolt-pill-group-inner'); + } - // For debugging: console.debug(`Highlighting ${part} of <${fileName}> as ${language}`); + const label = ` + `; + labels.insertAdjacentHTML('beforeend', label); + } - let stack = null; - for (const line of diffContainer.querySelectorAll(selector)) { - const result = hljs.highlight(language, line.innerText, true, stack); - stack = result.top; + function watchForNewDiffs(isDarkTheme) { + if (isDarkTheme) { + addStyleOnce('highlight', /* css */ ` + .hljs { + display: block; + overflow-x: auto; + background: #1e1e1e; + color: #dcdcdc; + } + + .hljs-keyword, + .hljs-literal, + .hljs-name, + .hljs-symbol { + color: #569cd6; + } + + .hljs-link { + color: #569cd6; + text-decoration: underline; + } + + .hljs-built_in, + .hljs-type { + color: #4ec9b0; + } + + .hljs-class, + .hljs-number { + color: #b8d7a3; + } + + .hljs-meta-string, + .hljs-string { + color: #d69d85; + } + + .hljs-regexp, + .hljs-template-tag { + color: #9a5334; + } + + .hljs-formula, + .hljs-function, + .hljs-params, + .hljs-subst, + .hljs-title { + color: var(--text-primary-color, rgba(0, 0, 0, .7)); + } + + .hljs-comment, + .hljs-quote { + color: #57a64a; + font-style: italic; + } + + .hljs-doctag { + color: #608b4e; + } + + .hljs-meta, + .hljs-meta-keyword, + .hljs-tag { + color: #9b9b9b; + } + .hljs-meta-keyword { + font-weight: bold; + } + + .hljs-template-variable, + .hljs-variable { + color: #bd63c5; + } + + .hljs-attr, + .hljs-attribute, + .hljs-builtin-name { + color: #9cdcfe; + } + + .hljs-section { + color: gold; + } + + .hljs-emphasis { + font-style: italic; + } + + .hljs-strong { + font-weight: 700; + } + + .hljs-bullet, + .hljs-selector-attr, + .hljs-selector-class, + .hljs-selector-id, + .hljs-selector-pseudo, + .hljs-selector-tag { + color: #d7ba7d; + } + + .hljs-addition { + background-color: #144212; + display: inline-block; + width: 100%; + } + + .hljs-deletion { + background-color: #600; + display: inline-block; + width: 100%; + }`); + } else { + addStyleOnce('highlight', /* css */ ` + .hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-comment,.hljs-quote,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag{color:#00f}.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type{color:#a31515}.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo{color:#2b91af}.hljs-doctag{color:grey}.hljs-attr{color:red}.hljs-bullet,.hljs-link,.hljs-symbol{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}`); + } - // We must add the extra span at the end or sometimes, when adding a comment to a line, the highlighting will go away. - line.innerHTML = `${result.value}`; + eus.onUrl(/\/pullrequest\//gi, (session, _urlMatch) => { + let languageDefinitions = null; + session.onEveryNew(document, '.text-diff-container', diff => { + if (eus.seen(diff)) return; + + if (!languageDefinitions) { + languageDefinitions = parseLanguageDefinitions(); + } + + // TODO: Handle new PR experience. + + session.onFirst(diff.closest('.file-container'), '.file-cell .file-name-link', fileNameLink => { + const fileName = fileNameLink.innerText.toLowerCase(); + const extension = getFileExt(fileName); + + const leftPane = diff.querySelector('.leftPane > div > .side-by-side-diff-container'); + const rightOrUnifiedPane = diff.querySelector('.rightPane > div > .side-by-side-diff-container') || diff; + + // Guess our language based on our file extension. The GitHub language definition keywords and the highlight.js language keywords are different, and may not match. This loop is a heuristic to find a language match. + // Supports languages listed here, without plugins: https://github.com/highlightjs/highlight.js/blob/master/SUPPORTED_LANGUAGES.md + let language = null; + for (const mode of [extension].concat(languageDefinitions.extensionToMode[extension]).concat(languageDefinitions.fileToMode[fileName])) { + if (hljs.getLanguage(mode)) { + language = mode; + break; + } + } + + // If we still don't have a language, try to guess it based on the code. + if (!language) { + let code = ''; + for (const line of rightOrUnifiedPane.querySelectorAll('.code-line:not(.deleted-content)')) { + code += `${line.innerText}\n`; + } + language = hljs.highlightAuto(code).language; + } + + // If we have a language, highlight it :) + if (language) { + highlightDiff(language, fileName, 'left', leftPane, '.code-line'); + highlightDiff(language, fileName, 'right/unified', rightOrUnifiedPane, '.code-line:not(.deleted-content)'); + } + }); + }); + }); + } - // We must wrap all text in spans for the comment highlighting to work. - for (let i = line.childNodes.length - 1; i > -1; i -= 1) { - const fragment = line.childNodes[i]; - if (fragment.nodeType === Node.TEXT_NODE) { - const span = document.createElement('span'); - span.innerText = fragment.textContent; - fragment.parentNode.replaceChild(span, fragment); + // Gets GitHub language definitions to parse extensions and filenames to a "mode" that we can try with highlight.js. + function parseLanguageDefinitions() { + const languages = jsyaml.load(GM_getResourceText('linguistLanguagesYml')); + const extensionToMode = {}; + const fileToMode = {}; + + for (const language of Object.values(languages)) { + const mode = [getFileExt(language.tm_scope), language.ace_mode]; + if (language.extensions) { + for (const extension of language.extensions) { + extensionToMode[extension.substring(1)] = mode; + } + } + if (language.filenames) { + for (const filename of language.filenames) { + fileToMode[filename.toLowerCase()] = mode; + } + } } - } + + // For debugging: console.debug(`Supporting ${Object.keys(extensionToMode).length} extensions and ${Object.keys(fileToMode).length} special filenames`); + return { + extensionToMode, + fileToMode + }; } - } - // Helper function to get the file extension out of a file path; e.g. `cs` from `blah.cs`. - function getFileExt(path) { - return /(?:\.([^.]+))?$/.exec(path)[1]; - } + function highlightDiff(language, _fileName, _part, diffContainer, selector) { + if (!diffContainer) return; - // Helper function to avoid adding CSS twice into a document. - function addStyleOnce(id, style) { - $(document.head).once(id).each(function () { - $('