diff --git a/.editorconfig b/.editorconfig
index 0f1786729..5d1263484 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,9 +1,13 @@
+# editorconfig.org
root = true
[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 2
indent_style = space
-insert_final_newline = true
+indent_size = 2
+end_of_line = lf
+charset = utf-8
trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.eslintrc.js b/.eslintrc.js
index d262d9909..8ff448efd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,6 +1,20 @@
module.exports = {
- "extends": "airbnb-base",
- "rules": {
- "no-param-reassign": 0
- }
-};
+ root: true,
+ env: {
+ browser: true,
+ node: true
+ },
+ parserOptions: {
+ parser: 'babel-eslint'
+ },
+ extends: [
+ '@nuxtjs',
+ 'prettier',
+ 'prettier/vue',
+ 'plugin:prettier/recommended',
+ 'plugin:nuxt/recommended'
+ ],
+ plugins: [
+ 'prettier'
+ ],
+}
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 000000000..59639c50d
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": false,
+ "arrowParens": "always",
+ "singleQuote": true
+}
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
deleted file mode 100644
index 221001f31..000000000
--- a/npm-shrinkwrap.json
+++ /dev/null
@@ -1,1781 +0,0 @@
-{
- "requires": true,
- "lockfileVersion": 1,
- "dependencies": {
- "acorn": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz",
- "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==",
- "dev": true
- },
- "acorn-jsx": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
- "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
- "dev": true,
- "requires": {
- "acorn": "^3.0.4"
- },
- "dependencies": {
- "acorn": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
- "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
- "dev": true
- }
- }
- },
- "ajv": {
- "version": "5.5.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
- "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
- "dev": true,
- "requires": {
- "co": "^4.6.0",
- "fast-deep-equal": "^1.0.0",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.3.0"
- }
- },
- "ajv-keywords": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
- "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
- "dev": true
- },
- "ansi-escapes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
- "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
- "dev": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "array-union": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
- "dev": true,
- "requires": {
- "array-uniq": "^1.0.1"
- }
- },
- "array-uniq": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
- "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
- "dev": true
- },
- "arrify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
- "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
- "dev": true
- },
- "assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true
- },
- "babel-code-frame": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
- "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "esutils": "^2.0.2",
- "js-tokens": "^3.0.2"
- },
- "dependencies": {
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "browser-stdout": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
- "dev": true
- },
- "buffer-from": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
- "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
- "dev": true
- },
- "builtin-modules": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
- "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
- "dev": true
- },
- "caller-path": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
- "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
- "dev": true,
- "requires": {
- "callsites": "^0.2.0"
- }
- },
- "callsites": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
- "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
- "dev": true
- },
- "chai": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz",
- "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=",
- "dev": true,
- "requires": {
- "assertion-error": "^1.0.1",
- "check-error": "^1.0.1",
- "deep-eql": "^3.0.0",
- "get-func-name": "^2.0.0",
- "pathval": "^1.0.0",
- "type-detect": "^4.0.0"
- }
- },
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- }
- }
- },
- "chardet": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
- "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
- "dev": true
- },
- "check-error": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
- "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
- "dev": true
- },
- "circular-json": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
- "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
- "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=",
- "dev": true,
- "requires": {
- "restore-cursor": "^2.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
- },
- "co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
- "dev": true
- },
- "color-convert": {
- "version": "1.9.2",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
- "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.1"
- }
- },
- "color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
- "dev": true
- },
- "commander": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
- "contains-path": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
- "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
- "dev": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true
- },
- "cross-spawn": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
- "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
- "dev": true,
- "requires": {
- "lru-cache": "^4.0.1",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
- "dev": true,
- "requires": {
- "type-detect": "^4.0.0"
- }
- },
- "deep-is": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
- "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
- "dev": true
- },
- "define-properties": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
- "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
- "dev": true,
- "requires": {
- "foreach": "^2.0.5",
- "object-keys": "^1.0.8"
- }
- },
- "del": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
- "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
- "dev": true,
- "requires": {
- "globby": "^5.0.0",
- "is-path-cwd": "^1.0.0",
- "is-path-in-cwd": "^1.0.0",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "rimraf": "^2.2.8"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
- "dev": true
- },
- "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"
- }
- },
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "es-abstract": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
- "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.1.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.1",
- "is-callable": "^1.1.3",
- "is-regex": "^1.0.4"
- }
- },
- "es-to-primitive": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
- "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.1",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.1"
- }
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "eslint": {
- "version": "4.19.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
- "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
- "dev": true,
- "requires": {
- "ajv": "^5.3.0",
- "babel-code-frame": "^6.22.0",
- "chalk": "^2.1.0",
- "concat-stream": "^1.6.0",
- "cross-spawn": "^5.1.0",
- "debug": "^3.1.0",
- "doctrine": "^2.1.0",
- "eslint-scope": "^3.7.1",
- "eslint-visitor-keys": "^1.0.0",
- "espree": "^3.5.4",
- "esquery": "^1.0.0",
- "esutils": "^2.0.2",
- "file-entry-cache": "^2.0.0",
- "functional-red-black-tree": "^1.0.1",
- "glob": "^7.1.2",
- "globals": "^11.0.1",
- "ignore": "^3.3.3",
- "imurmurhash": "^0.1.4",
- "inquirer": "^3.0.6",
- "is-resolvable": "^1.0.0",
- "js-yaml": "^3.9.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.3.0",
- "lodash": "^4.17.4",
- "minimatch": "^3.0.2",
- "mkdirp": "^0.5.1",
- "natural-compare": "^1.4.0",
- "optionator": "^0.8.2",
- "path-is-inside": "^1.0.2",
- "pluralize": "^7.0.0",
- "progress": "^2.0.0",
- "regexpp": "^1.0.1",
- "require-uncached": "^1.0.3",
- "semver": "^5.3.0",
- "strip-ansi": "^4.0.0",
- "strip-json-comments": "~2.0.1",
- "table": "4.0.2",
- "text-table": "~0.2.0"
- }
- },
- "eslint-config-airbnb-base": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.0.0.tgz",
- "integrity": "sha512-hUFXRlE6AY84z0qYh4wKdtSF4EqDnyT8sxrvTpcXCV4ENSLF8li5yNA1yDM26iinH8Ierbpc4lv8Rp62uX6VSQ==",
- "dev": true,
- "requires": {
- "eslint-restricted-globals": "^0.1.1",
- "object.assign": "^4.1.0",
- "object.entries": "^1.0.4"
- }
- },
- "eslint-import-resolver-node": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
- "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
- "dev": true,
- "requires": {
- "debug": "^2.6.9",
- "resolve": "^1.5.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "eslint-module-utils": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz",
- "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=",
- "dev": true,
- "requires": {
- "debug": "^2.6.8",
- "pkg-dir": "^1.0.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "eslint-plugin-import": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz",
- "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==",
- "dev": true,
- "requires": {
- "contains-path": "^0.1.0",
- "debug": "^2.6.8",
- "doctrine": "1.5.0",
- "eslint-import-resolver-node": "^0.3.1",
- "eslint-module-utils": "^2.2.0",
- "has": "^1.0.1",
- "lodash": "^4.17.4",
- "minimatch": "^3.0.3",
- "read-pkg-up": "^2.0.0",
- "resolve": "^1.6.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "doctrine": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
- "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2",
- "isarray": "^1.0.0"
- }
- }
- }
- },
- "eslint-restricted-globals": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz",
- "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=",
- "dev": true
- },
- "eslint-scope": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
- "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-visitor-keys": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
- "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
- "dev": true
- },
- "espree": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
- "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
- "dev": true,
- "requires": {
- "acorn": "^5.5.0",
- "acorn-jsx": "^3.0.0"
- }
- },
- "esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true
- },
- "esquery": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
- "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
- "dev": true,
- "requires": {
- "estraverse": "^4.0.0"
- }
- },
- "esrecurse": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
- "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
- "dev": true,
- "requires": {
- "estraverse": "^4.1.0"
- }
- },
- "estraverse": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
- "dev": true
- },
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
- "dev": true
- },
- "external-editor": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
- "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
- "dev": true,
- "requires": {
- "chardet": "^0.4.0",
- "iconv-lite": "^0.4.17",
- "tmp": "^0.0.33"
- }
- },
- "fast-deep-equal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
- "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
- "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=",
- "dev": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "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": "2.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
- "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
- "dev": true,
- "requires": {
- "flat-cache": "^1.2.1",
- "object-assign": "^4.0.1"
- }
- },
- "file-type": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.4.0.tgz",
- "integrity": "sha1-KnyU9ioAMBULt9m2xwz6HT51nIY="
- },
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "flat-cache": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
- "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
- "dev": true,
- "requires": {
- "circular-json": "^0.3.1",
- "del": "^2.0.2",
- "graceful-fs": "^4.1.2",
- "write": "^0.2.1"
- }
- },
- "foreach": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
- "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
- "dev": true
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
- "get-func-name": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
- "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
- "dev": true
- },
- "glob": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "globals": {
- "version": "11.7.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
- "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==",
- "dev": true
- },
- "globby": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
- "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
- "dev": true,
- "requires": {
- "array-union": "^1.0.1",
- "arrify": "^1.0.0",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "graceful-fs": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
- "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
- "dev": true
- },
- "growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-ansi": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
- "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "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=",
- "dev": true
- },
- "he": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
- "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
- "dev": true
- },
- "hosted-git-info": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
- "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
- "dev": true
- },
- "html-comment-regex": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
- "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4="
- },
- "iconv-lite": {
- "version": "0.4.23",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
- "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
- "dev": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore": {
- "version": "3.3.10",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
- "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
- "dev": true
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- },
- "inquirer": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
- "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
- "dev": true,
- "requires": {
- "ansi-escapes": "^3.0.0",
- "chalk": "^2.0.0",
- "cli-cursor": "^2.1.0",
- "cli-width": "^2.0.0",
- "external-editor": "^2.0.4",
- "figures": "^2.0.0",
- "lodash": "^4.3.0",
- "mute-stream": "0.0.7",
- "run-async": "^2.2.0",
- "rx-lite": "^4.0.8",
- "rx-lite-aggregates": "^4.0.8",
- "string-width": "^2.1.0",
- "strip-ansi": "^4.0.0",
- "through": "^2.3.6"
- }
- },
- "is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
- "is-builtin-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
- "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
- "dev": true,
- "requires": {
- "builtin-modules": "^1.0.0"
- }
- },
- "is-callable": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
- "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
- "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=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "is-path-cwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
- "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
- "dev": true
- },
- "is-path-in-cwd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
- "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
- "dev": true,
- "requires": {
- "is-path-inside": "^1.0.0"
- }
- },
- "is-path-inside": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
- "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
- "dev": true,
- "requires": {
- "path-is-inside": "^1.0.1"
- }
- },
- "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=",
- "dev": true,
- "requires": {
- "has": "^1.0.1"
- }
- },
- "is-resolvable": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
- "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
- "dev": true
- },
- "is-svg": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
- "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=",
- "requires": {
- "html-comment-regex": "^1.1.0"
- }
- },
- "is-symbol": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
- "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
- "dev": true
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
- "dev": true
- },
- "js-tokens": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
- "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
- "dev": true
- },
- "js-yaml": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
- "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
- "dev": true,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "json-schema-traverse": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
- "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
- "dev": true
- },
- "levn": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
- "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
- "dev": true,
- "requires": {
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2"
- }
- },
- "load-json-file": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
- "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "strip-bom": "^3.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
- "dev": true,
- "requires": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- },
- "dependencies": {
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- }
- }
- },
- "lodash": {
- "version": "4.17.10",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
- "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
- "dev": true
- },
- "lru-cache": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
- "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
- "dev": true,
- "requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
- "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==",
- "dev": true
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true
- },
- "mkdirp": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
- "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "dev": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "mocha": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
- "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
- "dev": true,
- "requires": {
- "browser-stdout": "1.3.1",
- "commander": "2.15.1",
- "debug": "3.1.0",
- "diff": "3.5.0",
- "escape-string-regexp": "1.0.5",
- "glob": "7.1.2",
- "growl": "1.10.5",
- "he": "1.1.1",
- "minimatch": "3.0.4",
- "mkdirp": "0.5.1",
- "supports-color": "5.4.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "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
- },
- "normalize-package-data": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
- "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "is-builtin-module": "^1.0.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "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-keys": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
- "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
- "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.0.4",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz",
- "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "es-abstract": "^1.6.1",
- "function-bind": "^1.1.0",
- "has": "^1.0.1"
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "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=",
- "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"
- }
- },
- "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",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
- "dev": true,
- "requires": {
- "p-try": "^1.0.0"
- }
- },
- "p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
- "dev": true,
- "requires": {
- "p-limit": "^1.1.0"
- }
- },
- "p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
- "dev": true
- },
- "parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
- "dev": true,
- "requires": {
- "error-ex": "^1.2.0"
- }
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "^2.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "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-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
- "dev": true
- },
- "path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
- "dev": true,
- "requires": {
- "pify": "^2.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "pathval": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
- "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
- "dev": true
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "dev": true,
- "requires": {
- "pinkie": "^2.0.0"
- }
- },
- "pkg-dir": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
- "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
- "dev": true,
- "requires": {
- "find-up": "^1.0.0"
- }
- },
- "pluralize": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
- "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
- "dev": true
- },
- "prelude-ls": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
- "dev": true
- },
- "process-nextick-args": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
- "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
- "dev": true
- },
- "progress": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
- "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
- "dev": true
- },
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
- "dev": true
- },
- "read-chunk": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz",
- "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=",
- "requires": {
- "pify": "^3.0.0",
- "safe-buffer": "^5.1.1"
- }
- },
- "read-pkg": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
- "dev": true,
- "requires": {
- "load-json-file": "^2.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^2.0.0"
- }
- },
- "read-pkg-up": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
- "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
- "dev": true,
- "requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^2.0.0"
- },
- "dependencies": {
- "find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "^2.0.0"
- }
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
- "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "regexpp": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
- "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
- "dev": true
- },
- "require-uncached": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
- "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
- "dev": true,
- "requires": {
- "caller-path": "^0.1.0",
- "resolve-from": "^1.0.0"
- }
- },
- "resolve": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
- "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
- "dev": true,
- "requires": {
- "path-parse": "^1.0.5"
- }
- },
- "resolve-from": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
- "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
- "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.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
- "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
- "dev": true,
- "requires": {
- "glob": "^7.0.5"
- }
- },
- "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"
- }
- },
- "rx-lite": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
- "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
- "dev": true
- },
- "rx-lite-aggregates": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
- "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
- "dev": true,
- "requires": {
- "rx-lite": "*"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
- "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.5.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
- "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=",
- "dev": true,
- "requires": {
- "shebang-regex": "^1.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
- },
- "signal-exit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
- "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
- "dev": true
- },
- "slice-ansi": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
- "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
- "dev": true,
- "requires": {
- "is-fullwidth-code-point": "^2.0.0"
- }
- },
- "spdx-correct": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
- "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
- "dev": true,
- "requires": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-exceptions": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
- "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
- "dev": true
- },
- "spdx-expression-parse": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
- "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
- "dev": true,
- "requires": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-license-ids": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
- "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
- "dev": true
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
- "dev": true
- },
- "string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
- "dev": true,
- "requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^3.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
- "dev": true
- }
- }
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "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=",
- "dev": true
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "table": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
- "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
- "dev": true,
- "requires": {
- "ajv": "^5.2.3",
- "ajv-keywords": "^2.1.0",
- "chalk": "^2.1.0",
- "lodash": "^4.17.4",
- "slice-ansi": "1.0.0",
- "string-width": "^2.1.1"
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "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"
- }
- },
- "type-check": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
- "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
- "dev": true,
- "requires": {
- "prelude-ls": "~1.1.2"
- }
- },
- "type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true
- },
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "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",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "requires": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "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=",
- "dev": true
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
- },
- "write": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
- "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
- "dev": true,
- "requires": {
- "mkdirp": "^0.5.1"
- }
- },
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
- "dev": true
- }
- }
-}
diff --git a/package.json b/package.json
index e7bee5930..d9df08782 100644
--- a/package.json
+++ b/package.json
@@ -5,11 +5,17 @@
"read-chunk": "2.1.*"
},
"devDependencies": {
- "chai": "^4.1.2",
- "eslint": "^4.19.1",
- "eslint-config-airbnb-base": "^13.0.0",
- "eslint-plugin-import": "^2.13.0",
- "mocha": "^5.2.0"
+ "@nuxtjs/eslint-config": "^1.0.1",
+ "@nuxtjs/eslint-module": "^1.2.0",
+ "babel-eslint": "^10.1.0",
+ "chai": "^4.2.0",
+ "dotenv": "^8.2.0",
+ "eslint": "^6.1.0",
+ "eslint-config-prettier": "^4.1.0",
+ "eslint-plugin-nuxt": "^0.5.2",
+ "eslint-plugin-prettier": "^3.1.3",
+ "mocha": "^5.2.0",
+ "prettier": "^1.16.4"
},
"scripts": {
"test": "mocha -R spec src",
diff --git a/schema.json b/schema.json
index 45b52ac12..c5a875676 100644
--- a/schema.json
+++ b/schema.json
@@ -1,19 +1,25 @@
{
"title": "Wappalyzer Schema",
+ "definitions": {
+ "non-empty-non-blank-sting": {
+ "type": "string",
+ "pattern": "^(?!\\s*$).+"
+ }
+ },
"type": "object",
"additionalProperties": false,
+ "required": ["categories","apps"],
"properties": {
"$schema": {
"type": "string"
},
"categories": {
"type": "object",
- "required": true,
+ "minProperties": 64,
"additionalProperties": false,
"patternProperties": {
"^[0-9]+$": {
"type": "object",
- "required": true,
"properties": {
"priority": {
"type": "number"
@@ -27,89 +33,124 @@
},
"apps": {
"type": "object",
- "required": true,
"additionalProperties": {
"additionalProperties": false,
+ "required": ["cats","website"],
"properties": {
"cats": {
"type": "array",
"items": {
"type": "number"
},
- "required": true
+ "minItems": 1
},
"cpe": {
- "type": "string"
+ "$ref": "#/definitions/non-empty-non-blank-sting"
},
"cookies": {
"type": "object",
- "additionalProperties": {
- "type": "string"
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ },
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"js": {
"type": "object",
- "additionalProperties": {
- "type": "string"
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ },
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"headers": {
"type": "object",
- "additionalProperties": {
- "type": "string"
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ },
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"html": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ },
+ {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ ]
},
"excludes": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ },
+ {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ ]
},
"implies": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ },
+ {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ ]
},
"meta": {
"type": "object",
- "additionalProperties": {
- "type": "string"
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ },
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"script": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ },
+ {
+ "$ref": "#/definitions/non-empty-non-blank-sting"
+ }
+ ]
},
"url": {
- "type": "string"
+ "$ref": "#/definitions/non-empty-non-blank-sting"
},
"website": {
- "type": "string",
- "required": true
+ "$ref": "#/definitions/non-empty-non-blank-sting"
},
"icon": {
- "type": "string"
+ "$ref": "#/definitions/non-empty-non-blank-sting"
}
}
}
diff --git a/src/apps.json b/src/apps.json
index 41f87971e..c69f74f18 100644
--- a/src/apps.json
+++ b/src/apps.json
@@ -83,8 +83,14 @@
"cats": [
12
],
- "html": "<[^>]+x-data[^<]+",
+ "html": "<[^>]+[^\\w-]x-data[^\\w-][^<]+\\;confidence:75",
+ "js": {
+ "Alpine.version": "^(.+)$\\;version:\\1"
+ },
"icon": "Alpine.js.png",
+ "script": [
+ "/alpine(?:\\.min)?\\.js"
+ ],
"website": "https://github.com/alpinejs/alpine"
},
"AOLserver": {
@@ -154,9 +160,7 @@
5
],
"icon": "Accelerated-Mobile-Pages.svg",
- "implies": [
- "WordPress"
- ],
+ "implies": "WordPress",
"meta": {
"generator": "^AMP Plugin v(\\d+\\.\\d+.*)$\\;version:\\1"
},
@@ -1052,9 +1056,7 @@
"Server": "Artifactory(?:/([\\d.]+))?\\;version:\\1"
},
"icon": "Artifactory.svg",
- "implies": [
- "Artifactory"
- ],
+ "implies": "Artifactory",
"website": "http://jfrog.com/open-source/#os-arti"
},
"ArvanCloud": {
@@ -1608,7 +1610,6 @@
32
],
"html": "]+wire:[^<]+",
+ "icon": "Livewire.png",
+ "implies": "Laravel",
+ "js": {
+ "livewire": ""
+ },
+ "script": "livewire(?:\\.min)?\\.js",
+ "website": "https://laravel-livewire.com"
+ },
"LocalFocus": {
"cats": [
61
@@ -7535,9 +7563,7 @@
"\\;version:\\1"
],
"icon": "NextGEN Gallery.png",
- "implies": [
- "WordPress"
- ],
+ "implies": "WordPress",
"script": "/nextgen-gallery/js/",
"website": "https://www.imagely.com/wordpress-gallery-plugin"
},
@@ -7588,6 +7614,15 @@
"icon": "vercel.svg",
"website": "https://vercel.com"
},
+ "Nuvemshop": {
+ "cats": [
+ 6
+ ],
+ "script": "(N|n)uvem",
+ "html": "]+(?:class|id)=\"phabricator-",
"icon": "Phabricator.png",
- "implies": [
- "PHP"
- ],
+ "implies": "PHP",
"script": "/phabricator/[a-f0-9]{8}/rsrc/js/phui/[a-z-]+\\.js$",
"website": "http://phacility.com"
},
@@ -8329,9 +8362,7 @@
"<[^>]+id=\"phenomic(?:root)?\""
],
"icon": "Phenomic.svg",
- "implies": [
- "React"
- ],
+ "implies": "React",
"script": "/phenomic\\.browser\\.[a-f0-9]+\\.js",
"website": "https://phenomic.io/"
},
@@ -8539,6 +8570,14 @@
"icon": "PostgreSQL.png",
"website": "http://www.postgresql.org/"
},
+ "Powerboutique": {
+ "cats": [
+ 6
+ ],
+ "script": "powerboutique",
+ "icon": "powerboutique.jpg",
+ "website": "https://www.powerboutique.com/"
+ },
"Powergap": {
"cats": [
6
@@ -9418,9 +9457,7 @@
9
],
"icon": "SlickStack.png",
- "implies": [
- "WordPress"
- ],
+ "implies": "WordPress",
"headers": {
"x-powered-by": "SlickStack"
},
@@ -9473,6 +9510,14 @@
},
"website": "http://www.spip.net"
},
+ "Splitbee": {
+ "cats": [
+ 10
+ ],
+ "icon": "splitbee.svg",
+ "script": "^https:\\/\\/cdn\\.splitbee\\.io\\/sb\\.js",
+ "website": "https://splitbee.io"
+ },
"SQL Buddy": {
"cats": [
3
@@ -9699,9 +9744,7 @@
"headers": {
"x-powered-by": "^Seravo"
},
- "implies": [
- "WordPress"
- ],
+ "implies": "WordPress",
"icon": "seravo.svg",
"website": "https://seravo.com"
},
@@ -10274,6 +10317,16 @@
"script": "^/js/bundles/sonar\\.js?v=([\\d.]+)$\\;version:\\1",
"website": "https://www.sonarqube.org/"
},
+ "Sotel": {
+ "cats": [
+ 1
+ ],
+ "icon": "Sotel.png",
+ "meta": {
+ "generator": "sotel"
+ },
+ "website": "https://www.soteledu.com/en/"
+ },
"SoundManager": {
"cats": [
59
@@ -10747,7 +10800,10 @@
"cats": [
66
],
- "html": "]+?href=\"[^\"]+tailwindcss(?:\\.min)?\\.css",
+ "html": [
+ "]+?href=\"[^\"]+tailwindcss(?:\\.min)?\\.css",
+ "[^>]*class=\"[^\"]*(?:sm:|md:|lg:|xl:)"
+ ],
"icon": "tailwindcss.svg",
"website": "https://tailwindcss.com/"
},
@@ -10864,9 +10920,7 @@
"cookies": {
"TNEW": ""
},
- "implies": [
- "Tessitura"
- ],
+ "implies": "Tessitura",
"icon": "tessitura.svg",
"website": "https://www.tessituranetwork.com"
},
@@ -11661,7 +11715,7 @@
"vue[.-]([\\d.]*\\d)[^/]*\\.js\\;version:\\1",
"(?:/([\\d.]+))?/vue(?:\\.min)?\\.js\\;version:\\1"
],
- "website": "http://vuejs.org"
+ "website": "https://vuejs.org"
},
"Nuxt.js": {
"cats": [
@@ -12098,9 +12152,7 @@
"X-Wix-Server-Artifact-Id": ""
},
"icon": "Wix.png",
- "implies": [
- "React"
- ],
+ "implies": "React",
"js": {
"wixBiSession": ""
},
@@ -12202,9 +12254,7 @@
"headers": {
"x-powered-by": "^WordPress\\.com VIP"
},
- "implies": [
- "WordPress"
- ],
+ "implies": "WordPress",
"icon": "wpvip.svg",
"website": "https://wpvip.com"
},
@@ -12373,9 +12423,7 @@
"X-Powered-By": "XeoraCube"
},
"html": "",
- "implies": [
- "Microsoft ASP.NET"
- ],
+ "implies": "Microsoft ASP.NET",
"icon": "xeora.png",
"script": "/_bi_sps_v.+\\.js",
"website": "http://www.xeora.org"
@@ -12526,9 +12574,7 @@
"Server": "Yaws(?: ([\\d.]+))?\\;version:\\1"
},
"icon": "Yaws.png",
- "implies": [
- "Erlang"
- ],
+ "implies": "Erlang",
"website": "http://yaws.hyber.org"
},
"Yieldlab": {
@@ -12552,9 +12598,7 @@
"]+sc-component-id: sc-"
],
"icon": "styled-components.png",
- "implies": [
- "React"
- ],
+ "implies": "React",
"js": {
"styled": ""
},
diff --git a/src/drivers/npm/browsers/puppeteer.js b/src/drivers/npm/browsers/puppeteer.js
index 7b0779adf..9e4d5f8e4 100644
--- a/src/drivers/npm/browsers/puppeteer.js
+++ b/src/drivers/npm/browsers/puppeteer.js
@@ -1,218 +1,245 @@
-const {
- AWS_LAMBDA_FUNCTION_NAME,
- CHROME_BIN,
-} = process.env;
+const { AWS_LAMBDA_FUNCTION_NAME, CHROME_BIN } = process.env
-let chromium;
-let puppeteer;
+let chromium
+let puppeteer
if (AWS_LAMBDA_FUNCTION_NAME) {
// eslint-disable-next-line global-require, import/no-unresolved
- chromium = require('chrome-aws-lambda');
-
- ({ puppeteer } = chromium);
+ chromium = require('chrome-aws-lambda')
+ ;({ puppeteer } = chromium)
} else {
// eslint-disable-next-line global-require
- puppeteer = require('puppeteer');
+ puppeteer = require('puppeteer')
}
-const Browser = require('../browser');
+const Browser = require('../browser')
function getJs() {
const dereference = (obj, level = 0) => {
try {
// eslint-disable-next-line no-undef
if (level > 5 || (level && obj === window)) {
- return '[Removed]';
+ return '[Removed]'
}
if (Array.isArray(obj)) {
- obj = obj.map(item => dereference(item, level + 1));
+ obj = obj.map((item) => dereference(item, level + 1))
}
- if (typeof obj === 'function' || (typeof obj === 'object' && obj !== null)) {
- const newObj = {};
+ if (
+ typeof obj === 'function' ||
+ (typeof obj === 'object' && obj !== null)
+ ) {
+ const newObj = {}
Object.keys(obj).forEach((key) => {
- newObj[key] = dereference(obj[key], level + 1);
- });
+ newObj[key] = dereference(obj[key], level + 1)
+ })
- return newObj;
+ return newObj
}
- return obj;
+ return obj
} catch (error) {
- return undefined;
+ return undefined
}
- };
+ }
// eslint-disable-next-line no-undef
- return dereference(window);
+ return dereference(window)
}
class PuppeteerBrowser extends Browser {
constructor(options) {
- options.maxWait = options.maxWait || 60;
+ options.maxWait = options.maxWait || 60
- super(options);
+ super(options)
}
async visit(url) {
- let done = false;
- let browser;
+ let done = false
+ let browser
try {
await new Promise(async (resolve, reject) => {
try {
- browser = await puppeteer.launch(chromium ? {
- args: [...chromium.args, '--ignore-certificate-errors'],
- defaultViewport: chromium.defaultViewport,
- executablePath: await chromium.executablePath,
- headless: chromium.headless,
- } : {
- args: ['--no-sandbox', '--headless', '--disable-gpu', '--ignore-certificate-errors'],
- executablePath: CHROME_BIN,
- });
+ browser = await puppeteer.launch(
+ chromium
+ ? {
+ args: [...chromium.args, '--ignore-certificate-errors'],
+ defaultViewport: chromium.defaultViewport,
+ executablePath: await chromium.executablePath,
+ headless: chromium.headless
+ }
+ : {
+ args: [
+ '--no-sandbox',
+ '--headless',
+ '--disable-gpu',
+ '--ignore-certificate-errors'
+ ],
+ executablePath: CHROME_BIN
+ }
+ )
browser.on('disconnected', () => {
if (!done) {
- reject(new Error('browser: disconnected'));
+ reject(new Error('browser: disconnected'))
}
- });
+ })
- const page = await browser.newPage();
+ const page = await browser.newPage()
- page.setDefaultTimeout(this.options.maxWait * 1.1);
+ page.setDefaultTimeout(this.options.maxWait * 1.1)
- await page.setRequestInterception(true);
+ await page.setRequestInterception(true)
- page.on('error', error => reject(new Error(`page error: ${error.message || error}`)));
+ page.on('error', (error) =>
+ reject(new Error(`page error: ${error.message || error}`))
+ )
- let responseReceived = false;
+ let responseReceived = false
page.on('request', (request) => {
try {
if (
- responseReceived
- && request.isNavigationRequest()
- && request.frame() === page.mainFrame()
- && request.url() !== url
+ responseReceived &&
+ request.isNavigationRequest() &&
+ request.frame() === page.mainFrame() &&
+ request.url() !== url
) {
- this.log(`abort navigation to ${request.url()}`);
+ this.log(`abort navigation to ${request.url()}`)
- request.abort('aborted');
+ request.abort('aborted')
} else if (!done) {
if (!['document', 'script'].includes(request.resourceType())) {
- request.abort();
+ request.abort()
} else {
- request.continue();
+ request.continue()
}
}
} catch (error) {
- reject(new Error(`page error: ${error.message || error}`));
+ reject(new Error(`page error: ${error.message || error}`))
}
- });
+ })
page.on('response', (response) => {
try {
if (!this.statusCode) {
- this.statusCode = response.status();
+ this.statusCode = response.status()
- this.headers = {};
+ this.headers = {}
- const headers = response.headers();
+ const headers = response.headers()
Object.keys(headers).forEach((key) => {
- this.headers[key] = Array.isArray(headers[key]) ? headers[key] : [headers[key]];
- });
+ this.headers[key] = Array.isArray(headers[key])
+ ? headers[key]
+ : [headers[key]]
+ })
- this.contentType = headers['content-type'] || null;
+ this.contentType = headers['content-type'] || null
}
if (response.status() < 300 || response.status() > 399) {
- responseReceived = true;
+ responseReceived = true
}
} catch (error) {
- reject(new Error(`page error: ${error.message || error}`));
+ reject(new Error(`page error: ${error.message || error}`))
}
- });
+ })
page.on('console', ({ _type, _text, _location }) => {
if (!/Failed to load resource: net::ERR_FAILED/.test(_text)) {
- this.log(`${_text} (${_location.url}: ${_location.lineNumber})`, _type);
+ this.log(
+ `${_text} (${_location.url}: ${_location.lineNumber})`,
+ _type
+ )
}
- });
+ })
if (this.options.userAgent) {
- await page.setUserAgent(this.options.userAgent);
+ await page.setUserAgent(this.options.userAgent)
}
try {
await Promise.race([
page.goto(url, { waitUntil: 'domcontentloaded' }),
// eslint-disable-next-line no-shadow
- new Promise((resolve, reject) => setTimeout(() => reject(new Error('timeout')), this.options.maxWait)),
- ]);
+ new Promise((resolve, reject) =>
+ setTimeout(
+ () => reject(new Error('timeout')),
+ this.options.maxWait
+ )
+ )
+ ])
} catch (error) {
- throw new Error(error.message || error.toString());
+ throw new Error(error.message || error.toString())
}
// eslint-disable-next-line no-undef
- const links = await page.evaluateHandle(() => Array.from(document.getElementsByTagName('a')).map(({
- hash, hostname, href, pathname, protocol, rel,
- }) => ({
- hash,
- hostname,
- href,
- pathname,
- protocol,
- rel,
- })));
-
- this.links = await links.jsonValue();
+ const links = await page.evaluateHandle(() =>
+ Array.from(document.getElementsByTagName('a')).map(
+ ({ hash, hostname, href, pathname, protocol, rel }) => ({
+ hash,
+ hostname,
+ href,
+ pathname,
+ protocol,
+ rel
+ })
+ )
+ )
+
+ this.links = await links.jsonValue()
// eslint-disable-next-line no-undef
- const scripts = await page.evaluateHandle(() => Array.from(document.getElementsByTagName('script')).map(({
- src,
- }) => src));
+ const scripts = await page.evaluateHandle(() =>
+ Array.from(document.getElementsByTagName('script')).map(
+ ({ src }) => src
+ )
+ )
- this.scripts = (await scripts.jsonValue()).filter(script => script);
+ this.scripts = (await scripts.jsonValue()).filter((script) => script)
- this.js = await page.evaluate(getJs);
+ this.js = await page.evaluate(getJs)
- this.cookies = (await page.cookies()).map(({
- name, value, domain, path,
- }) => ({
- name, value, domain, path,
- }));
+ this.cookies = (await page.cookies()).map(
+ ({ name, value, domain, path }) => ({
+ name,
+ value,
+ domain,
+ path
+ })
+ )
- this.html = await page.content();
+ this.html = await page.content()
- resolve();
+ resolve()
} catch (error) {
- reject(new Error(`visit error: ${error.message || error}`));
+ reject(new Error(`visit error: ${error.message || error}`))
}
- });
+ })
} catch (error) {
- this.log(`visit error: ${error.message || error} (${url})`, 'error');
+ this.log(`visit error: ${error.message || error} (${url})`, 'error')
- throw new Error(error.message || error.toString());
+ throw new Error(error.message || error.toString())
} finally {
- done = true;
+ done = true
if (browser) {
try {
- await browser.close();
+ await browser.close()
- this.log('browser close ok');
+ this.log('browser close ok')
} catch (error) {
- this.log(`browser close error: ${error.message || error}`, 'error');
+ this.log(`browser close error: ${error.message || error}`, 'error')
}
}
}
- this.log(`visit ok (${url})`);
+ this.log(`visit ok (${url})`)
}
}
-module.exports = PuppeteerBrowser;
+module.exports = PuppeteerBrowser
diff --git a/src/drivers/npm/npm-shrinkwrap.json b/src/drivers/npm/npm-shrinkwrap.json
index b7d31ac7c..1dd512a23 100644
--- a/src/drivers/npm/npm-shrinkwrap.json
+++ b/src/drivers/npm/npm-shrinkwrap.json
@@ -1,6 +1,6 @@
{
"name": "wappalyzer",
- "version": "5.9.33",
+ "version": "5.9.34",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/src/drivers/puppeteer/.gitignore b/src/drivers/puppeteer/.gitignore
new file mode 100644
index 000000000..5558dedd3
--- /dev/null
+++ b/src/drivers/puppeteer/.gitignore
@@ -0,0 +1,3 @@
+/apps.json
+/wappalyzer.js
+/node_modules
diff --git a/src/drivers/puppeteer/Dockerfile b/src/drivers/puppeteer/Dockerfile
new file mode 100644
index 000000000..4c1c3596b
--- /dev/null
+++ b/src/drivers/puppeteer/Dockerfile
@@ -0,0 +1,34 @@
+FROM node:12-alpine
+
+MAINTAINER Wappalyzer
+
+ENV WAPPALYZER_ROOT /opt/wappalyzer
+ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
+ENV CHROME_BIN /usr/bin/chromium-browser
+
+RUN apk update && apk add --no-cache \
+ nodejs \
+ nodejs-npm \
+ udev \
+ chromium \
+ ttf-freefont
+
+RUN mkdir -p "$WAPPALYZER_ROOT/browsers"
+
+WORKDIR "$WAPPALYZER_ROOT"
+
+ADD apps.json .
+ADD browser.js .
+ADD browsers/zombie.js ./browsers
+ADD browsers/puppeteer.js ./browsers
+ADD cli.js .
+ADD driver.js .
+ADD index.js .
+ADD package.json .
+ADD wappalyzer.js .
+
+RUN npm i && npm i puppeteer
+
+RUN /usr/bin/chromium-browser --version
+
+ENTRYPOINT ["node", "cli.js"]
diff --git a/src/drivers/puppeteer/README.md b/src/drivers/puppeteer/README.md
new file mode 100644
index 000000000..acfd9cbea
--- /dev/null
+++ b/src/drivers/puppeteer/README.md
@@ -0,0 +1,94 @@
+# Wappalyzer
+
+[Wappalyzer](https://www.wappalyzer.com/) is a
+[cross-platform](https://www.wappalyzer.com/nodejs) utility that uncovers the
+technologies used on websites. It detects
+[content management systems](https://www.wappalyzer.com/technologies/cms), [ecommerce platforms](https://www.wappalyzer.com/technologies/ecommerce), [web servers](https://www.wappalyzer.com/technologies/web-servers), [JavaScript frameworks](https://www.wappalyzer.com/technologies/javascript-frameworks),
+[analytics tools](https://www.wappalyzer.com/technologies/analytics) and
+[many more](https://www.wappalyzer.com/technologies).
+
+
+## Installation
+
+```shell
+$ npm i -g wappalyzer # Globally
+$ npm i wappalyzer --save # As a dependency
+```
+
+To use Puppeteer (headless Chrome browser), you must install the NPM package manually:
+
+```shell
+$ npm i puppeteer@^2.0.0
+```
+
+
+## Run from the command line
+
+```
+wappalyzer [options]
+```
+
+### Options
+
+```
+-b, --batch-size=... Process links in batches
+-d, --debug Output debug messages
+-t, --delay=ms Wait for ms milliseconds between requests
+-h, --help This text
+--html-max-cols=... Limit the number of HTML characters per line processed
+--html-max-rows=... Limit the number of HTML lines processed
+-D, --max-depth=... Don't analyse pages more than num levels deep
+-m, --max-urls=... Exit when num URLs have been analysed
+-w, --max-wait=... Wait no more than ms milliseconds for page resources to load
+-P, --pretty Pretty-print JSON output
+-r, --recursive Follow links on pages (crawler)
+-a, --user-agent=... Set the user agent string
+```
+
+
+## Run from a script
+
+```javascript
+const Wappalyzer = require('wappalyzer');
+
+const url = 'https://www.wappalyzer.com';
+
+const options = {
+ debug: false,
+ delay: 500,
+ maxDepth: 3,
+ maxUrls: 10,
+ maxWait: 5000,
+ recursive: true,
+ userAgent: 'Wappalyzer',
+ htmlMaxCols: 2000,
+ htmlMaxRows: 2000,
+};
+
+;(async function() {
+ const wappalyzer = await new Wappalyzer(options)
+
+ try {
+ await wappalyzer.init()
+
+ const site = await wappalyzer.open(url)
+
+ site.on('error', (error) => {
+ process.stderr.write(`error: ${error}\n`)
+ })
+
+ const results = await site.analyze()
+
+ process.stdout.write(`${JSON.stringify(results, null, 2)}\n`)
+
+ await wappalyzer.destroy()
+
+ process.exit(0)
+ } catch (error) {
+ process.stderr.write(error.toString())
+
+ await wappalyzer.destroy()
+
+ process.exit(1)
+ }
+})()
diff --git a/src/drivers/puppeteer/browser.js b/src/drivers/puppeteer/browser.js
new file mode 100644
index 000000000..532a75aa3
--- /dev/null
+++ b/src/drivers/puppeteer/browser.js
@@ -0,0 +1,20 @@
+class Browser {
+ constructor(options) {
+ this.options = options;
+
+ this.window = null;
+ this.document = null;
+ this.statusCode = null;
+ this.contentType = null;
+ this.headers = null;
+ this.statusCode = null;
+ this.contentType = null;
+ this.html = null;
+ this.js = null;
+ this.links = null;
+ this.scripts = null;
+ this.cookies = null;
+ }
+}
+
+module.exports = Browser;
diff --git a/src/drivers/puppeteer/cli.js b/src/drivers/puppeteer/cli.js
new file mode 100755
index 000000000..9348ce709
--- /dev/null
+++ b/src/drivers/puppeteer/cli.js
@@ -0,0 +1,107 @@
+#!/usr/bin/env node
+
+const Wappalyzer = require('./driver')
+
+const args = process.argv.slice(2)
+
+const options = {}
+
+let url
+let arg
+
+const aliases = {
+ a: 'userAgent',
+ b: 'batchSize',
+ d: 'debug',
+ t: 'delay',
+ h: 'help',
+ D: 'maxDepth',
+ m: 'maxUrls',
+ P: 'pretty',
+ r: 'recursive',
+ w: 'maxWait'
+}
+
+while (true) {
+ // eslint-disable-line no-constant-condition
+ arg = args.shift()
+
+ if (!arg) {
+ break
+ }
+
+ const matches = /^-?-([^=]+)(?:=(.+)?)?/.exec(arg)
+
+ if (matches) {
+ const key =
+ aliases[matches[1]] ||
+ matches[1].replace(/-\w/g, (_matches) => _matches[1].toUpperCase())
+ // eslint-disable-next-line no-nested-ternary
+ const value = matches[2]
+ ? matches[2]
+ : args[0] && !args[0].startsWith('-')
+ ? args.shift()
+ : true
+
+ options[key] = value
+ } else {
+ url = arg
+ }
+}
+
+if (!url || options.help) {
+ process.stdout.write(`Usage:
+ wappalyzer [options]
+
+Examples:
+ wappalyzer https://www.example.com
+ node cli.js https://www.example.com -r -D 3 -m 50
+ docker wappalyzer/cli https://www.example.com --pretty
+
+Options:
+ -b, --batch-size=... Process links in batches
+ -d, --debug Output debug messages
+ -t, --delay=ms Wait for ms milliseconds between requests
+ -h, --help This text
+ --html-max-cols=... Limit the number of HTML characters per line processed
+ --html-max-rows=... Limit the number of HTML lines processed
+ -D, --max-depth=... Don't analyse pages more than num levels deep
+ -m, --max-urls=... Exit when num URLs have been analysed
+ -w, --max-wait=... Wait no more than ms milliseconds for page resources to load
+ -P, --pretty Pretty-print JSON output
+ -r, --recursive Follow links on pages (crawler)
+ -a, --user-agent=... Set the user agent string
+`)
+
+ process.exit(1)
+}
+
+;(async function() {
+ const wappalyzer = await new Wappalyzer(options)
+
+ try {
+ await wappalyzer.init()
+
+ const site = await wappalyzer.open(url)
+
+ site.on('error', (error) => {
+ process.stderr.write(`page error: ${error}\n`)
+ })
+
+ const results = await site.analyze()
+
+ process.stdout.write(
+ `${JSON.stringify(results, null, options.pretty ? 2 : null)}\n`
+ )
+
+ await wappalyzer.destroy()
+
+ process.exit(0)
+ } catch (error) {
+ process.stderr.write(error.toString())
+
+ await wappalyzer.destroy()
+
+ process.exit(1)
+ }
+})()
diff --git a/src/drivers/puppeteer/driver.js b/src/drivers/puppeteer/driver.js
new file mode 100644
index 000000000..b8fb2534c
--- /dev/null
+++ b/src/drivers/puppeteer/driver.js
@@ -0,0 +1,540 @@
+const { URL } = require('url')
+const fs = require('fs')
+const LanguageDetect = require('languagedetect')
+const Wappalyzer = require('./wappalyzer')
+
+const { AWS_LAMBDA_FUNCTION_NAME } = process.env
+
+let puppeteer
+
+if (AWS_LAMBDA_FUNCTION_NAME) {
+ // eslint-disable-next-line global-require, import/no-unresolved
+ ;({
+ chromium: { puppeteer }
+ } = require('chrome-aws-lambda'))
+} else {
+ // eslint-disable-next-line global-require
+ puppeteer = require('puppeteer')
+}
+
+const languageDetect = new LanguageDetect()
+
+languageDetect.setLanguageType('iso2')
+
+const json = JSON.parse(fs.readFileSync('./apps.json'))
+
+const extensions = /^([^.]+$|\.(asp|aspx|cgi|htm|html|jsp|php)$)/
+
+const errorTypes = {
+ RESPONSE_NOT_OK: 'Response was not ok',
+ NO_RESPONSE: 'No response from server',
+ NO_HTML_DOCUMENT: 'No HTML document'
+}
+
+function sleep(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms))
+}
+
+function getJs() {
+ const dereference = (obj, level = 0) => {
+ try {
+ // eslint-disable-next-line no-undef
+ if (level > 5 || (level && obj === window)) {
+ return '[Removed]'
+ }
+
+ if (Array.isArray(obj)) {
+ obj = obj.map((item) => dereference(item, level + 1))
+ }
+
+ if (
+ typeof obj === 'function' ||
+ (typeof obj === 'object' && obj !== null)
+ ) {
+ const newObj = {}
+
+ Object.keys(obj).forEach((key) => {
+ newObj[key] = dereference(obj[key], level + 1)
+ })
+
+ return newObj
+ }
+
+ return obj
+ } catch (error) {
+ return undefined
+ }
+ }
+
+ // eslint-disable-next-line no-undef
+ return dereference(window)
+}
+
+function processJs(window, patterns) {
+ const js = {}
+
+ Object.keys(patterns).forEach((appName) => {
+ js[appName] = {}
+
+ Object.keys(patterns[appName]).forEach((chain) => {
+ js[appName][chain] = {}
+
+ patterns[appName][chain].forEach((pattern, index) => {
+ const properties = chain.split('.')
+
+ let value = properties.reduce(
+ (parent, property) =>
+ parent && parent[property] ? parent[property] : null,
+ window
+ )
+
+ value =
+ typeof value === 'string' || typeof value === 'number'
+ ? value
+ : !!value
+
+ if (value) {
+ js[appName][chain][index] = value
+ }
+ })
+ })
+ })
+
+ return js
+}
+
+function processHtml(html, maxCols, maxRows) {
+ if (maxCols || maxRows) {
+ const batchs = []
+ const rows = html.length / maxCols
+
+ for (let i = 0; i < rows; i += 1) {
+ if (i < maxRows / 2 || i > rows - maxRows / 2) {
+ batchs.push(html.slice(i * maxCols, (i + 1) * maxCols))
+ }
+ }
+
+ html = batchs.join('\n')
+ }
+
+ return html
+}
+
+class Driver {
+ constructor(options = {}) {
+ this.options = {
+ batchSize: 5,
+ debug: false,
+ delay: 500,
+ htmlMaxCols: 2000,
+ htmlMaxRows: 3000,
+ maxDepth: 3,
+ maxUrls: 10,
+ maxWait: 5000,
+ recursive: false,
+ ...options
+ }
+
+ this.options.debug = Boolean(+this.options.debug)
+ this.options.recursive = Boolean(+this.options.recursive)
+ this.options.delay = this.options.recursive
+ ? parseInt(this.options.delay, 10)
+ : 0
+ this.options.maxDepth = parseInt(this.options.maxDepth, 10)
+ this.options.maxUrls = parseInt(this.options.maxUrls, 10)
+ this.options.maxWait = parseInt(this.options.maxWait, 10)
+ this.options.htmlMaxCols = parseInt(this.options.htmlMaxCols, 10)
+ this.options.htmlMaxRows = parseInt(this.options.htmlMaxRows, 10)
+
+ this.destroyed = false
+ }
+
+ async init() {
+ this.log('Launching browser...')
+
+ try {
+ this.browser = await puppeteer.launch({
+ args: [
+ '--no-sandbox',
+ '--headless',
+ '--disable-gpu',
+ '--ignore-certificate-errors'
+ ]
+ })
+
+ this.browser.on('disconnected', async () => {
+ this.log('Browser disconnected')
+
+ if (!this.destroyed) {
+ await this.init()
+ }
+ })
+ } catch (error) {
+ throw new Error(error.toString())
+ }
+ }
+
+ async destroy() {
+ this.destroyed = true
+
+ if (this.browser) {
+ try {
+ await sleep(1)
+
+ await this.browser.close()
+
+ this.log('Done')
+ } catch (error) {
+ throw new Error(error.toString())
+ }
+ }
+ }
+
+ open(url) {
+ return new Site(url, this)
+ }
+
+ log(message, source = 'driver', type = 'debug') {
+ if (this.options.debug) {
+ // eslint-disable-next-line no-console
+ console.log(`${type.toUpperCase()} | ${source} | ${message}`)
+ }
+ }
+}
+
+class Site {
+ constructor(url, driver) {
+ ;({ options: this.options, browser: this.browser } = driver)
+
+ this.driver = driver
+
+ try {
+ this.originalUrl = new URL(url)
+ } catch (error) {
+ throw new Error(error.message || error.toString())
+ }
+
+ this.wappalyzer = new Wappalyzer()
+
+ this.wappalyzer.apps = json.apps
+ this.wappalyzer.categories = json.categories
+
+ this.wappalyzer.parseJsPatterns()
+
+ this.wappalyzer.driver.log = (message, source, type) =>
+ this.log(message, source, type)
+ this.wappalyzer.driver.displayApps = (detected, meta, context) =>
+ this.displayApps(detected, meta, context)
+
+ this.analyzedUrls = {}
+ this.technologies = []
+ this.meta = {}
+
+ this.listeners = {}
+
+ this.headers = {}
+ }
+
+ async init() {}
+
+ on(event, callback) {
+ if (!this.listeners[event]) {
+ this.listeners[event] = []
+ }
+
+ this.listeners[event].push(callback)
+ }
+
+ emit(event, params) {
+ if (this.listeners[event]) {
+ this.listeners[event].forEach((listener) => listener(params))
+ }
+ }
+
+ log(...args) {
+ this.emit('log', ...args)
+
+ this.driver.log(...args)
+ }
+
+ async fetch(url, index, depth) {}
+
+ async goto(url) {
+ // Return when the URL is a duplicate or maxUrls has been reached
+ if (
+ this.analyzedUrls[url.href] ||
+ Object.keys(this.analyzedUrls).length >= this.options.maxUrls
+ ) {
+ return
+ }
+
+ this.log(`Navigate to ${url}`, 'page')
+
+ this.analyzedUrls[url.href] = {
+ status: 0
+ }
+
+ if (!this.browser) {
+ throw new Error('Browser closed')
+ }
+
+ const page = await this.browser.newPage()
+
+ page.setDefaultTimeout(this.options.maxWait)
+
+ await page.setRequestInterception(true)
+
+ page.on('error', (error) => this.emit('error', error))
+
+ let responseReceived = false
+
+ page.on('request', (request) => {
+ try {
+ if (
+ (responseReceived && request.isNavigationRequest()) ||
+ request.frame() !== page.mainFrame() ||
+ !['document', 'script'].includes(request.resourceType())
+ ) {
+ request.abort('blockedbyclient')
+ } else {
+ request.continue()
+ }
+ } catch (error) {
+ this.emit('error', error)
+ }
+ })
+
+ page.on('response', (response) => {
+ try {
+ if (response.url() === url.href) {
+ this.analyzedUrls[url.href] = {
+ status: response.status()
+ }
+
+ const headers = response.headers()
+
+ Object.keys(headers).forEach((key) => {
+ this.headers[key] = [
+ ...(this.headers[key] || []),
+ ...(Array.isArray(headers[key]) ? headers[key] : [headers[key]])
+ ]
+ })
+
+ this.contentType = headers['content-type'] || null
+
+ if (response.status() >= 300 && response.status() < 400) {
+ if (this.headers.location) {
+ url = new URL(this.headers.location.slice(-1))
+ }
+ } else {
+ responseReceived = true
+ }
+ }
+ } catch (error) {
+ this.emit('error', error)
+ }
+ })
+
+ if (this.options.userAgent) {
+ await page.setUserAgent(this.options.userAgent)
+ }
+
+ try {
+ await Promise.race([
+ page.goto(url.href, { waitUntil: 'domcontentloaded' }),
+ new Promise((resolve, reject) =>
+ setTimeout(() => reject(new Error('Timeout')), this.options.maxWait)
+ )
+ ])
+ } catch (error) {
+ this.emit('error', error)
+ }
+
+ await sleep(1000)
+
+ const links = await (
+ await page.evaluateHandle(() =>
+ Array.from(document.getElementsByTagName('a')).map(
+ ({ hash, hostname, href, pathname, protocol, rel }) => ({
+ hash,
+ hostname,
+ href,
+ pathname,
+ protocol,
+ rel
+ })
+ )
+ )
+ ).jsonValue()
+
+ // eslint-disable-next-line no-undef
+ const scripts = (
+ await (
+ await page.evaluateHandle(() =>
+ Array.from(document.getElementsByTagName('script')).map(
+ ({ src }) => src
+ )
+ )
+ ).jsonValue()
+ ).filter((script) => script)
+
+ const js = processJs(await page.evaluate(getJs), this.wappalyzer.jsPatterns)
+
+ const cookies = (await page.cookies()).map(
+ ({ name, value, domain, path }) => ({
+ name,
+ value,
+ domain,
+ path
+ })
+ )
+
+ const html = processHtml(
+ await page.content(),
+ this.options.htmlMaxCols,
+ this.options.htmlMaxRows
+ )
+
+ // Validate response
+ if (!this.analyzedUrls[url.href].status) {
+ throw new Error('NO_RESPONSE')
+ }
+
+ let language = null
+
+ try {
+ const [attrs] = languageDetect.detect(
+ html.replace(/<\/?[^>]+(>|$)/g, ' '),
+ 1
+ )
+
+ if (attrs) {
+ ;[language] = attrs
+ }
+ } catch (error) {
+ this.log(`${error} (${url.href})`, 'driver', 'error')
+ }
+
+ await this.wappalyzer.analyze(url, {
+ cookies,
+ headers: this.headers,
+ html,
+ js,
+ scripts,
+ language
+ })
+
+ const reducedLinks = Array.prototype.reduce.call(
+ links,
+ (results, link) => {
+ if (
+ results &&
+ Object.prototype.hasOwnProperty.call(
+ Object.getPrototypeOf(results),
+ 'push'
+ ) &&
+ link.protocol &&
+ link.protocol.match(/https?:/) &&
+ link.rel !== 'nofollow' &&
+ link.hostname === url.hostname &&
+ extensions.test(link.pathname)
+ ) {
+ results.push(new URL(link.href.split('#')[0]))
+ }
+
+ return results
+ },
+ []
+ )
+
+ this.emit('goto', url)
+
+ return reducedLinks
+ }
+
+ async analyze(url = this.originalUrl, index = 1, depth = 1) {
+ try {
+ await sleep(this.options.delay * index)
+
+ const links = await this.goto(url)
+
+ if (links && this.options.recursive && depth < this.options.maxDepth) {
+ await this.batch(links.slice(0, this.options.maxUrls), depth + 1)
+ }
+ } catch (error) {
+ const type =
+ error.message && errorTypes[error.message]
+ ? error.message
+ : 'UNKNOWN_ERROR'
+ const message =
+ error.message && errorTypes[error.message]
+ ? errorTypes[error.message]
+ : 'Unknown error'
+
+ this.analyzedUrls[url.href] = {
+ status: 0,
+ error: {
+ type,
+ message
+ }
+ }
+
+ this.log(`${message} (${url.href})`, 'driver', 'error')
+ }
+
+ return {
+ urls: this.analyzedUrls,
+ applications: this.technologies,
+ meta: this.meta
+ }
+ }
+
+ async batch(links, depth, batch = 0) {
+ if (links.length === 0) {
+ return
+ }
+
+ const batched = links.splice(0, this.options.batchSize)
+
+ await Promise.all(
+ batched.map((link, index) => this.analyze(link, index, depth))
+ )
+
+ await this.batch(links, depth, batch + 1)
+ }
+
+ displayApps(technologies, meta) {
+ this.meta = meta
+
+ Object.keys(technologies).forEach((name) => {
+ const {
+ confidenceTotal: confidence,
+ version,
+ props: { cats, icon, website, cpe }
+ } = technologies[name]
+
+ const categories = cats.reduce((categories, id) => {
+ categories[id] = json.categories[id].name
+
+ return categories
+ }, {})
+
+ if (!this.technologies.some(({ name: _name }) => name === _name)) {
+ this.technologies.push({
+ name,
+ confidence,
+ version: version || null,
+ icon: icon || 'default.svg',
+ website,
+ cpe: cpe || null,
+ categories
+ })
+ }
+ })
+ }
+}
+
+module.exports = Driver
+
+module.exports.processJs = processJs
+module.exports.processHtml = processHtml
diff --git a/src/drivers/puppeteer/index.js b/src/drivers/puppeteer/index.js
new file mode 100755
index 000000000..81cf5899f
--- /dev/null
+++ b/src/drivers/puppeteer/index.js
@@ -0,0 +1,12 @@
+const Driver = require('./driver');
+
+class Wappalyzer {
+ constructor(pageUrl, options) {
+ // eslint-disable-next-line import/no-dynamic-require, global-require
+ const Browser = require(`./browsers/${options.browser || 'zombie'}`);
+
+ return new Driver(Browser, pageUrl, options);
+ }
+}
+
+module.exports = Wappalyzer;
diff --git a/src/drivers/puppeteer/package.json b/src/drivers/puppeteer/package.json
new file mode 100644
index 000000000..6c2059d93
--- /dev/null
+++ b/src/drivers/puppeteer/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "wappalyzer",
+ "description": "Identify technology on websites",
+ "homepage": "https://www.wappalyzer.com",
+ "version": "6.0.0",
+ "author": "Wappalyzer",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/aliasio/wappalyzer"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/aliasio"
+ },
+ "main": "index.js",
+ "files": [
+ "apps.json",
+ "cli.js",
+ "driver.js",
+ "index.js",
+ "wappalyzer.js"
+ ],
+ "bin": {
+ "wappalyzer": "./cli.js"
+ },
+ "dependencies": {
+ "languagedetect": "^2.0.0",
+ "puppeteer": "^2.0.0"
+ }
+}
diff --git a/src/drivers/puppeteer/yarn.lock b/src/drivers/puppeteer/yarn.lock
new file mode 100644
index 000000000..0fb2fe9c8
--- /dev/null
+++ b/src/drivers/puppeteer/yarn.lock
@@ -0,0 +1,296 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/mime-types@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73"
+ integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=
+
+agent-base@5:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
+ integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
+
+async-limiter@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
+
+buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+concat-stream@^1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+debug@4, debug@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
+debug@^2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+extract-zip@^1.6.6:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
+ integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
+ dependencies:
+ concat-stream "^1.6.2"
+ debug "^2.6.9"
+ mkdirp "^0.5.4"
+ yauzl "^2.10.0"
+
+fd-slicer@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+ integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
+ dependencies:
+ pend "~1.2.0"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+glob@^7.1.3:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+https-proxy-agent@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b"
+ integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==
+ dependencies:
+ agent-base "5"
+ debug "4"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@^2.0.3, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
+languagedetect@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/languagedetect/-/languagedetect-2.0.0.tgz#4b8fa2b7593b2a3a02fb1100891041c53238936c"
+ integrity sha512-AZb/liiQ+6ZoTj4f1J0aE6OkzhCo8fyH+tuSaPfSo8YHCWLFJrdSixhtO2TYdIkjcDQNaR4RmGaV2A5FJklDMQ==
+
+mime-db@1.44.0:
+ version "1.44.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
+ integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
+
+mime-types@^2.1.25:
+ version "2.1.27"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
+ integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
+ dependencies:
+ mime-db "1.44.0"
+
+mime@^2.0.3:
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009"
+ integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==
+
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+ integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
+mkdirp@^0.5.4:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+ integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+ dependencies:
+ minimist "^1.2.5"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+ dependencies:
+ wrappy "1"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+pend@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+ integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+progress@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+proxy-from-env@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+puppeteer@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-2.1.1.tgz#ccde47c2a688f131883b50f2d697bd25189da27e"
+ integrity sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==
+ dependencies:
+ "@types/mime-types" "^2.1.0"
+ debug "^4.1.0"
+ extract-zip "^1.6.6"
+ https-proxy-agent "^4.0.0"
+ mime "^2.0.3"
+ mime-types "^2.1.25"
+ progress "^2.0.1"
+ proxy-from-env "^1.0.0"
+ rimraf "^2.6.1"
+ ws "^6.1.0"
+
+readable-stream@^2.2.2:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+rimraf@^2.6.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+
+util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+ws@^6.1.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
+ integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
+ dependencies:
+ async-limiter "~1.0.0"
+
+yauzl@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+ integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
+ dependencies:
+ buffer-crc32 "~0.2.3"
+ fd-slicer "~1.1.0"
diff --git a/src/drivers/webextension/_locales/ca/messages.json b/src/drivers/webextension/_locales/ca/messages.json
index 825dcf3e4..721464c9d 100644
--- a/src/drivers/webextension/_locales/ca/messages.json
+++ b/src/drivers/webextension/_locales/ca/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "Acceptar" },
"termsContent": { "message": "Aquesta extensió envia informació anònima sobre els llocs web que visiteu, inclosos el nom de domini i les tecnologies identificades a wappalyzer.com. Això pot desactivar-se a Opcions." },
"privacyPolicy": { "message": "Política de privadesa" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Taulers de missatgeria" },
"categoryName3": { "message": "Gestor de bases de dades" },
diff --git a/src/drivers/webextension/_locales/de/messages.json b/src/drivers/webextension/_locales/de/messages.json
index f49ecc216..847dbf1fa 100644
--- a/src/drivers/webextension/_locales/de/messages.json
+++ b/src/drivers/webextension/_locales/de/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Immer Icon anzeigen" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Nachrichten Board" },
"categoryName3": { "message": "Datenbankverwaltung" },
diff --git a/src/drivers/webextension/_locales/el/messages.json b/src/drivers/webextension/_locales/el/messages.json
index 6f46ccd03..766f7f9b7 100644
--- a/src/drivers/webextension/_locales/el/messages.json
+++ b/src/drivers/webextension/_locales/el/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
diff --git a/src/drivers/webextension/_locales/en/messages.json b/src/drivers/webextension/_locales/en/messages.json
index c2b6245c7..f65fc1a43 100644
--- a/src/drivers/webextension/_locales/en/messages.json
+++ b/src/drivers/webextension/_locales/en/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
"privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Message boards" },
"categoryName3": { "message": "Database managers" },
diff --git a/src/drivers/webextension/_locales/es/messages.json b/src/drivers/webextension/_locales/es/messages.json
index ee0a480ee..14d102648 100644
--- a/src/drivers/webextension/_locales/es/messages.json
+++ b/src/drivers/webextension/_locales/es/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "Gestor de Contenido" },
"categoryName2": { "message": "Foro" },
"categoryName3": { "message": "Gestor de Bases de Datos" },
diff --git a/src/drivers/webextension/_locales/fa/messages.json b/src/drivers/webextension/_locales/fa/messages.json
index 1407f089b..adb30b530 100644
--- a/src/drivers/webextension/_locales/fa/messages.json
+++ b/src/drivers/webextension/_locales/fa/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "همیشه نماد را نشان بده" },
"termsAccept": { "message": "قبول" },
"termsContent": { "message": "این افزونه اطلاعات وبسایتهای بازدید شده توسط شما را به صورت ناشناس ارسال میکند، مانند آدرس سایت و تکنولوژیهای استفاده شده در آن سایت را ارسال میکند. اطلاعات بیشتر در wappalyzer.com. شما میتوانید این افزونه را غیرفعال کنید." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "سیستم مدیریت محتوا" },
"categoryName2": { "message": "انجمن پیام" },
"categoryName3": { "message": "مدیریت پایگاه داده" },
diff --git a/src/drivers/webextension/_locales/fr/messages.json b/src/drivers/webextension/_locales/fr/messages.json
index 88a4ba138..37fd1c2ce 100644
--- a/src/drivers/webextension/_locales/fr/messages.json
+++ b/src/drivers/webextension/_locales/fr/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": " Toujours afficher l'icône" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "Gestionnaire de base de données" },
diff --git a/src/drivers/webextension/_locales/gl_ES/messages.json b/src/drivers/webextension/_locales/gl_ES/messages.json
index 6e54050a1..795060901 100644
--- a/src/drivers/webextension/_locales/gl_ES/messages.json
+++ b/src/drivers/webextension/_locales/gl_ES/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "Aceptar" },
"termsContent": { "message": "Esta extensión envía anonimamente información acerca das webs que visitas, incluindo dominio e aplicativos identificados, a wappalyzer.com. Isto pode ser desactivado nas preferencias." },
"privacyPolicy": { "message": "Política de privacidade" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Taboleiro de mensaxes" },
"categoryName3": { "message": "Xestor de base de datos" },
diff --git a/src/drivers/webextension/_locales/gr/messages.json b/src/drivers/webextension/_locales/gr/messages.json
index 6dceaf22c..b631044ee 100644
--- a/src/drivers/webextension/_locales/gr/messages.json
+++ b/src/drivers/webextension/_locales/gr/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
diff --git a/src/drivers/webextension/_locales/id/messages.json b/src/drivers/webextension/_locales/id/messages.json
index 31f4b64f7..11d46d599 100644
--- a/src/drivers/webextension/_locales/id/messages.json
+++ b/src/drivers/webextension/_locales/id/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "Sistem Pengelola Konten" },
"categoryName2": { "message": "Papan Pesan" },
"categoryName3": { "message": "Pengelola Basis Data" },
diff --git a/src/drivers/webextension/_locales/it/messages.json b/src/drivers/webextension/_locales/it/messages.json
index 0f6f656d1..27882408a 100644
--- a/src/drivers/webextension/_locales/it/messages.json
+++ b/src/drivers/webextension/_locales/it/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "Gestore di Database" },
diff --git a/src/drivers/webextension/_locales/ja/messages.json b/src/drivers/webextension/_locales/ja/messages.json
index 362b88f5f..666d4d957 100644
--- a/src/drivers/webextension/_locales/ja/messages.json
+++ b/src/drivers/webextension/_locales/ja/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "受諾する" },
"termsContent": { "message": "この拡張機能は、ドメイン名や特定された技術など、アクセスしたWebサイトに関する匿名情報をwappalyzer.comに送信します。これは設定で無効にできます。" },
"privacyPolicy": { "message": "プライバシーポリシー" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "メッセージボード" },
"categoryName3": { "message": "データベースマネージャー" },
diff --git a/src/drivers/webextension/_locales/pl/messages.json b/src/drivers/webextension/_locales/pl/messages.json
index b04f2400e..90e83acfd 100644
--- a/src/drivers/webextension/_locales/pl/messages.json
+++ b/src/drivers/webextension/_locales/pl/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Zawsze pokazuj tą ikonę" },
"termsAccept": { "message": "Akceptuj" },
"termsContent": { "message": "To rozszerzenie wysyła anonimowe informacje o stronach, które odwiedzasz, uwzględniając nazwy domen i zidentyfikowane technologie do wappalyzer.com. Opcja może zostać wyłączona w ustawieniach." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "System zarządzania treścią" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "Menedżer baz danych" },
diff --git a/src/drivers/webextension/_locales/pt/messages.json b/src/drivers/webextension/_locales/pt/messages.json
index e358292b1..a7fd7a55a 100644
--- a/src/drivers/webextension/_locales/pt/messages.json
+++ b/src/drivers/webextension/_locales/pt/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "Aceitar" },
"termsContent": { "message": "Esta extensão envia informações anónimas sobre os sites que visitas, incluindo o nome de domínio e as tecnologias identificadas, para o wappalyzer.com. Isso pode ser desativado nas configurações." },
"privacyPolicy": { "message": "Políticas de Privacidade" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Fórum" },
"categoryName3": { "message": "Gestor de Base de Dados" },
diff --git a/src/drivers/webextension/_locales/pt_BR/messages.json b/src/drivers/webextension/_locales/pt_BR/messages.json
index 217d81b16..e32b108aa 100644
--- a/src/drivers/webextension/_locales/pt_BR/messages.json
+++ b/src/drivers/webextension/_locales/pt_BR/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Sempre mostrar ícone" },
"termsAccept": { "message": "Aceitar" },
"termsContent": { "message": "Esta extensão envia informações anônimas sobre os sites que você visita, incluindo domínio e tecnologias identificadas para wappalyzer.com. Este comportamento pode ser desativado nas configurações." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Fórum" },
"categoryName3": { "message": "Gestão de Banco de Dados" },
diff --git a/src/drivers/webextension/_locales/ro/messages.json b/src/drivers/webextension/_locales/ro/messages.json
index 68415aa06..a3036e74a 100644
--- a/src/drivers/webextension/_locales/ro/messages.json
+++ b/src/drivers/webextension/_locales/ro/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Afișează icon tot timpul" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Forum de discuții" },
"categoryName3": { "message": "Manager baze de date" },
diff --git a/src/drivers/webextension/_locales/ru/messages.json b/src/drivers/webextension/_locales/ru/messages.json
index cde758742..0947f8895 100644
--- a/src/drivers/webextension/_locales/ru/messages.json
+++ b/src/drivers/webextension/_locales/ru/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "Принять" },
"termsContent": { "message": "Расширение отправляет обезличенную статистику посещенных сайтов, включая доменное имя и распознанные технологии на wappalyzer.com. Это можно отключить в настройках." },
"privacyPolicy": { "message": "Политика конфиденциальности" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Форум" },
"categoryName3": { "message": "Менеджер БД" },
diff --git a/src/drivers/webextension/_locales/sk/messages.json b/src/drivers/webextension/_locales/sk/messages.json
index e07d4c928..b9ed2ce77 100644
--- a/src/drivers/webextension/_locales/sk/messages.json
+++ b/src/drivers/webextension/_locales/sk/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Message Board" },
"categoryName3": { "message": "Správca databáz" },
diff --git a/src/drivers/webextension/_locales/tr/messages.json b/src/drivers/webextension/_locales/tr/messages.json
index 5ded59dd2..63167726a 100644
--- a/src/drivers/webextension/_locales/tr/messages.json
+++ b/src/drivers/webextension/_locales/tr/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Her zaman bu kategorinin ikonunu kullan" },
"termsAccept": { "message": "Kabul Ediyorum" },
"termsContent": { "message": "Bu eklenti, ziyaret ettiğiniz web site bilgilerini, alan adları ve tespit edilen teknolojiler ile beraber anonim olarak wappalyzer.com'a gönderir. Bunu, eklenti ayarlarından değiştirebilirsiniz." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "İçerik Yönetim Sistemi" },
"categoryName2": { "message": "Mesaj Tahtası" },
"categoryName3": { "message": "Veritabanı Yöneticisi" },
diff --git a/src/drivers/webextension/_locales/uk/messages.json b/src/drivers/webextension/_locales/uk/messages.json
index 176a02601..c8c28983f 100644
--- a/src/drivers/webextension/_locales/uk/messages.json
+++ b/src/drivers/webextension/_locales/uk/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Форум" },
"categoryName3": { "message": "Менеджер БД" },
diff --git a/src/drivers/webextension/_locales/uz/messages.json b/src/drivers/webextension/_locales/uz/messages.json
index 6557c08d1..b0af1ba9f 100644
--- a/src/drivers/webextension/_locales/uz/messages.json
+++ b/src/drivers/webextension/_locales/uz/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "Accept" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com. This can be disabled in the settings." },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "CMS (KBT)" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "MB boshqaruvi" },
diff --git a/src/drivers/webextension/_locales/zh_CN/messages.json b/src/drivers/webextension/_locales/zh_CN/messages.json
index 270801b1a..2aadbda4c 100644
--- a/src/drivers/webextension/_locales/zh_CN/messages.json
+++ b/src/drivers/webextension/_locales/zh_CN/messages.json
@@ -15,6 +15,7 @@
"termsAccept": { "message": "接受" },
"termsContent": { "message": "此扩展程序发送关于您访问的网站的匿名信息至 wappalyzer.com,包含域名和检测到的技术。这可以在设置中禁用。" },
"privacyPolicy": { "message": "隐私政策" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "内容管理系统(CMS)" },
"categoryName2": { "message": "消息板" },
"categoryName3": { "message": "数据库管理器" },
diff --git a/src/drivers/webextension/_locales/zh_TW/messages.json b/src/drivers/webextension/_locales/zh_TW/messages.json
index ac32f3009..9ca2612f3 100644
--- a/src/drivers/webextension/_locales/zh_TW/messages.json
+++ b/src/drivers/webextension/_locales/zh_TW/messages.json
@@ -14,6 +14,8 @@
"categoryPin": { "message": "永遠顯示圖示" },
"termsAccept": { "message": "接受" },
"termsContent": { "message": "這個擴充功能將你所造訪網站的網域名稱和識別到的技術等資訊,匿名傳送至 wappalyzer.com。你可以在選項中停用。" },
+ "privacyPolicy": { "message": "Privacy policy" },
+ "createAlert": { "message": "Create an alert for this website" },
"categoryName1": { "message": "內容管理系統(CMS)" },
"categoryName2": { "message": "留言板/討論區" },
"categoryName3": { "message": "資料庫管理" },
diff --git a/src/drivers/webextension/css/popup.css b/src/drivers/webextension/css/popup.css
index c8968157c..14ecfd695 100644
--- a/src/drivers/webextension/css/popup.css
+++ b/src/drivers/webextension/css/popup.css
@@ -31,6 +31,24 @@ body {
display: none;
}
+.footer {
+ align-items: center;
+ border-top: 1px solid #dbdbdb;
+ height: 3rem;
+ display: flex;
+ padding: 0 1.5rem;
+}
+
+.footer__link {
+ color: #4608ad;
+ text-decoration: none;
+}
+
+.footer__link:hover, .footer__link:active {
+ color: #4608ad;
+ text-decoration: underline;
+}
+
.container {
min-height: 5rem;
padding: 1rem 1.5rem 0rem 1.5rem;
@@ -202,50 +220,68 @@ body {
margin-top: 1rem;
}
-/* Add alternative color palette for Dark mode theme. */
-body.theme-mode-sync {
- background: linear-gradient(160deg, #32067c, #150233);
-}
+@media (prefers-color-scheme: dark) {
+ /* Add alternative color palette for Dark mode theme. */
+ body.theme-mode-sync {
+ background: linear-gradient(160deg, #32067c, #150233);
+ }
-.theme-mode-sync .header {
- border-bottom: 1px solid #000;
-}
+ .theme-mode-sync .header {
+ border-bottom: 1px solid rgba(255, 255, 255, .2);
+ }
-.theme-mode-sync .header__logo--dark {
- display: inline-block;
-}
+ .theme-mode-sync .header__logo--dark {
+ display: inline-block;
+ }
-.theme-mode-sync .header__logo--light {
- display: none;
-}
+ .theme-mode-sync .header__logo--light {
+ display: none;
+ }
-.theme-mode-sync .container {
- color: white;
-}
+ .theme-mode-sync .footer {
+ border-top: 1px solid rgba(255, 255, 255, .2);
+ }
-.theme-mode-sync .detected__category-link, .theme-mode-sync .detected__app {
- color: white;
-}
+ .theme-mode-sync .footer__link {
+ color: rgba(255, 255, 255, .8);
+ }
-.theme-mode-sync .detected__category-link:hover {
- color: white;
- border-bottom: 1px solid white;
-}
+ .theme-mode-sync .footer__link:hover, .theme-mode-sync .footer__link:active {
+ color: rgba(255, 255, 255, .8);
+ }
-.theme-mode-sync .detected__app-version, .theme-mode-sync .detected__app-confidence {
- background-color: #4608ad;
-}
+ .theme-mode-sync .container {
+ color: white;
+ }
-.theme-mode-sync .detected__app:hover .detected__app-name {
- border-bottom: 1px solid white;
-}
+ .theme-mode-sync .detected__category-link {
+ color: #fff;
+ }
-.theme-mode-sync .detected__app:hover .theme-mode-sync .detected__app-version,
-.theme-mode-sync .detected__app:hover .theme-mode-sync .detected__app-confidence {
- border-bottom: none;
-}
+ .theme-mode-sync .detected__app {
+ color: rgba(255, 255, 255, .8);
+ }
-.theme-mode-sync .terms__accept,
-.theme-mode-sync .terms__privacy {
- color: white;
+ .theme-mode-sync .detected__category-link:hover {
+ color: white;
+ border-bottom: 1px solid white;
+ }
+
+ .theme-mode-sync .detected__app-version, .theme-mode-sync .detected__app-confidence {
+ background-color: #4608ad;
+ }
+
+ .theme-mode-sync .detected__app:hover .detected__app-name {
+ border-bottom: 1px solid white;
+ }
+
+ .theme-mode-sync .detected__app:hover .theme-mode-sync .detected__app-version,
+ .theme-mode-sync .detected__app:hover .theme-mode-sync .detected__app-confidence {
+ border-bottom: none;
+ }
+
+ .theme-mode-sync .terms__accept,
+ .theme-mode-sync .terms__privacy {
+ color: white;
+ }
}
diff --git a/src/drivers/webextension/html/popup.html b/src/drivers/webextension/html/popup.html
index 730a1f496..15fdc91dd 100644
--- a/src/drivers/webextension/html/popup.html
+++ b/src/drivers/webextension/html/popup.html
@@ -14,8 +14,8 @@
@@ -24,11 +24,15 @@
+
+