From c1c8fa7b6ad897f9af0bf2a21523455151bf0be6 Mon Sep 17 00:00:00 2001 From: Max Teegen <870074+max-te@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:58:00 +0100 Subject: [PATCH 01/21] prepare for bulk-decaffeinate: install decaffeinate --- bulk-decaffeinate.config.js | 4 + package-lock.json | 10438 ++++++++++++++++++++++++---------- package.json | 6 +- 3 files changed, 7330 insertions(+), 3118 deletions(-) create mode 100644 bulk-decaffeinate.config.js diff --git a/bulk-decaffeinate.config.js b/bulk-decaffeinate.config.js new file mode 100644 index 00000000..7c37e9a6 --- /dev/null +++ b/bulk-decaffeinate.config.js @@ -0,0 +1,4 @@ +module.exports = { + searchDirectory : "src/js", + decaffeinateArgs: ["--use-cs2", "--loose"] +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 60c41fe4..6fbcde63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2109 +1,4581 @@ { "name": "kodi-webinterface", - "version": "2.4.6", - "lockfileVersion": 1, + "version": "21.x-1.0.1", + "lockfileVersion": 3, "requires": true, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "packages": { + "": { + "name": "kodi-webinterface", + "version": "21.x-1.0.1", + "license": "GPL-2.0", + "devDependencies": { + "bulk-decaffeinate": "3.3.1", + "decaffeinate": "8.1.4", + "eslint": "8.57.0", + "grunt": "~0.4.5", + "grunt-browser-sync": "~2.2.0", + "grunt-contrib-coffee": "~1.0.0", + "grunt-contrib-compass": "~1.1.1", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jshint": "~2.0.0", + "grunt-contrib-uglify": "~4.0.1", + "grunt-contrib-watch": "~1.1.0", + "grunt-eco": "~0.1.2", + "grunt-execute": "~0.2.2", + "grunt-marked": "~0.1.3", + "grunt-po2json": "~0.3.0", + "grunt-shell": "2.1.0", + "jscodeshift": "0.15.2" + }, + "engines": { + "node": ">=0.8.0" + } }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "engines": { + "node": ">=0.10.0" } }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "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 - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, - "argparse": { - "version": "0.1.16", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", - "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, - "requires": { - "underscore": "~1.7.0", - "underscore.string": "~2.4.0" - }, "dependencies": { - "underscore.string": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", - "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", - "dev": true - } + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "node_modules/@babel/compat-data": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true + "node_modules/@babel/core": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } }, - "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 + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "node_modules/@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } }, - "async": { - "version": "0.1.22", - "resolved": "http://registry.npmjs.org/async/-/async-0.1.22.tgz", - "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", - "dev": true + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "async-each-series": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", - "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", - "dev": true + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", + "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, - "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - }, "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "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 + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "dependencies": { + "@babel/types": "^7.23.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, - "requires": { - "callsite": "1.0.0" + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "bin-version": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", - "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, - "requires": { - "find-versions": "^1.0.0" + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "bin-version-check": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", - "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dev": true, - "requires": { - "bin-version": "^1.0.0", - "minimist": "^1.1.0", - "semver": "^4.0.3", - "semver-truncate": "^1.0.0" + "dependencies": { + "@babel/types": "^7.22.5" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, "dependencies": { - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, - "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - }, - "dependencies": { - "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "engines": { + "node": ">=6.9.0" } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/helpers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/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, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "browser-sync": { - "version": "2.26.7", - "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.7.tgz", - "integrity": "sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w==", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { - "browser-sync-client": "^2.26.6", - "browser-sync-ui": "^2.26.4", - "bs-recipes": "1.3.4", - "bs-snippet-injector": "^2.0.1", - "chokidar": "^2.0.4", - "connect": "3.6.6", - "connect-history-api-fallback": "^1", - "dev-ip": "^1.0.1", - "easy-extender": "^2.3.4", - "eazy-logger": "^3", - "etag": "^1.8.1", - "fresh": "^0.5.2", - "fs-extra": "3.0.1", - "http-proxy": "1.15.2", - "immutable": "^3", - "localtunnel": "1.9.2", - "micromatch": "^3.1.10", - "opn": "5.3.0", - "portscanner": "2.1.1", - "qs": "6.2.3", - "raw-body": "^2.3.2", - "resp-modifier": "6.0.2", - "rx": "4.1.0", - "send": "0.16.2", - "serve-index": "1.9.1", - "serve-static": "1.13.2", - "server-destroy": "1.0.1", - "socket.io": "2.1.1", - "ua-parser-js": "0.7.17", - "yargs": "6.4.0" + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "browser-sync-client": { - "version": "2.26.6", - "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.6.tgz", - "integrity": "sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { - "etag": "1.8.1", - "fresh": "0.5.2", - "mitt": "^1.1.3", - "rxjs": "^5.5.6" + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "browser-sync-ui": { - "version": "2.26.4", - "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz", - "integrity": "sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA==", + "node_modules/@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, - "requires": { - "async-each-series": "0.1.1", - "connect-history-api-fallback": "^1", - "immutable": "^3", - "server-destroy": "1.0.1", - "socket.io-client": "^2.0.4", - "stream-throttle": "^0.1.3" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "bs-recipes": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", - "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", - "dev": true + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "bs-snippet-injector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", - "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", - "dev": true + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz", + "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==", "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-flow": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "dev": true, "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", "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" + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", + "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz", + "integrity": "sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w==", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "node_modules/@babel/preset-flow": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.1.tgz", + "integrity": "sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==", "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-transform-flow-strip-types": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "node_modules/@babel/preset-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "node_modules/@babel/register": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "coffee-script": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", - "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", - "dev": true + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "requires": { - "color-name": "1.1.3" + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "colors": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", - "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", - "dev": true + "node_modules/@codemod/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@codemod/core/-/core-2.2.0.tgz", + "integrity": "sha512-H2Qa+hbHFf05xl4YpmvCoczgozQohl+cNiLlCDOmnwcSAgnurZCMRbAR7ppkXjoZ9LRosw3OyY9MTpiKhngWIg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.12", + "@babel/generator": "^7.20.14", + "@codemod/parser": "^1.4.0", + "is-ci-cli": "^2.2.0", + "recast": "^0.19.0", + "resolve": "^1.12.0" + } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/@codemod/parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@codemod/parser/-/parser-1.4.1.tgz", + "integrity": "sha512-w9bvtcC1oJTuXAnp+ZOYLOWagtb8UBBZEKp9fYI0dA5KARiUJf00MmtDQyULaeZj/AQAGuOrm739DFDLeHv+0g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15" + } }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - }, "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "requires": { - "date-now": "^0.1.4" + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } }, - "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 + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "requires": { - "array-find-index": "^1.0.1" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "dargs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-2.1.0.tgz", - "integrity": "sha1-RsJ/+rH/sTeO8hJZchNxn+YCvJM=", - "dev": true + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } }, - "dateformat": { - "version": "1.0.2-1.2.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", - "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", - "dev": true + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "requires": { - "ms": "^2.1.1" + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "dev-ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", - "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, "dependencies": { - "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true - }, - "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", - "dev": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "requires": { - "domelementtype": "1" + "engines": { + "node": ">= 8" } }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "node_modules/@resugar/codemod-declarations-block-scope": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@resugar/codemod-declarations-block-scope/-/codemod-declarations-block-scope-1.0.3.tgz", + "integrity": "sha512-jnoNiz/PY4zZXPaLIeiKkGX6xau83Vn2lJRffIKuTPRMRTegFD2G7MmjxgZx9htJ/H9huqKJIhhqfj4VbuaDbA==", "dev": true }, - "easy-extender": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", - "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", + "node_modules/@resugar/codemod-functions-arrow": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@resugar/codemod-functions-arrow/-/codemod-functions-arrow-1.0.2.tgz", + "integrity": "sha512-6dfHOEIxZw6sc0auiDpELDRYGFfVhrJwc6xN4JxpGE9vc3Hg954svu8MhedSV7VTVSClLv4CE0RvUOD+09DAuw==", "dev": true, - "requires": { - "lodash": "^4.17.10" - }, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } + "@resugar/helper-comments": "^1.0.0" } }, - "eazy-logger": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz", - "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=", + "node_modules/@resugar/codemod-modules-commonjs": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@resugar/codemod-modules-commonjs/-/codemod-modules-commonjs-1.0.5.tgz", + "integrity": "sha512-A1lBMZWNEUFpmSGgTRzEaRUOWxZ/aNjil2ekCfjiITRJ3UrvsSF7PIPgv5waKzsgimtiQ0Wm+fcqFko0itZ21A==", "dev": true, - "requires": { - "tfunk": "^3.0.1" + "dependencies": { + "@resugar/helper-comments": "^1.0.0" } }, - "eco": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/eco/-/eco-1.0.3.tgz", - "integrity": "sha1-Yk6s0JyXle1l2D2oZTddxSRk5W0=", + "node_modules/@resugar/codemod-objects-concise": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@resugar/codemod-objects-concise/-/codemod-objects-concise-1.0.2.tgz", + "integrity": "sha512-Qf/zKkBzfGg1Q+2HSrssPllKYrwLxuDF/p39pz10keJtAhkYEcCbWcaHJRr5TgV9Pl9qnzzMImP9TG6KBwx7eA==", + "dev": true + }, + "node_modules/@resugar/codemod-objects-destructuring": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@resugar/codemod-objects-destructuring/-/codemod-objects-destructuring-1.0.1.tgz", + "integrity": "sha512-xvJ1YAsV3/eSgL7BaSXRNnnz3B8f+dv+KNpi/07RF46L5ah3E8TLb2Ge/IgJB9lz/mhTDfB+pmFem9J3ndfN6w==", + "dev": true + }, + "node_modules/@resugar/codemod-objects-shorthand": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@resugar/codemod-objects-shorthand/-/codemod-objects-shorthand-1.0.1.tgz", + "integrity": "sha512-1QZxpc2cX1DgxAWPDrp4l9VD1d+RZrqOXcXuckQmEIHr5TeSOhdBs2r3zFEbijxCTKD7fWsFgkas7LKh+KqGvQ==", "dev": true, - "requires": { - "coffee-script": ">=1.0.1", - "strscan": ">=1.0.1" + "dependencies": { + "@resugar/helper-comments": "^1.0.0" } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "node_modules/@resugar/codemod-strings-template": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@resugar/codemod-strings-template/-/codemod-strings-template-1.0.1.tgz", + "integrity": "sha512-ruVwOE67lmFGiyVr8I60l5lEDi0xKk1FYXyTGKMZdiiM2+W+L/qquOEqZmxOPA/xDNc5JG9VZXQ+4TZH9HqYxw==", "dev": true }, - "encodeurl": { + "node_modules/@resugar/helper-comments": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "resolved": "https://registry.npmjs.org/@resugar/helper-comments/-/helper-comments-1.0.2.tgz", + "integrity": "sha512-AXXKDyRcTN3naXhfvu/2mWX5OTc4RqlJIERCfnFs+M2VrawqoZU+oFS3L4ZsdP+/4rcofMCs9CMsYKc4S40PPQ==", "dev": true }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, - "requires": { - "iconv-lite": "~0.4.13" - }, "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" } }, - "engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" + "bin": { + "acorn": "bin/acorn" }, - "dependencies": { - "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" - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - } + "engines": { + "node": ">=0.4.0" } }, - "engine.io-client": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", - "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "engine.io-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", - "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", + "node_modules/add-variable-declarations": { + "version": "6.0.27", + "resolved": "https://registry.npmjs.org/add-variable-declarations/-/add-variable-declarations-6.0.27.tgz", + "integrity": "sha512-9lc+6sNfavbdve6XKmIeEHZ7Qaqhxxy7WJUwcPrB4eVPKGw64m/cyHJYT16RAonaWoeacLI0vLTae+Vwdgohng==", "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "dependencies": { + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", + "@codemod/parser": "^1.2.1", + "magic-string": "^0.30.0" } }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "node_modules/after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, - "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { - "string-template": "~0.2.1" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "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==", + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, - "requires": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">=0.10.0" } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "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 - }, - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", - "dev": true - }, - "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", - "dev": true + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "remove-trailing-separator": "^1.0.1" }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">=0.10.0" } }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "node_modules/argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" + "dependencies": { + "underscore": "~1.7.0", + "underscore.string": "~2.4.0" } }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "node_modules/argparse/node_modules/underscore.string": { + "version": "2.4.0", + "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "engines": { + "node": "*" } }, - "file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", - "dev": true - }, - "fill-range": { + "node_modules/arr-diff": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "engines": { + "node": ">=0.10.0" } }, - "finalhandler": { + "node_modules/arr-flatten": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "find-versions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", - "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true, - "requires": { - "array-uniq": "^1.0.0", - "get-stdin": "^4.0.1", - "meow": "^3.5.0", - "semver-regex": "^1.0.0" + "engines": { + "node": ">=0.10.0" } }, - "findup-sync": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", - "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "node_modules/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, - "requires": { - "glob": "~3.2.9", - "lodash": "~2.4.1" - }, - "dependencies": { - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2", - "minimatch": "0.3" - } - }, - "lodash": { - "version": "2.4.2", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", - "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", - "dev": true - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } + "engines": { + "node": ">=0.10.0" } }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "node_modules/arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true, - "requires": { - "map-cache": "^0.2.2" + "engines": { + "node": ">=0.10.0" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "node_modules/ast-types": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz", + "integrity": "sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA==", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", - "universalify": "^0.1.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - } + "engines": { + "node": ">=4" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "node_modules/async": { + "version": "0.1.22", + "resolved": "http://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true, + "engines": { + "node": "*" + } }, - "fsevents": { + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-each-series": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", + "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/automatic-semicolon-insertion": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/automatic-semicolon-insertion/-/automatic-semicolon-insertion-3.0.6.tgz", + "integrity": "sha512-M/+n8XFfrGzjgjXm+zzaCEy9nqiM+YkxQUN/P8Kfdu2i9FPvix7ece4B9kBN8Ca76UYiBJRQ+5u9DlLa7ownsA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.4" + } + }, + "node_modules/axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", + "dev": true, + "dependencies": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "node_modules/axios/node_modules/is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "node_modules/better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "dependencies": { + "callsite": "1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/bin-version": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "dev": true, + "dependencies": { + "find-versions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-version-check": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "dev": true, + "dependencies": { + "bin-version": "^1.0.0", + "minimist": "^1.1.0", + "semver": "^4.0.3", + "semver-truncate": "^1.0.0" + }, + "bin": { + "bin-version-check": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-version-check/node_modules/semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true, + "dependencies": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "node_modules/body/node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "node_modules/body/node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", + "dev": true, + "dependencies": { + "bytes": "1", + "string_decoder": "0.10" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/body/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/browser-sync": { + "version": "2.26.7", + "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.7.tgz", + "integrity": "sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w==", + "dev": true, + "dependencies": { + "browser-sync-client": "^2.26.6", + "browser-sync-ui": "^2.26.4", + "bs-recipes": "1.3.4", + "bs-snippet-injector": "^2.0.1", + "chokidar": "^2.0.4", + "connect": "3.6.6", + "connect-history-api-fallback": "^1", + "dev-ip": "^1.0.1", + "easy-extender": "^2.3.4", + "eazy-logger": "^3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "fs-extra": "3.0.1", + "http-proxy": "1.15.2", + "immutable": "^3", + "localtunnel": "1.9.2", + "micromatch": "^3.1.10", + "opn": "5.3.0", + "portscanner": "2.1.1", + "qs": "6.2.3", + "raw-body": "^2.3.2", + "resp-modifier": "6.0.2", + "rx": "4.1.0", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.13.2", + "server-destroy": "1.0.1", + "socket.io": "2.1.1", + "ua-parser-js": "0.7.17", + "yargs": "6.4.0" + }, + "bin": { + "browser-sync": "dist/bin.js" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/browser-sync-client": { + "version": "2.26.6", + "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.6.tgz", + "integrity": "sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw==", + "dev": true, + "dependencies": { + "etag": "1.8.1", + "fresh": "0.5.2", + "mitt": "^1.1.3", + "rxjs": "^5.5.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/browser-sync-ui": { + "version": "2.26.4", + "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz", + "integrity": "sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA==", + "dev": true, + "dependencies": { + "async-each-series": "0.1.1", + "connect-history-api-fallback": "^1", + "immutable": "^3", + "server-destroy": "1.0.1", + "socket.io-client": "^2.0.4", + "stream-throttle": "^0.1.3" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-recipes": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", + "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", + "dev": true + }, + "node_modules/bs-snippet-injector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", + "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bulk-decaffeinate": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/bulk-decaffeinate/-/bulk-decaffeinate-3.3.1.tgz", + "integrity": "sha512-wIG4kCPi176YAB2hpmOPcbzTgU+5njLay7bV0SohQnn0eB4cTaCP0wTKkzYGN8ihVMja1wr3GO+4PvjLpe3bgw==", + "dev": true, + "dependencies": { + "babel-polyfill": "^6.13.0", + "commander": "^2.9.0", + "executable": "^4.1.0", + "fs-promise": "^1.0.0", + "moment": "^2.19.1", + "mz": "^2.4.0", + "opn": "^4.0.2", + "require-uncached": "^1.0.2", + "simple-git": "^1.70.0" + }, + "bin": { + "bulk-decaffeinate": "bin/bulk-decaffeinate" + } + }, + "node_modules/bulk-decaffeinate/node_modules/opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha512-iPBWbPP4OEOzR1xfhpGLDh+ypKBOygunZhM9jBtA7FS5sKjEiMZw0EFb82hnDOmTZX90ZWLoZKUza4cVt8MexA==", + "dev": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha512-UJiE1otjXPF5/x+T3zTnSFiTOEmJoGTD9HmBoxnCUwho61a2eSNn/VwtwuIBDAo2SEOv1AJ7ARI5gCmohFLu/g==", + "dev": true, + "dependencies": { + "callsites": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caller-path/node_modules/callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha512-Zv4Dns9IbXXmPkgRRUjAaJQgfN4xX5p6+RQFhWUqscdvvK2xK/ZL8b3IXIJsj+4sD+f24NwnWy2BY8AJ82JB0A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "dependencies": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffee-lex": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/coffee-lex/-/coffee-lex-9.3.2.tgz", + "integrity": "sha512-lft4PwdLuqh3q50uR+yU5rpBKif1asJsXFPQ8AHDLs9woru6ENJ7jUVLGHk8cuCktvPFxaIzNeES9bNuSd89RA==", + "dev": true + }, + "node_modules/coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "node_modules/component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "node_modules/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 + }, + "node_modules/connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/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 + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dargs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-2.1.0.tgz", + "integrity": "sha1-RsJ/+rH/sTeO8hJZchNxn+YCvJM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "node_modules/dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decaffeinate": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/decaffeinate/-/decaffeinate-8.1.4.tgz", + "integrity": "sha512-fdy0A61uYy0ks0Scqpa2ICUf9cwU7/4+4yBhIE7egR8qCp34LzWYda7iD2TCoiEBohcoNhtpT/o3N6qyvnFX4A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.6", + "@codemod/core": "^2.0.1", + "@codemod/parser": "^1.2.1", + "@resugar/codemod-declarations-block-scope": "^1.0.3", + "@resugar/codemod-functions-arrow": "^1.0.2", + "@resugar/codemod-modules-commonjs": "^1.0.5", + "@resugar/codemod-objects-concise": "^1.0.2", + "@resugar/codemod-objects-destructuring": "^1.0.1", + "@resugar/codemod-objects-shorthand": "^1.0.1", + "@resugar/codemod-strings-template": "^1.0.1", + "add-variable-declarations": "^6.0.0", + "automatic-semicolon-insertion": "^3.0.2", + "coffee-lex": "^9.3.2", + "decaffeinate-coffeescript": "1.12.7-patch.4", + "decaffeinate-coffeescript2": "2.2.1-patch.6", + "decaffeinate-parser": "^23.0.1", + "detect-indent": "^4.0.0", + "is-ci-cli": "^2.2.0", + "lines-and-columns": "^2.0.3", + "magic-string": "^0.30.0", + "mz": "^2.7.0", + "tslib": "^2.4.0" + }, + "bin": { + "decaffeinate": "bin/decaffeinate" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/decaffeinate-coffeescript": { + "version": "1.12.7-patch.4", + "resolved": "https://registry.npmjs.org/decaffeinate-coffeescript/-/decaffeinate-coffeescript-1.12.7-patch.4.tgz", + "integrity": "sha512-VLVyuAahCJMskqpbgcyg7MrxIVeooPDWoU8atvotH+OgLdIIJlKzFFHZoJCTaMdSxqtbCkli7dFzCeqnTixp5Q==", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/decaffeinate-coffeescript2": { + "version": "2.2.1-patch.6", + "resolved": "https://registry.npmjs.org/decaffeinate-coffeescript2/-/decaffeinate-coffeescript2-2.2.1-patch.6.tgz", + "integrity": "sha512-R9QhWXDmRGs/uSPliv5n3FALNQwHYlkf6lhP5ZZ0QQ8NqZZJNfqLuiiSwe2t2/o6hHmIEkRSfQL/Ex1SEhSAHg==", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/decaffeinate-parser": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/decaffeinate-parser/-/decaffeinate-parser-23.0.1.tgz", + "integrity": "sha512-H0fuEdP2GWDhFIg4Ejlx2Loz6/yqEvWR3i2+mU8TNJkkJ9txd/4TEIdLcdMmBd9vw3eeBs0HHH+Yj8QbRO5aZQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.4", + "@codemod/parser": "^1.2.1", + "coffee-lex": "^9.3.1", + "decaffeinate-coffeescript": "^1.12.7-patch.4", + "decaffeinate-coffeescript2": "^2.2.1-patch.6", + "lines-and-columns": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dev-ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", + "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", + "dev": true, + "bin": { + "dev-ip": "lib/dev-ip.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "node_modules/easy-extender": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", + "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", + "dev": true, + "dependencies": { + "lodash": "^4.17.10" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/easy-extender/node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "node_modules/eazy-logger": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz", + "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=", + "dev": true, + "dependencies": { + "tfunk": "^3.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eco": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/eco/-/eco-1.0.3.tgz", + "integrity": "sha1-Yk6s0JyXle1l2D2oZTddxSRk5W0=", + "dev": true, + "dependencies": { + "coffee-script": ">=1.0.1", + "strscan": ">=1.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.719", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.719.tgz", + "integrity": "sha512-FbWy2Q2YgdFzkFUW/W5jBjE9dj+804+98E4Pup78JBPnbdb3pv6IneY2JCPKdeKLh3AOKHQeYf+KwLr7mxGh6Q==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "dependencies": { + "iconv-lite": "~0.4.13" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + } + }, + "node_modules/engine.io-client": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", + "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", + "dev": true, + "dependencies": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "node_modules/engine.io-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", + "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", + "dev": true, + "dependencies": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/engine.io/node_modules/engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "dependencies": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/engine.io/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "node_modules/error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "dev": true, + "dependencies": { + "string-template": "~0.2.1" + } + }, + "node_modules/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, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", + "dev": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-versions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.0", + "get-stdin": "^4.0.1", + "meow": "^3.5.0", + "semver-regex": "^1.0.0" + }, + "bin": { + "find-versions": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "dependencies": { + "glob": "~3.2.9", + "lodash": "~2.4.1" + }, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/findup-sync/node_modules/glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "dependencies": { + "inherits": "2", + "minimatch": "0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/findup-sync/node_modules/lodash": { + "version": "2.4.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true, + "engines": [ + "node", + "rhino" + ] + }, + "node_modules/findup-sync/node_modules/minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dev": true, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/flow-parser": { + "version": "0.232.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.232.0.tgz", + "integrity": "sha512-U8vcKyYdM+Kb0tPzfPJ5JyPMU0uXKwHxp0L6BcEc+wBlbTW9qRhOqV5DeGXclgclVvtqQNGEG8Strj/b6c/IxA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "dependencies": { + "debug": "=3.1.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/follow-redirects/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/follow-redirects/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/fs-extra/node_modules/graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "node_modules/fs-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-1.0.0.tgz", + "integrity": "sha512-FXxDCsJ8iBVvoJtp1s5KhnK4jrPW5y5zd82ztrwQYx9a4goOb40rxrQYTndB/OOSl2LHNOyIb+jfmzuXNQM4jQ==", + "deprecated": "Use mz or fs-extra^3.0 with Promise Support", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "fs-extra": "^1.0.0", + "mz": "^2.3.1", + "thenify-all": "^1.6.0" + } + }, + "node_modules/fs-promise/node_modules/fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + }, + "node_modules/fs-promise/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/fs-promise/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "bundleDependencies": [ + "node-pre-gyp" + ], + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/fsevents/node_modules/abbrev": { + "version": "1.1.1", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/aproba": { + "version": "1.2.0", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/are-we-there-yet": { + "version": "1.1.5", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/fsevents/node_modules/balanced-match": { + "version": "1.0.0", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/brace-expansion": { + "version": "1.1.11", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fsevents/node_modules/chownr": { + "version": "1.1.1", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/code-point-at": { + "version": "1.1.0", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/concat-map": { + "version": "0.0.1", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/console-control-strings": { + "version": "1.1.0", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/core-util-is": { + "version": "1.0.2", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/debug": { + "version": "4.1.1", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/fsevents/node_modules/deep-extend": { + "version": "0.6.0", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fsevents/node_modules/delegates": { + "version": "1.0.0", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/detect-libc": { + "version": "1.0.3", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "inBundle": true, + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/fsevents/node_modules/fs-minipass": { + "version": "1.2.5", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "minipass": "^2.2.1" + } + }, + "node_modules/fsevents/node_modules/fs.realpath": { + "version": "1.0.0", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/gauge": { + "version": "2.7.4", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/fsevents/node_modules/glob": { + "version": "7.1.3", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "inBundle": true, + "optional": true, + "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" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/has-unicode": { + "version": "2.0.1", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/iconv-lite": { + "version": "0.4.24", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/ignore-walk": { + "version": "3.0.1", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/fsevents/node_modules/inflight": { + "version": "1.0.6", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/inherits": { + "version": "2.0.3", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/ini": { + "version": "1.3.5", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/isarray": { + "version": "1.0.0", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/minimatch": { + "version": "3.0.4", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/minimist": { + "version": "0.0.8", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/minipass": { + "version": "2.3.5", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/fsevents/node_modules/minizlib": { + "version": "1.2.1", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "minipass": "^2.2.1" + } + }, + "node_modules/fsevents/node_modules/mkdirp": { + "version": "0.5.1", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "dev": true, + "inBundle": true, "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" + "dependencies": { + "minimist": "0.0.8" }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fsevents/node_modules/ms": { + "version": "2.1.1", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/needle": { + "version": "2.3.0", + "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", + "dev": true, + "inBundle": true, + "optional": true, "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": false, - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "resolved": false, - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": false, - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": false, - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": false, - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "minipass": { - "version": "2.3.5", - "resolved": false, - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": false, - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "resolved": false, - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "resolved": false, - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": 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" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": false, - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "resolved": false, - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "resolved": false, - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "resolved": false, - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": false, - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/fsevents/node_modules/node-pre-gyp": { + "version": "0.12.0", + "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/fsevents/node_modules/nopt": { + "version": "4.0.1", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/fsevents/node_modules/npm-bundled": { + "version": "1.0.6", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/npm-packlist": { + "version": "1.4.1", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "node_modules/fsevents/node_modules/npmlog": { + "version": "4.1.2", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/fsevents/node_modules/number-is-nan": { + "version": "1.0.1", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/object-assign": { + "version": "4.1.1", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/once": { + "version": "1.4.0", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/os-homedir": { + "version": "1.0.2", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/os-tmpdir": { + "version": "1.0.2", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/osenv": { + "version": "0.1.5", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/fsevents/node_modules/path-is-absolute": { + "version": "1.0.1", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/process-nextick-args": { + "version": "2.0.0", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/rc": { + "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/fsevents/node_modules/rc/node_modules/minimist": { + "version": "1.2.0", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/readable-stream": { + "version": "2.3.6", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "inBundle": true, + "optional": true, + "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" + } + }, + "node_modules/fsevents/node_modules/rimraf": { + "version": "2.6.3", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/fsevents/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/safer-buffer": { + "version": "2.1.2", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/sax": { + "version": "1.2.4", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/semver": { + "version": "5.7.0", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true, + "inBundle": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/fsevents/node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/signal-exit": { + "version": "3.0.2", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fsevents/node_modules/string-width": { + "version": "1.0.2", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "gaze": { + "node_modules/fsevents/node_modules/strip-ansi": { + "version": "3.0.1", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/strip-json-comments": { + "version": "2.0.1", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/tar": { + "version": "4.4.8", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/fsevents/node_modules/util-deprecate": { + "version": "1.0.2", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/wide-align": { + "version": "1.1.3", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "inBundle": true, + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/fsevents/node_modules/wrappy": { + "version": "1.0.2", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/fsevents/node_modules/yallist": { + "version": "3.0.3", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true, + "inBundle": true, + "optional": true + }, + "node_modules/gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "dev": true, - "requires": { + "dependencies": { "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "get-caller-file": { + "node_modules/get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "get-stdin": { + "node_modules/get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "get-value": { + "node_modules/get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "getobject": { + "node_modules/getobject": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "gettext-parser": { + "node_modules/gettext-parser": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz", "integrity": "sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=", "dev": true, - "requires": { + "dependencies": { "encoding": "^0.1.11" } }, - "glob": { + "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, - "requires": { + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", @@ -2111,79 +4583,110 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, - "dependencies": { - "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" - } - } + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "glob-parent": { + "node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { + "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" } }, - "globule": { + "node_modules/globule": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", "dev": true, - "requires": { + "dependencies": { "glob": "~7.1.1", "lodash": "~4.17.10", "minimatch": "~3.0.2" }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/globule/node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "node_modules/globule/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "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" - } - } + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "graceful-fs": { + "node_modules/graceful-fs": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "deprecated": "please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "grunt": { + "node_modules/grunt": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", "dev": true, - "requires": { + "dependencies": { "async": "~0.1.22", "coffee-script": "~1.3.3", "colors": "~0.6.2", @@ -2205,111 +4708,134 @@ "underscore.string": "~2.2.1", "which": "~1.0.5" }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - } + "engines": { + "node": ">= 0.8.0" } }, - "grunt-browser-sync": { + "node_modules/grunt-browser-sync": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/grunt-browser-sync/-/grunt-browser-sync-2.2.0.tgz", "integrity": "sha1-oOnB/RzLXEVMJexRcBE///BqR3I=", "dev": true, - "requires": { + "dependencies": { "browser-sync": "^2.6.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "grunt-contrib-coffee": { + "node_modules/grunt-contrib-coffee": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-1.0.0.tgz", "integrity": "sha1-2u6wSVTxTihovMm6bq+RBf3C2kw=", "dev": true, - "requires": { + "dependencies": { "chalk": "~1.0.0", "coffee-script": "~1.10.0", "lodash": "~4.3.0", "uri-path": "~1.0.0" }, + "engines": { + "node": ">= 0.10.0" + }, + "peerDependencies": { + "grunt": ">= 0.4.5" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/chalk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", + "integrity": "sha1-s89O0P9Tl8mcdbj2edsvUoMfltw=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.0.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^1.0.3", + "strip-ansi": "^2.0.1", + "supports-color": "^1.3.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/coffee-script": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz", + "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/has-ansi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", + "integrity": "sha1-wLWxYV2eOCsP9nFp2We0JeSMpTg=", + "dev": true, "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "chalk": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", - "integrity": "sha1-s89O0P9Tl8mcdbj2edsvUoMfltw=", - "dev": true, - "requires": { - "ansi-styles": "^2.0.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^1.0.3", - "strip-ansi": "^2.0.1", - "supports-color": "^1.3.0" - } - }, - "coffee-script": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz", - "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=", - "dev": true - }, - "has-ansi": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", - "integrity": "sha1-wLWxYV2eOCsP9nFp2We0JeSMpTg=", - "dev": true, - "requires": { - "ansi-regex": "^1.1.0", - "get-stdin": "^4.0.1" - } - }, - "lodash": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", - "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", - "dev": true - }, - "strip-ansi": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", - "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", - "dev": true, - "requires": { - "ansi-regex": "^1.0.0" - } - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", - "dev": true - } + "ansi-regex": "^1.1.0", + "get-stdin": "^4.0.1" + }, + "bin": { + "has-ansi": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/lodash": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "dev": true + }, + "node_modules/grunt-contrib-coffee/node_modules/strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true, + "dependencies": { + "ansi-regex": "^1.0.0" + }, + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-coffee/node_modules/supports-color": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "dev": true, + "bin": { + "supports-color": "cli.js" + }, + "engines": { + "node": ">=0.8.0" } }, - "grunt-contrib-compass": { + "node_modules/grunt-contrib-compass": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/grunt-contrib-compass/-/grunt-contrib-compass-1.1.1.tgz", "integrity": "sha1-PCXSCeAYglqsn6gjFbvm38HGNtw=", "dev": true, - "requires": { + "dependencies": { "async": "^1.5.2", "bin-version-check": "^2.0.0", "dargs": "^2.0.3", @@ -2317,222 +4843,287 @@ "tmp": "0.0.28", "which": "^1.0.9" }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "grunt": ">= 0.4.5" } }, - "grunt-contrib-concat": { + "node_modules/grunt-contrib-compass/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/grunt-contrib-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=", "dev": true, - "requires": { + "dependencies": { "chalk": "^1.0.0", "source-map": "^0.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" } }, - "grunt-contrib-copy": { + "node_modules/grunt-contrib-copy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", "dev": true, - "requires": { + "dependencies": { "chalk": "^1.1.1", "file-sync-cmp": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "grunt-contrib-jshint": { + "node_modules/grunt-contrib-jshint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-2.0.0.tgz", "integrity": "sha512-4qR411I1bhvVrPkKBzCUcrWkTEtBuWioXi9ABWRXHoplRScg03jiMqLDpzS4pDhVsLOTx5F9l+0cnMc+Gd2MWg==", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.4.1", "hooker": "^0.2.3", "jshint": "~2.9.6" }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-contrib-jshint/node_modules/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, "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-jshint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-jshint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "grunt-contrib-uglify": { + "node_modules/grunt-contrib-uglify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz", "integrity": "sha512-dwf8/+4uW1+7pH72WButOEnzErPGmtUvc8p08B0eQS/6ON0WdeQu0+WFeafaPTbbY1GqtS25lsHWaDeiTQNWPg==", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.4.1", "maxmin": "^2.1.0", "uglify-js": "^3.5.0", "uri-path": "^1.0.0" }, + "engines": { + "node": ">=6" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "grunt-contrib-watch": { + "node_modules/grunt-contrib-watch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", "dev": true, - "requires": { + "dependencies": { "async": "^2.6.0", "gaze": "^1.1.0", "lodash": "^4.17.10", "tiny-lr": "^1.1.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-watch/node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } + "lodash": "^4.17.14" } }, - "grunt-eco": { + "node_modules/grunt-contrib-watch/node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "node_modules/grunt-eco": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/grunt-eco/-/grunt-eco-0.1.3.tgz", "integrity": "sha1-TmuoaUihEimQp+rmHFerlhp2ntY=", "dev": true, - "requires": { + "dependencies": { "eco": "~1.0" + }, + "engines": { + "node": ">=0.8" + }, + "peerDependencies": { + "grunt": ">=0.4.0" } }, - "grunt-execute": { + "node_modules/grunt-execute": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz", "integrity": "sha1-TpRf5XlZzA3neZCDtrQq7ZYWNQo=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": "~0.4.1" + } }, - "grunt-legacy-log": { + "node_modules/grunt-legacy-log": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", "dev": true, - "requires": { + "dependencies": { "colors": "~0.6.2", "grunt-legacy-log-utils": "~0.1.1", "hooker": "~0.2.3", "lodash": "~2.4.1", "underscore.string": "~2.3.3" }, - "dependencies": { - "lodash": { - "version": "2.4.2", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", - "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", - "dev": true - }, - "underscore.string": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", - "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", - "dev": true - } + "engines": { + "node": ">= 0.8.0" } }, - "grunt-legacy-log-utils": { + "node_modules/grunt-legacy-log-utils": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", "dev": true, - "requires": { + "dependencies": { "colors": "~0.6.2", "lodash": "~2.4.1", "underscore.string": "~2.3.3" }, - "dependencies": { - "lodash": { - "version": "2.4.2", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", - "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", - "dev": true - }, - "underscore.string": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", - "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", - "dev": true - } + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/grunt-legacy-log-utils/node_modules/lodash": { + "version": "2.4.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true, + "engines": [ + "node", + "rhino" + ] + }, + "node_modules/grunt-legacy-log-utils/node_modules/underscore.string": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/grunt-legacy-log/node_modules/lodash": { + "version": "2.4.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true, + "engines": [ + "node", + "rhino" + ] + }, + "node_modules/grunt-legacy-log/node_modules/underscore.string": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true, + "engines": { + "node": "*" } }, - "grunt-legacy-util": { + "node_modules/grunt-legacy-util": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", "dev": true, - "requires": { + "dependencies": { "async": "~0.1.22", "exit": "~0.1.1", "getobject": "~0.1.0", @@ -2540,475 +5131,930 @@ "lodash": "~0.9.2", "underscore.string": "~2.2.1", "which": "~1.0.5" + }, + "engines": { + "node": ">= 0.8.0" } }, - "grunt-marked": { + "node_modules/grunt-marked": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/grunt-marked/-/grunt-marked-0.1.3.tgz", "integrity": "sha1-bbVt64kGf1+nGuPwGt9D291HQAo=", "dev": true, - "requires": { + "dependencies": { "async": "~0.2.10", "highlight.js": "~8.0.0", "marked": "~0.3.1" }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4.2" } }, - "grunt-po2json": { + "node_modules/grunt-marked/node_modules/async": { + "version": "0.2.10", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "node_modules/grunt-po2json": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/grunt-po2json/-/grunt-po2json-0.3.0.tgz", "integrity": "sha1-y4hZOErUzFokTHfMAm846sayhMM=", "dev": true, - "requires": { + "dependencies": { "po2json": "*" + }, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": "~0.4.1" } }, - "grunt-shell": { + "node_modules/grunt-shell": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-2.1.0.tgz", "integrity": "sha1-Q595FZ7RHmSmUaacyKPQK+v17MI=", "dev": true, - "requires": { + "dependencies": { "chalk": "^1.0.0", "npm-run-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "grunt": ">=0.4.0" } }, - "gzip-size": { + "node_modules/grunt/node_modules/glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "dependencies": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + }, + "engines": { + "node": "*" + } + }, + "node_modules/grunt/node_modules/inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "node_modules/gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", "dev": true, - "requires": { + "dependencies": { "duplexer": "^0.1.1" + }, + "engines": { + "node": ">=0.12.0" } }, - "has-ansi": { + "node_modules/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": { + "dependencies": { "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "has-binary2": { + "node_modules/has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, - "requires": { + "dependencies": { "isarray": "2.0.1" } }, - "has-color": { + "node_modules/has-color": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "has-cors": { + "node_modules/has-cors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", "dev": true }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "has-value": { + "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, - "requires": { + "dependencies": { "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "has-values": { + "node_modules/has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, - "requires": { + "dependencies": { "is-number": "^3.0.0", "kind-of": "^4.0.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "highlight.js": { + "node_modules/highlight.js": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-8.0.0.tgz", "integrity": "sha1-uB21vo5vXFApxAtmtHMXDNPgh1o=", - "dev": true + "deprecated": "Version no longer supported. Upgrade to @latest", + "dev": true, + "engines": { + "node": "*" + } }, - "hooker": { + "node_modules/hooker": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "hosted-git-info": { + "node_modules/hosted-git-info": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, - "htmlparser2": { + "node_modules/htmlparser2": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", "dev": true, - "requires": { + "dependencies": { "domelementtype": "1", "domhandler": "2.3", "domutils": "1.5", "entities": "1.0", "readable-stream": "1.1" - }, + } + }, + "node_modules/htmlparser2/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/htmlparser2/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "http-errors": { + "node_modules/htmlparser2/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, - "requires": { + "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "http-parser-js": { + "node_modules/http-parser-js": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, - "http-proxy": { + "node_modules/http-proxy": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.15.2.tgz", "integrity": "sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE=", "dev": true, - "requires": { + "dependencies": { "eventemitter3": "1.x.x", "requires-port": "1.x.x" + }, + "engines": { + "node": ">=0.10.0" } }, - "iconv-lite": { + "node_modules/iconv-lite": { "version": "0.2.11", "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } }, - "immutable": { + "node_modules/immutable": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } }, - "indent-string": { + "node_modules/indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, - "requires": { + "dependencies": { "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "indexof": { + "node_modules/indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "invert-kv": { + "node_modules/invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-accessor-descriptor": { + "node_modules/is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "deprecated": "Please upgrade to v0.1.7", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-arrayish": { + "node_modules/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-binary-path": { + "node_modules/is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, - "requires": { + "dependencies": { "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-buffer": { + "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-data-descriptor": { + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-ci-cli/-/is-ci-cli-2.2.0.tgz", + "integrity": "sha512-Xg97ZGDzU0a9gPTAli+TNegMk+PI3x0KLRYCfBa2LAboF1YyuA03Gwdc9vpu3VRNU+lFFNkvXnIQuJ0PgB120Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "is-ci": "^2.0.0" + }, + "bin": { + "is-ci": "cli.js", + "is-ci-cli": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "deprecated": "Please upgrade to v0.1.5", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-descriptor": { + "node_modules/is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, - "requires": { + "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "is-extendable": { + "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-extglob": { + "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-finite": { + "node_modules/is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, - "requires": { + "dependencies": { "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "requires": { + "dependencies": { "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dev": true, + "dependencies": { + "lodash.isfinite": "^3.3.2" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "dependencies": { + "argparse": "~ 0.1.11", + "esprima": "~ 1.0.2" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + }, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jscodeshift/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jscodeshift/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jscodeshift/node_modules/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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jscodeshift/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jscodeshift/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jscodeshift/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "node_modules/jscodeshift/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "requires": { - "is-extglob": "^2.1.1" + "engines": { + "node": ">=0.12.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "node_modules/jscodeshift/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "node_modules/jscodeshift/node_modules/recast": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz", + "integrity": "sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==", "dev": true, - "requires": { - "lodash.isfinite": "^3.3.2" + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/jscodeshift/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "requires": { - "isobject": "^3.0.1" + "engines": { + "node": ">=0.10.0" } }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true + "node_modules/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "node_modules/jscodeshift/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } }, - "js-yaml": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", - "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "requires": { - "argparse": "~ 0.1.11", - "esprima": "~ 1.0.2" + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" } }, - "jshint": { + "node_modules/jshint": { "version": "2.9.7", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.7.tgz", "integrity": "sha512-Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA==", "dev": true, - "requires": { + "dependencies": { "cli": "~1.0.0", "console-browserify": "1.1.x", "exit": "0.1.x", @@ -3018,198 +6064,365 @@ "shelljs": "0.3.x", "strip-json-comments": "1.0.x" }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "node_modules/jshint/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "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" - } - } + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, - "jsonfile": { + "node_modules/jsonfile": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", "dev": true, - "requires": { + "optionalDependencies": { "graceful-fs": "^4.1.6" - }, + } + }, + "node_modules/jsonfile/node_modules/graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true, + "optional": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true, - "optional": true - } + "json-buffer": "3.0.1" } }, - "kind-of": { + "node_modules/kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } }, - "lcid": { + "node_modules/klaw/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "optional": true + }, + "node_modules/lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, - "requires": { + "dependencies": { "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "limiter": { + "node_modules/limiter": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz", "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==", "dev": true }, - "livereload-js": { + "node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/livereload-js": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", "dev": true }, - "load-json-file": { + "node_modules/load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "strip-bom": "^2.0.0" }, - "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "localtunnel": { + "node_modules/load-json-file/node_modules/graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "node_modules/localtunnel": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.2.tgz", "integrity": "sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg==", "dev": true, - "requires": { + "dependencies": { "axios": "0.19.0", "debug": "4.1.1", "openurl": "1.1.1", "yargs": "6.6.0" }, + "bin": { + "lt": "bin/client" + } + }, + "node_modules/localtunnel/node_modules/yargs": { + "version": "6.6.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, "dependencies": { - "yargs": { - "version": "6.6.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" - } - } + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.2.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lodash": { + "node_modules/lodash": { "version": "0.9.2", "resolved": "http://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", - "dev": true + "dev": true, + "engines": [ + "node", + "rhino" + ] }, - "lodash.isfinite": { + "node_modules/lodash.isfinite": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", "dev": true }, - "loud-rejection": { + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, - "requires": { + "dependencies": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "lru-cache": { + "node_modules/lru-cache": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, - "map-cache": { + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "map-obj": { + "node_modules/map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "map-visit": { + "node_modules/map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, - "requires": { + "dependencies": { "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "marked": { + "node_modules/marked": { "version": "0.3.19", "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", - "dev": true + "dev": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">=0.10.0" + } }, - "maxmin": { + "node_modules/maxmin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=", "dev": true, - "requires": { + "dependencies": { "chalk": "^1.0.0", "figures": "^1.0.1", "gzip-size": "^3.0.0", "pretty-bytes": "^3.0.0" + }, + "engines": { + "node": ">=0.12" } }, - "meow": { + "node_modules/meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "requires": { + "dependencies": { "camelcase-keys": "^2.0.0", "decamelize": "^1.1.2", "loud-rejection": "^1.0.0", @@ -3220,14 +6433,17 @@ "read-pkg-up": "^1.0.1", "redent": "^1.0.0", "trim-newlines": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "micromatch": { + "node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "requires": { + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", @@ -3241,91 +6457,131 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "mime": { + "node_modules/mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true + "dev": true, + "bin": { + "mime": "cli.js" + } }, - "mime-db": { + "node_modules/mime-db": { "version": "1.42.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "mime-types": { + "node_modules/mime-types": { "version": "2.1.25", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", "dev": true, - "requires": { + "dependencies": { "mime-db": "1.42.0" + }, + "engines": { + "node": ">= 0.6" } }, - "minimatch": { + "node_modules/minimatch": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", "dev": true, - "requires": { + "dependencies": { "lru-cache": "2", "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" } }, - "minimist": { + "node_modules/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mitt": { + "node_modules/mitt": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", "dev": true }, - "mixin-deep": { + "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, - "requires": { + "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, + "engines": { + "node": "*" } }, - "ms": { + "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "nan": { + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, - "nanomatch": { + "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, - "requires": { + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", @@ -3337,441 +6593,822 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "negotiator": { + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, - "nomnom": { + "node_modules/nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.", "dev": true, - "requires": { + "dependencies": { "chalk": "~0.4.0", "underscore": "~1.6.0" - }, + } + }, + "node_modules/nomnom/node_modules/ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nomnom/node_modules/chalk": { + "version": "0.4.0", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true - }, - "chalk": { - "version": "0.4.0", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - } + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nomnom/node_modules/strip-ansi": { + "version": "0.1.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true, + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.8.0" } }, - "nopt": { + "node_modules/nomnom/node_modules/underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + }, + "node_modules/nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", "dev": true, - "requires": { + "dependencies": { "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" } }, - "normalize-package-data": { + "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "requires": { + "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, - "normalize-path": { + "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "npm-run-path": { + "node_modules/npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, - "requires": { + "dependencies": { "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "number-is-nan": { + "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "object-assign": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "object-component": { + "node_modules/object-component": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, - "object-copy": { + "node_modules/object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { + "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "object-path": { + "node_modules/object-path": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz", "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "object-visit": { + "node_modules/object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "object.pick": { + "node_modules/object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "on-finished": { + "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, - "requires": { + "dependencies": { "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "openurl": { + "node_modules/openurl": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", "dev": true }, - "opn": { + "node_modules/opn": { "version": "5.3.0", "resolved": "http://registry.npmjs.org/opn/-/opn-5.3.0.tgz", "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, - "requires": { + "dependencies": { "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "os-locale": { + "node_modules/os-locale": { "version": "1.4.0", "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, - "requires": { + "dependencies": { "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "os-tmpdir": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "parse-json": { + "node_modules/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": { + "dependencies": { "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "parseqs": { + "node_modules/parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, - "requires": { + "dependencies": { "better-assert": "~1.0.0" } }, - "parseuri": { + "node_modules/parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, - "requires": { + "dependencies": { "better-assert": "~1.0.0" } }, - "parseurl": { + "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8" + } }, - "pascalcase": { + "node_modules/pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-dirname": { + "node_modules/path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, - "path-exists": { + "node_modules/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": { + "dependencies": { "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "path-is-absolute": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { + "node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "path-parse": { + "node_modules/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": { + "node_modules/path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" }, - "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - } + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type/node_modules/graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "pify": { + "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "pinkie": { + "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "pinkie-promise": { + "node_modules/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": { + "dependencies": { "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" } }, - "po2json": { + "node_modules/po2json": { "version": "0.4.5", "resolved": "http://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz", "integrity": "sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=", "dev": true, - "requires": { + "dependencies": { "gettext-parser": "1.1.0", "nomnom": "1.8.1" + }, + "bin": { + "po2json": "bin/po2json" + }, + "engines": { + "node": ">= 0.8.0" } }, - "portscanner": { + "node_modules/portscanner": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", "dev": true, - "requires": { + "dependencies": { "async": "1.5.2", "is-number-like": "^1.0.3" }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } + "engines": { + "node": ">=0.4", + "npm": ">=1.0.0" } }, - "posix-character-classes": { + "node_modules/portscanner/node_modules/async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "pretty-bytes": { + "node_modules/pretty-bytes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", "dev": true, - "requires": { + "dependencies": { "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "process-nextick-args": { + "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "qs": { + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "range-parser": { + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "raw-body": { + "node_modules/raw-body": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", "dev": true, - "requires": { + "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.3", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "read-pkg": { + "node_modules/read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, - "requires": { + "dependencies": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "read-pkg-up": { + "node_modules/read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, - "requires": { + "dependencies": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "readable-stream": { + "node_modules/readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -3779,232 +7416,379 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } } }, - "readdirp": { + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/readdirp/node_modules/graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "node_modules/recast": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.19.1.tgz", + "integrity": "sha512-8FCjrBxjeEU2O6I+2hyHyBFH1siJbMBLwIRvVr1T3FD2cL754sOaJDsJ/8h3xYltasbJ8jqWRIhMuDGBSiSbjw==", + "dev": true, "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - } + "ast-types": "0.13.3", + "esprima": "~4.0.0", + "private": "^0.1.8", + "source-map": "~0.6.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "redent": { + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, - "requires": { + "dependencies": { "indent-string": "^2.1.0", "strip-indent": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "regex-not": { + "node_modules/regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", + "dev": true + }, + "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "remove-trailing-separator": { + "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "repeat-element": { + "node_modules/repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "repeat-string": { + "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10" + } }, - "repeating": { + "node_modules/repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, - "requires": { + "dependencies": { "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "require-directory": { + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "require-main-filename": { + "node_modules/require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "requires-port": { + "node_modules/require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha512-Xct+41K3twrbBHdxAgMoOS+cNcoqIjfM2/VxBF4LL2hVph7YsF8VSKyQ3BDFZwEVbok9yeDl2le/qo0S77WG2w==", + "dev": true, + "dependencies": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-uncached/node_modules/resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha512-kT10v4dhrlLNcnO084hEjvXCI1wUG9qZLoz2RogxqDQQYy7IxjI/iMUkOtQTNEh6rzHxvdQWHsJyel1pKOVCxg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, - "resolve": { + "node_modules/resolve": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", "dev": true, - "requires": { + "dependencies": { "path-parse": "^1.0.6" } }, - "resolve-url": { + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", "dev": true }, - "resp-modifier": { + "node_modules/resp-modifier": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", "dev": true, - "requires": { - "debug": "^2.2.0", - "minimatch": "^3.0.2" - }, "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" - } - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "debug": "^2.2.0", + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/resp-modifier/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/resp-modifier/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "ret": { + "node_modules/resp-modifier/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } }, - "rimraf": { + "node_modules/rimraf": { "version": "2.2.8", "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "dev": true, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } }, - "rx": { + "node_modules/rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", "dev": true }, - "rxjs": { + "node_modules/rxjs": { "version": "5.5.12", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", "dev": true, - "requires": { + "dependencies": { "symbol-observable": "1.0.1" + }, + "engines": { + "npm": ">=2.0.0" } }, - "safe-buffer": { + "node_modules/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==", "dev": true }, - "safe-json-parse": { + "node_modules/safe-json-parse": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", "dev": true }, - "safe-regex": { + "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, - "requires": { + "dependencies": { "ret": "~0.1.10" } }, - "safer-buffer": { + "node_modules/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": { + "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "semver-regex": { + "node_modules/semver-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "semver-truncate": { + "node_modules/semver-truncate": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", "dev": true, - "requires": { + "dependencies": { "semver": "^5.3.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "send": { + "node_modules/send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, - "requires": { + "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", @@ -4019,54 +7803,61 @@ "range-parser": "~1.2.0", "statuses": "~1.4.0" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "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" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "serve-index": { + "node_modules/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, - "requires": { + "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", @@ -4075,125 +7866,187 @@ "mime-types": "~2.1.17", "parseurl": "~1.3.2" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "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" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "serve-static": { + "node_modules/serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, - "requires": { + "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.2", "send": "0.16.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "server-destroy": { + "node_modules/server-destroy": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", "dev": true }, - "set-blocking": { + "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-value": { + "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "setprototypeof": { + "node_modules/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, - "shelljs": { + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true + "dev": true, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } }, - "sigmund": { + "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "snapdragon": { + "node_modules/simple-git": { + "version": "1.132.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.132.0.tgz", + "integrity": "sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg==", + "dev": true, + "dependencies": { + "debug": "^4.0.1" + } + }, + "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, - "requires": { + "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", @@ -4203,288 +8056,314 @@ "source-map-resolve": "^0.5.0", "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-node": { + "node_modules/snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, - "requires": { + "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-util": { + "node_modules/snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.2.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "socket.io": { + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, - "requires": { + "dependencies": { "debug": "~3.1.0", "engine.io": "~3.2.0", "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", "socket.io-client": "2.1.1", "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "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" - } - }, - "engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - } - }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - } } }, - "socket.io-adapter": { + "node_modules/socket.io-adapter": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", "dev": true }, - "socket.io-client": { + "node_modules/socket.io-client": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", "dev": true, - "requires": { + "dependencies": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + } + }, + "node_modules/socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "dev": true, + "dependencies": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/socket.io/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/socket.io/node_modules/engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "dependencies": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "node_modules/socket.io/node_modules/engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "dependencies": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/socket.io/node_modules/socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "dependencies": { "backo2": "1.0.2", "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" } }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "node_modules/socket.io/node_modules/socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, - "requires": { + "dependencies": { "component-emitter": "1.2.1", "debug": "~3.1.0", "isarray": "2.0.1" - }, + } + }, + "node_modules/socket.io/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, "dependencies": { - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, - "source-map": { + "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "source-map-resolve": { + "node_modules/source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dev": true, - "requires": { + "dependencies": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", @@ -4492,513 +8371,826 @@ "urix": "^0.1.0" } }, - "source-map-url": { + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, - "spdx-correct": { + "node_modules/spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, - "requires": { + "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-exceptions": { + "node_modules/spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, - "spdx-expression-parse": { + "node_modules/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": { + "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { + "node_modules/spdx-license-ids": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "split-string": { + "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "static-extend": { + "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { + "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "statuses": { + "node_modules/statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "stream-throttle": { + "node_modules/stream-throttle": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", "dev": true, - "requires": { + "dependencies": { "commander": "^2.2.0", "limiter": "^1.0.5" + }, + "bin": { + "throttleproxy": "bin/throttleproxy.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "string-template": { + "node_modules/string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", "dev": true }, - "string-width": { + "node_modules/string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "requires": { + "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.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": { + "node_modules/strip-ansi": { "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "strip-bom": { + "node_modules/strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, - "requires": { + "dependencies": { "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "strip-indent": { + "node_modules/strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, - "requires": { + "dependencies": { "get-stdin": "^4.0.1" + }, + "bin": { + "strip-indent": "cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true + "dev": true, + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } }, - "strscan": { + "node_modules/strscan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strscan/-/strscan-1.0.1.tgz", "integrity": "sha1-Ry2bwAxo6QbvL8Is33Yr58YazE0=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "supports-color": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "symbol-observable": { + "node_modules/symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "tfunk": { + "node_modules/tfunk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-3.1.0.tgz", "integrity": "sha1-OORBT8ZJd9h6/apy+sttKfgve1s=", "dev": true, - "requires": { + "dependencies": { "chalk": "^1.1.1", "object-path": "^0.9.0" } }, - "tiny-lr": { + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tiny-lr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, - "requires": { + "dependencies": { "body": "^5.1.0", "debug": "^3.1.0", "faye-websocket": "~0.10.0", "livereload-js": "^2.3.0", "object-assign": "^4.1.0", "qs": "^6.4.0" - }, + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "qs": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", - "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", - "dev": true - } + "ms": "^2.1.1" + } + }, + "node_modules/tiny-lr/node_modules/qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "tmp": { + "node_modules/tmp": { "version": "0.0.28", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", "dev": true, - "requires": { + "dependencies": { "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" } }, - "to-array": { + "node_modules/to-array": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, - "to-object-path": { + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "to-regex": { + "node_modules/to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, - "requires": { + "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, - "requires": { + "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "toidentifier": { + "node_modules/toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "trim-newlines": { + "node_modules/trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "ua-parser-js": { + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ua-parser-js": { "version": "0.7.17", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "uglify-js": { + "node_modules/uglify-js": { "version": "3.6.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", "dev": true, - "requires": { + "dependencies": { "commander": "~2.20.3", "source-map": "~0.6.1" }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-js/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "ultron": { + "node_modules/ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, - "underscore": { + "node_modules/underscore": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, - "underscore.string": { + "node_modules/underscore.string": { "version": "2.2.1", "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "union-value": { + "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, - "requires": { + "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "universalify": { + "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 4.0.0" + } }, - "unpipe": { + "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8" + } }, - "unset-value": { + "node_modules/unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, - "requires": { + "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "upath": { + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } }, - "uri-path": { + "node_modules/uri-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "urix": { + "node_modules/urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", "dev": true }, - "use": { + "node_modules/use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "utils-merge": { + "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4.0" + } }, - "validate-npm-package-license": { + "node_modules/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": { + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "websocket-driver": { + "node_modules/websocket-driver": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", "dev": true, - "requires": { + "dependencies": { "http-parser-js": ">=0.4.0 <0.4.11", "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" } }, - "websocket-extensions": { + "node_modules/websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "which": { + "node_modules/which": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", - "dev": true + "dev": true, + "bin": { + "which": "bin/which" + } }, - "which-module": { + "node_modules/which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "window-size": { + "node_modules/window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "dev": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "2.1.0", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, - "requires": { + "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "ws": { + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/write-file-atomic/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/ws": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", "dev": true, - "requires": { + "dependencies": { "async-limiter": "~1.0.0" } }, - "xmlhttprequest-ssl": { + "node_modules/xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "y18n": { + "node_modules/y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, - "yargs": { + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { "version": "6.4.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz", "integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=", "dev": true, - "requires": { + "dependencies": { "camelcase": "^3.0.0", "cliui": "^3.2.0", "decamelize": "^1.1.1", @@ -5015,20 +9207,32 @@ "yargs-parser": "^4.1.0" } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "4.2.1", "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", "dev": true, - "requires": { + "dependencies": { "camelcase": "^3.0.0" } }, - "yeast": { + "node_modules/yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 87e0c47d..8b876aa2 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,11 @@ "grunt-execute": "~0.2.2", "grunt-marked": "~0.1.3", "grunt-po2json": "~0.3.0", - "grunt-shell": "2.1.0" + "grunt-shell": "2.1.0", + "bulk-decaffeinate": "3.3.1", + "decaffeinate": "8.1.4", + "eslint": "8.57.0", + "jscodeshift": "0.15.2" }, "engines": { "node": ">=0.8.0" From 2b6dc3ce7c6708581c4eb141f01195106260ffdb Mon Sep 17 00:00:00 2001 From: Max Teegen <870074+max-te@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:01:38 +0100 Subject: [PATCH 02/21] prepare for bulk-decaffeinate: rename .js.coffee to .coffee --- src/js/apps/addon/{addon_app.js.coffee => addon_app.coffee} | 0 ...don_googlemusic_app.js.coffee => addon_googlemusic_app.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/addon/list/{list_view.js.coffee => list_view.coffee} | 0 .../{addon_mixcloud_app.js.coffee => addon_mixcloud_app.coffee} | 0 .../addon/pvr/{addons_pvr_ap.js.coffee => addons_pvr_ap.coffee} | 0 .../radio/{addon_radio_app.js.coffee => addon_radio_app.coffee} | 0 ...addon_soundcloud_app.js.coffee => addon_soundcloud_app.coffee} | 0 .../{addon_youtube_app.js.coffee => addon_youtube_app.coffee} | 0 src/js/apps/album/{album_app.js.coffee => album_app.coffee} | 0 .../edit/{edit_controller.js.coffee => edit_controller.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/album/list/{list_view.js.coffee => list_view.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/album/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/artist/{artist_app.js.coffee => artist_app.coffee} | 0 .../edit/{edit_controller.js.coffee => edit_controller.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/artist/list/{list_view.js.coffee => list_view.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/artist/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/audioStream/{init.js.coffee => init.coffee} | 0 src/js/apps/browser/{browser_app.js.coffee => browser_app.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 .../apps/browser/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/cast/{cast_app.js.coffee => cast_app.coffee} | 0 src/js/apps/cast/list/{list_view.js.coffee => list_view.coffee} | 0 .../apps/category/{category_app.js.coffee => category_app.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 .../apps/category/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/command/{command_app.js.coffee => command_app.coffee} | 0 src/js/apps/command/kodi/_base/{_base.js.coffee => _base.coffee} | 0 src/js/apps/command/kodi/_base/{api.js.coffee => api.coffee} | 0 .../apps/command/kodi/helpers/{addon.js.coffee => addon.coffee} | 0 .../kodi/helpers/{application.js.coffee => application.coffee} | 0 .../kodi/helpers/{audiolibrary.js.coffee => audiolibrary.coffee} | 0 src/js/apps/command/kodi/helpers/{file.js.coffee => file.coffee} | 0 .../apps/command/kodi/helpers/{input.js.coffee => input.coffee} | 0 .../command/kodi/helpers/{playlist.js.coffee => playlist.coffee} | 0 src/js/apps/command/kodi/helpers/{pvr.js.coffee => pvr.coffee} | 0 .../apps/command/kodi/helpers/{system.js.coffee => system.coffee} | 0 .../kodi/helpers/{videolibrary.js.coffee => videolibrary.coffee} | 0 src/js/apps/command/local/_base/{_base.js.coffee => _base.coffee} | 0 src/js/apps/command/local/_base/{api.js.coffee => api.coffee} | 0 .../local/helpers/{application.js.coffee => application.coffee} | 0 .../command/local/helpers/{playlist.js.coffee => playlist.coffee} | 0 .../local/helpers/{videoplayer.js.coffee => videoplayer.coffee} | 0 src/js/apps/epg/{epg_app.js.coffee => epg_app.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/epg/list/{list_view.js.coffee => list_view.coffee} | 0 .../apps/external/{external_app.js.coffee => external_app.coffee} | 0 .../{youtube_controller.js.coffee => youtube_controller.coffee} | 0 .../youtube/{youtube_view.js.coffee => youtube_view.coffee} | 0 src/js/apps/filter/{filter_app.js.coffee => filter_app.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/filter/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/help/{help_app.js.coffee => help_app.coffee} | 0 .../{overview_controller.js.coffee => overview_controller.coffee} | 0 .../overview/{overview_view.js.coffee => overview_view.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/help/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/images/{images_app.js.coffee => images_app.coffee} | 0 src/js/apps/input/{input_app.js.coffee => input_app.coffee} | 0 .../{remote_controller.js.coffee => remote_controller.coffee} | 0 .../input/remote/{remote_view.js.coffee => remote_view.coffee} | 0 .../{resume_controller.js.coffee => resume_controller.coffee} | 0 ...iBrowser_controller.js.coffee => apiBrowser_controller.coffee} | 0 .../{apiBrowser_view.js.coffee => apiBrowser_view.coffee} | 0 .../{iconBrowser_view.js.coffee => iconBrowser_view.coffee} | 0 src/js/apps/lab/lab/{lab_view.js.coffee => lab_view.coffee} | 0 src/js/apps/lab/{lab_app.js.coffee => lab_app.coffee} | 0 src/js/apps/landing/{landing_app.js.coffee => landing_app.coffee} | 0 .../{landing_controller.js.coffee => landing_controller.coffee} | 0 .../landing/show/{landing_view.js.coffee => landing_view.coffee} | 0 src/js/apps/loading/{loading_app.js.coffee => loading_app.coffee} | 0 .../loading/show/{loading_view.js.coffee => loading_view.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 .../localPlaylist/list/{list_view.js.coffee => list_view.coffee} | 0 .../{localPlaylist_app.js.coffee => localPlaylist_app.coffee} | 0 .../edit/{edit_controller.js.coffee => edit_controller.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/movie/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/movie/{movie_app.js.coffee => movie_app.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/movie/show/{show_view.js.coffee => show_view.coffee} | 0 .../edit/{edit_controller.js.coffee => edit_controller.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 .../musicvideo/list/{list_view.js.coffee => list_view.coffee} | 0 .../{musicvideo_app.js.coffee => musicvideo_app.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 .../musicvideo/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/navMain/{navMain_app.js.coffee => navMain_app.coffee} | 0 .../navMain/show/{navMain_view.js.coffee => navMain_view.coffee} | 0 .../{notifications_app.js.coffee => notifications_app.coffee} | 0 src/js/apps/player/{player_app.js.coffee => player_app.coffee} | 0 .../player/show/{player_view.js.coffee => player_view.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 .../apps/playlist/list/{list_view.js.coffee => list_view.coffee} | 0 .../localParty/{local_party.js.coffee => local_party.coffee} | 0 .../m3u/{m3u_controller.js.coffee => m3u_controller.coffee} | 0 src/js/apps/playlist/m3u/{m3u_view.js.coffee => m3u_view.coffee} | 0 .../apps/playlist/{playlist_app.js.coffee => playlist_app.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 .../apps/playlist/show/{show_view.js.coffee => show_view.coffee} | 0 ...l_list_controller.js.coffee => channel_list_controller.coffee} | 0 .../{channel_list_view.js.coffee => channel_list_view.coffee} | 0 src/js/apps/pvr/{pvr_app.js.coffee => pvr_app.coffee} | 0 ...list_controller.js.coffee => recording_list_controller.coffee} | 0 .../{recording_list_view.js.coffee => recording_list_view.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/search/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/search/{search_app.js.coffee => search_app.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/search/show/{show_view.js.coffee => show_view.coffee} | 0 .../apps/selected/{selected_app.js.coffee => selected_app.coffee} | 0 .../apps/settings/{settings_app.js.coffee => settings_app.coffee} | 0 .../_base/{base_controller.js.coffee => base_controller.coffee} | 0 .../{addons_controller.js.coffee => addons_controller.coffee} | 0 .../kodi/{kodi_controller.js.coffee => kodi_controller.coffee} | 0 .../settings/show/kodi/{kodi_view.js.coffee => kodi_view.coffee} | 0 .../local/{local_controller.js.coffee => local_controller.coffee} | 0 .../{navMain_controller.js.coffee => navMain_controller.coffee} | 0 .../{search_controller.js.coffee => search_controller.coffee} | 0 .../apps/settings/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/shell/{shell_app.js.coffee => shell_app.coffee} | 0 .../apps/shell/show/{shell_view.js.coffee => shell_view.coffee} | 0 .../edit/{edit_controller.js.coffee => edit_controller.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/song/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/song/{song_app.js.coffee => song_app.coffee} | 0 src/js/apps/state/_base/{base.js.coffee => base.coffee} | 0 src/js/apps/state/kodi/{kodi.js.coffee => kodi.coffee} | 0 .../state/kodi/{notifications.js.coffee => notifications.coffee} | 0 src/js/apps/state/kodi/{polling.js.coffee => polling.coffee} | 0 src/js/apps/state/local/{local.js.coffee => local.coffee} | 0 src/js/apps/state/{state_app.js.coffee => state_app.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/thumbs/list/{list_view.js.coffee => list_view.coffee} | 0 src/js/apps/thumbs/{thumbs_app.js.coffee => thumbs_app.coffee} | 0 ...pisode_controller.js.coffee => edit_episode_controller.coffee} | 0 ...edit_show_controller.js.coffee => edit_show_controller.coffee} | 0 .../{episode_controller.js.coffee => episode_controller.coffee} | 0 .../episode/{episode_view.js.coffee => episode_view.coffee} | 0 .../list/{list_controller.js.coffee => list_controller.coffee} | 0 src/js/apps/tvshow/list/{list_view.js.coffee => list_view.coffee} | 0 .../{season_controller.js.coffee => season_controller.coffee} | 0 .../tvshow/season/{season_view.js.coffee => season_view.coffee} | 0 .../show/{show_controller.js.coffee => show_controller.coffee} | 0 src/js/apps/tvshow/show/{show_view.js.coffee => show_view.coffee} | 0 src/js/apps/tvshow/{tvshow_app.js.coffee => tvshow_app.coffee} | 0 src/js/apps/ui/{ui_app.js.coffee => ui_app.coffee} | 0 .../form/{form_controller.js.coffee => form_controller.coffee} | 0 src/js/components/form/{form_view.js.coffee => form_view.coffee} | 0 src/js/config/backbone/{sync.js.coffee => sync.coffee} | 0 .../marionette/{application.js.coffee => application.coffee} | 0 src/js/config/marionette/{renderer.js.coffee => renderer.coffee} | 0 src/js/controllers/{_base.js.coffee => _base.coffee} | 0 src/js/controllers/{router.js.coffee => router.coffee} | 0 .../entities/_base/{collections.js.coffee => collections.coffee} | 0 src/js/entities/_base/{filtered.js.coffee => filtered.coffee} | 0 src/js/entities/_base/{models.js.coffee => models.coffee} | 0 src/js/entities/config/{configApp.js.coffee => configApp.coffee} | 0 .../entities/config/{configKodi.js.coffee => configKodi.coffee} | 0 src/js/entities/external/{_base.js.coffee => _base.coffee} | 0 src/js/entities/external/{fanarttv.js.coffee => fanarttv.coffee} | 0 .../external/{musicbrainz.js.coffee => musicbrainz.coffee} | 0 .../entities/external/{themoviedb.js.coffee => themoviedb.coffee} | 0 src/js/entities/external/{youtube.js.coffee => youtube.coffee} | 0 src/js/entities/filter/{filter.js.coffee => filter.coffee} | 0 src/js/entities/form/{form.js.coffee => form.coffee} | 0 src/js/entities/kodi/_base/{_fetch.js.coffee => _fetch.coffee} | 0 .../kodi/_base/{collections.js.coffee => collections.coffee} | 0 src/js/entities/kodi/_base/{models.js.coffee => models.coffee} | 0 src/js/entities/kodi/{addon.js.coffee => addon.coffee} | 0 src/js/entities/kodi/{album.js.coffee => album.coffee} | 0 src/js/entities/kodi/{artist.js.coffee => artist.coffee} | 0 src/js/entities/kodi/{cast.js.coffee => cast.coffee} | 0 src/js/entities/kodi/{epg.js.coffee => epg.coffee} | 0 src/js/entities/kodi/{episode.js.coffee => episode.coffee} | 0 src/js/entities/kodi/{file.js.coffee => file.coffee} | 0 src/js/entities/kodi/{genres.js.coffee => genres.coffee} | 0 src/js/entities/kodi/{movie.js.coffee => movie.coffee} | 0 src/js/entities/kodi/{musicvideo.js.coffee => musicvideo.coffee} | 0 src/js/entities/kodi/{playlist.js.coffee => playlist.coffee} | 0 src/js/entities/kodi/{pvr.js.coffee => pvr.coffee} | 0 src/js/entities/kodi/{season.js.coffee => season.coffee} | 0 src/js/entities/kodi/{settings.js.coffee => settings.coffee} | 0 src/js/entities/kodi/{song.js.coffee => song.coffee} | 0 src/js/entities/kodi/{tvshow.js.coffee => tvshow.coffee} | 0 src/js/entities/lab/{apiBrowser.js.coffee => apiBrowser.coffee} | 0 .../{localPlaylist.js.coffee => localPlaylist.coffee} | 0 src/js/entities/nav/{navMain.js.coffee => navMain.coffee} | 0 .../search/{searchAddons.js.coffee => searchAddons.coffee} | 0 src/js/helpers/{backscroll.js.coffee => backscroll.coffee} | 0 src/js/helpers/{cache.js.coffee => cache.coffee} | 0 src/js/helpers/{config.js.coffee => config.coffee} | 0 src/js/helpers/{connection.js.coffee => connection.coffee} | 0 .../{kodi_entities.js.coffee => kodi_entities.coffee} | 0 src/js/helpers/{debug.js.coffee => debug.coffee} | 0 src/js/helpers/{entities.js.coffee => entities.coffee} | 0 src/js/helpers/{global.js.coffee => global.coffee} | 0 src/js/helpers/{jquery.js.coffee => jquery.coffee} | 0 src/js/helpers/{streams.js.coffee => streams.coffee} | 0 src/js/helpers/{translate.js.coffee => translate.coffee} | 0 src/js/helpers/{ui.js.coffee => ui.coffee} | 0 src/js/helpers/{url.js.coffee => url.coffee} | 0 .../_base/{collectionview.js.coffee => collectionview.coffee} | 0 .../views/_base/{compositeview.js.coffee => compositeview.coffee} | 0 src/js/views/_base/{itemview.js.coffee => itemview.coffee} | 0 src/js/views/_base/{layout.js.coffee => layout.coffee} | 0 src/js/views/_base/{view.js.coffee => view.coffee} | 0 .../_base/{virtuallistview.js.coffee => virtuallistview.coffee} | 0 src/js/views/card/{card_view.js.coffee => card_view.coffee} | 0 .../views/details/{detailsitem.js.coffee => detailsitem.coffee} | 0 src/js/views/empty/{empty_view.js.coffee => empty_view.coffee} | 0 .../views/layouts/{layouts_view.js.coffee => layouts_view.coffee} | 0 src/js/views/set/{set_view.js.coffee => set_view.coffee} | 0 src/js/views/song/{song_view.js.coffee => song_view.coffee} | 0 218 files changed, 0 insertions(+), 0 deletions(-) rename src/js/apps/addon/{addon_app.js.coffee => addon_app.coffee} (100%) rename src/js/apps/addon/googlemusic/{addon_googlemusic_app.js.coffee => addon_googlemusic_app.coffee} (100%) rename src/js/apps/addon/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/addon/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/addon/mixcloud/{addon_mixcloud_app.js.coffee => addon_mixcloud_app.coffee} (100%) rename src/js/apps/addon/pvr/{addons_pvr_ap.js.coffee => addons_pvr_ap.coffee} (100%) rename src/js/apps/addon/radio/{addon_radio_app.js.coffee => addon_radio_app.coffee} (100%) rename src/js/apps/addon/soundcloud/{addon_soundcloud_app.js.coffee => addon_soundcloud_app.coffee} (100%) rename src/js/apps/addon/youtube/{addon_youtube_app.js.coffee => addon_youtube_app.coffee} (100%) rename src/js/apps/album/{album_app.js.coffee => album_app.coffee} (100%) rename src/js/apps/album/edit/{edit_controller.js.coffee => edit_controller.coffee} (100%) rename src/js/apps/album/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/album/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/album/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/album/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/artist/{artist_app.js.coffee => artist_app.coffee} (100%) rename src/js/apps/artist/edit/{edit_controller.js.coffee => edit_controller.coffee} (100%) rename src/js/apps/artist/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/artist/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/artist/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/artist/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/audioStream/{init.js.coffee => init.coffee} (100%) rename src/js/apps/browser/{browser_app.js.coffee => browser_app.coffee} (100%) rename src/js/apps/browser/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/browser/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/cast/{cast_app.js.coffee => cast_app.coffee} (100%) rename src/js/apps/cast/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/category/{category_app.js.coffee => category_app.coffee} (100%) rename src/js/apps/category/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/category/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/command/{command_app.js.coffee => command_app.coffee} (100%) rename src/js/apps/command/kodi/_base/{_base.js.coffee => _base.coffee} (100%) rename src/js/apps/command/kodi/_base/{api.js.coffee => api.coffee} (100%) rename src/js/apps/command/kodi/helpers/{addon.js.coffee => addon.coffee} (100%) rename src/js/apps/command/kodi/helpers/{application.js.coffee => application.coffee} (100%) rename src/js/apps/command/kodi/helpers/{audiolibrary.js.coffee => audiolibrary.coffee} (100%) rename src/js/apps/command/kodi/helpers/{file.js.coffee => file.coffee} (100%) rename src/js/apps/command/kodi/helpers/{input.js.coffee => input.coffee} (100%) rename src/js/apps/command/kodi/helpers/{playlist.js.coffee => playlist.coffee} (100%) rename src/js/apps/command/kodi/helpers/{pvr.js.coffee => pvr.coffee} (100%) rename src/js/apps/command/kodi/helpers/{system.js.coffee => system.coffee} (100%) rename src/js/apps/command/kodi/helpers/{videolibrary.js.coffee => videolibrary.coffee} (100%) rename src/js/apps/command/local/_base/{_base.js.coffee => _base.coffee} (100%) rename src/js/apps/command/local/_base/{api.js.coffee => api.coffee} (100%) rename src/js/apps/command/local/helpers/{application.js.coffee => application.coffee} (100%) rename src/js/apps/command/local/helpers/{playlist.js.coffee => playlist.coffee} (100%) rename src/js/apps/command/local/helpers/{videoplayer.js.coffee => videoplayer.coffee} (100%) rename src/js/apps/epg/{epg_app.js.coffee => epg_app.coffee} (100%) rename src/js/apps/epg/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/epg/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/external/{external_app.js.coffee => external_app.coffee} (100%) rename src/js/apps/external/youtube/{youtube_controller.js.coffee => youtube_controller.coffee} (100%) rename src/js/apps/external/youtube/{youtube_view.js.coffee => youtube_view.coffee} (100%) rename src/js/apps/filter/{filter_app.js.coffee => filter_app.coffee} (100%) rename src/js/apps/filter/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/filter/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/help/{help_app.js.coffee => help_app.coffee} (100%) rename src/js/apps/help/overview/{overview_controller.js.coffee => overview_controller.coffee} (100%) rename src/js/apps/help/overview/{overview_view.js.coffee => overview_view.coffee} (100%) rename src/js/apps/help/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/help/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/images/{images_app.js.coffee => images_app.coffee} (100%) rename src/js/apps/input/{input_app.js.coffee => input_app.coffee} (100%) rename src/js/apps/input/remote/{remote_controller.js.coffee => remote_controller.coffee} (100%) rename src/js/apps/input/remote/{remote_view.js.coffee => remote_view.coffee} (100%) rename src/js/apps/input/resume/{resume_controller.js.coffee => resume_controller.coffee} (100%) rename src/js/apps/lab/apiBrowser/{apiBrowser_controller.js.coffee => apiBrowser_controller.coffee} (100%) rename src/js/apps/lab/apiBrowser/{apiBrowser_view.js.coffee => apiBrowser_view.coffee} (100%) rename src/js/apps/lab/iconBrowser/{iconBrowser_view.js.coffee => iconBrowser_view.coffee} (100%) rename src/js/apps/lab/lab/{lab_view.js.coffee => lab_view.coffee} (100%) rename src/js/apps/lab/{lab_app.js.coffee => lab_app.coffee} (100%) rename src/js/apps/landing/{landing_app.js.coffee => landing_app.coffee} (100%) rename src/js/apps/landing/show/{landing_controller.js.coffee => landing_controller.coffee} (100%) rename src/js/apps/landing/show/{landing_view.js.coffee => landing_view.coffee} (100%) rename src/js/apps/loading/{loading_app.js.coffee => loading_app.coffee} (100%) rename src/js/apps/loading/show/{loading_view.js.coffee => loading_view.coffee} (100%) rename src/js/apps/localPlaylist/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/localPlaylist/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/localPlaylist/{localPlaylist_app.js.coffee => localPlaylist_app.coffee} (100%) rename src/js/apps/movie/edit/{edit_controller.js.coffee => edit_controller.coffee} (100%) rename src/js/apps/movie/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/movie/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/movie/{movie_app.js.coffee => movie_app.coffee} (100%) rename src/js/apps/movie/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/movie/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/musicvideo/edit/{edit_controller.js.coffee => edit_controller.coffee} (100%) rename src/js/apps/musicvideo/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/musicvideo/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/musicvideo/{musicvideo_app.js.coffee => musicvideo_app.coffee} (100%) rename src/js/apps/musicvideo/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/musicvideo/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/navMain/{navMain_app.js.coffee => navMain_app.coffee} (100%) rename src/js/apps/navMain/show/{navMain_view.js.coffee => navMain_view.coffee} (100%) rename src/js/apps/notifications/{notifications_app.js.coffee => notifications_app.coffee} (100%) rename src/js/apps/player/{player_app.js.coffee => player_app.coffee} (100%) rename src/js/apps/player/show/{player_view.js.coffee => player_view.coffee} (100%) rename src/js/apps/playlist/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/playlist/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/playlist/localParty/{local_party.js.coffee => local_party.coffee} (100%) rename src/js/apps/playlist/m3u/{m3u_controller.js.coffee => m3u_controller.coffee} (100%) rename src/js/apps/playlist/m3u/{m3u_view.js.coffee => m3u_view.coffee} (100%) rename src/js/apps/playlist/{playlist_app.js.coffee => playlist_app.coffee} (100%) rename src/js/apps/playlist/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/playlist/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/pvr/channelList/{channel_list_controller.js.coffee => channel_list_controller.coffee} (100%) rename src/js/apps/pvr/channelList/{channel_list_view.js.coffee => channel_list_view.coffee} (100%) rename src/js/apps/pvr/{pvr_app.js.coffee => pvr_app.coffee} (100%) rename src/js/apps/pvr/recordingList/{recording_list_controller.js.coffee => recording_list_controller.coffee} (100%) rename src/js/apps/pvr/recordingList/{recording_list_view.js.coffee => recording_list_view.coffee} (100%) rename src/js/apps/search/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/search/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/search/{search_app.js.coffee => search_app.coffee} (100%) rename src/js/apps/search/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/search/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/selected/{selected_app.js.coffee => selected_app.coffee} (100%) rename src/js/apps/settings/{settings_app.js.coffee => settings_app.coffee} (100%) rename src/js/apps/settings/show/_base/{base_controller.js.coffee => base_controller.coffee} (100%) rename src/js/apps/settings/show/addons/{addons_controller.js.coffee => addons_controller.coffee} (100%) rename src/js/apps/settings/show/kodi/{kodi_controller.js.coffee => kodi_controller.coffee} (100%) rename src/js/apps/settings/show/kodi/{kodi_view.js.coffee => kodi_view.coffee} (100%) rename src/js/apps/settings/show/local/{local_controller.js.coffee => local_controller.coffee} (100%) rename src/js/apps/settings/show/navMain/{navMain_controller.js.coffee => navMain_controller.coffee} (100%) rename src/js/apps/settings/show/search/{search_controller.js.coffee => search_controller.coffee} (100%) rename src/js/apps/settings/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/shell/{shell_app.js.coffee => shell_app.coffee} (100%) rename src/js/apps/shell/show/{shell_view.js.coffee => shell_view.coffee} (100%) rename src/js/apps/song/edit/{edit_controller.js.coffee => edit_controller.coffee} (100%) rename src/js/apps/song/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/song/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/song/{song_app.js.coffee => song_app.coffee} (100%) rename src/js/apps/state/_base/{base.js.coffee => base.coffee} (100%) rename src/js/apps/state/kodi/{kodi.js.coffee => kodi.coffee} (100%) rename src/js/apps/state/kodi/{notifications.js.coffee => notifications.coffee} (100%) rename src/js/apps/state/kodi/{polling.js.coffee => polling.coffee} (100%) rename src/js/apps/state/local/{local.js.coffee => local.coffee} (100%) rename src/js/apps/state/{state_app.js.coffee => state_app.coffee} (100%) rename src/js/apps/thumbs/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/thumbs/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/thumbs/{thumbs_app.js.coffee => thumbs_app.coffee} (100%) rename src/js/apps/tvshow/editEpisode/{edit_episode_controller.js.coffee => edit_episode_controller.coffee} (100%) rename src/js/apps/tvshow/editShow/{edit_show_controller.js.coffee => edit_show_controller.coffee} (100%) rename src/js/apps/tvshow/episode/{episode_controller.js.coffee => episode_controller.coffee} (100%) rename src/js/apps/tvshow/episode/{episode_view.js.coffee => episode_view.coffee} (100%) rename src/js/apps/tvshow/list/{list_controller.js.coffee => list_controller.coffee} (100%) rename src/js/apps/tvshow/list/{list_view.js.coffee => list_view.coffee} (100%) rename src/js/apps/tvshow/season/{season_controller.js.coffee => season_controller.coffee} (100%) rename src/js/apps/tvshow/season/{season_view.js.coffee => season_view.coffee} (100%) rename src/js/apps/tvshow/show/{show_controller.js.coffee => show_controller.coffee} (100%) rename src/js/apps/tvshow/show/{show_view.js.coffee => show_view.coffee} (100%) rename src/js/apps/tvshow/{tvshow_app.js.coffee => tvshow_app.coffee} (100%) rename src/js/apps/ui/{ui_app.js.coffee => ui_app.coffee} (100%) rename src/js/components/form/{form_controller.js.coffee => form_controller.coffee} (100%) rename src/js/components/form/{form_view.js.coffee => form_view.coffee} (100%) rename src/js/config/backbone/{sync.js.coffee => sync.coffee} (100%) rename src/js/config/marionette/{application.js.coffee => application.coffee} (100%) rename src/js/config/marionette/{renderer.js.coffee => renderer.coffee} (100%) rename src/js/controllers/{_base.js.coffee => _base.coffee} (100%) rename src/js/controllers/{router.js.coffee => router.coffee} (100%) rename src/js/entities/_base/{collections.js.coffee => collections.coffee} (100%) rename src/js/entities/_base/{filtered.js.coffee => filtered.coffee} (100%) rename src/js/entities/_base/{models.js.coffee => models.coffee} (100%) rename src/js/entities/config/{configApp.js.coffee => configApp.coffee} (100%) rename src/js/entities/config/{configKodi.js.coffee => configKodi.coffee} (100%) rename src/js/entities/external/{_base.js.coffee => _base.coffee} (100%) rename src/js/entities/external/{fanarttv.js.coffee => fanarttv.coffee} (100%) rename src/js/entities/external/{musicbrainz.js.coffee => musicbrainz.coffee} (100%) rename src/js/entities/external/{themoviedb.js.coffee => themoviedb.coffee} (100%) rename src/js/entities/external/{youtube.js.coffee => youtube.coffee} (100%) rename src/js/entities/filter/{filter.js.coffee => filter.coffee} (100%) rename src/js/entities/form/{form.js.coffee => form.coffee} (100%) rename src/js/entities/kodi/_base/{_fetch.js.coffee => _fetch.coffee} (100%) rename src/js/entities/kodi/_base/{collections.js.coffee => collections.coffee} (100%) rename src/js/entities/kodi/_base/{models.js.coffee => models.coffee} (100%) rename src/js/entities/kodi/{addon.js.coffee => addon.coffee} (100%) rename src/js/entities/kodi/{album.js.coffee => album.coffee} (100%) rename src/js/entities/kodi/{artist.js.coffee => artist.coffee} (100%) rename src/js/entities/kodi/{cast.js.coffee => cast.coffee} (100%) rename src/js/entities/kodi/{epg.js.coffee => epg.coffee} (100%) rename src/js/entities/kodi/{episode.js.coffee => episode.coffee} (100%) rename src/js/entities/kodi/{file.js.coffee => file.coffee} (100%) rename src/js/entities/kodi/{genres.js.coffee => genres.coffee} (100%) rename src/js/entities/kodi/{movie.js.coffee => movie.coffee} (100%) rename src/js/entities/kodi/{musicvideo.js.coffee => musicvideo.coffee} (100%) rename src/js/entities/kodi/{playlist.js.coffee => playlist.coffee} (100%) rename src/js/entities/kodi/{pvr.js.coffee => pvr.coffee} (100%) rename src/js/entities/kodi/{season.js.coffee => season.coffee} (100%) rename src/js/entities/kodi/{settings.js.coffee => settings.coffee} (100%) rename src/js/entities/kodi/{song.js.coffee => song.coffee} (100%) rename src/js/entities/kodi/{tvshow.js.coffee => tvshow.coffee} (100%) rename src/js/entities/lab/{apiBrowser.js.coffee => apiBrowser.coffee} (100%) rename src/js/entities/localPlaylist/{localPlaylist.js.coffee => localPlaylist.coffee} (100%) rename src/js/entities/nav/{navMain.js.coffee => navMain.coffee} (100%) rename src/js/entities/search/{searchAddons.js.coffee => searchAddons.coffee} (100%) rename src/js/helpers/{backscroll.js.coffee => backscroll.coffee} (100%) rename src/js/helpers/{cache.js.coffee => cache.coffee} (100%) rename src/js/helpers/{config.js.coffee => config.coffee} (100%) rename src/js/helpers/{connection.js.coffee => connection.coffee} (100%) rename src/js/helpers/customMixins/{kodi_entities.js.coffee => kodi_entities.coffee} (100%) rename src/js/helpers/{debug.js.coffee => debug.coffee} (100%) rename src/js/helpers/{entities.js.coffee => entities.coffee} (100%) rename src/js/helpers/{global.js.coffee => global.coffee} (100%) rename src/js/helpers/{jquery.js.coffee => jquery.coffee} (100%) rename src/js/helpers/{streams.js.coffee => streams.coffee} (100%) rename src/js/helpers/{translate.js.coffee => translate.coffee} (100%) rename src/js/helpers/{ui.js.coffee => ui.coffee} (100%) rename src/js/helpers/{url.js.coffee => url.coffee} (100%) rename src/js/views/_base/{collectionview.js.coffee => collectionview.coffee} (100%) rename src/js/views/_base/{compositeview.js.coffee => compositeview.coffee} (100%) rename src/js/views/_base/{itemview.js.coffee => itemview.coffee} (100%) rename src/js/views/_base/{layout.js.coffee => layout.coffee} (100%) rename src/js/views/_base/{view.js.coffee => view.coffee} (100%) rename src/js/views/_base/{virtuallistview.js.coffee => virtuallistview.coffee} (100%) rename src/js/views/card/{card_view.js.coffee => card_view.coffee} (100%) rename src/js/views/details/{detailsitem.js.coffee => detailsitem.coffee} (100%) rename src/js/views/empty/{empty_view.js.coffee => empty_view.coffee} (100%) rename src/js/views/layouts/{layouts_view.js.coffee => layouts_view.coffee} (100%) rename src/js/views/set/{set_view.js.coffee => set_view.coffee} (100%) rename src/js/views/song/{song_view.js.coffee => song_view.coffee} (100%) diff --git a/src/js/apps/addon/addon_app.js.coffee b/src/js/apps/addon/addon_app.coffee similarity index 100% rename from src/js/apps/addon/addon_app.js.coffee rename to src/js/apps/addon/addon_app.coffee diff --git a/src/js/apps/addon/googlemusic/addon_googlemusic_app.js.coffee b/src/js/apps/addon/googlemusic/addon_googlemusic_app.coffee similarity index 100% rename from src/js/apps/addon/googlemusic/addon_googlemusic_app.js.coffee rename to src/js/apps/addon/googlemusic/addon_googlemusic_app.coffee diff --git a/src/js/apps/addon/list/list_controller.js.coffee b/src/js/apps/addon/list/list_controller.coffee similarity index 100% rename from src/js/apps/addon/list/list_controller.js.coffee rename to src/js/apps/addon/list/list_controller.coffee diff --git a/src/js/apps/addon/list/list_view.js.coffee b/src/js/apps/addon/list/list_view.coffee similarity index 100% rename from src/js/apps/addon/list/list_view.js.coffee rename to src/js/apps/addon/list/list_view.coffee diff --git a/src/js/apps/addon/mixcloud/addon_mixcloud_app.js.coffee b/src/js/apps/addon/mixcloud/addon_mixcloud_app.coffee similarity index 100% rename from src/js/apps/addon/mixcloud/addon_mixcloud_app.js.coffee rename to src/js/apps/addon/mixcloud/addon_mixcloud_app.coffee diff --git a/src/js/apps/addon/pvr/addons_pvr_ap.js.coffee b/src/js/apps/addon/pvr/addons_pvr_ap.coffee similarity index 100% rename from src/js/apps/addon/pvr/addons_pvr_ap.js.coffee rename to src/js/apps/addon/pvr/addons_pvr_ap.coffee diff --git a/src/js/apps/addon/radio/addon_radio_app.js.coffee b/src/js/apps/addon/radio/addon_radio_app.coffee similarity index 100% rename from src/js/apps/addon/radio/addon_radio_app.js.coffee rename to src/js/apps/addon/radio/addon_radio_app.coffee diff --git a/src/js/apps/addon/soundcloud/addon_soundcloud_app.js.coffee b/src/js/apps/addon/soundcloud/addon_soundcloud_app.coffee similarity index 100% rename from src/js/apps/addon/soundcloud/addon_soundcloud_app.js.coffee rename to src/js/apps/addon/soundcloud/addon_soundcloud_app.coffee diff --git a/src/js/apps/addon/youtube/addon_youtube_app.js.coffee b/src/js/apps/addon/youtube/addon_youtube_app.coffee similarity index 100% rename from src/js/apps/addon/youtube/addon_youtube_app.js.coffee rename to src/js/apps/addon/youtube/addon_youtube_app.coffee diff --git a/src/js/apps/album/album_app.js.coffee b/src/js/apps/album/album_app.coffee similarity index 100% rename from src/js/apps/album/album_app.js.coffee rename to src/js/apps/album/album_app.coffee diff --git a/src/js/apps/album/edit/edit_controller.js.coffee b/src/js/apps/album/edit/edit_controller.coffee similarity index 100% rename from src/js/apps/album/edit/edit_controller.js.coffee rename to src/js/apps/album/edit/edit_controller.coffee diff --git a/src/js/apps/album/list/list_controller.js.coffee b/src/js/apps/album/list/list_controller.coffee similarity index 100% rename from src/js/apps/album/list/list_controller.js.coffee rename to src/js/apps/album/list/list_controller.coffee diff --git a/src/js/apps/album/list/list_view.js.coffee b/src/js/apps/album/list/list_view.coffee similarity index 100% rename from src/js/apps/album/list/list_view.js.coffee rename to src/js/apps/album/list/list_view.coffee diff --git a/src/js/apps/album/show/show_controller.js.coffee b/src/js/apps/album/show/show_controller.coffee similarity index 100% rename from src/js/apps/album/show/show_controller.js.coffee rename to src/js/apps/album/show/show_controller.coffee diff --git a/src/js/apps/album/show/show_view.js.coffee b/src/js/apps/album/show/show_view.coffee similarity index 100% rename from src/js/apps/album/show/show_view.js.coffee rename to src/js/apps/album/show/show_view.coffee diff --git a/src/js/apps/artist/artist_app.js.coffee b/src/js/apps/artist/artist_app.coffee similarity index 100% rename from src/js/apps/artist/artist_app.js.coffee rename to src/js/apps/artist/artist_app.coffee diff --git a/src/js/apps/artist/edit/edit_controller.js.coffee b/src/js/apps/artist/edit/edit_controller.coffee similarity index 100% rename from src/js/apps/artist/edit/edit_controller.js.coffee rename to src/js/apps/artist/edit/edit_controller.coffee diff --git a/src/js/apps/artist/list/list_controller.js.coffee b/src/js/apps/artist/list/list_controller.coffee similarity index 100% rename from src/js/apps/artist/list/list_controller.js.coffee rename to src/js/apps/artist/list/list_controller.coffee diff --git a/src/js/apps/artist/list/list_view.js.coffee b/src/js/apps/artist/list/list_view.coffee similarity index 100% rename from src/js/apps/artist/list/list_view.js.coffee rename to src/js/apps/artist/list/list_view.coffee diff --git a/src/js/apps/artist/show/show_controller.js.coffee b/src/js/apps/artist/show/show_controller.coffee similarity index 100% rename from src/js/apps/artist/show/show_controller.js.coffee rename to src/js/apps/artist/show/show_controller.coffee diff --git a/src/js/apps/artist/show/show_view.js.coffee b/src/js/apps/artist/show/show_view.coffee similarity index 100% rename from src/js/apps/artist/show/show_view.js.coffee rename to src/js/apps/artist/show/show_view.coffee diff --git a/src/js/apps/audioStream/init.js.coffee b/src/js/apps/audioStream/init.coffee similarity index 100% rename from src/js/apps/audioStream/init.js.coffee rename to src/js/apps/audioStream/init.coffee diff --git a/src/js/apps/browser/browser_app.js.coffee b/src/js/apps/browser/browser_app.coffee similarity index 100% rename from src/js/apps/browser/browser_app.js.coffee rename to src/js/apps/browser/browser_app.coffee diff --git a/src/js/apps/browser/list/list_controller.js.coffee b/src/js/apps/browser/list/list_controller.coffee similarity index 100% rename from src/js/apps/browser/list/list_controller.js.coffee rename to src/js/apps/browser/list/list_controller.coffee diff --git a/src/js/apps/browser/list/list_view.js.coffee b/src/js/apps/browser/list/list_view.coffee similarity index 100% rename from src/js/apps/browser/list/list_view.js.coffee rename to src/js/apps/browser/list/list_view.coffee diff --git a/src/js/apps/cast/cast_app.js.coffee b/src/js/apps/cast/cast_app.coffee similarity index 100% rename from src/js/apps/cast/cast_app.js.coffee rename to src/js/apps/cast/cast_app.coffee diff --git a/src/js/apps/cast/list/list_view.js.coffee b/src/js/apps/cast/list/list_view.coffee similarity index 100% rename from src/js/apps/cast/list/list_view.js.coffee rename to src/js/apps/cast/list/list_view.coffee diff --git a/src/js/apps/category/category_app.js.coffee b/src/js/apps/category/category_app.coffee similarity index 100% rename from src/js/apps/category/category_app.js.coffee rename to src/js/apps/category/category_app.coffee diff --git a/src/js/apps/category/list/list_controller.js.coffee b/src/js/apps/category/list/list_controller.coffee similarity index 100% rename from src/js/apps/category/list/list_controller.js.coffee rename to src/js/apps/category/list/list_controller.coffee diff --git a/src/js/apps/category/list/list_view.js.coffee b/src/js/apps/category/list/list_view.coffee similarity index 100% rename from src/js/apps/category/list/list_view.js.coffee rename to src/js/apps/category/list/list_view.coffee diff --git a/src/js/apps/command/command_app.js.coffee b/src/js/apps/command/command_app.coffee similarity index 100% rename from src/js/apps/command/command_app.js.coffee rename to src/js/apps/command/command_app.coffee diff --git a/src/js/apps/command/kodi/_base/_base.js.coffee b/src/js/apps/command/kodi/_base/_base.coffee similarity index 100% rename from src/js/apps/command/kodi/_base/_base.js.coffee rename to src/js/apps/command/kodi/_base/_base.coffee diff --git a/src/js/apps/command/kodi/_base/api.js.coffee b/src/js/apps/command/kodi/_base/api.coffee similarity index 100% rename from src/js/apps/command/kodi/_base/api.js.coffee rename to src/js/apps/command/kodi/_base/api.coffee diff --git a/src/js/apps/command/kodi/helpers/addon.js.coffee b/src/js/apps/command/kodi/helpers/addon.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/addon.js.coffee rename to src/js/apps/command/kodi/helpers/addon.coffee diff --git a/src/js/apps/command/kodi/helpers/application.js.coffee b/src/js/apps/command/kodi/helpers/application.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/application.js.coffee rename to src/js/apps/command/kodi/helpers/application.coffee diff --git a/src/js/apps/command/kodi/helpers/audiolibrary.js.coffee b/src/js/apps/command/kodi/helpers/audiolibrary.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/audiolibrary.js.coffee rename to src/js/apps/command/kodi/helpers/audiolibrary.coffee diff --git a/src/js/apps/command/kodi/helpers/file.js.coffee b/src/js/apps/command/kodi/helpers/file.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/file.js.coffee rename to src/js/apps/command/kodi/helpers/file.coffee diff --git a/src/js/apps/command/kodi/helpers/input.js.coffee b/src/js/apps/command/kodi/helpers/input.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/input.js.coffee rename to src/js/apps/command/kodi/helpers/input.coffee diff --git a/src/js/apps/command/kodi/helpers/playlist.js.coffee b/src/js/apps/command/kodi/helpers/playlist.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/playlist.js.coffee rename to src/js/apps/command/kodi/helpers/playlist.coffee diff --git a/src/js/apps/command/kodi/helpers/pvr.js.coffee b/src/js/apps/command/kodi/helpers/pvr.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/pvr.js.coffee rename to src/js/apps/command/kodi/helpers/pvr.coffee diff --git a/src/js/apps/command/kodi/helpers/system.js.coffee b/src/js/apps/command/kodi/helpers/system.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/system.js.coffee rename to src/js/apps/command/kodi/helpers/system.coffee diff --git a/src/js/apps/command/kodi/helpers/videolibrary.js.coffee b/src/js/apps/command/kodi/helpers/videolibrary.coffee similarity index 100% rename from src/js/apps/command/kodi/helpers/videolibrary.js.coffee rename to src/js/apps/command/kodi/helpers/videolibrary.coffee diff --git a/src/js/apps/command/local/_base/_base.js.coffee b/src/js/apps/command/local/_base/_base.coffee similarity index 100% rename from src/js/apps/command/local/_base/_base.js.coffee rename to src/js/apps/command/local/_base/_base.coffee diff --git a/src/js/apps/command/local/_base/api.js.coffee b/src/js/apps/command/local/_base/api.coffee similarity index 100% rename from src/js/apps/command/local/_base/api.js.coffee rename to src/js/apps/command/local/_base/api.coffee diff --git a/src/js/apps/command/local/helpers/application.js.coffee b/src/js/apps/command/local/helpers/application.coffee similarity index 100% rename from src/js/apps/command/local/helpers/application.js.coffee rename to src/js/apps/command/local/helpers/application.coffee diff --git a/src/js/apps/command/local/helpers/playlist.js.coffee b/src/js/apps/command/local/helpers/playlist.coffee similarity index 100% rename from src/js/apps/command/local/helpers/playlist.js.coffee rename to src/js/apps/command/local/helpers/playlist.coffee diff --git a/src/js/apps/command/local/helpers/videoplayer.js.coffee b/src/js/apps/command/local/helpers/videoplayer.coffee similarity index 100% rename from src/js/apps/command/local/helpers/videoplayer.js.coffee rename to src/js/apps/command/local/helpers/videoplayer.coffee diff --git a/src/js/apps/epg/epg_app.js.coffee b/src/js/apps/epg/epg_app.coffee similarity index 100% rename from src/js/apps/epg/epg_app.js.coffee rename to src/js/apps/epg/epg_app.coffee diff --git a/src/js/apps/epg/list/list_controller.js.coffee b/src/js/apps/epg/list/list_controller.coffee similarity index 100% rename from src/js/apps/epg/list/list_controller.js.coffee rename to src/js/apps/epg/list/list_controller.coffee diff --git a/src/js/apps/epg/list/list_view.js.coffee b/src/js/apps/epg/list/list_view.coffee similarity index 100% rename from src/js/apps/epg/list/list_view.js.coffee rename to src/js/apps/epg/list/list_view.coffee diff --git a/src/js/apps/external/external_app.js.coffee b/src/js/apps/external/external_app.coffee similarity index 100% rename from src/js/apps/external/external_app.js.coffee rename to src/js/apps/external/external_app.coffee diff --git a/src/js/apps/external/youtube/youtube_controller.js.coffee b/src/js/apps/external/youtube/youtube_controller.coffee similarity index 100% rename from src/js/apps/external/youtube/youtube_controller.js.coffee rename to src/js/apps/external/youtube/youtube_controller.coffee diff --git a/src/js/apps/external/youtube/youtube_view.js.coffee b/src/js/apps/external/youtube/youtube_view.coffee similarity index 100% rename from src/js/apps/external/youtube/youtube_view.js.coffee rename to src/js/apps/external/youtube/youtube_view.coffee diff --git a/src/js/apps/filter/filter_app.js.coffee b/src/js/apps/filter/filter_app.coffee similarity index 100% rename from src/js/apps/filter/filter_app.js.coffee rename to src/js/apps/filter/filter_app.coffee diff --git a/src/js/apps/filter/show/show_controller.js.coffee b/src/js/apps/filter/show/show_controller.coffee similarity index 100% rename from src/js/apps/filter/show/show_controller.js.coffee rename to src/js/apps/filter/show/show_controller.coffee diff --git a/src/js/apps/filter/show/show_view.js.coffee b/src/js/apps/filter/show/show_view.coffee similarity index 100% rename from src/js/apps/filter/show/show_view.js.coffee rename to src/js/apps/filter/show/show_view.coffee diff --git a/src/js/apps/help/help_app.js.coffee b/src/js/apps/help/help_app.coffee similarity index 100% rename from src/js/apps/help/help_app.js.coffee rename to src/js/apps/help/help_app.coffee diff --git a/src/js/apps/help/overview/overview_controller.js.coffee b/src/js/apps/help/overview/overview_controller.coffee similarity index 100% rename from src/js/apps/help/overview/overview_controller.js.coffee rename to src/js/apps/help/overview/overview_controller.coffee diff --git a/src/js/apps/help/overview/overview_view.js.coffee b/src/js/apps/help/overview/overview_view.coffee similarity index 100% rename from src/js/apps/help/overview/overview_view.js.coffee rename to src/js/apps/help/overview/overview_view.coffee diff --git a/src/js/apps/help/show/show_controller.js.coffee b/src/js/apps/help/show/show_controller.coffee similarity index 100% rename from src/js/apps/help/show/show_controller.js.coffee rename to src/js/apps/help/show/show_controller.coffee diff --git a/src/js/apps/help/show/show_view.js.coffee b/src/js/apps/help/show/show_view.coffee similarity index 100% rename from src/js/apps/help/show/show_view.js.coffee rename to src/js/apps/help/show/show_view.coffee diff --git a/src/js/apps/images/images_app.js.coffee b/src/js/apps/images/images_app.coffee similarity index 100% rename from src/js/apps/images/images_app.js.coffee rename to src/js/apps/images/images_app.coffee diff --git a/src/js/apps/input/input_app.js.coffee b/src/js/apps/input/input_app.coffee similarity index 100% rename from src/js/apps/input/input_app.js.coffee rename to src/js/apps/input/input_app.coffee diff --git a/src/js/apps/input/remote/remote_controller.js.coffee b/src/js/apps/input/remote/remote_controller.coffee similarity index 100% rename from src/js/apps/input/remote/remote_controller.js.coffee rename to src/js/apps/input/remote/remote_controller.coffee diff --git a/src/js/apps/input/remote/remote_view.js.coffee b/src/js/apps/input/remote/remote_view.coffee similarity index 100% rename from src/js/apps/input/remote/remote_view.js.coffee rename to src/js/apps/input/remote/remote_view.coffee diff --git a/src/js/apps/input/resume/resume_controller.js.coffee b/src/js/apps/input/resume/resume_controller.coffee similarity index 100% rename from src/js/apps/input/resume/resume_controller.js.coffee rename to src/js/apps/input/resume/resume_controller.coffee diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_controller.js.coffee b/src/js/apps/lab/apiBrowser/apiBrowser_controller.coffee similarity index 100% rename from src/js/apps/lab/apiBrowser/apiBrowser_controller.js.coffee rename to src/js/apps/lab/apiBrowser/apiBrowser_controller.coffee diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_view.js.coffee b/src/js/apps/lab/apiBrowser/apiBrowser_view.coffee similarity index 100% rename from src/js/apps/lab/apiBrowser/apiBrowser_view.js.coffee rename to src/js/apps/lab/apiBrowser/apiBrowser_view.coffee diff --git a/src/js/apps/lab/iconBrowser/iconBrowser_view.js.coffee b/src/js/apps/lab/iconBrowser/iconBrowser_view.coffee similarity index 100% rename from src/js/apps/lab/iconBrowser/iconBrowser_view.js.coffee rename to src/js/apps/lab/iconBrowser/iconBrowser_view.coffee diff --git a/src/js/apps/lab/lab/lab_view.js.coffee b/src/js/apps/lab/lab/lab_view.coffee similarity index 100% rename from src/js/apps/lab/lab/lab_view.js.coffee rename to src/js/apps/lab/lab/lab_view.coffee diff --git a/src/js/apps/lab/lab_app.js.coffee b/src/js/apps/lab/lab_app.coffee similarity index 100% rename from src/js/apps/lab/lab_app.js.coffee rename to src/js/apps/lab/lab_app.coffee diff --git a/src/js/apps/landing/landing_app.js.coffee b/src/js/apps/landing/landing_app.coffee similarity index 100% rename from src/js/apps/landing/landing_app.js.coffee rename to src/js/apps/landing/landing_app.coffee diff --git a/src/js/apps/landing/show/landing_controller.js.coffee b/src/js/apps/landing/show/landing_controller.coffee similarity index 100% rename from src/js/apps/landing/show/landing_controller.js.coffee rename to src/js/apps/landing/show/landing_controller.coffee diff --git a/src/js/apps/landing/show/landing_view.js.coffee b/src/js/apps/landing/show/landing_view.coffee similarity index 100% rename from src/js/apps/landing/show/landing_view.js.coffee rename to src/js/apps/landing/show/landing_view.coffee diff --git a/src/js/apps/loading/loading_app.js.coffee b/src/js/apps/loading/loading_app.coffee similarity index 100% rename from src/js/apps/loading/loading_app.js.coffee rename to src/js/apps/loading/loading_app.coffee diff --git a/src/js/apps/loading/show/loading_view.js.coffee b/src/js/apps/loading/show/loading_view.coffee similarity index 100% rename from src/js/apps/loading/show/loading_view.js.coffee rename to src/js/apps/loading/show/loading_view.coffee diff --git a/src/js/apps/localPlaylist/list/list_controller.js.coffee b/src/js/apps/localPlaylist/list/list_controller.coffee similarity index 100% rename from src/js/apps/localPlaylist/list/list_controller.js.coffee rename to src/js/apps/localPlaylist/list/list_controller.coffee diff --git a/src/js/apps/localPlaylist/list/list_view.js.coffee b/src/js/apps/localPlaylist/list/list_view.coffee similarity index 100% rename from src/js/apps/localPlaylist/list/list_view.js.coffee rename to src/js/apps/localPlaylist/list/list_view.coffee diff --git a/src/js/apps/localPlaylist/localPlaylist_app.js.coffee b/src/js/apps/localPlaylist/localPlaylist_app.coffee similarity index 100% rename from src/js/apps/localPlaylist/localPlaylist_app.js.coffee rename to src/js/apps/localPlaylist/localPlaylist_app.coffee diff --git a/src/js/apps/movie/edit/edit_controller.js.coffee b/src/js/apps/movie/edit/edit_controller.coffee similarity index 100% rename from src/js/apps/movie/edit/edit_controller.js.coffee rename to src/js/apps/movie/edit/edit_controller.coffee diff --git a/src/js/apps/movie/list/list_controller.js.coffee b/src/js/apps/movie/list/list_controller.coffee similarity index 100% rename from src/js/apps/movie/list/list_controller.js.coffee rename to src/js/apps/movie/list/list_controller.coffee diff --git a/src/js/apps/movie/list/list_view.js.coffee b/src/js/apps/movie/list/list_view.coffee similarity index 100% rename from src/js/apps/movie/list/list_view.js.coffee rename to src/js/apps/movie/list/list_view.coffee diff --git a/src/js/apps/movie/movie_app.js.coffee b/src/js/apps/movie/movie_app.coffee similarity index 100% rename from src/js/apps/movie/movie_app.js.coffee rename to src/js/apps/movie/movie_app.coffee diff --git a/src/js/apps/movie/show/show_controller.js.coffee b/src/js/apps/movie/show/show_controller.coffee similarity index 100% rename from src/js/apps/movie/show/show_controller.js.coffee rename to src/js/apps/movie/show/show_controller.coffee diff --git a/src/js/apps/movie/show/show_view.js.coffee b/src/js/apps/movie/show/show_view.coffee similarity index 100% rename from src/js/apps/movie/show/show_view.js.coffee rename to src/js/apps/movie/show/show_view.coffee diff --git a/src/js/apps/musicvideo/edit/edit_controller.js.coffee b/src/js/apps/musicvideo/edit/edit_controller.coffee similarity index 100% rename from src/js/apps/musicvideo/edit/edit_controller.js.coffee rename to src/js/apps/musicvideo/edit/edit_controller.coffee diff --git a/src/js/apps/musicvideo/list/list_controller.js.coffee b/src/js/apps/musicvideo/list/list_controller.coffee similarity index 100% rename from src/js/apps/musicvideo/list/list_controller.js.coffee rename to src/js/apps/musicvideo/list/list_controller.coffee diff --git a/src/js/apps/musicvideo/list/list_view.js.coffee b/src/js/apps/musicvideo/list/list_view.coffee similarity index 100% rename from src/js/apps/musicvideo/list/list_view.js.coffee rename to src/js/apps/musicvideo/list/list_view.coffee diff --git a/src/js/apps/musicvideo/musicvideo_app.js.coffee b/src/js/apps/musicvideo/musicvideo_app.coffee similarity index 100% rename from src/js/apps/musicvideo/musicvideo_app.js.coffee rename to src/js/apps/musicvideo/musicvideo_app.coffee diff --git a/src/js/apps/musicvideo/show/show_controller.js.coffee b/src/js/apps/musicvideo/show/show_controller.coffee similarity index 100% rename from src/js/apps/musicvideo/show/show_controller.js.coffee rename to src/js/apps/musicvideo/show/show_controller.coffee diff --git a/src/js/apps/musicvideo/show/show_view.js.coffee b/src/js/apps/musicvideo/show/show_view.coffee similarity index 100% rename from src/js/apps/musicvideo/show/show_view.js.coffee rename to src/js/apps/musicvideo/show/show_view.coffee diff --git a/src/js/apps/navMain/navMain_app.js.coffee b/src/js/apps/navMain/navMain_app.coffee similarity index 100% rename from src/js/apps/navMain/navMain_app.js.coffee rename to src/js/apps/navMain/navMain_app.coffee diff --git a/src/js/apps/navMain/show/navMain_view.js.coffee b/src/js/apps/navMain/show/navMain_view.coffee similarity index 100% rename from src/js/apps/navMain/show/navMain_view.js.coffee rename to src/js/apps/navMain/show/navMain_view.coffee diff --git a/src/js/apps/notifications/notifications_app.js.coffee b/src/js/apps/notifications/notifications_app.coffee similarity index 100% rename from src/js/apps/notifications/notifications_app.js.coffee rename to src/js/apps/notifications/notifications_app.coffee diff --git a/src/js/apps/player/player_app.js.coffee b/src/js/apps/player/player_app.coffee similarity index 100% rename from src/js/apps/player/player_app.js.coffee rename to src/js/apps/player/player_app.coffee diff --git a/src/js/apps/player/show/player_view.js.coffee b/src/js/apps/player/show/player_view.coffee similarity index 100% rename from src/js/apps/player/show/player_view.js.coffee rename to src/js/apps/player/show/player_view.coffee diff --git a/src/js/apps/playlist/list/list_controller.js.coffee b/src/js/apps/playlist/list/list_controller.coffee similarity index 100% rename from src/js/apps/playlist/list/list_controller.js.coffee rename to src/js/apps/playlist/list/list_controller.coffee diff --git a/src/js/apps/playlist/list/list_view.js.coffee b/src/js/apps/playlist/list/list_view.coffee similarity index 100% rename from src/js/apps/playlist/list/list_view.js.coffee rename to src/js/apps/playlist/list/list_view.coffee diff --git a/src/js/apps/playlist/localParty/local_party.js.coffee b/src/js/apps/playlist/localParty/local_party.coffee similarity index 100% rename from src/js/apps/playlist/localParty/local_party.js.coffee rename to src/js/apps/playlist/localParty/local_party.coffee diff --git a/src/js/apps/playlist/m3u/m3u_controller.js.coffee b/src/js/apps/playlist/m3u/m3u_controller.coffee similarity index 100% rename from src/js/apps/playlist/m3u/m3u_controller.js.coffee rename to src/js/apps/playlist/m3u/m3u_controller.coffee diff --git a/src/js/apps/playlist/m3u/m3u_view.js.coffee b/src/js/apps/playlist/m3u/m3u_view.coffee similarity index 100% rename from src/js/apps/playlist/m3u/m3u_view.js.coffee rename to src/js/apps/playlist/m3u/m3u_view.coffee diff --git a/src/js/apps/playlist/playlist_app.js.coffee b/src/js/apps/playlist/playlist_app.coffee similarity index 100% rename from src/js/apps/playlist/playlist_app.js.coffee rename to src/js/apps/playlist/playlist_app.coffee diff --git a/src/js/apps/playlist/show/show_controller.js.coffee b/src/js/apps/playlist/show/show_controller.coffee similarity index 100% rename from src/js/apps/playlist/show/show_controller.js.coffee rename to src/js/apps/playlist/show/show_controller.coffee diff --git a/src/js/apps/playlist/show/show_view.js.coffee b/src/js/apps/playlist/show/show_view.coffee similarity index 100% rename from src/js/apps/playlist/show/show_view.js.coffee rename to src/js/apps/playlist/show/show_view.coffee diff --git a/src/js/apps/pvr/channelList/channel_list_controller.js.coffee b/src/js/apps/pvr/channelList/channel_list_controller.coffee similarity index 100% rename from src/js/apps/pvr/channelList/channel_list_controller.js.coffee rename to src/js/apps/pvr/channelList/channel_list_controller.coffee diff --git a/src/js/apps/pvr/channelList/channel_list_view.js.coffee b/src/js/apps/pvr/channelList/channel_list_view.coffee similarity index 100% rename from src/js/apps/pvr/channelList/channel_list_view.js.coffee rename to src/js/apps/pvr/channelList/channel_list_view.coffee diff --git a/src/js/apps/pvr/pvr_app.js.coffee b/src/js/apps/pvr/pvr_app.coffee similarity index 100% rename from src/js/apps/pvr/pvr_app.js.coffee rename to src/js/apps/pvr/pvr_app.coffee diff --git a/src/js/apps/pvr/recordingList/recording_list_controller.js.coffee b/src/js/apps/pvr/recordingList/recording_list_controller.coffee similarity index 100% rename from src/js/apps/pvr/recordingList/recording_list_controller.js.coffee rename to src/js/apps/pvr/recordingList/recording_list_controller.coffee diff --git a/src/js/apps/pvr/recordingList/recording_list_view.js.coffee b/src/js/apps/pvr/recordingList/recording_list_view.coffee similarity index 100% rename from src/js/apps/pvr/recordingList/recording_list_view.js.coffee rename to src/js/apps/pvr/recordingList/recording_list_view.coffee diff --git a/src/js/apps/search/list/list_controller.js.coffee b/src/js/apps/search/list/list_controller.coffee similarity index 100% rename from src/js/apps/search/list/list_controller.js.coffee rename to src/js/apps/search/list/list_controller.coffee diff --git a/src/js/apps/search/list/list_view.js.coffee b/src/js/apps/search/list/list_view.coffee similarity index 100% rename from src/js/apps/search/list/list_view.js.coffee rename to src/js/apps/search/list/list_view.coffee diff --git a/src/js/apps/search/search_app.js.coffee b/src/js/apps/search/search_app.coffee similarity index 100% rename from src/js/apps/search/search_app.js.coffee rename to src/js/apps/search/search_app.coffee diff --git a/src/js/apps/search/show/show_controller.js.coffee b/src/js/apps/search/show/show_controller.coffee similarity index 100% rename from src/js/apps/search/show/show_controller.js.coffee rename to src/js/apps/search/show/show_controller.coffee diff --git a/src/js/apps/search/show/show_view.js.coffee b/src/js/apps/search/show/show_view.coffee similarity index 100% rename from src/js/apps/search/show/show_view.js.coffee rename to src/js/apps/search/show/show_view.coffee diff --git a/src/js/apps/selected/selected_app.js.coffee b/src/js/apps/selected/selected_app.coffee similarity index 100% rename from src/js/apps/selected/selected_app.js.coffee rename to src/js/apps/selected/selected_app.coffee diff --git a/src/js/apps/settings/settings_app.js.coffee b/src/js/apps/settings/settings_app.coffee similarity index 100% rename from src/js/apps/settings/settings_app.js.coffee rename to src/js/apps/settings/settings_app.coffee diff --git a/src/js/apps/settings/show/_base/base_controller.js.coffee b/src/js/apps/settings/show/_base/base_controller.coffee similarity index 100% rename from src/js/apps/settings/show/_base/base_controller.js.coffee rename to src/js/apps/settings/show/_base/base_controller.coffee diff --git a/src/js/apps/settings/show/addons/addons_controller.js.coffee b/src/js/apps/settings/show/addons/addons_controller.coffee similarity index 100% rename from src/js/apps/settings/show/addons/addons_controller.js.coffee rename to src/js/apps/settings/show/addons/addons_controller.coffee diff --git a/src/js/apps/settings/show/kodi/kodi_controller.js.coffee b/src/js/apps/settings/show/kodi/kodi_controller.coffee similarity index 100% rename from src/js/apps/settings/show/kodi/kodi_controller.js.coffee rename to src/js/apps/settings/show/kodi/kodi_controller.coffee diff --git a/src/js/apps/settings/show/kodi/kodi_view.js.coffee b/src/js/apps/settings/show/kodi/kodi_view.coffee similarity index 100% rename from src/js/apps/settings/show/kodi/kodi_view.js.coffee rename to src/js/apps/settings/show/kodi/kodi_view.coffee diff --git a/src/js/apps/settings/show/local/local_controller.js.coffee b/src/js/apps/settings/show/local/local_controller.coffee similarity index 100% rename from src/js/apps/settings/show/local/local_controller.js.coffee rename to src/js/apps/settings/show/local/local_controller.coffee diff --git a/src/js/apps/settings/show/navMain/navMain_controller.js.coffee b/src/js/apps/settings/show/navMain/navMain_controller.coffee similarity index 100% rename from src/js/apps/settings/show/navMain/navMain_controller.js.coffee rename to src/js/apps/settings/show/navMain/navMain_controller.coffee diff --git a/src/js/apps/settings/show/search/search_controller.js.coffee b/src/js/apps/settings/show/search/search_controller.coffee similarity index 100% rename from src/js/apps/settings/show/search/search_controller.js.coffee rename to src/js/apps/settings/show/search/search_controller.coffee diff --git a/src/js/apps/settings/show/show_view.js.coffee b/src/js/apps/settings/show/show_view.coffee similarity index 100% rename from src/js/apps/settings/show/show_view.js.coffee rename to src/js/apps/settings/show/show_view.coffee diff --git a/src/js/apps/shell/shell_app.js.coffee b/src/js/apps/shell/shell_app.coffee similarity index 100% rename from src/js/apps/shell/shell_app.js.coffee rename to src/js/apps/shell/shell_app.coffee diff --git a/src/js/apps/shell/show/shell_view.js.coffee b/src/js/apps/shell/show/shell_view.coffee similarity index 100% rename from src/js/apps/shell/show/shell_view.js.coffee rename to src/js/apps/shell/show/shell_view.coffee diff --git a/src/js/apps/song/edit/edit_controller.js.coffee b/src/js/apps/song/edit/edit_controller.coffee similarity index 100% rename from src/js/apps/song/edit/edit_controller.js.coffee rename to src/js/apps/song/edit/edit_controller.coffee diff --git a/src/js/apps/song/list/list_controller.js.coffee b/src/js/apps/song/list/list_controller.coffee similarity index 100% rename from src/js/apps/song/list/list_controller.js.coffee rename to src/js/apps/song/list/list_controller.coffee diff --git a/src/js/apps/song/list/list_view.js.coffee b/src/js/apps/song/list/list_view.coffee similarity index 100% rename from src/js/apps/song/list/list_view.js.coffee rename to src/js/apps/song/list/list_view.coffee diff --git a/src/js/apps/song/song_app.js.coffee b/src/js/apps/song/song_app.coffee similarity index 100% rename from src/js/apps/song/song_app.js.coffee rename to src/js/apps/song/song_app.coffee diff --git a/src/js/apps/state/_base/base.js.coffee b/src/js/apps/state/_base/base.coffee similarity index 100% rename from src/js/apps/state/_base/base.js.coffee rename to src/js/apps/state/_base/base.coffee diff --git a/src/js/apps/state/kodi/kodi.js.coffee b/src/js/apps/state/kodi/kodi.coffee similarity index 100% rename from src/js/apps/state/kodi/kodi.js.coffee rename to src/js/apps/state/kodi/kodi.coffee diff --git a/src/js/apps/state/kodi/notifications.js.coffee b/src/js/apps/state/kodi/notifications.coffee similarity index 100% rename from src/js/apps/state/kodi/notifications.js.coffee rename to src/js/apps/state/kodi/notifications.coffee diff --git a/src/js/apps/state/kodi/polling.js.coffee b/src/js/apps/state/kodi/polling.coffee similarity index 100% rename from src/js/apps/state/kodi/polling.js.coffee rename to src/js/apps/state/kodi/polling.coffee diff --git a/src/js/apps/state/local/local.js.coffee b/src/js/apps/state/local/local.coffee similarity index 100% rename from src/js/apps/state/local/local.js.coffee rename to src/js/apps/state/local/local.coffee diff --git a/src/js/apps/state/state_app.js.coffee b/src/js/apps/state/state_app.coffee similarity index 100% rename from src/js/apps/state/state_app.js.coffee rename to src/js/apps/state/state_app.coffee diff --git a/src/js/apps/thumbs/list/list_controller.js.coffee b/src/js/apps/thumbs/list/list_controller.coffee similarity index 100% rename from src/js/apps/thumbs/list/list_controller.js.coffee rename to src/js/apps/thumbs/list/list_controller.coffee diff --git a/src/js/apps/thumbs/list/list_view.js.coffee b/src/js/apps/thumbs/list/list_view.coffee similarity index 100% rename from src/js/apps/thumbs/list/list_view.js.coffee rename to src/js/apps/thumbs/list/list_view.coffee diff --git a/src/js/apps/thumbs/thumbs_app.js.coffee b/src/js/apps/thumbs/thumbs_app.coffee similarity index 100% rename from src/js/apps/thumbs/thumbs_app.js.coffee rename to src/js/apps/thumbs/thumbs_app.coffee diff --git a/src/js/apps/tvshow/editEpisode/edit_episode_controller.js.coffee b/src/js/apps/tvshow/editEpisode/edit_episode_controller.coffee similarity index 100% rename from src/js/apps/tvshow/editEpisode/edit_episode_controller.js.coffee rename to src/js/apps/tvshow/editEpisode/edit_episode_controller.coffee diff --git a/src/js/apps/tvshow/editShow/edit_show_controller.js.coffee b/src/js/apps/tvshow/editShow/edit_show_controller.coffee similarity index 100% rename from src/js/apps/tvshow/editShow/edit_show_controller.js.coffee rename to src/js/apps/tvshow/editShow/edit_show_controller.coffee diff --git a/src/js/apps/tvshow/episode/episode_controller.js.coffee b/src/js/apps/tvshow/episode/episode_controller.coffee similarity index 100% rename from src/js/apps/tvshow/episode/episode_controller.js.coffee rename to src/js/apps/tvshow/episode/episode_controller.coffee diff --git a/src/js/apps/tvshow/episode/episode_view.js.coffee b/src/js/apps/tvshow/episode/episode_view.coffee similarity index 100% rename from src/js/apps/tvshow/episode/episode_view.js.coffee rename to src/js/apps/tvshow/episode/episode_view.coffee diff --git a/src/js/apps/tvshow/list/list_controller.js.coffee b/src/js/apps/tvshow/list/list_controller.coffee similarity index 100% rename from src/js/apps/tvshow/list/list_controller.js.coffee rename to src/js/apps/tvshow/list/list_controller.coffee diff --git a/src/js/apps/tvshow/list/list_view.js.coffee b/src/js/apps/tvshow/list/list_view.coffee similarity index 100% rename from src/js/apps/tvshow/list/list_view.js.coffee rename to src/js/apps/tvshow/list/list_view.coffee diff --git a/src/js/apps/tvshow/season/season_controller.js.coffee b/src/js/apps/tvshow/season/season_controller.coffee similarity index 100% rename from src/js/apps/tvshow/season/season_controller.js.coffee rename to src/js/apps/tvshow/season/season_controller.coffee diff --git a/src/js/apps/tvshow/season/season_view.js.coffee b/src/js/apps/tvshow/season/season_view.coffee similarity index 100% rename from src/js/apps/tvshow/season/season_view.js.coffee rename to src/js/apps/tvshow/season/season_view.coffee diff --git a/src/js/apps/tvshow/show/show_controller.js.coffee b/src/js/apps/tvshow/show/show_controller.coffee similarity index 100% rename from src/js/apps/tvshow/show/show_controller.js.coffee rename to src/js/apps/tvshow/show/show_controller.coffee diff --git a/src/js/apps/tvshow/show/show_view.js.coffee b/src/js/apps/tvshow/show/show_view.coffee similarity index 100% rename from src/js/apps/tvshow/show/show_view.js.coffee rename to src/js/apps/tvshow/show/show_view.coffee diff --git a/src/js/apps/tvshow/tvshow_app.js.coffee b/src/js/apps/tvshow/tvshow_app.coffee similarity index 100% rename from src/js/apps/tvshow/tvshow_app.js.coffee rename to src/js/apps/tvshow/tvshow_app.coffee diff --git a/src/js/apps/ui/ui_app.js.coffee b/src/js/apps/ui/ui_app.coffee similarity index 100% rename from src/js/apps/ui/ui_app.js.coffee rename to src/js/apps/ui/ui_app.coffee diff --git a/src/js/components/form/form_controller.js.coffee b/src/js/components/form/form_controller.coffee similarity index 100% rename from src/js/components/form/form_controller.js.coffee rename to src/js/components/form/form_controller.coffee diff --git a/src/js/components/form/form_view.js.coffee b/src/js/components/form/form_view.coffee similarity index 100% rename from src/js/components/form/form_view.js.coffee rename to src/js/components/form/form_view.coffee diff --git a/src/js/config/backbone/sync.js.coffee b/src/js/config/backbone/sync.coffee similarity index 100% rename from src/js/config/backbone/sync.js.coffee rename to src/js/config/backbone/sync.coffee diff --git a/src/js/config/marionette/application.js.coffee b/src/js/config/marionette/application.coffee similarity index 100% rename from src/js/config/marionette/application.js.coffee rename to src/js/config/marionette/application.coffee diff --git a/src/js/config/marionette/renderer.js.coffee b/src/js/config/marionette/renderer.coffee similarity index 100% rename from src/js/config/marionette/renderer.js.coffee rename to src/js/config/marionette/renderer.coffee diff --git a/src/js/controllers/_base.js.coffee b/src/js/controllers/_base.coffee similarity index 100% rename from src/js/controllers/_base.js.coffee rename to src/js/controllers/_base.coffee diff --git a/src/js/controllers/router.js.coffee b/src/js/controllers/router.coffee similarity index 100% rename from src/js/controllers/router.js.coffee rename to src/js/controllers/router.coffee diff --git a/src/js/entities/_base/collections.js.coffee b/src/js/entities/_base/collections.coffee similarity index 100% rename from src/js/entities/_base/collections.js.coffee rename to src/js/entities/_base/collections.coffee diff --git a/src/js/entities/_base/filtered.js.coffee b/src/js/entities/_base/filtered.coffee similarity index 100% rename from src/js/entities/_base/filtered.js.coffee rename to src/js/entities/_base/filtered.coffee diff --git a/src/js/entities/_base/models.js.coffee b/src/js/entities/_base/models.coffee similarity index 100% rename from src/js/entities/_base/models.js.coffee rename to src/js/entities/_base/models.coffee diff --git a/src/js/entities/config/configApp.js.coffee b/src/js/entities/config/configApp.coffee similarity index 100% rename from src/js/entities/config/configApp.js.coffee rename to src/js/entities/config/configApp.coffee diff --git a/src/js/entities/config/configKodi.js.coffee b/src/js/entities/config/configKodi.coffee similarity index 100% rename from src/js/entities/config/configKodi.js.coffee rename to src/js/entities/config/configKodi.coffee diff --git a/src/js/entities/external/_base.js.coffee b/src/js/entities/external/_base.coffee similarity index 100% rename from src/js/entities/external/_base.js.coffee rename to src/js/entities/external/_base.coffee diff --git a/src/js/entities/external/fanarttv.js.coffee b/src/js/entities/external/fanarttv.coffee similarity index 100% rename from src/js/entities/external/fanarttv.js.coffee rename to src/js/entities/external/fanarttv.coffee diff --git a/src/js/entities/external/musicbrainz.js.coffee b/src/js/entities/external/musicbrainz.coffee similarity index 100% rename from src/js/entities/external/musicbrainz.js.coffee rename to src/js/entities/external/musicbrainz.coffee diff --git a/src/js/entities/external/themoviedb.js.coffee b/src/js/entities/external/themoviedb.coffee similarity index 100% rename from src/js/entities/external/themoviedb.js.coffee rename to src/js/entities/external/themoviedb.coffee diff --git a/src/js/entities/external/youtube.js.coffee b/src/js/entities/external/youtube.coffee similarity index 100% rename from src/js/entities/external/youtube.js.coffee rename to src/js/entities/external/youtube.coffee diff --git a/src/js/entities/filter/filter.js.coffee b/src/js/entities/filter/filter.coffee similarity index 100% rename from src/js/entities/filter/filter.js.coffee rename to src/js/entities/filter/filter.coffee diff --git a/src/js/entities/form/form.js.coffee b/src/js/entities/form/form.coffee similarity index 100% rename from src/js/entities/form/form.js.coffee rename to src/js/entities/form/form.coffee diff --git a/src/js/entities/kodi/_base/_fetch.js.coffee b/src/js/entities/kodi/_base/_fetch.coffee similarity index 100% rename from src/js/entities/kodi/_base/_fetch.js.coffee rename to src/js/entities/kodi/_base/_fetch.coffee diff --git a/src/js/entities/kodi/_base/collections.js.coffee b/src/js/entities/kodi/_base/collections.coffee similarity index 100% rename from src/js/entities/kodi/_base/collections.js.coffee rename to src/js/entities/kodi/_base/collections.coffee diff --git a/src/js/entities/kodi/_base/models.js.coffee b/src/js/entities/kodi/_base/models.coffee similarity index 100% rename from src/js/entities/kodi/_base/models.js.coffee rename to src/js/entities/kodi/_base/models.coffee diff --git a/src/js/entities/kodi/addon.js.coffee b/src/js/entities/kodi/addon.coffee similarity index 100% rename from src/js/entities/kodi/addon.js.coffee rename to src/js/entities/kodi/addon.coffee diff --git a/src/js/entities/kodi/album.js.coffee b/src/js/entities/kodi/album.coffee similarity index 100% rename from src/js/entities/kodi/album.js.coffee rename to src/js/entities/kodi/album.coffee diff --git a/src/js/entities/kodi/artist.js.coffee b/src/js/entities/kodi/artist.coffee similarity index 100% rename from src/js/entities/kodi/artist.js.coffee rename to src/js/entities/kodi/artist.coffee diff --git a/src/js/entities/kodi/cast.js.coffee b/src/js/entities/kodi/cast.coffee similarity index 100% rename from src/js/entities/kodi/cast.js.coffee rename to src/js/entities/kodi/cast.coffee diff --git a/src/js/entities/kodi/epg.js.coffee b/src/js/entities/kodi/epg.coffee similarity index 100% rename from src/js/entities/kodi/epg.js.coffee rename to src/js/entities/kodi/epg.coffee diff --git a/src/js/entities/kodi/episode.js.coffee b/src/js/entities/kodi/episode.coffee similarity index 100% rename from src/js/entities/kodi/episode.js.coffee rename to src/js/entities/kodi/episode.coffee diff --git a/src/js/entities/kodi/file.js.coffee b/src/js/entities/kodi/file.coffee similarity index 100% rename from src/js/entities/kodi/file.js.coffee rename to src/js/entities/kodi/file.coffee diff --git a/src/js/entities/kodi/genres.js.coffee b/src/js/entities/kodi/genres.coffee similarity index 100% rename from src/js/entities/kodi/genres.js.coffee rename to src/js/entities/kodi/genres.coffee diff --git a/src/js/entities/kodi/movie.js.coffee b/src/js/entities/kodi/movie.coffee similarity index 100% rename from src/js/entities/kodi/movie.js.coffee rename to src/js/entities/kodi/movie.coffee diff --git a/src/js/entities/kodi/musicvideo.js.coffee b/src/js/entities/kodi/musicvideo.coffee similarity index 100% rename from src/js/entities/kodi/musicvideo.js.coffee rename to src/js/entities/kodi/musicvideo.coffee diff --git a/src/js/entities/kodi/playlist.js.coffee b/src/js/entities/kodi/playlist.coffee similarity index 100% rename from src/js/entities/kodi/playlist.js.coffee rename to src/js/entities/kodi/playlist.coffee diff --git a/src/js/entities/kodi/pvr.js.coffee b/src/js/entities/kodi/pvr.coffee similarity index 100% rename from src/js/entities/kodi/pvr.js.coffee rename to src/js/entities/kodi/pvr.coffee diff --git a/src/js/entities/kodi/season.js.coffee b/src/js/entities/kodi/season.coffee similarity index 100% rename from src/js/entities/kodi/season.js.coffee rename to src/js/entities/kodi/season.coffee diff --git a/src/js/entities/kodi/settings.js.coffee b/src/js/entities/kodi/settings.coffee similarity index 100% rename from src/js/entities/kodi/settings.js.coffee rename to src/js/entities/kodi/settings.coffee diff --git a/src/js/entities/kodi/song.js.coffee b/src/js/entities/kodi/song.coffee similarity index 100% rename from src/js/entities/kodi/song.js.coffee rename to src/js/entities/kodi/song.coffee diff --git a/src/js/entities/kodi/tvshow.js.coffee b/src/js/entities/kodi/tvshow.coffee similarity index 100% rename from src/js/entities/kodi/tvshow.js.coffee rename to src/js/entities/kodi/tvshow.coffee diff --git a/src/js/entities/lab/apiBrowser.js.coffee b/src/js/entities/lab/apiBrowser.coffee similarity index 100% rename from src/js/entities/lab/apiBrowser.js.coffee rename to src/js/entities/lab/apiBrowser.coffee diff --git a/src/js/entities/localPlaylist/localPlaylist.js.coffee b/src/js/entities/localPlaylist/localPlaylist.coffee similarity index 100% rename from src/js/entities/localPlaylist/localPlaylist.js.coffee rename to src/js/entities/localPlaylist/localPlaylist.coffee diff --git a/src/js/entities/nav/navMain.js.coffee b/src/js/entities/nav/navMain.coffee similarity index 100% rename from src/js/entities/nav/navMain.js.coffee rename to src/js/entities/nav/navMain.coffee diff --git a/src/js/entities/search/searchAddons.js.coffee b/src/js/entities/search/searchAddons.coffee similarity index 100% rename from src/js/entities/search/searchAddons.js.coffee rename to src/js/entities/search/searchAddons.coffee diff --git a/src/js/helpers/backscroll.js.coffee b/src/js/helpers/backscroll.coffee similarity index 100% rename from src/js/helpers/backscroll.js.coffee rename to src/js/helpers/backscroll.coffee diff --git a/src/js/helpers/cache.js.coffee b/src/js/helpers/cache.coffee similarity index 100% rename from src/js/helpers/cache.js.coffee rename to src/js/helpers/cache.coffee diff --git a/src/js/helpers/config.js.coffee b/src/js/helpers/config.coffee similarity index 100% rename from src/js/helpers/config.js.coffee rename to src/js/helpers/config.coffee diff --git a/src/js/helpers/connection.js.coffee b/src/js/helpers/connection.coffee similarity index 100% rename from src/js/helpers/connection.js.coffee rename to src/js/helpers/connection.coffee diff --git a/src/js/helpers/customMixins/kodi_entities.js.coffee b/src/js/helpers/customMixins/kodi_entities.coffee similarity index 100% rename from src/js/helpers/customMixins/kodi_entities.js.coffee rename to src/js/helpers/customMixins/kodi_entities.coffee diff --git a/src/js/helpers/debug.js.coffee b/src/js/helpers/debug.coffee similarity index 100% rename from src/js/helpers/debug.js.coffee rename to src/js/helpers/debug.coffee diff --git a/src/js/helpers/entities.js.coffee b/src/js/helpers/entities.coffee similarity index 100% rename from src/js/helpers/entities.js.coffee rename to src/js/helpers/entities.coffee diff --git a/src/js/helpers/global.js.coffee b/src/js/helpers/global.coffee similarity index 100% rename from src/js/helpers/global.js.coffee rename to src/js/helpers/global.coffee diff --git a/src/js/helpers/jquery.js.coffee b/src/js/helpers/jquery.coffee similarity index 100% rename from src/js/helpers/jquery.js.coffee rename to src/js/helpers/jquery.coffee diff --git a/src/js/helpers/streams.js.coffee b/src/js/helpers/streams.coffee similarity index 100% rename from src/js/helpers/streams.js.coffee rename to src/js/helpers/streams.coffee diff --git a/src/js/helpers/translate.js.coffee b/src/js/helpers/translate.coffee similarity index 100% rename from src/js/helpers/translate.js.coffee rename to src/js/helpers/translate.coffee diff --git a/src/js/helpers/ui.js.coffee b/src/js/helpers/ui.coffee similarity index 100% rename from src/js/helpers/ui.js.coffee rename to src/js/helpers/ui.coffee diff --git a/src/js/helpers/url.js.coffee b/src/js/helpers/url.coffee similarity index 100% rename from src/js/helpers/url.js.coffee rename to src/js/helpers/url.coffee diff --git a/src/js/views/_base/collectionview.js.coffee b/src/js/views/_base/collectionview.coffee similarity index 100% rename from src/js/views/_base/collectionview.js.coffee rename to src/js/views/_base/collectionview.coffee diff --git a/src/js/views/_base/compositeview.js.coffee b/src/js/views/_base/compositeview.coffee similarity index 100% rename from src/js/views/_base/compositeview.js.coffee rename to src/js/views/_base/compositeview.coffee diff --git a/src/js/views/_base/itemview.js.coffee b/src/js/views/_base/itemview.coffee similarity index 100% rename from src/js/views/_base/itemview.js.coffee rename to src/js/views/_base/itemview.coffee diff --git a/src/js/views/_base/layout.js.coffee b/src/js/views/_base/layout.coffee similarity index 100% rename from src/js/views/_base/layout.js.coffee rename to src/js/views/_base/layout.coffee diff --git a/src/js/views/_base/view.js.coffee b/src/js/views/_base/view.coffee similarity index 100% rename from src/js/views/_base/view.js.coffee rename to src/js/views/_base/view.coffee diff --git a/src/js/views/_base/virtuallistview.js.coffee b/src/js/views/_base/virtuallistview.coffee similarity index 100% rename from src/js/views/_base/virtuallistview.js.coffee rename to src/js/views/_base/virtuallistview.coffee diff --git a/src/js/views/card/card_view.js.coffee b/src/js/views/card/card_view.coffee similarity index 100% rename from src/js/views/card/card_view.js.coffee rename to src/js/views/card/card_view.coffee diff --git a/src/js/views/details/detailsitem.js.coffee b/src/js/views/details/detailsitem.coffee similarity index 100% rename from src/js/views/details/detailsitem.js.coffee rename to src/js/views/details/detailsitem.coffee diff --git a/src/js/views/empty/empty_view.js.coffee b/src/js/views/empty/empty_view.coffee similarity index 100% rename from src/js/views/empty/empty_view.js.coffee rename to src/js/views/empty/empty_view.coffee diff --git a/src/js/views/layouts/layouts_view.js.coffee b/src/js/views/layouts/layouts_view.coffee similarity index 100% rename from src/js/views/layouts/layouts_view.js.coffee rename to src/js/views/layouts/layouts_view.coffee diff --git a/src/js/views/set/set_view.js.coffee b/src/js/views/set/set_view.coffee similarity index 100% rename from src/js/views/set/set_view.js.coffee rename to src/js/views/set/set_view.coffee diff --git a/src/js/views/song/song_view.js.coffee b/src/js/views/song/song_view.coffee similarity index 100% rename from src/js/views/song/song_view.js.coffee rename to src/js/views/song/song_view.coffee From 43199043b743f65ff1006e1f9bc54e953e3218bd Mon Sep 17 00:00:00 2001 From: decaffeinate <870074+max-te@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:03:07 +0100 Subject: [PATCH 03/21] decaffeinate: Rename app.coffee and 220 other files from .coffee to .js --- src/js/{app.coffee => app.js} | 0 src/js/apps/addon/{addon_app.coffee => addon_app.js} | 0 .../{addon_googlemusic_app.coffee => addon_googlemusic_app.js} | 0 .../addon/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/addon/list/{list_view.coffee => list_view.js} | 0 .../mixcloud/{addon_mixcloud_app.coffee => addon_mixcloud_app.js} | 0 src/js/apps/addon/pvr/{addons_pvr_ap.coffee => addons_pvr_ap.js} | 0 .../addon/radio/{addon_radio_app.coffee => addon_radio_app.js} | 0 .../{addon_soundcloud_app.coffee => addon_soundcloud_app.js} | 0 .../youtube/{addon_youtube_app.coffee => addon_youtube_app.js} | 0 src/js/apps/album/{album_app.coffee => album_app.js} | 0 .../album/edit/{edit_controller.coffee => edit_controller.js} | 0 .../album/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/album/list/{list_view.coffee => list_view.js} | 0 .../album/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/album/show/{show_view.coffee => show_view.js} | 0 src/js/apps/artist/{artist_app.coffee => artist_app.js} | 0 .../artist/edit/{edit_controller.coffee => edit_controller.js} | 0 .../artist/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/artist/list/{list_view.coffee => list_view.js} | 0 .../artist/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/artist/show/{show_view.coffee => show_view.js} | 0 src/js/apps/audioStream/{init.coffee => init.js} | 0 src/js/apps/browser/{browser_app.coffee => browser_app.js} | 0 .../browser/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/browser/list/{list_view.coffee => list_view.js} | 0 src/js/apps/cast/{cast_app.coffee => cast_app.js} | 0 src/js/apps/cast/list/{list_view.coffee => list_view.js} | 0 src/js/apps/category/{category_app.coffee => category_app.js} | 0 .../category/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/category/list/{list_view.coffee => list_view.js} | 0 src/js/apps/command/{command_app.coffee => command_app.js} | 0 src/js/apps/command/kodi/_base/{_base.coffee => _base.js} | 0 src/js/apps/command/kodi/_base/{api.coffee => api.js} | 0 src/js/apps/command/kodi/helpers/{addon.coffee => addon.js} | 0 .../command/kodi/helpers/{application.coffee => application.js} | 0 .../command/kodi/helpers/{audiolibrary.coffee => audiolibrary.js} | 0 src/js/apps/command/kodi/helpers/{file.coffee => file.js} | 0 src/js/apps/command/kodi/helpers/{gui.coffee => gui.js} | 0 src/js/apps/command/kodi/helpers/{input.coffee => input.js} | 0 src/js/apps/command/kodi/helpers/{playlist.coffee => playlist.js} | 0 src/js/apps/command/kodi/helpers/{pvr.coffee => pvr.js} | 0 src/js/apps/command/kodi/helpers/{settings.coffee => settings.js} | 0 src/js/apps/command/kodi/helpers/{system.coffee => system.js} | 0 .../command/kodi/helpers/{videolibrary.coffee => videolibrary.js} | 0 src/js/apps/command/local/_base/{_base.coffee => _base.js} | 0 src/js/apps/command/local/_base/{api.coffee => api.js} | 0 .../command/local/helpers/{application.coffee => application.js} | 0 .../apps/command/local/helpers/{playlist.coffee => playlist.js} | 0 .../command/local/helpers/{videoplayer.coffee => videoplayer.js} | 0 src/js/apps/epg/{epg_app.coffee => epg_app.js} | 0 .../apps/epg/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/epg/list/{list_view.coffee => list_view.js} | 0 src/js/apps/external/{external_app.coffee => external_app.js} | 0 .../youtube/{youtube_controller.coffee => youtube_controller.js} | 0 .../external/youtube/{youtube_view.coffee => youtube_view.js} | 0 src/js/apps/filter/{filter_app.coffee => filter_app.js} | 0 .../filter/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/filter/show/{show_view.coffee => show_view.js} | 0 src/js/apps/help/{help_app.coffee => help_app.js} | 0 .../{overview_controller.coffee => overview_controller.js} | 0 .../apps/help/overview/{overview_view.coffee => overview_view.js} | 0 .../apps/help/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/help/show/{show_view.coffee => show_view.js} | 0 src/js/apps/images/{images_app.coffee => images_app.js} | 0 src/js/apps/input/{input_app.coffee => input_app.js} | 0 .../remote/{remote_controller.coffee => remote_controller.js} | 0 src/js/apps/input/remote/{remote_view.coffee => remote_view.js} | 0 .../resume/{resume_controller.coffee => resume_controller.js} | 0 .../{apiBrowser_controller.coffee => apiBrowser_controller.js} | 0 .../lab/apiBrowser/{apiBrowser_view.coffee => apiBrowser_view.js} | 0 .../iconBrowser/{iconBrowser_view.coffee => iconBrowser_view.js} | 0 src/js/apps/lab/lab/{lab_view.coffee => lab_view.js} | 0 src/js/apps/lab/{lab_app.coffee => lab_app.js} | 0 src/js/apps/landing/{landing_app.coffee => landing_app.js} | 0 .../show/{landing_controller.coffee => landing_controller.js} | 0 src/js/apps/landing/show/{landing_view.coffee => landing_view.js} | 0 src/js/apps/loading/{loading_app.coffee => loading_app.js} | 0 src/js/apps/loading/show/{loading_view.coffee => loading_view.js} | 0 .../list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/localPlaylist/list/{list_view.coffee => list_view.js} | 0 .../{localPlaylist_app.coffee => localPlaylist_app.js} | 0 .../movie/edit/{edit_controller.coffee => edit_controller.js} | 0 .../movie/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/movie/list/{list_view.coffee => list_view.js} | 0 src/js/apps/movie/{movie_app.coffee => movie_app.js} | 0 .../movie/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/movie/show/{show_view.coffee => show_view.js} | 0 .../edit/{edit_controller.coffee => edit_controller.js} | 0 .../list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/musicvideo/list/{list_view.coffee => list_view.js} | 0 .../apps/musicvideo/{musicvideo_app.coffee => musicvideo_app.js} | 0 .../show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/musicvideo/show/{show_view.coffee => show_view.js} | 0 src/js/apps/navMain/{navMain_app.coffee => navMain_app.js} | 0 src/js/apps/navMain/show/{navMain_view.coffee => navMain_view.js} | 0 .../{notifications_app.coffee => notifications_app.js} | 0 src/js/apps/player/{player_app.coffee => player_app.js} | 0 src/js/apps/player/show/{player_view.coffee => player_view.js} | 0 .../playlist/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/playlist/list/{list_view.coffee => list_view.js} | 0 .../playlist/localParty/{local_party.coffee => local_party.js} | 0 .../playlist/m3u/{m3u_controller.coffee => m3u_controller.js} | 0 src/js/apps/playlist/m3u/{m3u_view.coffee => m3u_view.js} | 0 src/js/apps/playlist/{playlist_app.coffee => playlist_app.js} | 0 .../playlist/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/playlist/show/{show_view.coffee => show_view.js} | 0 ...{channel_list_controller.coffee => channel_list_controller.js} | 0 .../{channel_list_view.coffee => channel_list_view.js} | 0 src/js/apps/pvr/{pvr_app.coffee => pvr_app.js} | 0 ...ording_list_controller.coffee => recording_list_controller.js} | 0 .../{recording_list_view.coffee => recording_list_view.js} | 0 .../search/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/search/list/{list_view.coffee => list_view.js} | 0 src/js/apps/search/{search_app.coffee => search_app.js} | 0 .../search/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/search/show/{show_view.coffee => show_view.js} | 0 src/js/apps/selected/{selected_app.coffee => selected_app.js} | 0 src/js/apps/settings/{settings_app.coffee => settings_app.js} | 0 .../show/_base/{base_controller.coffee => base_controller.js} | 0 .../addons/{addons_controller.coffee => addons_controller.js} | 0 .../show/kodi/{kodi_controller.coffee => kodi_controller.js} | 0 src/js/apps/settings/show/kodi/{kodi_view.coffee => kodi_view.js} | 0 .../show/local/{local_controller.coffee => local_controller.js} | 0 .../navMain/{navMain_controller.coffee => navMain_controller.js} | 0 .../search/{search_controller.coffee => search_controller.js} | 0 src/js/apps/settings/show/{show_view.coffee => show_view.js} | 0 src/js/apps/shell/{shell_app.coffee => shell_app.js} | 0 src/js/apps/shell/show/{shell_view.coffee => shell_view.js} | 0 .../apps/song/edit/{edit_controller.coffee => edit_controller.js} | 0 .../apps/song/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/song/list/{list_view.coffee => list_view.js} | 0 src/js/apps/song/{song_app.coffee => song_app.js} | 0 src/js/apps/state/_base/{base.coffee => base.js} | 0 src/js/apps/state/kodi/{kodi.coffee => kodi.js} | 0 src/js/apps/state/kodi/{notifications.coffee => notifications.js} | 0 src/js/apps/state/kodi/{polling.coffee => polling.js} | 0 src/js/apps/state/local/{local.coffee => local.js} | 0 src/js/apps/state/{state_app.coffee => state_app.js} | 0 .../thumbs/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/thumbs/list/{list_view.coffee => list_view.js} | 0 src/js/apps/thumbs/{thumbs_app.coffee => thumbs_app.js} | 0 ...{edit_episode_controller.coffee => edit_episode_controller.js} | 0 .../{edit_show_controller.coffee => edit_show_controller.js} | 0 .../episode/{episode_controller.coffee => episode_controller.js} | 0 .../apps/tvshow/episode/{episode_view.coffee => episode_view.js} | 0 .../tvshow/list/{list_controller.coffee => list_controller.js} | 0 src/js/apps/tvshow/list/{list_view.coffee => list_view.js} | 0 .../season/{season_controller.coffee => season_controller.js} | 0 src/js/apps/tvshow/season/{season_view.coffee => season_view.js} | 0 .../tvshow/show/{show_controller.coffee => show_controller.js} | 0 src/js/apps/tvshow/show/{show_view.coffee => show_view.js} | 0 src/js/apps/tvshow/{tvshow_app.coffee => tvshow_app.js} | 0 src/js/apps/ui/{ui_app.coffee => ui_app.js} | 0 .../form/{form_controller.coffee => form_controller.js} | 0 src/js/components/form/{form_view.coffee => form_view.js} | 0 src/js/config/backbone/{sync.coffee => sync.js} | 0 src/js/config/marionette/{application.coffee => application.js} | 0 src/js/config/marionette/{renderer.coffee => renderer.js} | 0 src/js/controllers/{_base.coffee => _base.js} | 0 src/js/controllers/{router.coffee => router.js} | 0 src/js/entities/_base/{collections.coffee => collections.js} | 0 src/js/entities/_base/{filtered.coffee => filtered.js} | 0 src/js/entities/_base/{models.coffee => models.js} | 0 src/js/entities/config/{configApp.coffee => configApp.js} | 0 src/js/entities/config/{configKodi.coffee => configKodi.js} | 0 src/js/entities/external/{_base.coffee => _base.js} | 0 src/js/entities/external/{fanarttv.coffee => fanarttv.js} | 0 src/js/entities/external/{musicbrainz.coffee => musicbrainz.js} | 0 src/js/entities/external/{themoviedb.coffee => themoviedb.js} | 0 src/js/entities/external/{youtube.coffee => youtube.js} | 0 src/js/entities/filter/{filter.coffee => filter.js} | 0 src/js/entities/form/{form.coffee => form.js} | 0 src/js/entities/kodi/_base/{_fetch.coffee => _fetch.js} | 0 src/js/entities/kodi/_base/{collections.coffee => collections.js} | 0 src/js/entities/kodi/_base/{models.coffee => models.js} | 0 src/js/entities/kodi/{addon.coffee => addon.js} | 0 src/js/entities/kodi/{album.coffee => album.js} | 0 src/js/entities/kodi/{artist.coffee => artist.js} | 0 src/js/entities/kodi/{cast.coffee => cast.js} | 0 src/js/entities/kodi/{epg.coffee => epg.js} | 0 src/js/entities/kodi/{episode.coffee => episode.js} | 0 src/js/entities/kodi/{file.coffee => file.js} | 0 src/js/entities/kodi/{genres.coffee => genres.js} | 0 src/js/entities/kodi/{movie.coffee => movie.js} | 0 src/js/entities/kodi/{musicvideo.coffee => musicvideo.js} | 0 src/js/entities/kodi/{playlist.coffee => playlist.js} | 0 src/js/entities/kodi/{pvr.coffee => pvr.js} | 0 src/js/entities/kodi/{season.coffee => season.js} | 0 src/js/entities/kodi/{settings.coffee => settings.js} | 0 src/js/entities/kodi/{song.coffee => song.js} | 0 src/js/entities/kodi/{tvshow.coffee => tvshow.js} | 0 src/js/entities/lab/{apiBrowser.coffee => apiBrowser.js} | 0 .../localPlaylist/{localPlaylist.coffee => localPlaylist.js} | 0 src/js/entities/nav/{navMain.coffee => navMain.js} | 0 src/js/entities/search/{searchAddons.coffee => searchAddons.js} | 0 src/js/helpers/{backscroll.coffee => backscroll.js} | 0 src/js/helpers/{cache.coffee => cache.js} | 0 src/js/helpers/{config.coffee => config.js} | 0 src/js/helpers/{connection.coffee => connection.js} | 0 .../customMixins/{kodi_entities.coffee => kodi_entities.js} | 0 src/js/helpers/{debug.coffee => debug.js} | 0 src/js/helpers/{entities.coffee => entities.js} | 0 src/js/helpers/{global.coffee => global.js} | 0 src/js/helpers/{jquery.coffee => jquery.js} | 0 src/js/helpers/{streams.coffee => streams.js} | 0 src/js/helpers/{translate.coffee => translate.js} | 0 src/js/helpers/{ui.coffee => ui.js} | 0 src/js/helpers/{url.coffee => url.js} | 0 src/js/views/_base/{collectionview.coffee => collectionview.js} | 0 src/js/views/_base/{compositeview.coffee => compositeview.js} | 0 src/js/views/_base/{itemview.coffee => itemview.js} | 0 src/js/views/_base/{layout.coffee => layout.js} | 0 src/js/views/_base/{view.coffee => view.js} | 0 src/js/views/_base/{virtuallistview.coffee => virtuallistview.js} | 0 src/js/views/card/{card_view.coffee => card_view.js} | 0 src/js/views/details/{detailsitem.coffee => detailsitem.js} | 0 src/js/views/empty/{empty_view.coffee => empty_view.js} | 0 src/js/views/layouts/{layouts_view.coffee => layouts_view.js} | 0 src/js/views/set/{set_view.coffee => set_view.js} | 0 src/js/views/song/{song_view.coffee => song_view.js} | 0 221 files changed, 0 insertions(+), 0 deletions(-) rename src/js/{app.coffee => app.js} (100%) rename src/js/apps/addon/{addon_app.coffee => addon_app.js} (100%) rename src/js/apps/addon/googlemusic/{addon_googlemusic_app.coffee => addon_googlemusic_app.js} (100%) rename src/js/apps/addon/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/addon/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/addon/mixcloud/{addon_mixcloud_app.coffee => addon_mixcloud_app.js} (100%) rename src/js/apps/addon/pvr/{addons_pvr_ap.coffee => addons_pvr_ap.js} (100%) rename src/js/apps/addon/radio/{addon_radio_app.coffee => addon_radio_app.js} (100%) rename src/js/apps/addon/soundcloud/{addon_soundcloud_app.coffee => addon_soundcloud_app.js} (100%) rename src/js/apps/addon/youtube/{addon_youtube_app.coffee => addon_youtube_app.js} (100%) rename src/js/apps/album/{album_app.coffee => album_app.js} (100%) rename src/js/apps/album/edit/{edit_controller.coffee => edit_controller.js} (100%) rename src/js/apps/album/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/album/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/album/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/album/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/artist/{artist_app.coffee => artist_app.js} (100%) rename src/js/apps/artist/edit/{edit_controller.coffee => edit_controller.js} (100%) rename src/js/apps/artist/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/artist/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/artist/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/artist/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/audioStream/{init.coffee => init.js} (100%) rename src/js/apps/browser/{browser_app.coffee => browser_app.js} (100%) rename src/js/apps/browser/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/browser/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/cast/{cast_app.coffee => cast_app.js} (100%) rename src/js/apps/cast/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/category/{category_app.coffee => category_app.js} (100%) rename src/js/apps/category/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/category/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/command/{command_app.coffee => command_app.js} (100%) rename src/js/apps/command/kodi/_base/{_base.coffee => _base.js} (100%) rename src/js/apps/command/kodi/_base/{api.coffee => api.js} (100%) rename src/js/apps/command/kodi/helpers/{addon.coffee => addon.js} (100%) rename src/js/apps/command/kodi/helpers/{application.coffee => application.js} (100%) rename src/js/apps/command/kodi/helpers/{audiolibrary.coffee => audiolibrary.js} (100%) rename src/js/apps/command/kodi/helpers/{file.coffee => file.js} (100%) rename src/js/apps/command/kodi/helpers/{gui.coffee => gui.js} (100%) rename src/js/apps/command/kodi/helpers/{input.coffee => input.js} (100%) rename src/js/apps/command/kodi/helpers/{playlist.coffee => playlist.js} (100%) rename src/js/apps/command/kodi/helpers/{pvr.coffee => pvr.js} (100%) rename src/js/apps/command/kodi/helpers/{settings.coffee => settings.js} (100%) rename src/js/apps/command/kodi/helpers/{system.coffee => system.js} (100%) rename src/js/apps/command/kodi/helpers/{videolibrary.coffee => videolibrary.js} (100%) rename src/js/apps/command/local/_base/{_base.coffee => _base.js} (100%) rename src/js/apps/command/local/_base/{api.coffee => api.js} (100%) rename src/js/apps/command/local/helpers/{application.coffee => application.js} (100%) rename src/js/apps/command/local/helpers/{playlist.coffee => playlist.js} (100%) rename src/js/apps/command/local/helpers/{videoplayer.coffee => videoplayer.js} (100%) rename src/js/apps/epg/{epg_app.coffee => epg_app.js} (100%) rename src/js/apps/epg/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/epg/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/external/{external_app.coffee => external_app.js} (100%) rename src/js/apps/external/youtube/{youtube_controller.coffee => youtube_controller.js} (100%) rename src/js/apps/external/youtube/{youtube_view.coffee => youtube_view.js} (100%) rename src/js/apps/filter/{filter_app.coffee => filter_app.js} (100%) rename src/js/apps/filter/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/filter/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/help/{help_app.coffee => help_app.js} (100%) rename src/js/apps/help/overview/{overview_controller.coffee => overview_controller.js} (100%) rename src/js/apps/help/overview/{overview_view.coffee => overview_view.js} (100%) rename src/js/apps/help/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/help/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/images/{images_app.coffee => images_app.js} (100%) rename src/js/apps/input/{input_app.coffee => input_app.js} (100%) rename src/js/apps/input/remote/{remote_controller.coffee => remote_controller.js} (100%) rename src/js/apps/input/remote/{remote_view.coffee => remote_view.js} (100%) rename src/js/apps/input/resume/{resume_controller.coffee => resume_controller.js} (100%) rename src/js/apps/lab/apiBrowser/{apiBrowser_controller.coffee => apiBrowser_controller.js} (100%) rename src/js/apps/lab/apiBrowser/{apiBrowser_view.coffee => apiBrowser_view.js} (100%) rename src/js/apps/lab/iconBrowser/{iconBrowser_view.coffee => iconBrowser_view.js} (100%) rename src/js/apps/lab/lab/{lab_view.coffee => lab_view.js} (100%) rename src/js/apps/lab/{lab_app.coffee => lab_app.js} (100%) rename src/js/apps/landing/{landing_app.coffee => landing_app.js} (100%) rename src/js/apps/landing/show/{landing_controller.coffee => landing_controller.js} (100%) rename src/js/apps/landing/show/{landing_view.coffee => landing_view.js} (100%) rename src/js/apps/loading/{loading_app.coffee => loading_app.js} (100%) rename src/js/apps/loading/show/{loading_view.coffee => loading_view.js} (100%) rename src/js/apps/localPlaylist/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/localPlaylist/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/localPlaylist/{localPlaylist_app.coffee => localPlaylist_app.js} (100%) rename src/js/apps/movie/edit/{edit_controller.coffee => edit_controller.js} (100%) rename src/js/apps/movie/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/movie/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/movie/{movie_app.coffee => movie_app.js} (100%) rename src/js/apps/movie/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/movie/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/musicvideo/edit/{edit_controller.coffee => edit_controller.js} (100%) rename src/js/apps/musicvideo/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/musicvideo/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/musicvideo/{musicvideo_app.coffee => musicvideo_app.js} (100%) rename src/js/apps/musicvideo/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/musicvideo/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/navMain/{navMain_app.coffee => navMain_app.js} (100%) rename src/js/apps/navMain/show/{navMain_view.coffee => navMain_view.js} (100%) rename src/js/apps/notifications/{notifications_app.coffee => notifications_app.js} (100%) rename src/js/apps/player/{player_app.coffee => player_app.js} (100%) rename src/js/apps/player/show/{player_view.coffee => player_view.js} (100%) rename src/js/apps/playlist/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/playlist/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/playlist/localParty/{local_party.coffee => local_party.js} (100%) rename src/js/apps/playlist/m3u/{m3u_controller.coffee => m3u_controller.js} (100%) rename src/js/apps/playlist/m3u/{m3u_view.coffee => m3u_view.js} (100%) rename src/js/apps/playlist/{playlist_app.coffee => playlist_app.js} (100%) rename src/js/apps/playlist/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/playlist/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/pvr/channelList/{channel_list_controller.coffee => channel_list_controller.js} (100%) rename src/js/apps/pvr/channelList/{channel_list_view.coffee => channel_list_view.js} (100%) rename src/js/apps/pvr/{pvr_app.coffee => pvr_app.js} (100%) rename src/js/apps/pvr/recordingList/{recording_list_controller.coffee => recording_list_controller.js} (100%) rename src/js/apps/pvr/recordingList/{recording_list_view.coffee => recording_list_view.js} (100%) rename src/js/apps/search/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/search/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/search/{search_app.coffee => search_app.js} (100%) rename src/js/apps/search/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/search/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/selected/{selected_app.coffee => selected_app.js} (100%) rename src/js/apps/settings/{settings_app.coffee => settings_app.js} (100%) rename src/js/apps/settings/show/_base/{base_controller.coffee => base_controller.js} (100%) rename src/js/apps/settings/show/addons/{addons_controller.coffee => addons_controller.js} (100%) rename src/js/apps/settings/show/kodi/{kodi_controller.coffee => kodi_controller.js} (100%) rename src/js/apps/settings/show/kodi/{kodi_view.coffee => kodi_view.js} (100%) rename src/js/apps/settings/show/local/{local_controller.coffee => local_controller.js} (100%) rename src/js/apps/settings/show/navMain/{navMain_controller.coffee => navMain_controller.js} (100%) rename src/js/apps/settings/show/search/{search_controller.coffee => search_controller.js} (100%) rename src/js/apps/settings/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/shell/{shell_app.coffee => shell_app.js} (100%) rename src/js/apps/shell/show/{shell_view.coffee => shell_view.js} (100%) rename src/js/apps/song/edit/{edit_controller.coffee => edit_controller.js} (100%) rename src/js/apps/song/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/song/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/song/{song_app.coffee => song_app.js} (100%) rename src/js/apps/state/_base/{base.coffee => base.js} (100%) rename src/js/apps/state/kodi/{kodi.coffee => kodi.js} (100%) rename src/js/apps/state/kodi/{notifications.coffee => notifications.js} (100%) rename src/js/apps/state/kodi/{polling.coffee => polling.js} (100%) rename src/js/apps/state/local/{local.coffee => local.js} (100%) rename src/js/apps/state/{state_app.coffee => state_app.js} (100%) rename src/js/apps/thumbs/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/thumbs/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/thumbs/{thumbs_app.coffee => thumbs_app.js} (100%) rename src/js/apps/tvshow/editEpisode/{edit_episode_controller.coffee => edit_episode_controller.js} (100%) rename src/js/apps/tvshow/editShow/{edit_show_controller.coffee => edit_show_controller.js} (100%) rename src/js/apps/tvshow/episode/{episode_controller.coffee => episode_controller.js} (100%) rename src/js/apps/tvshow/episode/{episode_view.coffee => episode_view.js} (100%) rename src/js/apps/tvshow/list/{list_controller.coffee => list_controller.js} (100%) rename src/js/apps/tvshow/list/{list_view.coffee => list_view.js} (100%) rename src/js/apps/tvshow/season/{season_controller.coffee => season_controller.js} (100%) rename src/js/apps/tvshow/season/{season_view.coffee => season_view.js} (100%) rename src/js/apps/tvshow/show/{show_controller.coffee => show_controller.js} (100%) rename src/js/apps/tvshow/show/{show_view.coffee => show_view.js} (100%) rename src/js/apps/tvshow/{tvshow_app.coffee => tvshow_app.js} (100%) rename src/js/apps/ui/{ui_app.coffee => ui_app.js} (100%) rename src/js/components/form/{form_controller.coffee => form_controller.js} (100%) rename src/js/components/form/{form_view.coffee => form_view.js} (100%) rename src/js/config/backbone/{sync.coffee => sync.js} (100%) rename src/js/config/marionette/{application.coffee => application.js} (100%) rename src/js/config/marionette/{renderer.coffee => renderer.js} (100%) rename src/js/controllers/{_base.coffee => _base.js} (100%) rename src/js/controllers/{router.coffee => router.js} (100%) rename src/js/entities/_base/{collections.coffee => collections.js} (100%) rename src/js/entities/_base/{filtered.coffee => filtered.js} (100%) rename src/js/entities/_base/{models.coffee => models.js} (100%) rename src/js/entities/config/{configApp.coffee => configApp.js} (100%) rename src/js/entities/config/{configKodi.coffee => configKodi.js} (100%) rename src/js/entities/external/{_base.coffee => _base.js} (100%) rename src/js/entities/external/{fanarttv.coffee => fanarttv.js} (100%) rename src/js/entities/external/{musicbrainz.coffee => musicbrainz.js} (100%) rename src/js/entities/external/{themoviedb.coffee => themoviedb.js} (100%) rename src/js/entities/external/{youtube.coffee => youtube.js} (100%) rename src/js/entities/filter/{filter.coffee => filter.js} (100%) rename src/js/entities/form/{form.coffee => form.js} (100%) rename src/js/entities/kodi/_base/{_fetch.coffee => _fetch.js} (100%) rename src/js/entities/kodi/_base/{collections.coffee => collections.js} (100%) rename src/js/entities/kodi/_base/{models.coffee => models.js} (100%) rename src/js/entities/kodi/{addon.coffee => addon.js} (100%) rename src/js/entities/kodi/{album.coffee => album.js} (100%) rename src/js/entities/kodi/{artist.coffee => artist.js} (100%) rename src/js/entities/kodi/{cast.coffee => cast.js} (100%) rename src/js/entities/kodi/{epg.coffee => epg.js} (100%) rename src/js/entities/kodi/{episode.coffee => episode.js} (100%) rename src/js/entities/kodi/{file.coffee => file.js} (100%) rename src/js/entities/kodi/{genres.coffee => genres.js} (100%) rename src/js/entities/kodi/{movie.coffee => movie.js} (100%) rename src/js/entities/kodi/{musicvideo.coffee => musicvideo.js} (100%) rename src/js/entities/kodi/{playlist.coffee => playlist.js} (100%) rename src/js/entities/kodi/{pvr.coffee => pvr.js} (100%) rename src/js/entities/kodi/{season.coffee => season.js} (100%) rename src/js/entities/kodi/{settings.coffee => settings.js} (100%) rename src/js/entities/kodi/{song.coffee => song.js} (100%) rename src/js/entities/kodi/{tvshow.coffee => tvshow.js} (100%) rename src/js/entities/lab/{apiBrowser.coffee => apiBrowser.js} (100%) rename src/js/entities/localPlaylist/{localPlaylist.coffee => localPlaylist.js} (100%) rename src/js/entities/nav/{navMain.coffee => navMain.js} (100%) rename src/js/entities/search/{searchAddons.coffee => searchAddons.js} (100%) rename src/js/helpers/{backscroll.coffee => backscroll.js} (100%) rename src/js/helpers/{cache.coffee => cache.js} (100%) rename src/js/helpers/{config.coffee => config.js} (100%) rename src/js/helpers/{connection.coffee => connection.js} (100%) rename src/js/helpers/customMixins/{kodi_entities.coffee => kodi_entities.js} (100%) rename src/js/helpers/{debug.coffee => debug.js} (100%) rename src/js/helpers/{entities.coffee => entities.js} (100%) rename src/js/helpers/{global.coffee => global.js} (100%) rename src/js/helpers/{jquery.coffee => jquery.js} (100%) rename src/js/helpers/{streams.coffee => streams.js} (100%) rename src/js/helpers/{translate.coffee => translate.js} (100%) rename src/js/helpers/{ui.coffee => ui.js} (100%) rename src/js/helpers/{url.coffee => url.js} (100%) rename src/js/views/_base/{collectionview.coffee => collectionview.js} (100%) rename src/js/views/_base/{compositeview.coffee => compositeview.js} (100%) rename src/js/views/_base/{itemview.coffee => itemview.js} (100%) rename src/js/views/_base/{layout.coffee => layout.js} (100%) rename src/js/views/_base/{view.coffee => view.js} (100%) rename src/js/views/_base/{virtuallistview.coffee => virtuallistview.js} (100%) rename src/js/views/card/{card_view.coffee => card_view.js} (100%) rename src/js/views/details/{detailsitem.coffee => detailsitem.js} (100%) rename src/js/views/empty/{empty_view.coffee => empty_view.js} (100%) rename src/js/views/layouts/{layouts_view.coffee => layouts_view.js} (100%) rename src/js/views/set/{set_view.coffee => set_view.js} (100%) rename src/js/views/song/{song_view.coffee => song_view.js} (100%) diff --git a/src/js/app.coffee b/src/js/app.js similarity index 100% rename from src/js/app.coffee rename to src/js/app.js diff --git a/src/js/apps/addon/addon_app.coffee b/src/js/apps/addon/addon_app.js similarity index 100% rename from src/js/apps/addon/addon_app.coffee rename to src/js/apps/addon/addon_app.js diff --git a/src/js/apps/addon/googlemusic/addon_googlemusic_app.coffee b/src/js/apps/addon/googlemusic/addon_googlemusic_app.js similarity index 100% rename from src/js/apps/addon/googlemusic/addon_googlemusic_app.coffee rename to src/js/apps/addon/googlemusic/addon_googlemusic_app.js diff --git a/src/js/apps/addon/list/list_controller.coffee b/src/js/apps/addon/list/list_controller.js similarity index 100% rename from src/js/apps/addon/list/list_controller.coffee rename to src/js/apps/addon/list/list_controller.js diff --git a/src/js/apps/addon/list/list_view.coffee b/src/js/apps/addon/list/list_view.js similarity index 100% rename from src/js/apps/addon/list/list_view.coffee rename to src/js/apps/addon/list/list_view.js diff --git a/src/js/apps/addon/mixcloud/addon_mixcloud_app.coffee b/src/js/apps/addon/mixcloud/addon_mixcloud_app.js similarity index 100% rename from src/js/apps/addon/mixcloud/addon_mixcloud_app.coffee rename to src/js/apps/addon/mixcloud/addon_mixcloud_app.js diff --git a/src/js/apps/addon/pvr/addons_pvr_ap.coffee b/src/js/apps/addon/pvr/addons_pvr_ap.js similarity index 100% rename from src/js/apps/addon/pvr/addons_pvr_ap.coffee rename to src/js/apps/addon/pvr/addons_pvr_ap.js diff --git a/src/js/apps/addon/radio/addon_radio_app.coffee b/src/js/apps/addon/radio/addon_radio_app.js similarity index 100% rename from src/js/apps/addon/radio/addon_radio_app.coffee rename to src/js/apps/addon/radio/addon_radio_app.js diff --git a/src/js/apps/addon/soundcloud/addon_soundcloud_app.coffee b/src/js/apps/addon/soundcloud/addon_soundcloud_app.js similarity index 100% rename from src/js/apps/addon/soundcloud/addon_soundcloud_app.coffee rename to src/js/apps/addon/soundcloud/addon_soundcloud_app.js diff --git a/src/js/apps/addon/youtube/addon_youtube_app.coffee b/src/js/apps/addon/youtube/addon_youtube_app.js similarity index 100% rename from src/js/apps/addon/youtube/addon_youtube_app.coffee rename to src/js/apps/addon/youtube/addon_youtube_app.js diff --git a/src/js/apps/album/album_app.coffee b/src/js/apps/album/album_app.js similarity index 100% rename from src/js/apps/album/album_app.coffee rename to src/js/apps/album/album_app.js diff --git a/src/js/apps/album/edit/edit_controller.coffee b/src/js/apps/album/edit/edit_controller.js similarity index 100% rename from src/js/apps/album/edit/edit_controller.coffee rename to src/js/apps/album/edit/edit_controller.js diff --git a/src/js/apps/album/list/list_controller.coffee b/src/js/apps/album/list/list_controller.js similarity index 100% rename from src/js/apps/album/list/list_controller.coffee rename to src/js/apps/album/list/list_controller.js diff --git a/src/js/apps/album/list/list_view.coffee b/src/js/apps/album/list/list_view.js similarity index 100% rename from src/js/apps/album/list/list_view.coffee rename to src/js/apps/album/list/list_view.js diff --git a/src/js/apps/album/show/show_controller.coffee b/src/js/apps/album/show/show_controller.js similarity index 100% rename from src/js/apps/album/show/show_controller.coffee rename to src/js/apps/album/show/show_controller.js diff --git a/src/js/apps/album/show/show_view.coffee b/src/js/apps/album/show/show_view.js similarity index 100% rename from src/js/apps/album/show/show_view.coffee rename to src/js/apps/album/show/show_view.js diff --git a/src/js/apps/artist/artist_app.coffee b/src/js/apps/artist/artist_app.js similarity index 100% rename from src/js/apps/artist/artist_app.coffee rename to src/js/apps/artist/artist_app.js diff --git a/src/js/apps/artist/edit/edit_controller.coffee b/src/js/apps/artist/edit/edit_controller.js similarity index 100% rename from src/js/apps/artist/edit/edit_controller.coffee rename to src/js/apps/artist/edit/edit_controller.js diff --git a/src/js/apps/artist/list/list_controller.coffee b/src/js/apps/artist/list/list_controller.js similarity index 100% rename from src/js/apps/artist/list/list_controller.coffee rename to src/js/apps/artist/list/list_controller.js diff --git a/src/js/apps/artist/list/list_view.coffee b/src/js/apps/artist/list/list_view.js similarity index 100% rename from src/js/apps/artist/list/list_view.coffee rename to src/js/apps/artist/list/list_view.js diff --git a/src/js/apps/artist/show/show_controller.coffee b/src/js/apps/artist/show/show_controller.js similarity index 100% rename from src/js/apps/artist/show/show_controller.coffee rename to src/js/apps/artist/show/show_controller.js diff --git a/src/js/apps/artist/show/show_view.coffee b/src/js/apps/artist/show/show_view.js similarity index 100% rename from src/js/apps/artist/show/show_view.coffee rename to src/js/apps/artist/show/show_view.js diff --git a/src/js/apps/audioStream/init.coffee b/src/js/apps/audioStream/init.js similarity index 100% rename from src/js/apps/audioStream/init.coffee rename to src/js/apps/audioStream/init.js diff --git a/src/js/apps/browser/browser_app.coffee b/src/js/apps/browser/browser_app.js similarity index 100% rename from src/js/apps/browser/browser_app.coffee rename to src/js/apps/browser/browser_app.js diff --git a/src/js/apps/browser/list/list_controller.coffee b/src/js/apps/browser/list/list_controller.js similarity index 100% rename from src/js/apps/browser/list/list_controller.coffee rename to src/js/apps/browser/list/list_controller.js diff --git a/src/js/apps/browser/list/list_view.coffee b/src/js/apps/browser/list/list_view.js similarity index 100% rename from src/js/apps/browser/list/list_view.coffee rename to src/js/apps/browser/list/list_view.js diff --git a/src/js/apps/cast/cast_app.coffee b/src/js/apps/cast/cast_app.js similarity index 100% rename from src/js/apps/cast/cast_app.coffee rename to src/js/apps/cast/cast_app.js diff --git a/src/js/apps/cast/list/list_view.coffee b/src/js/apps/cast/list/list_view.js similarity index 100% rename from src/js/apps/cast/list/list_view.coffee rename to src/js/apps/cast/list/list_view.js diff --git a/src/js/apps/category/category_app.coffee b/src/js/apps/category/category_app.js similarity index 100% rename from src/js/apps/category/category_app.coffee rename to src/js/apps/category/category_app.js diff --git a/src/js/apps/category/list/list_controller.coffee b/src/js/apps/category/list/list_controller.js similarity index 100% rename from src/js/apps/category/list/list_controller.coffee rename to src/js/apps/category/list/list_controller.js diff --git a/src/js/apps/category/list/list_view.coffee b/src/js/apps/category/list/list_view.js similarity index 100% rename from src/js/apps/category/list/list_view.coffee rename to src/js/apps/category/list/list_view.js diff --git a/src/js/apps/command/command_app.coffee b/src/js/apps/command/command_app.js similarity index 100% rename from src/js/apps/command/command_app.coffee rename to src/js/apps/command/command_app.js diff --git a/src/js/apps/command/kodi/_base/_base.coffee b/src/js/apps/command/kodi/_base/_base.js similarity index 100% rename from src/js/apps/command/kodi/_base/_base.coffee rename to src/js/apps/command/kodi/_base/_base.js diff --git a/src/js/apps/command/kodi/_base/api.coffee b/src/js/apps/command/kodi/_base/api.js similarity index 100% rename from src/js/apps/command/kodi/_base/api.coffee rename to src/js/apps/command/kodi/_base/api.js diff --git a/src/js/apps/command/kodi/helpers/addon.coffee b/src/js/apps/command/kodi/helpers/addon.js similarity index 100% rename from src/js/apps/command/kodi/helpers/addon.coffee rename to src/js/apps/command/kodi/helpers/addon.js diff --git a/src/js/apps/command/kodi/helpers/application.coffee b/src/js/apps/command/kodi/helpers/application.js similarity index 100% rename from src/js/apps/command/kodi/helpers/application.coffee rename to src/js/apps/command/kodi/helpers/application.js diff --git a/src/js/apps/command/kodi/helpers/audiolibrary.coffee b/src/js/apps/command/kodi/helpers/audiolibrary.js similarity index 100% rename from src/js/apps/command/kodi/helpers/audiolibrary.coffee rename to src/js/apps/command/kodi/helpers/audiolibrary.js diff --git a/src/js/apps/command/kodi/helpers/file.coffee b/src/js/apps/command/kodi/helpers/file.js similarity index 100% rename from src/js/apps/command/kodi/helpers/file.coffee rename to src/js/apps/command/kodi/helpers/file.js diff --git a/src/js/apps/command/kodi/helpers/gui.coffee b/src/js/apps/command/kodi/helpers/gui.js similarity index 100% rename from src/js/apps/command/kodi/helpers/gui.coffee rename to src/js/apps/command/kodi/helpers/gui.js diff --git a/src/js/apps/command/kodi/helpers/input.coffee b/src/js/apps/command/kodi/helpers/input.js similarity index 100% rename from src/js/apps/command/kodi/helpers/input.coffee rename to src/js/apps/command/kodi/helpers/input.js diff --git a/src/js/apps/command/kodi/helpers/playlist.coffee b/src/js/apps/command/kodi/helpers/playlist.js similarity index 100% rename from src/js/apps/command/kodi/helpers/playlist.coffee rename to src/js/apps/command/kodi/helpers/playlist.js diff --git a/src/js/apps/command/kodi/helpers/pvr.coffee b/src/js/apps/command/kodi/helpers/pvr.js similarity index 100% rename from src/js/apps/command/kodi/helpers/pvr.coffee rename to src/js/apps/command/kodi/helpers/pvr.js diff --git a/src/js/apps/command/kodi/helpers/settings.coffee b/src/js/apps/command/kodi/helpers/settings.js similarity index 100% rename from src/js/apps/command/kodi/helpers/settings.coffee rename to src/js/apps/command/kodi/helpers/settings.js diff --git a/src/js/apps/command/kodi/helpers/system.coffee b/src/js/apps/command/kodi/helpers/system.js similarity index 100% rename from src/js/apps/command/kodi/helpers/system.coffee rename to src/js/apps/command/kodi/helpers/system.js diff --git a/src/js/apps/command/kodi/helpers/videolibrary.coffee b/src/js/apps/command/kodi/helpers/videolibrary.js similarity index 100% rename from src/js/apps/command/kodi/helpers/videolibrary.coffee rename to src/js/apps/command/kodi/helpers/videolibrary.js diff --git a/src/js/apps/command/local/_base/_base.coffee b/src/js/apps/command/local/_base/_base.js similarity index 100% rename from src/js/apps/command/local/_base/_base.coffee rename to src/js/apps/command/local/_base/_base.js diff --git a/src/js/apps/command/local/_base/api.coffee b/src/js/apps/command/local/_base/api.js similarity index 100% rename from src/js/apps/command/local/_base/api.coffee rename to src/js/apps/command/local/_base/api.js diff --git a/src/js/apps/command/local/helpers/application.coffee b/src/js/apps/command/local/helpers/application.js similarity index 100% rename from src/js/apps/command/local/helpers/application.coffee rename to src/js/apps/command/local/helpers/application.js diff --git a/src/js/apps/command/local/helpers/playlist.coffee b/src/js/apps/command/local/helpers/playlist.js similarity index 100% rename from src/js/apps/command/local/helpers/playlist.coffee rename to src/js/apps/command/local/helpers/playlist.js diff --git a/src/js/apps/command/local/helpers/videoplayer.coffee b/src/js/apps/command/local/helpers/videoplayer.js similarity index 100% rename from src/js/apps/command/local/helpers/videoplayer.coffee rename to src/js/apps/command/local/helpers/videoplayer.js diff --git a/src/js/apps/epg/epg_app.coffee b/src/js/apps/epg/epg_app.js similarity index 100% rename from src/js/apps/epg/epg_app.coffee rename to src/js/apps/epg/epg_app.js diff --git a/src/js/apps/epg/list/list_controller.coffee b/src/js/apps/epg/list/list_controller.js similarity index 100% rename from src/js/apps/epg/list/list_controller.coffee rename to src/js/apps/epg/list/list_controller.js diff --git a/src/js/apps/epg/list/list_view.coffee b/src/js/apps/epg/list/list_view.js similarity index 100% rename from src/js/apps/epg/list/list_view.coffee rename to src/js/apps/epg/list/list_view.js diff --git a/src/js/apps/external/external_app.coffee b/src/js/apps/external/external_app.js similarity index 100% rename from src/js/apps/external/external_app.coffee rename to src/js/apps/external/external_app.js diff --git a/src/js/apps/external/youtube/youtube_controller.coffee b/src/js/apps/external/youtube/youtube_controller.js similarity index 100% rename from src/js/apps/external/youtube/youtube_controller.coffee rename to src/js/apps/external/youtube/youtube_controller.js diff --git a/src/js/apps/external/youtube/youtube_view.coffee b/src/js/apps/external/youtube/youtube_view.js similarity index 100% rename from src/js/apps/external/youtube/youtube_view.coffee rename to src/js/apps/external/youtube/youtube_view.js diff --git a/src/js/apps/filter/filter_app.coffee b/src/js/apps/filter/filter_app.js similarity index 100% rename from src/js/apps/filter/filter_app.coffee rename to src/js/apps/filter/filter_app.js diff --git a/src/js/apps/filter/show/show_controller.coffee b/src/js/apps/filter/show/show_controller.js similarity index 100% rename from src/js/apps/filter/show/show_controller.coffee rename to src/js/apps/filter/show/show_controller.js diff --git a/src/js/apps/filter/show/show_view.coffee b/src/js/apps/filter/show/show_view.js similarity index 100% rename from src/js/apps/filter/show/show_view.coffee rename to src/js/apps/filter/show/show_view.js diff --git a/src/js/apps/help/help_app.coffee b/src/js/apps/help/help_app.js similarity index 100% rename from src/js/apps/help/help_app.coffee rename to src/js/apps/help/help_app.js diff --git a/src/js/apps/help/overview/overview_controller.coffee b/src/js/apps/help/overview/overview_controller.js similarity index 100% rename from src/js/apps/help/overview/overview_controller.coffee rename to src/js/apps/help/overview/overview_controller.js diff --git a/src/js/apps/help/overview/overview_view.coffee b/src/js/apps/help/overview/overview_view.js similarity index 100% rename from src/js/apps/help/overview/overview_view.coffee rename to src/js/apps/help/overview/overview_view.js diff --git a/src/js/apps/help/show/show_controller.coffee b/src/js/apps/help/show/show_controller.js similarity index 100% rename from src/js/apps/help/show/show_controller.coffee rename to src/js/apps/help/show/show_controller.js diff --git a/src/js/apps/help/show/show_view.coffee b/src/js/apps/help/show/show_view.js similarity index 100% rename from src/js/apps/help/show/show_view.coffee rename to src/js/apps/help/show/show_view.js diff --git a/src/js/apps/images/images_app.coffee b/src/js/apps/images/images_app.js similarity index 100% rename from src/js/apps/images/images_app.coffee rename to src/js/apps/images/images_app.js diff --git a/src/js/apps/input/input_app.coffee b/src/js/apps/input/input_app.js similarity index 100% rename from src/js/apps/input/input_app.coffee rename to src/js/apps/input/input_app.js diff --git a/src/js/apps/input/remote/remote_controller.coffee b/src/js/apps/input/remote/remote_controller.js similarity index 100% rename from src/js/apps/input/remote/remote_controller.coffee rename to src/js/apps/input/remote/remote_controller.js diff --git a/src/js/apps/input/remote/remote_view.coffee b/src/js/apps/input/remote/remote_view.js similarity index 100% rename from src/js/apps/input/remote/remote_view.coffee rename to src/js/apps/input/remote/remote_view.js diff --git a/src/js/apps/input/resume/resume_controller.coffee b/src/js/apps/input/resume/resume_controller.js similarity index 100% rename from src/js/apps/input/resume/resume_controller.coffee rename to src/js/apps/input/resume/resume_controller.js diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_controller.coffee b/src/js/apps/lab/apiBrowser/apiBrowser_controller.js similarity index 100% rename from src/js/apps/lab/apiBrowser/apiBrowser_controller.coffee rename to src/js/apps/lab/apiBrowser/apiBrowser_controller.js diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_view.coffee b/src/js/apps/lab/apiBrowser/apiBrowser_view.js similarity index 100% rename from src/js/apps/lab/apiBrowser/apiBrowser_view.coffee rename to src/js/apps/lab/apiBrowser/apiBrowser_view.js diff --git a/src/js/apps/lab/iconBrowser/iconBrowser_view.coffee b/src/js/apps/lab/iconBrowser/iconBrowser_view.js similarity index 100% rename from src/js/apps/lab/iconBrowser/iconBrowser_view.coffee rename to src/js/apps/lab/iconBrowser/iconBrowser_view.js diff --git a/src/js/apps/lab/lab/lab_view.coffee b/src/js/apps/lab/lab/lab_view.js similarity index 100% rename from src/js/apps/lab/lab/lab_view.coffee rename to src/js/apps/lab/lab/lab_view.js diff --git a/src/js/apps/lab/lab_app.coffee b/src/js/apps/lab/lab_app.js similarity index 100% rename from src/js/apps/lab/lab_app.coffee rename to src/js/apps/lab/lab_app.js diff --git a/src/js/apps/landing/landing_app.coffee b/src/js/apps/landing/landing_app.js similarity index 100% rename from src/js/apps/landing/landing_app.coffee rename to src/js/apps/landing/landing_app.js diff --git a/src/js/apps/landing/show/landing_controller.coffee b/src/js/apps/landing/show/landing_controller.js similarity index 100% rename from src/js/apps/landing/show/landing_controller.coffee rename to src/js/apps/landing/show/landing_controller.js diff --git a/src/js/apps/landing/show/landing_view.coffee b/src/js/apps/landing/show/landing_view.js similarity index 100% rename from src/js/apps/landing/show/landing_view.coffee rename to src/js/apps/landing/show/landing_view.js diff --git a/src/js/apps/loading/loading_app.coffee b/src/js/apps/loading/loading_app.js similarity index 100% rename from src/js/apps/loading/loading_app.coffee rename to src/js/apps/loading/loading_app.js diff --git a/src/js/apps/loading/show/loading_view.coffee b/src/js/apps/loading/show/loading_view.js similarity index 100% rename from src/js/apps/loading/show/loading_view.coffee rename to src/js/apps/loading/show/loading_view.js diff --git a/src/js/apps/localPlaylist/list/list_controller.coffee b/src/js/apps/localPlaylist/list/list_controller.js similarity index 100% rename from src/js/apps/localPlaylist/list/list_controller.coffee rename to src/js/apps/localPlaylist/list/list_controller.js diff --git a/src/js/apps/localPlaylist/list/list_view.coffee b/src/js/apps/localPlaylist/list/list_view.js similarity index 100% rename from src/js/apps/localPlaylist/list/list_view.coffee rename to src/js/apps/localPlaylist/list/list_view.js diff --git a/src/js/apps/localPlaylist/localPlaylist_app.coffee b/src/js/apps/localPlaylist/localPlaylist_app.js similarity index 100% rename from src/js/apps/localPlaylist/localPlaylist_app.coffee rename to src/js/apps/localPlaylist/localPlaylist_app.js diff --git a/src/js/apps/movie/edit/edit_controller.coffee b/src/js/apps/movie/edit/edit_controller.js similarity index 100% rename from src/js/apps/movie/edit/edit_controller.coffee rename to src/js/apps/movie/edit/edit_controller.js diff --git a/src/js/apps/movie/list/list_controller.coffee b/src/js/apps/movie/list/list_controller.js similarity index 100% rename from src/js/apps/movie/list/list_controller.coffee rename to src/js/apps/movie/list/list_controller.js diff --git a/src/js/apps/movie/list/list_view.coffee b/src/js/apps/movie/list/list_view.js similarity index 100% rename from src/js/apps/movie/list/list_view.coffee rename to src/js/apps/movie/list/list_view.js diff --git a/src/js/apps/movie/movie_app.coffee b/src/js/apps/movie/movie_app.js similarity index 100% rename from src/js/apps/movie/movie_app.coffee rename to src/js/apps/movie/movie_app.js diff --git a/src/js/apps/movie/show/show_controller.coffee b/src/js/apps/movie/show/show_controller.js similarity index 100% rename from src/js/apps/movie/show/show_controller.coffee rename to src/js/apps/movie/show/show_controller.js diff --git a/src/js/apps/movie/show/show_view.coffee b/src/js/apps/movie/show/show_view.js similarity index 100% rename from src/js/apps/movie/show/show_view.coffee rename to src/js/apps/movie/show/show_view.js diff --git a/src/js/apps/musicvideo/edit/edit_controller.coffee b/src/js/apps/musicvideo/edit/edit_controller.js similarity index 100% rename from src/js/apps/musicvideo/edit/edit_controller.coffee rename to src/js/apps/musicvideo/edit/edit_controller.js diff --git a/src/js/apps/musicvideo/list/list_controller.coffee b/src/js/apps/musicvideo/list/list_controller.js similarity index 100% rename from src/js/apps/musicvideo/list/list_controller.coffee rename to src/js/apps/musicvideo/list/list_controller.js diff --git a/src/js/apps/musicvideo/list/list_view.coffee b/src/js/apps/musicvideo/list/list_view.js similarity index 100% rename from src/js/apps/musicvideo/list/list_view.coffee rename to src/js/apps/musicvideo/list/list_view.js diff --git a/src/js/apps/musicvideo/musicvideo_app.coffee b/src/js/apps/musicvideo/musicvideo_app.js similarity index 100% rename from src/js/apps/musicvideo/musicvideo_app.coffee rename to src/js/apps/musicvideo/musicvideo_app.js diff --git a/src/js/apps/musicvideo/show/show_controller.coffee b/src/js/apps/musicvideo/show/show_controller.js similarity index 100% rename from src/js/apps/musicvideo/show/show_controller.coffee rename to src/js/apps/musicvideo/show/show_controller.js diff --git a/src/js/apps/musicvideo/show/show_view.coffee b/src/js/apps/musicvideo/show/show_view.js similarity index 100% rename from src/js/apps/musicvideo/show/show_view.coffee rename to src/js/apps/musicvideo/show/show_view.js diff --git a/src/js/apps/navMain/navMain_app.coffee b/src/js/apps/navMain/navMain_app.js similarity index 100% rename from src/js/apps/navMain/navMain_app.coffee rename to src/js/apps/navMain/navMain_app.js diff --git a/src/js/apps/navMain/show/navMain_view.coffee b/src/js/apps/navMain/show/navMain_view.js similarity index 100% rename from src/js/apps/navMain/show/navMain_view.coffee rename to src/js/apps/navMain/show/navMain_view.js diff --git a/src/js/apps/notifications/notifications_app.coffee b/src/js/apps/notifications/notifications_app.js similarity index 100% rename from src/js/apps/notifications/notifications_app.coffee rename to src/js/apps/notifications/notifications_app.js diff --git a/src/js/apps/player/player_app.coffee b/src/js/apps/player/player_app.js similarity index 100% rename from src/js/apps/player/player_app.coffee rename to src/js/apps/player/player_app.js diff --git a/src/js/apps/player/show/player_view.coffee b/src/js/apps/player/show/player_view.js similarity index 100% rename from src/js/apps/player/show/player_view.coffee rename to src/js/apps/player/show/player_view.js diff --git a/src/js/apps/playlist/list/list_controller.coffee b/src/js/apps/playlist/list/list_controller.js similarity index 100% rename from src/js/apps/playlist/list/list_controller.coffee rename to src/js/apps/playlist/list/list_controller.js diff --git a/src/js/apps/playlist/list/list_view.coffee b/src/js/apps/playlist/list/list_view.js similarity index 100% rename from src/js/apps/playlist/list/list_view.coffee rename to src/js/apps/playlist/list/list_view.js diff --git a/src/js/apps/playlist/localParty/local_party.coffee b/src/js/apps/playlist/localParty/local_party.js similarity index 100% rename from src/js/apps/playlist/localParty/local_party.coffee rename to src/js/apps/playlist/localParty/local_party.js diff --git a/src/js/apps/playlist/m3u/m3u_controller.coffee b/src/js/apps/playlist/m3u/m3u_controller.js similarity index 100% rename from src/js/apps/playlist/m3u/m3u_controller.coffee rename to src/js/apps/playlist/m3u/m3u_controller.js diff --git a/src/js/apps/playlist/m3u/m3u_view.coffee b/src/js/apps/playlist/m3u/m3u_view.js similarity index 100% rename from src/js/apps/playlist/m3u/m3u_view.coffee rename to src/js/apps/playlist/m3u/m3u_view.js diff --git a/src/js/apps/playlist/playlist_app.coffee b/src/js/apps/playlist/playlist_app.js similarity index 100% rename from src/js/apps/playlist/playlist_app.coffee rename to src/js/apps/playlist/playlist_app.js diff --git a/src/js/apps/playlist/show/show_controller.coffee b/src/js/apps/playlist/show/show_controller.js similarity index 100% rename from src/js/apps/playlist/show/show_controller.coffee rename to src/js/apps/playlist/show/show_controller.js diff --git a/src/js/apps/playlist/show/show_view.coffee b/src/js/apps/playlist/show/show_view.js similarity index 100% rename from src/js/apps/playlist/show/show_view.coffee rename to src/js/apps/playlist/show/show_view.js diff --git a/src/js/apps/pvr/channelList/channel_list_controller.coffee b/src/js/apps/pvr/channelList/channel_list_controller.js similarity index 100% rename from src/js/apps/pvr/channelList/channel_list_controller.coffee rename to src/js/apps/pvr/channelList/channel_list_controller.js diff --git a/src/js/apps/pvr/channelList/channel_list_view.coffee b/src/js/apps/pvr/channelList/channel_list_view.js similarity index 100% rename from src/js/apps/pvr/channelList/channel_list_view.coffee rename to src/js/apps/pvr/channelList/channel_list_view.js diff --git a/src/js/apps/pvr/pvr_app.coffee b/src/js/apps/pvr/pvr_app.js similarity index 100% rename from src/js/apps/pvr/pvr_app.coffee rename to src/js/apps/pvr/pvr_app.js diff --git a/src/js/apps/pvr/recordingList/recording_list_controller.coffee b/src/js/apps/pvr/recordingList/recording_list_controller.js similarity index 100% rename from src/js/apps/pvr/recordingList/recording_list_controller.coffee rename to src/js/apps/pvr/recordingList/recording_list_controller.js diff --git a/src/js/apps/pvr/recordingList/recording_list_view.coffee b/src/js/apps/pvr/recordingList/recording_list_view.js similarity index 100% rename from src/js/apps/pvr/recordingList/recording_list_view.coffee rename to src/js/apps/pvr/recordingList/recording_list_view.js diff --git a/src/js/apps/search/list/list_controller.coffee b/src/js/apps/search/list/list_controller.js similarity index 100% rename from src/js/apps/search/list/list_controller.coffee rename to src/js/apps/search/list/list_controller.js diff --git a/src/js/apps/search/list/list_view.coffee b/src/js/apps/search/list/list_view.js similarity index 100% rename from src/js/apps/search/list/list_view.coffee rename to src/js/apps/search/list/list_view.js diff --git a/src/js/apps/search/search_app.coffee b/src/js/apps/search/search_app.js similarity index 100% rename from src/js/apps/search/search_app.coffee rename to src/js/apps/search/search_app.js diff --git a/src/js/apps/search/show/show_controller.coffee b/src/js/apps/search/show/show_controller.js similarity index 100% rename from src/js/apps/search/show/show_controller.coffee rename to src/js/apps/search/show/show_controller.js diff --git a/src/js/apps/search/show/show_view.coffee b/src/js/apps/search/show/show_view.js similarity index 100% rename from src/js/apps/search/show/show_view.coffee rename to src/js/apps/search/show/show_view.js diff --git a/src/js/apps/selected/selected_app.coffee b/src/js/apps/selected/selected_app.js similarity index 100% rename from src/js/apps/selected/selected_app.coffee rename to src/js/apps/selected/selected_app.js diff --git a/src/js/apps/settings/settings_app.coffee b/src/js/apps/settings/settings_app.js similarity index 100% rename from src/js/apps/settings/settings_app.coffee rename to src/js/apps/settings/settings_app.js diff --git a/src/js/apps/settings/show/_base/base_controller.coffee b/src/js/apps/settings/show/_base/base_controller.js similarity index 100% rename from src/js/apps/settings/show/_base/base_controller.coffee rename to src/js/apps/settings/show/_base/base_controller.js diff --git a/src/js/apps/settings/show/addons/addons_controller.coffee b/src/js/apps/settings/show/addons/addons_controller.js similarity index 100% rename from src/js/apps/settings/show/addons/addons_controller.coffee rename to src/js/apps/settings/show/addons/addons_controller.js diff --git a/src/js/apps/settings/show/kodi/kodi_controller.coffee b/src/js/apps/settings/show/kodi/kodi_controller.js similarity index 100% rename from src/js/apps/settings/show/kodi/kodi_controller.coffee rename to src/js/apps/settings/show/kodi/kodi_controller.js diff --git a/src/js/apps/settings/show/kodi/kodi_view.coffee b/src/js/apps/settings/show/kodi/kodi_view.js similarity index 100% rename from src/js/apps/settings/show/kodi/kodi_view.coffee rename to src/js/apps/settings/show/kodi/kodi_view.js diff --git a/src/js/apps/settings/show/local/local_controller.coffee b/src/js/apps/settings/show/local/local_controller.js similarity index 100% rename from src/js/apps/settings/show/local/local_controller.coffee rename to src/js/apps/settings/show/local/local_controller.js diff --git a/src/js/apps/settings/show/navMain/navMain_controller.coffee b/src/js/apps/settings/show/navMain/navMain_controller.js similarity index 100% rename from src/js/apps/settings/show/navMain/navMain_controller.coffee rename to src/js/apps/settings/show/navMain/navMain_controller.js diff --git a/src/js/apps/settings/show/search/search_controller.coffee b/src/js/apps/settings/show/search/search_controller.js similarity index 100% rename from src/js/apps/settings/show/search/search_controller.coffee rename to src/js/apps/settings/show/search/search_controller.js diff --git a/src/js/apps/settings/show/show_view.coffee b/src/js/apps/settings/show/show_view.js similarity index 100% rename from src/js/apps/settings/show/show_view.coffee rename to src/js/apps/settings/show/show_view.js diff --git a/src/js/apps/shell/shell_app.coffee b/src/js/apps/shell/shell_app.js similarity index 100% rename from src/js/apps/shell/shell_app.coffee rename to src/js/apps/shell/shell_app.js diff --git a/src/js/apps/shell/show/shell_view.coffee b/src/js/apps/shell/show/shell_view.js similarity index 100% rename from src/js/apps/shell/show/shell_view.coffee rename to src/js/apps/shell/show/shell_view.js diff --git a/src/js/apps/song/edit/edit_controller.coffee b/src/js/apps/song/edit/edit_controller.js similarity index 100% rename from src/js/apps/song/edit/edit_controller.coffee rename to src/js/apps/song/edit/edit_controller.js diff --git a/src/js/apps/song/list/list_controller.coffee b/src/js/apps/song/list/list_controller.js similarity index 100% rename from src/js/apps/song/list/list_controller.coffee rename to src/js/apps/song/list/list_controller.js diff --git a/src/js/apps/song/list/list_view.coffee b/src/js/apps/song/list/list_view.js similarity index 100% rename from src/js/apps/song/list/list_view.coffee rename to src/js/apps/song/list/list_view.js diff --git a/src/js/apps/song/song_app.coffee b/src/js/apps/song/song_app.js similarity index 100% rename from src/js/apps/song/song_app.coffee rename to src/js/apps/song/song_app.js diff --git a/src/js/apps/state/_base/base.coffee b/src/js/apps/state/_base/base.js similarity index 100% rename from src/js/apps/state/_base/base.coffee rename to src/js/apps/state/_base/base.js diff --git a/src/js/apps/state/kodi/kodi.coffee b/src/js/apps/state/kodi/kodi.js similarity index 100% rename from src/js/apps/state/kodi/kodi.coffee rename to src/js/apps/state/kodi/kodi.js diff --git a/src/js/apps/state/kodi/notifications.coffee b/src/js/apps/state/kodi/notifications.js similarity index 100% rename from src/js/apps/state/kodi/notifications.coffee rename to src/js/apps/state/kodi/notifications.js diff --git a/src/js/apps/state/kodi/polling.coffee b/src/js/apps/state/kodi/polling.js similarity index 100% rename from src/js/apps/state/kodi/polling.coffee rename to src/js/apps/state/kodi/polling.js diff --git a/src/js/apps/state/local/local.coffee b/src/js/apps/state/local/local.js similarity index 100% rename from src/js/apps/state/local/local.coffee rename to src/js/apps/state/local/local.js diff --git a/src/js/apps/state/state_app.coffee b/src/js/apps/state/state_app.js similarity index 100% rename from src/js/apps/state/state_app.coffee rename to src/js/apps/state/state_app.js diff --git a/src/js/apps/thumbs/list/list_controller.coffee b/src/js/apps/thumbs/list/list_controller.js similarity index 100% rename from src/js/apps/thumbs/list/list_controller.coffee rename to src/js/apps/thumbs/list/list_controller.js diff --git a/src/js/apps/thumbs/list/list_view.coffee b/src/js/apps/thumbs/list/list_view.js similarity index 100% rename from src/js/apps/thumbs/list/list_view.coffee rename to src/js/apps/thumbs/list/list_view.js diff --git a/src/js/apps/thumbs/thumbs_app.coffee b/src/js/apps/thumbs/thumbs_app.js similarity index 100% rename from src/js/apps/thumbs/thumbs_app.coffee rename to src/js/apps/thumbs/thumbs_app.js diff --git a/src/js/apps/tvshow/editEpisode/edit_episode_controller.coffee b/src/js/apps/tvshow/editEpisode/edit_episode_controller.js similarity index 100% rename from src/js/apps/tvshow/editEpisode/edit_episode_controller.coffee rename to src/js/apps/tvshow/editEpisode/edit_episode_controller.js diff --git a/src/js/apps/tvshow/editShow/edit_show_controller.coffee b/src/js/apps/tvshow/editShow/edit_show_controller.js similarity index 100% rename from src/js/apps/tvshow/editShow/edit_show_controller.coffee rename to src/js/apps/tvshow/editShow/edit_show_controller.js diff --git a/src/js/apps/tvshow/episode/episode_controller.coffee b/src/js/apps/tvshow/episode/episode_controller.js similarity index 100% rename from src/js/apps/tvshow/episode/episode_controller.coffee rename to src/js/apps/tvshow/episode/episode_controller.js diff --git a/src/js/apps/tvshow/episode/episode_view.coffee b/src/js/apps/tvshow/episode/episode_view.js similarity index 100% rename from src/js/apps/tvshow/episode/episode_view.coffee rename to src/js/apps/tvshow/episode/episode_view.js diff --git a/src/js/apps/tvshow/list/list_controller.coffee b/src/js/apps/tvshow/list/list_controller.js similarity index 100% rename from src/js/apps/tvshow/list/list_controller.coffee rename to src/js/apps/tvshow/list/list_controller.js diff --git a/src/js/apps/tvshow/list/list_view.coffee b/src/js/apps/tvshow/list/list_view.js similarity index 100% rename from src/js/apps/tvshow/list/list_view.coffee rename to src/js/apps/tvshow/list/list_view.js diff --git a/src/js/apps/tvshow/season/season_controller.coffee b/src/js/apps/tvshow/season/season_controller.js similarity index 100% rename from src/js/apps/tvshow/season/season_controller.coffee rename to src/js/apps/tvshow/season/season_controller.js diff --git a/src/js/apps/tvshow/season/season_view.coffee b/src/js/apps/tvshow/season/season_view.js similarity index 100% rename from src/js/apps/tvshow/season/season_view.coffee rename to src/js/apps/tvshow/season/season_view.js diff --git a/src/js/apps/tvshow/show/show_controller.coffee b/src/js/apps/tvshow/show/show_controller.js similarity index 100% rename from src/js/apps/tvshow/show/show_controller.coffee rename to src/js/apps/tvshow/show/show_controller.js diff --git a/src/js/apps/tvshow/show/show_view.coffee b/src/js/apps/tvshow/show/show_view.js similarity index 100% rename from src/js/apps/tvshow/show/show_view.coffee rename to src/js/apps/tvshow/show/show_view.js diff --git a/src/js/apps/tvshow/tvshow_app.coffee b/src/js/apps/tvshow/tvshow_app.js similarity index 100% rename from src/js/apps/tvshow/tvshow_app.coffee rename to src/js/apps/tvshow/tvshow_app.js diff --git a/src/js/apps/ui/ui_app.coffee b/src/js/apps/ui/ui_app.js similarity index 100% rename from src/js/apps/ui/ui_app.coffee rename to src/js/apps/ui/ui_app.js diff --git a/src/js/components/form/form_controller.coffee b/src/js/components/form/form_controller.js similarity index 100% rename from src/js/components/form/form_controller.coffee rename to src/js/components/form/form_controller.js diff --git a/src/js/components/form/form_view.coffee b/src/js/components/form/form_view.js similarity index 100% rename from src/js/components/form/form_view.coffee rename to src/js/components/form/form_view.js diff --git a/src/js/config/backbone/sync.coffee b/src/js/config/backbone/sync.js similarity index 100% rename from src/js/config/backbone/sync.coffee rename to src/js/config/backbone/sync.js diff --git a/src/js/config/marionette/application.coffee b/src/js/config/marionette/application.js similarity index 100% rename from src/js/config/marionette/application.coffee rename to src/js/config/marionette/application.js diff --git a/src/js/config/marionette/renderer.coffee b/src/js/config/marionette/renderer.js similarity index 100% rename from src/js/config/marionette/renderer.coffee rename to src/js/config/marionette/renderer.js diff --git a/src/js/controllers/_base.coffee b/src/js/controllers/_base.js similarity index 100% rename from src/js/controllers/_base.coffee rename to src/js/controllers/_base.js diff --git a/src/js/controllers/router.coffee b/src/js/controllers/router.js similarity index 100% rename from src/js/controllers/router.coffee rename to src/js/controllers/router.js diff --git a/src/js/entities/_base/collections.coffee b/src/js/entities/_base/collections.js similarity index 100% rename from src/js/entities/_base/collections.coffee rename to src/js/entities/_base/collections.js diff --git a/src/js/entities/_base/filtered.coffee b/src/js/entities/_base/filtered.js similarity index 100% rename from src/js/entities/_base/filtered.coffee rename to src/js/entities/_base/filtered.js diff --git a/src/js/entities/_base/models.coffee b/src/js/entities/_base/models.js similarity index 100% rename from src/js/entities/_base/models.coffee rename to src/js/entities/_base/models.js diff --git a/src/js/entities/config/configApp.coffee b/src/js/entities/config/configApp.js similarity index 100% rename from src/js/entities/config/configApp.coffee rename to src/js/entities/config/configApp.js diff --git a/src/js/entities/config/configKodi.coffee b/src/js/entities/config/configKodi.js similarity index 100% rename from src/js/entities/config/configKodi.coffee rename to src/js/entities/config/configKodi.js diff --git a/src/js/entities/external/_base.coffee b/src/js/entities/external/_base.js similarity index 100% rename from src/js/entities/external/_base.coffee rename to src/js/entities/external/_base.js diff --git a/src/js/entities/external/fanarttv.coffee b/src/js/entities/external/fanarttv.js similarity index 100% rename from src/js/entities/external/fanarttv.coffee rename to src/js/entities/external/fanarttv.js diff --git a/src/js/entities/external/musicbrainz.coffee b/src/js/entities/external/musicbrainz.js similarity index 100% rename from src/js/entities/external/musicbrainz.coffee rename to src/js/entities/external/musicbrainz.js diff --git a/src/js/entities/external/themoviedb.coffee b/src/js/entities/external/themoviedb.js similarity index 100% rename from src/js/entities/external/themoviedb.coffee rename to src/js/entities/external/themoviedb.js diff --git a/src/js/entities/external/youtube.coffee b/src/js/entities/external/youtube.js similarity index 100% rename from src/js/entities/external/youtube.coffee rename to src/js/entities/external/youtube.js diff --git a/src/js/entities/filter/filter.coffee b/src/js/entities/filter/filter.js similarity index 100% rename from src/js/entities/filter/filter.coffee rename to src/js/entities/filter/filter.js diff --git a/src/js/entities/form/form.coffee b/src/js/entities/form/form.js similarity index 100% rename from src/js/entities/form/form.coffee rename to src/js/entities/form/form.js diff --git a/src/js/entities/kodi/_base/_fetch.coffee b/src/js/entities/kodi/_base/_fetch.js similarity index 100% rename from src/js/entities/kodi/_base/_fetch.coffee rename to src/js/entities/kodi/_base/_fetch.js diff --git a/src/js/entities/kodi/_base/collections.coffee b/src/js/entities/kodi/_base/collections.js similarity index 100% rename from src/js/entities/kodi/_base/collections.coffee rename to src/js/entities/kodi/_base/collections.js diff --git a/src/js/entities/kodi/_base/models.coffee b/src/js/entities/kodi/_base/models.js similarity index 100% rename from src/js/entities/kodi/_base/models.coffee rename to src/js/entities/kodi/_base/models.js diff --git a/src/js/entities/kodi/addon.coffee b/src/js/entities/kodi/addon.js similarity index 100% rename from src/js/entities/kodi/addon.coffee rename to src/js/entities/kodi/addon.js diff --git a/src/js/entities/kodi/album.coffee b/src/js/entities/kodi/album.js similarity index 100% rename from src/js/entities/kodi/album.coffee rename to src/js/entities/kodi/album.js diff --git a/src/js/entities/kodi/artist.coffee b/src/js/entities/kodi/artist.js similarity index 100% rename from src/js/entities/kodi/artist.coffee rename to src/js/entities/kodi/artist.js diff --git a/src/js/entities/kodi/cast.coffee b/src/js/entities/kodi/cast.js similarity index 100% rename from src/js/entities/kodi/cast.coffee rename to src/js/entities/kodi/cast.js diff --git a/src/js/entities/kodi/epg.coffee b/src/js/entities/kodi/epg.js similarity index 100% rename from src/js/entities/kodi/epg.coffee rename to src/js/entities/kodi/epg.js diff --git a/src/js/entities/kodi/episode.coffee b/src/js/entities/kodi/episode.js similarity index 100% rename from src/js/entities/kodi/episode.coffee rename to src/js/entities/kodi/episode.js diff --git a/src/js/entities/kodi/file.coffee b/src/js/entities/kodi/file.js similarity index 100% rename from src/js/entities/kodi/file.coffee rename to src/js/entities/kodi/file.js diff --git a/src/js/entities/kodi/genres.coffee b/src/js/entities/kodi/genres.js similarity index 100% rename from src/js/entities/kodi/genres.coffee rename to src/js/entities/kodi/genres.js diff --git a/src/js/entities/kodi/movie.coffee b/src/js/entities/kodi/movie.js similarity index 100% rename from src/js/entities/kodi/movie.coffee rename to src/js/entities/kodi/movie.js diff --git a/src/js/entities/kodi/musicvideo.coffee b/src/js/entities/kodi/musicvideo.js similarity index 100% rename from src/js/entities/kodi/musicvideo.coffee rename to src/js/entities/kodi/musicvideo.js diff --git a/src/js/entities/kodi/playlist.coffee b/src/js/entities/kodi/playlist.js similarity index 100% rename from src/js/entities/kodi/playlist.coffee rename to src/js/entities/kodi/playlist.js diff --git a/src/js/entities/kodi/pvr.coffee b/src/js/entities/kodi/pvr.js similarity index 100% rename from src/js/entities/kodi/pvr.coffee rename to src/js/entities/kodi/pvr.js diff --git a/src/js/entities/kodi/season.coffee b/src/js/entities/kodi/season.js similarity index 100% rename from src/js/entities/kodi/season.coffee rename to src/js/entities/kodi/season.js diff --git a/src/js/entities/kodi/settings.coffee b/src/js/entities/kodi/settings.js similarity index 100% rename from src/js/entities/kodi/settings.coffee rename to src/js/entities/kodi/settings.js diff --git a/src/js/entities/kodi/song.coffee b/src/js/entities/kodi/song.js similarity index 100% rename from src/js/entities/kodi/song.coffee rename to src/js/entities/kodi/song.js diff --git a/src/js/entities/kodi/tvshow.coffee b/src/js/entities/kodi/tvshow.js similarity index 100% rename from src/js/entities/kodi/tvshow.coffee rename to src/js/entities/kodi/tvshow.js diff --git a/src/js/entities/lab/apiBrowser.coffee b/src/js/entities/lab/apiBrowser.js similarity index 100% rename from src/js/entities/lab/apiBrowser.coffee rename to src/js/entities/lab/apiBrowser.js diff --git a/src/js/entities/localPlaylist/localPlaylist.coffee b/src/js/entities/localPlaylist/localPlaylist.js similarity index 100% rename from src/js/entities/localPlaylist/localPlaylist.coffee rename to src/js/entities/localPlaylist/localPlaylist.js diff --git a/src/js/entities/nav/navMain.coffee b/src/js/entities/nav/navMain.js similarity index 100% rename from src/js/entities/nav/navMain.coffee rename to src/js/entities/nav/navMain.js diff --git a/src/js/entities/search/searchAddons.coffee b/src/js/entities/search/searchAddons.js similarity index 100% rename from src/js/entities/search/searchAddons.coffee rename to src/js/entities/search/searchAddons.js diff --git a/src/js/helpers/backscroll.coffee b/src/js/helpers/backscroll.js similarity index 100% rename from src/js/helpers/backscroll.coffee rename to src/js/helpers/backscroll.js diff --git a/src/js/helpers/cache.coffee b/src/js/helpers/cache.js similarity index 100% rename from src/js/helpers/cache.coffee rename to src/js/helpers/cache.js diff --git a/src/js/helpers/config.coffee b/src/js/helpers/config.js similarity index 100% rename from src/js/helpers/config.coffee rename to src/js/helpers/config.js diff --git a/src/js/helpers/connection.coffee b/src/js/helpers/connection.js similarity index 100% rename from src/js/helpers/connection.coffee rename to src/js/helpers/connection.js diff --git a/src/js/helpers/customMixins/kodi_entities.coffee b/src/js/helpers/customMixins/kodi_entities.js similarity index 100% rename from src/js/helpers/customMixins/kodi_entities.coffee rename to src/js/helpers/customMixins/kodi_entities.js diff --git a/src/js/helpers/debug.coffee b/src/js/helpers/debug.js similarity index 100% rename from src/js/helpers/debug.coffee rename to src/js/helpers/debug.js diff --git a/src/js/helpers/entities.coffee b/src/js/helpers/entities.js similarity index 100% rename from src/js/helpers/entities.coffee rename to src/js/helpers/entities.js diff --git a/src/js/helpers/global.coffee b/src/js/helpers/global.js similarity index 100% rename from src/js/helpers/global.coffee rename to src/js/helpers/global.js diff --git a/src/js/helpers/jquery.coffee b/src/js/helpers/jquery.js similarity index 100% rename from src/js/helpers/jquery.coffee rename to src/js/helpers/jquery.js diff --git a/src/js/helpers/streams.coffee b/src/js/helpers/streams.js similarity index 100% rename from src/js/helpers/streams.coffee rename to src/js/helpers/streams.js diff --git a/src/js/helpers/translate.coffee b/src/js/helpers/translate.js similarity index 100% rename from src/js/helpers/translate.coffee rename to src/js/helpers/translate.js diff --git a/src/js/helpers/ui.coffee b/src/js/helpers/ui.js similarity index 100% rename from src/js/helpers/ui.coffee rename to src/js/helpers/ui.js diff --git a/src/js/helpers/url.coffee b/src/js/helpers/url.js similarity index 100% rename from src/js/helpers/url.coffee rename to src/js/helpers/url.js diff --git a/src/js/views/_base/collectionview.coffee b/src/js/views/_base/collectionview.js similarity index 100% rename from src/js/views/_base/collectionview.coffee rename to src/js/views/_base/collectionview.js diff --git a/src/js/views/_base/compositeview.coffee b/src/js/views/_base/compositeview.js similarity index 100% rename from src/js/views/_base/compositeview.coffee rename to src/js/views/_base/compositeview.js diff --git a/src/js/views/_base/itemview.coffee b/src/js/views/_base/itemview.js similarity index 100% rename from src/js/views/_base/itemview.coffee rename to src/js/views/_base/itemview.js diff --git a/src/js/views/_base/layout.coffee b/src/js/views/_base/layout.js similarity index 100% rename from src/js/views/_base/layout.coffee rename to src/js/views/_base/layout.js diff --git a/src/js/views/_base/view.coffee b/src/js/views/_base/view.js similarity index 100% rename from src/js/views/_base/view.coffee rename to src/js/views/_base/view.js diff --git a/src/js/views/_base/virtuallistview.coffee b/src/js/views/_base/virtuallistview.js similarity index 100% rename from src/js/views/_base/virtuallistview.coffee rename to src/js/views/_base/virtuallistview.js diff --git a/src/js/views/card/card_view.coffee b/src/js/views/card/card_view.js similarity index 100% rename from src/js/views/card/card_view.coffee rename to src/js/views/card/card_view.js diff --git a/src/js/views/details/detailsitem.coffee b/src/js/views/details/detailsitem.js similarity index 100% rename from src/js/views/details/detailsitem.coffee rename to src/js/views/details/detailsitem.js diff --git a/src/js/views/empty/empty_view.coffee b/src/js/views/empty/empty_view.js similarity index 100% rename from src/js/views/empty/empty_view.coffee rename to src/js/views/empty/empty_view.js diff --git a/src/js/views/layouts/layouts_view.coffee b/src/js/views/layouts/layouts_view.js similarity index 100% rename from src/js/views/layouts/layouts_view.coffee rename to src/js/views/layouts/layouts_view.js diff --git a/src/js/views/set/set_view.coffee b/src/js/views/set/set_view.js similarity index 100% rename from src/js/views/set/set_view.coffee rename to src/js/views/set/set_view.js diff --git a/src/js/views/song/song_view.coffee b/src/js/views/song/song_view.js similarity index 100% rename from src/js/views/song/song_view.coffee rename to src/js/views/song/song_view.js From c8e678c3bce160271fe66696f33406f9133267a1 Mon Sep 17 00:00:00 2001 From: decaffeinate <870074+max-te@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:04:26 +0100 Subject: [PATCH 04/21] decaffeinate: Convert app.coffee and 220 other files to JS --- src/js/app.js | 114 ++- src/js/apps/addon/addon_app.js | 184 ++-- .../googlemusic/addon_googlemusic_app.js | 28 +- src/js/apps/addon/list/list_controller.js | 66 +- src/js/apps/addon/list/list_view.js | 45 +- .../apps/addon/mixcloud/addon_mixcloud_app.js | 28 +- src/js/apps/addon/pvr/addons_pvr_ap.js | 22 +- src/js/apps/addon/radio/addon_radio_app.js | 28 +- .../addon/soundcloud/addon_soundcloud_app.js | 28 +- .../apps/addon/youtube/addon_youtube_app.js | 61 +- src/js/apps/album/album_app.js | 117 ++- src/js/apps/album/edit/edit_controller.js | 75 +- src/js/apps/album/list/list_controller.js | 167 ++-- src/js/apps/album/list/list_view.js | 87 +- src/js/apps/album/show/show_controller.js | 198 ++-- src/js/apps/album/show/show_view.js | 135 ++- src/js/apps/artist/artist_app.js | 117 ++- src/js/apps/artist/edit/edit_controller.js | 75 +- src/js/apps/artist/list/list_controller.js | 167 ++-- src/js/apps/artist/list/list_view.js | 75 +- src/js/apps/artist/show/show_controller.js | 137 +-- src/js/apps/artist/show/show_view.js | 68 +- src/js/apps/audioStream/init.js | 49 +- src/js/apps/browser/browser_app.js | 58 +- src/js/apps/browser/list/list_controller.js | 404 ++++---- src/js/apps/browser/list/list_view.js | 357 ++++--- src/js/apps/cast/cast_app.js | 39 +- src/js/apps/cast/list/list_view.js | 57 +- src/js/apps/category/category_app.js | 50 +- src/js/apps/category/list/list_controller.js | 72 +- src/js/apps/category/list/list_view.js | 45 +- src/js/apps/command/command_app.js | 143 +-- src/js/apps/command/kodi/_base/_base.js | 134 ++- src/js/apps/command/kodi/_base/api.js | 288 +++--- src/js/apps/command/kodi/helpers/addon.js | 107 ++- .../apps/command/kodi/helpers/application.js | 56 +- .../apps/command/kodi/helpers/audiolibrary.js | 84 +- src/js/apps/command/kodi/helpers/file.js | 63 +- src/js/apps/command/kodi/helpers/gui.js | 40 +- src/js/apps/command/kodi/helpers/input.js | 48 +- src/js/apps/command/kodi/helpers/playlist.js | 317 +++--- src/js/apps/command/kodi/helpers/pvr.js | 72 +- src/js/apps/command/kodi/helpers/settings.js | 30 +- src/js/apps/command/kodi/helpers/system.js | 64 +- .../apps/command/kodi/helpers/videolibrary.js | 188 ++-- src/js/apps/command/local/_base/_base.js | 467 +++++---- src/js/apps/command/local/_base/api.js | 94 +- .../apps/command/local/helpers/application.js | 70 +- src/js/apps/command/local/helpers/playlist.js | 344 ++++--- .../apps/command/local/helpers/videoplayer.js | 36 +- src/js/apps/epg/epg_app.js | 83 +- src/js/apps/epg/list/list_controller.js | 133 +-- src/js/apps/epg/list/list_view.js | 124 ++- src/js/apps/external/external_app.js | 7 +- .../external/youtube/youtube_controller.js | 88 +- src/js/apps/external/youtube/youtube_view.js | 97 +- src/js/apps/filter/filter_app.js | 905 ++++++++++-------- src/js/apps/filter/show/show_controller.js | 327 ++++--- src/js/apps/filter/show/show_view.js | 333 ++++--- src/js/apps/help/help_app.js | 129 +-- .../apps/help/overview/overview_controller.js | 182 ++-- src/js/apps/help/overview/overview_view.js | 58 +- src/js/apps/help/show/show_controller.js | 73 +- src/js/apps/help/show/show_view.js | 45 +- src/js/apps/images/images_app.js | 143 +-- src/js/apps/input/input_app.js | 356 +++---- src/js/apps/input/remote/remote_controller.js | 143 +-- src/js/apps/input/remote/remote_view.js | 93 +- src/js/apps/input/resume/resume_controller.js | 83 +- .../lab/apiBrowser/apiBrowser_controller.js | 135 +-- src/js/apps/lab/apiBrowser/apiBrowser_view.js | 130 ++- .../apps/lab/iconBrowser/iconBrowser_view.js | 51 +- src/js/apps/lab/lab/lab_view.js | 68 +- src/js/apps/lab/lab_app.js | 137 +-- src/js/apps/landing/landing_app.js | 256 ++--- .../apps/landing/show/landing_controller.js | 181 ++-- src/js/apps/landing/show/landing_view.js | 96 +- src/js/apps/loading/loading_app.js | 41 +- src/js/apps/loading/show/loading_view.js | 35 +- .../localPlaylist/list/list_controller.js | 198 ++-- src/js/apps/localPlaylist/list/list_view.js | 161 ++-- .../apps/localPlaylist/localPlaylist_app.js | 252 ++--- src/js/apps/movie/edit/edit_controller.js | 122 ++- src/js/apps/movie/list/list_controller.js | 170 ++-- src/js/apps/movie/list/list_view.js | 111 ++- src/js/apps/movie/movie_app.js | 130 +-- src/js/apps/movie/show/show_controller.js | 254 ++--- src/js/apps/movie/show/show_view.js | 142 ++- .../apps/musicvideo/edit/edit_controller.js | 93 +- .../apps/musicvideo/list/list_controller.js | 169 ++-- src/js/apps/musicvideo/list/list_view.js | 89 +- src/js/apps/musicvideo/musicvideo_app.js | 138 +-- .../apps/musicvideo/show/show_controller.js | 134 +-- src/js/apps/musicvideo/show/show_view.js | 55 +- src/js/apps/navMain/navMain_app.js | 84 +- src/js/apps/navMain/show/navMain_view.js | 66 +- .../apps/notifications/notifications_app.js | 32 +- src/js/apps/player/player_app.js | 382 ++++---- src/js/apps/player/show/player_view.js | 58 +- src/js/apps/playlist/list/list_controller.js | 272 +++--- src/js/apps/playlist/list/list_view.js | 141 +-- .../apps/playlist/localParty/local_party.js | 153 +-- src/js/apps/playlist/m3u/m3u_controller.js | 28 +- src/js/apps/playlist/m3u/m3u_view.js | 35 +- src/js/apps/playlist/playlist_app.js | 88 +- src/js/apps/playlist/show/show_controller.js | 28 +- src/js/apps/playlist/show/show_view.js | 20 +- .../channelList/channel_list_controller.js | 97 +- .../apps/pvr/channelList/channel_list_view.js | 59 +- src/js/apps/pvr/pvr_app.js | 66 +- .../recording_list_controller.js | 94 +- .../pvr/recordingList/recording_list_view.js | 49 +- src/js/apps/search/list/list_controller.js | 338 ++++--- src/js/apps/search/list/list_view.js | 137 ++- src/js/apps/search/search_app.js | 126 ++- src/js/apps/search/show/show_controller.js | 37 +- src/js/apps/search/show/show_view.js | 20 +- src/js/apps/selected/selected_app.js | 244 ++--- src/js/apps/settings/settings_app.js | 135 +-- .../settings/show/_base/base_controller.js | 140 +-- .../settings/show/addons/addons_controller.js | 177 ++-- .../settings/show/kodi/kodi_controller.js | 399 ++++---- src/js/apps/settings/show/kodi/kodi_view.js | 7 +- .../settings/show/local/local_controller.js | 154 +-- .../show/navMain/navMain_controller.js | 230 +++-- .../settings/show/search/search_controller.js | 204 ++-- src/js/apps/settings/show/show_view.js | 40 +- src/js/apps/shell/shell_app.js | 350 +++---- src/js/apps/shell/show/shell_view.js | 103 +- src/js/apps/song/edit/edit_controller.js | 83 +- src/js/apps/song/list/list_controller.js | 136 +-- src/js/apps/song/list/list_view.js | 157 +-- src/js/apps/song/song_app.js | 21 +- src/js/apps/state/_base/base.js | 247 ++--- src/js/apps/state/kodi/kodi.js | 173 ++-- src/js/apps/state/kodi/notifications.js | 491 +++++----- src/js/apps/state/kodi/polling.js | 144 +-- src/js/apps/state/local/local.js | 48 +- src/js/apps/state/state_app.js | 350 +++---- src/js/apps/thumbs/list/list_controller.js | 89 +- src/js/apps/thumbs/list/list_view.js | 65 +- src/js/apps/thumbs/thumbs_app.js | 33 +- .../editEpisode/edit_episode_controller.js | 81 +- .../tvshow/editShow/edit_show_controller.js | 110 ++- .../apps/tvshow/episode/episode_controller.js | 212 ++-- src/js/apps/tvshow/episode/episode_view.js | 190 ++-- src/js/apps/tvshow/list/list_controller.js | 174 ++-- src/js/apps/tvshow/list/list_view.js | 100 +- .../apps/tvshow/season/season_controller.js | 184 ++-- src/js/apps/tvshow/season/season_view.js | 134 ++- src/js/apps/tvshow/show/show_controller.js | 146 +-- src/js/apps/tvshow/show/show_view.js | 77 +- src/js/apps/tvshow/tvshow_app.js | 351 ++++--- src/js/apps/ui/ui_app.js | 325 ++++--- src/js/components/form/form_controller.js | 142 +-- src/js/components/form/form_view.js | 558 ++++++----- src/js/config/backbone/sync.js | 40 +- src/js/config/marionette/application.js | 83 +- src/js/config/marionette/renderer.js | 47 +- src/js/controllers/_base.js | 51 +- src/js/controllers/router.js | 50 +- src/js/entities/_base/collections.js | 140 +-- src/js/entities/_base/filtered.js | 139 +-- src/js/entities/_base/models.js | 97 +- src/js/entities/config/configApp.js | 118 ++- src/js/entities/external/_base.js | 44 +- src/js/entities/external/fanarttv.js | 146 +-- src/js/entities/external/musicbrainz.js | 91 +- src/js/entities/external/themoviedb.js | 213 +++-- src/js/entities/external/youtube.js | 147 +-- src/js/entities/filter/filter.js | 180 ++-- src/js/entities/form/form.js | 182 ++-- src/js/entities/kodi/_base/_fetch.js | 58 +- src/js/entities/kodi/_base/collections.js | 178 ++-- src/js/entities/kodi/_base/models.js | 209 ++-- src/js/entities/kodi/addon.js | 136 +-- src/js/entities/kodi/album.js | 128 ++- src/js/entities/kodi/artist.js | 137 +-- src/js/entities/kodi/cast.js | 84 +- src/js/entities/kodi/epg.js | 130 ++- src/js/entities/kodi/episode.js | 197 ++-- src/js/entities/kodi/file.js | 591 +++++++----- src/js/entities/kodi/genres.js | 112 ++- src/js/entities/kodi/movie.js | 143 +-- src/js/entities/kodi/musicvideo.js | 139 +-- src/js/entities/kodi/playlist.js | 201 ++-- src/js/entities/kodi/pvr.js | 263 ++--- src/js/entities/kodi/season.js | 128 ++- src/js/entities/kodi/settings.js | 306 +++--- src/js/entities/kodi/song.js | 384 ++++---- src/js/entities/kodi/tvshow.js | 129 +-- src/js/entities/lab/apiBrowser.js | 175 ++-- .../entities/localPlaylist/localPlaylist.js | 446 +++++---- src/js/entities/nav/navMain.js | 436 +++++---- src/js/entities/search/searchAddons.js | 122 ++- src/js/helpers/backscroll.js | 33 +- src/js/helpers/cache.js | 97 +- src/js/helpers/config.js | 79 +- src/js/helpers/connection.js | 54 +- src/js/helpers/customMixins/kodi_entities.js | 393 ++++---- src/js/helpers/debug.js | 157 +-- src/js/helpers/entities.js | 258 ++--- src/js/helpers/global.js | 366 +++---- src/js/helpers/jquery.js | 136 +-- src/js/helpers/streams.js | 616 ++++++------ src/js/helpers/translate.js | 220 ++--- src/js/helpers/ui.js | 118 ++- src/js/helpers/url.js | 302 +++--- src/js/views/_base/collectionview.js | 25 +- src/js/views/_base/compositeview.js | 20 +- src/js/views/_base/itemview.js | 92 +- src/js/views/_base/layout.js | 19 +- src/js/views/_base/view.js | 130 ++- src/js/views/_base/virtuallistview.js | 174 ++-- src/js/views/card/card_view.js | 129 ++- src/js/views/details/detailsitem.js | 78 +- src/js/views/empty/empty_view.js | 50 +- src/js/views/layouts/layouts_view.js | 106 +- src/js/views/set/set_view.js | 132 ++- src/js/views/song/song_view.js | 34 +- 220 files changed, 18943 insertions(+), 13437 deletions(-) diff --git a/src/js/app.js b/src/js/app.js index 9c034a5f..da0e58ec 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -1,60 +1,70 @@ -## Our global objects -@helpers = {} -@config = { - static: - appTitle: 'Kodi' - jsonRpcEndpoint: 'jsonrpc' - socketsHost: location.hostname - socketsPort: 9090 - ajaxTimeout: 5000 - connected: true - hashKey: 'kodi' - defaultPlayer: 'auto' - ignoreArticle: true - pollInterval: 10000 - reverseProxy: false - albumArtistsOnly: true - searchIndexCacheExpiry: (24 * 60 * 60) # 1 day - collectionCacheExpiry: (7 * 24 * 60 * 60) # 1 week (gets wiped on library update) - addOnsLoaded: false - vibrantHeaders: false - lang: "en" - kodiSettingsLevel: 'standard' - playlistFocusPlaying: true - keyboardControl: 'kodi' - disableThumbs: false - showDeviceName: false - refreshIgnoreNFO: true - largeBreakpoint: 910 - apiKeyTMDB: '' - apiKeyTVDB: '' - apiKeyFanartTv: '' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +//# Our global objects +this.helpers = {}; +this.config = { + static: { + appTitle: 'Kodi', + jsonRpcEndpoint: 'jsonrpc', + socketsHost: location.hostname, + socketsPort: 9090, + ajaxTimeout: 5000, + connected: true, + hashKey: 'kodi', + defaultPlayer: 'auto', + ignoreArticle: true, + pollInterval: 10000, + reverseProxy: false, + albumArtistsOnly: true, + searchIndexCacheExpiry: (24 * 60 * 60), // 1 day + collectionCacheExpiry: (7 * 24 * 60 * 60), // 1 week (gets wiped on library update) + addOnsLoaded: false, + vibrantHeaders: false, + lang: "en", + kodiSettingsLevel: 'standard', + playlistFocusPlaying: true, + keyboardControl: 'kodi', + disableThumbs: false, + showDeviceName: false, + refreshIgnoreNFO: true, + largeBreakpoint: 910, + apiKeyTMDB: '', + apiKeyTVDB: '', + apiKeyFanartTv: '', apiKeyYouTube: '' -} + } +}; -## The App Instance -@Kodi = do (Backbone, Marionette) -> +//# The App Instance +this.Kodi = (function(Backbone, Marionette) { - App = new Backbone.Marionette.Application() + const App = new Backbone.Marionette.Application(); - App.addRegions - root: "body" + App.addRegions({ + root: "body"}); - ## Load custom config settings. - App.on "before:start", -> - config.static = _.extend config.static, config.get('app', 'config:local', config.static) + //# Load custom config settings. + App.on("before:start", () => config.static = _.extend(config.static, config.get('app', 'config:local', config.static))); - App.vent.on "shell:ready", (options) => - App.startHistory() + App.vent.on("shell:ready", options => { + return App.startHistory(); + }); - App + return App; +})(Backbone, Marionette); -$(document).ready => - # Initialise language support - helpers.translate.init -> - # Start the app - Kodi.start() - # Start material - $.material.init() - # Bind to scroll/resize for redraw trigger - helpers.ui.bindOnScrollResize() +$(document).ready(() => { + // Initialise language support + return helpers.translate.init(function() { + // Start the app + Kodi.start(); + // Start material + $.material.init(); + // Bind to scroll/resize for redraw trigger + return helpers.ui.bindOnScrollResize(); + }); +}); diff --git a/src/js/apps/addon/addon_app.js b/src/js/apps/addon/addon_app.js index 6554fd74..e9340db0 100644 --- a/src/js/apps/addon/addon_app.js +++ b/src/js/apps/addon/addon_app.js @@ -1,91 +1,123 @@ -@Kodi.module "AddonApp", (AddonApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp", function(AddonApp, App, Backbone, Marionette, $, _) { - class AddonApp.Router extends App.Router.Base - appRoutes: - "addons/:type" : "list" - "addon/execute/:id" : "execute" + const Cls = (AddonApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "addons/:type" : "list", + "addon/execute/:id" : "execute" + }; + } + }); + Cls.initClass(); - API = + var API = { - # Get list page - list: (type) -> - new AddonApp.List.Controller - type: type + // Get list page + list(type) { + return new AddonApp.List.Controller({ + type}); + }, - # Execute addon - execute: (id) -> - API.addonController().executeAddon id, helpers.url.params(), () -> - Kodi.execute "notification:show", tr('Executed addon') - App.navigate "addons/executable", {trigger: true} + // Execute addon + execute(id) { + API.addonController().executeAddon(id, helpers.url.params(), () => Kodi.execute("notification:show", tr('Executed addon'))); + return App.navigate("addons/executable", {trigger: true}); + }, - # Get the addon controller - addonController: -> - App.request "command:kodi:controller", 'auto', 'AddOn' + // Get the addon controller + addonController() { + return App.request("command:kodi:controller", 'auto', 'AddOn'); + }, - # Get all enabled addons - getEnabledAddons: (callback) -> - addons = [] - # If loaded, return from static - if config.getLocal("addOnsLoaded", false) is true - addons = config.getLocal("addOnsEnabled", []) - if callback - callback addons - else - # Not loaded, lookup and set to static - @addonController().getEnabledAddons true, (addons) -> - config.setLocal "addOnsEnabled", addons - config.setLocal "addOnsLoaded", true - config.set 'app', "addOnsSearchSettings", API.getSearchSettings(addons) - if callback - callback addons - addons + // Get all enabled addons + getEnabledAddons(callback) { + let addons = []; + // If loaded, return from static + if (config.getLocal("addOnsLoaded", false) === true) { + addons = config.getLocal("addOnsEnabled", []); + if (callback) { + callback(addons); + } + } else { + // Not loaded, lookup and set to static + this.addonController().getEnabledAddons(true, function(addons) { + config.setLocal("addOnsEnabled", addons); + config.setLocal("addOnsLoaded", true); + config.set('app', "addOnsSearchSettings", API.getSearchSettings(addons)); + if (callback) { + return callback(addons); + } + }); + } + return addons; + }, - ## Get search settings - getSearchSettings: (addons) -> - searchSettings = [] - for addon in addons - searchSetting = App.request("addon:search:settings:" + addon.addonid) - if searchSetting - if not _.isArray(searchSetting) - searchSetting = [searchSetting] - for i, set of searchSetting - set.id = addon.addonid + '.' + i - searchSettings.push set - searchSettings + //# Get search settings + getSearchSettings(addons) { + const searchSettings = []; + for (var addon of addons) { + var searchSetting = App.request("addon:search:settings:" + addon.addonid); + if (searchSetting) { + if (!_.isArray(searchSetting)) { + searchSetting = [searchSetting]; + } + for (var i in searchSetting) { + var set = searchSetting[i]; + set.id = addon.addonid + '.' + i; + searchSettings.push(set); + } + } + } + return searchSettings; + }, - # Given a filter check if addon is enabled, if addons not loaded returns false. - isAddOnEnabled: (filter = {}, callback) -> - addons = @getEnabledAddons callback - _.findWhere addons, filter + // Given a filter check if addon is enabled, if addons not loaded returns false. + isAddOnEnabled(filter = {}, callback) { + const addons = this.getEnabledAddons(callback); + return _.findWhere(addons, filter); + } + }; - App.on "before:start", -> - new AddonApp.Router - controller: API - # Store enabled addons. - API.getEnabledAddons (resp) -> - App.vent.trigger "navMain:refresh" - # Addons loaded to cache, hopefully before required + App.on("before:start", function() { + new AddonApp.Router({ + controller: API}); + // Store enabled addons. + return API.getEnabledAddons(resp => App.vent.trigger("navMain:refresh")); + }); + // Addons loaded to cache, hopefully before required - # Request is addon enabled. - App.reqres.setHandler 'addon:isEnabled', (filter, callback) -> - API.isAddOnEnabled filter, (enabled) -> if callback then callback(enabled) + // Request is addon enabled. + App.reqres.setHandler('addon:isEnabled', (filter, callback) => API.isAddOnEnabled(filter, function(enabled) { if (callback) { return callback(enabled); } })); - # Request is addon enabled. - App.reqres.setHandler 'addon:enabled:addons', (callback) -> - API.getEnabledAddons (addons) -> if callback then callback(addons) + // Request is addon enabled. + App.reqres.setHandler('addon:enabled:addons', callback => API.getEnabledAddons(function(addons) { if (callback) { return callback(addons); } })); - # Request excluded breadcrumb paths - App.reqres.setHandler 'addon:excludedPaths', (addonId) -> - if addonId? - excludedPaths = App.request "addon:excludedPaths:" + addonId - if not excludedPaths? - excludedPaths = [] - excludedPaths + // Request excluded breadcrumb paths + App.reqres.setHandler('addon:excludedPaths', function(addonId) { + let excludedPaths; + if (addonId != null) { + excludedPaths = App.request("addon:excludedPaths:" + addonId); + } + if ((excludedPaths == null)) { + excludedPaths = []; + } + return excludedPaths; + }); - # Request excluded breadcrumb paths - App.reqres.setHandler 'addon:search:enabled', -> - settings = config.get 'app', "addOnsSearchSettings", [] - settings = settings.concat App.request('searchAddons:entities').toJSON() - settings + // Request excluded breadcrumb paths + return App.reqres.setHandler('addon:search:enabled', function() { + let settings = config.get('app', "addOnsSearchSettings", []); + settings = settings.concat(App.request('searchAddons:entities').toJSON()); + return settings; + }); +}); diff --git a/src/js/apps/addon/googlemusic/addon_googlemusic_app.js b/src/js/apps/addon/googlemusic/addon_googlemusic_app.js index 50248ebf..acb6ef7e 100644 --- a/src/js/apps/addon/googlemusic/addon_googlemusic_app.js +++ b/src/js/apps/addon/googlemusic/addon_googlemusic_app.js @@ -1,16 +1,24 @@ -@Kodi.module "AddonApp.GoogleMusic", (GoogleMusic, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.GoogleMusic", function(GoogleMusic, App, Backbone, Marionette, $, _) { - API = + const API = { - addonId: 'plugin.audio.googlemusic.exp' + addonId: 'plugin.audio.googlemusic.exp', - searchAddon: - id: @addonId - url: 'plugin://plugin.audio.googlemusic.exp/?path=search_result&type=track&query=[QUERY]' - title: 'GoogleMusic' + searchAddon: { + id: this.addonId, + url: 'plugin://plugin.audio.googlemusic.exp/?path=search_result&type=track&query=[QUERY]', + title: 'GoogleMusic', media: 'music' + } + }; - ## Provide search settings - App.reqres.setHandler "addon:search:settings:" + API.addonId, -> - API.searchAddon + //# Provide search settings + return App.reqres.setHandler("addon:search:settings:" + API.addonId, () => API.searchAddon); +}); diff --git a/src/js/apps/addon/list/list_controller.js b/src/js/apps/addon/list/list_controller.js index fbbbe52b..98828afc 100644 --- a/src/js/apps/addon/list/list_controller.js +++ b/src/js/apps/addon/list/list_controller.js @@ -1,33 +1,47 @@ -@Kodi.module "AddonApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.List", function(List, App, Backbone, Marionette, $, _) { - ## Main controller - class List.Controller extends App.Controllers.Base + //# Main controller + return List.Controller = class Controller extends App.Controllers.Base { - ## Setup - initialize: (options) -> - @type = options.type - App.request "addon:entities", @type, (collection) => - collection.sortCollection 'name' - @layout = @getLayoutView collection - @listenTo @layout, "show", => - @renderList collection - @renderSidebar() - App.regionContent.show @layout + //# Setup + initialize(options) { + this.type = options.type; + return App.request("addon:entities", this.type, collection => { + collection.sortCollection('name'); + this.layout = this.getLayoutView(collection); + this.listenTo(this.layout, "show", () => { + this.renderList(collection); + return this.renderSidebar(); + }); + return App.regionContent.show(this.layout); + }); + } - ## Render items - renderList: (collection) -> - view = new List.Addons - collection: collection - @layout.regionContent.show view + //# Render items + renderList(collection) { + const view = new List.Addons({ + collection}); + return this.layout.regionContent.show(view); + } - ## Get the base layout - getLayoutView: (collection) -> - new List.ListLayout - collection: collection + //# Get the base layout + getLayoutView(collection) { + return new List.ListLayout({ + collection}); + } - ## Add side nav - renderSidebar: -> - settingsNavView = App.request "navMain:children:show", 'addons/all', 'Add-ons' - @layout.regionSidebarFirst.show settingsNavView + //# Add side nav + renderSidebar() { + const settingsNavView = App.request("navMain:children:show", 'addons/all', 'Add-ons'); + return this.layout.regionSidebarFirst.show(settingsNavView); + } + }; +}); diff --git a/src/js/apps/addon/list/list_view.js b/src/js/apps/addon/list/list_view.js index d80b0f99..1c0987c9 100644 --- a/src/js/apps/addon/list/list_view.js +++ b/src/js/apps/addon/list/list_view.js @@ -1,14 +1,37 @@ -@Kodi.module "AddonApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.ListLayout extends App.Views.LayoutWithSidebarFirstView - className: "addon-list" + let Cls = (List.ListLayout = class ListLayout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "addon-list"; + } + }); + Cls.initClass(); - class List.Teaser extends App.Views.CardView - tagName: "li" + Cls = (List.Teaser = class Teaser extends App.Views.CardView { + static initClass() { + this.prototype.tagName = "li"; + } + }); + Cls.initClass(); - class List.Addons extends App.Views.CollectionView - childView: List.Teaser - emptyView: App.Views.EmptyViewResults - tagName: "ul" - sort: 'name' - className: "card-grid--square" + return (function() { + Cls = (List.Addons = class Addons extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = List.Teaser; + this.prototype.emptyView = App.Views.EmptyViewResults; + this.prototype.tagName = "ul"; + this.prototype.sort = 'name'; + this.prototype.className = "card-grid--square"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/addon/mixcloud/addon_mixcloud_app.js b/src/js/apps/addon/mixcloud/addon_mixcloud_app.js index 452d8650..ec8e18bc 100644 --- a/src/js/apps/addon/mixcloud/addon_mixcloud_app.js +++ b/src/js/apps/addon/mixcloud/addon_mixcloud_app.js @@ -1,15 +1,23 @@ -@Kodi.module "AddonApp.MixCloud", (MixCloud, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.MixCloud", function(MixCloud, App, Backbone, Marionette, $, _) { - API = + const API = { - addonId: 'plugin.audio.mixcloud' + addonId: 'plugin.audio.mixcloud', - searchAddon: - id: @addonId - url: 'plugin://plugin.audio.mixcloud/?mode=30&key=cloudcast&offset=0&query=[QUERY]' - title: 'MixCloud' + searchAddon: { + id: this.addonId, + url: 'plugin://plugin.audio.mixcloud/?mode=30&key=cloudcast&offset=0&query=[QUERY]', + title: 'MixCloud', media: 'music' + } + }; - ## Provide search settings - App.reqres.setHandler "addon:search:settings:" + API.addonId, -> - API.searchAddon + //# Provide search settings + return App.reqres.setHandler("addon:search:settings:" + API.addonId, () => API.searchAddon); +}); diff --git a/src/js/apps/addon/pvr/addons_pvr_ap.js b/src/js/apps/addon/pvr/addons_pvr_ap.js index 311b9968..918dad9b 100644 --- a/src/js/apps/addon/pvr/addons_pvr_ap.js +++ b/src/js/apps/addon/pvr/addons_pvr_ap.js @@ -1,10 +1,18 @@ -@Kodi.module "AddonApp.Pvr", (Pvr, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.Pvr", function(Pvr, App, Backbone, Marionette, $, _) { - API = + const API = { - isEnabled: -> - App.request "addon:isEnabled", {type: 'kodi.pvrclient'} + isEnabled() { + return App.request("addon:isEnabled", {type: 'kodi.pvrclient'}); + } + }; - ## Is a pvr client enabled (used for menu visibility). - App.reqres.setHandler "addon:pvr:enabled", -> - API.isEnabled() + //# Is a pvr client enabled (used for menu visibility). + return App.reqres.setHandler("addon:pvr:enabled", () => API.isEnabled()); +}); diff --git a/src/js/apps/addon/radio/addon_radio_app.js b/src/js/apps/addon/radio/addon_radio_app.js index db168f14..f0a86594 100644 --- a/src/js/apps/addon/radio/addon_radio_app.js +++ b/src/js/apps/addon/radio/addon_radio_app.js @@ -1,16 +1,24 @@ -@Kodi.module "AddonApp.Radio", (Radio, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.Radio", function(Radio, App, Backbone, Marionette, $, _) { - API = + const API = { - addonId: 'plugin.audio.radio_de' + addonId: 'plugin.audio.radio_de', - searchAddon: - id: @addonId - url: 'plugin://plugin.audio.radio_de/stations/search/[QUERY]' - title: 'Radio' + searchAddon: { + id: this.addonId, + url: 'plugin://plugin.audio.radio_de/stations/search/[QUERY]', + title: 'Radio', media: 'music' + } + }; - ## Provide search settings - App.reqres.setHandler "addon:search:settings:" + API.addonId, -> - API.searchAddon + //# Provide search settings + return App.reqres.setHandler("addon:search:settings:" + API.addonId, () => API.searchAddon); +}); diff --git a/src/js/apps/addon/soundcloud/addon_soundcloud_app.js b/src/js/apps/addon/soundcloud/addon_soundcloud_app.js index 4c72c390..ff448d12 100644 --- a/src/js/apps/addon/soundcloud/addon_soundcloud_app.js +++ b/src/js/apps/addon/soundcloud/addon_soundcloud_app.js @@ -1,15 +1,23 @@ -@Kodi.module "AddonApp.SoundCloud", (Soundcloud, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.SoundCloud", function(Soundcloud, App, Backbone, Marionette, $, _) { - API = + const API = { - addonId: 'plugin.audio.soundcloud' + addonId: 'plugin.audio.soundcloud', - searchAddon: - id: @addonId - url: 'plugin://plugin.audio.soundcloud/search/?query=[QUERY]' - title: 'SoundCloud' + searchAddon: { + id: this.addonId, + url: 'plugin://plugin.audio.soundcloud/search/?query=[QUERY]', + title: 'SoundCloud', media: 'music' + } + }; - ## Provide search settings - App.reqres.setHandler "addon:search:settings:" + API.addonId, -> - API.searchAddon + //# Provide search settings + return App.reqres.setHandler("addon:search:settings:" + API.addonId, () => API.searchAddon); +}); diff --git a/src/js/apps/addon/youtube/addon_youtube_app.js b/src/js/apps/addon/youtube/addon_youtube_app.js index fe8be27c..35718cc1 100644 --- a/src/js/apps/addon/youtube/addon_youtube_app.js +++ b/src/js/apps/addon/youtube/addon_youtube_app.js @@ -1,33 +1,40 @@ -@Kodi.module "AddonApp.YouTube", (Soundcloud, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AddonApp.YouTube", function(Soundcloud, App, Backbone, Marionette, $, _) { - API = + const API = { - addonId: 'plugin.video.youtube' + addonId: 'plugin.video.youtube', - searchAddon: - url: 'plugin://plugin.video.youtube/search/?q=[QUERY]' - title: 'YouTube' + searchAddon: { + url: 'plugin://plugin.video.youtube/search/?q=[QUERY]', + title: 'YouTube', media: 'video' + } + }; - ## Provide search settings - App.reqres.setHandler "addon:search:settings:" + API.addonId, -> - API.searchAddon + //# Provide search settings + App.reqres.setHandler("addon:search:settings:" + API.addonId, () => API.searchAddon); - ## - ## Get any excluded paths that should not appear in breadcrumbs. - ## - ## Called via App.request("addon:excludedPaths", addonId) - ## - ## Eg. the youtube path "special" and "kodion" is used but both are - ## invalid paths when requesting that url, yet they appear in breadcrumbs - ## because they are part of the base url for other pages. - ## - ## Note the naming convention of the handler has the plugin id in it. - ## - App.reqres.setHandler "addon:excludedPaths:" + API.addonId, -> - [ - 'plugin://plugin.video.youtube/special/', - 'plugin://plugin.video.youtube/kodion/search/', - 'plugin://plugin.video.youtube/kodion/', - 'plugin://plugin.video.youtube/channel/', - ] + //# + //# Get any excluded paths that should not appear in breadcrumbs. + //# + //# Called via App.request("addon:excludedPaths", addonId) + //# + //# Eg. the youtube path "special" and "kodion" is used but both are + //# invalid paths when requesting that url, yet they appear in breadcrumbs + //# because they are part of the base url for other pages. + //# + //# Note the naming convention of the handler has the plugin id in it. + //# + return App.reqres.setHandler("addon:excludedPaths:" + API.addonId, () => [ + 'plugin://plugin.video.youtube/special/', + 'plugin://plugin.video.youtube/kodion/search/', + 'plugin://plugin.video.youtube/kodion/', + 'plugin://plugin.video.youtube/channel/', + ]); +}); diff --git a/src/js/apps/album/album_app.js b/src/js/apps/album/album_app.js index c15642f6..fbfacb88 100644 --- a/src/js/apps/album/album_app.js +++ b/src/js/apps/album/album_app.js @@ -1,51 +1,70 @@ -@Kodi.module "AlbumApp", (AlbumApp, App, Backbone, Marionette, $, _) -> - - class AlbumApp.Router extends App.Router.Base - appRoutes: - "music/albums" : "list" - "music/album/:id" : "view" - - API = - - list: -> - new AlbumApp.List.Controller() - - view: (id) -> - new AlbumApp.Show.Controller - id: id - - action: (op, view) -> - model = view.model - playlist = App.request "command:kodi:controller", 'audio', 'PlayList' - switch op - when 'play' - App.execute "command:audio:play", 'albumid', model.get('albumid') - when 'add' - playlist.add 'albumid', model.get('albumid') - when 'localadd' - App.execute "localplaylist:addentity", 'albumid', model.get('albumid') - when 'localplay' - localPlaylist = App.request "command:local:controller", 'audio', 'PlayList' - localPlaylist.play 'albumid', model.get('albumid') - else - ## nothing - - - App.on "before:start", -> - new AlbumApp.Router - controller: API - - App.commands.setHandler 'album:action', (op, model) -> - API.action op, model - - App.reqres.setHandler 'album:action:items', -> - { - actions: {thumbs: 'Thumbs up'} - menu: {add: tr('Queue in Kodi'), 'divider-1': '', localadd: tr('Add to playlist'), localplay: tr('Play in browser'), 'divider-2': '', edit: tr('Edit')} +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp", function(AlbumApp, App, Backbone, Marionette, $, _) { + + const Cls = (AlbumApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "music/albums" : "list", + "music/album/:id" : "view" + }; + } + }); + Cls.initClass(); + + const API = { + + list() { + return new AlbumApp.List.Controller(); + }, + + view(id) { + return new AlbumApp.Show.Controller({ + id}); + }, + + action(op, view) { + const { + model + } = view; + const playlist = App.request("command:kodi:controller", 'audio', 'PlayList'); + switch (op) { + case 'play': + return App.execute("command:audio:play", 'albumid', model.get('albumid')); + case 'add': + return playlist.add('albumid', model.get('albumid')); + case 'localadd': + return App.execute("localplaylist:addentity", 'albumid', model.get('albumid')); + case 'localplay': + var localPlaylist = App.request("command:local:controller", 'audio', 'PlayList'); + return localPlaylist.play('albumid', model.get('albumid')); + default: + } } + }; + //# nothing + + + App.on("before:start", () => new AlbumApp.Router({ + controller: API})); + + App.commands.setHandler('album:action', (op, model) => API.action(op, model)); + + App.reqres.setHandler('album:action:items', () => ({ + actions: {thumbs: 'Thumbs up'}, + menu: {add: tr('Queue in Kodi'), 'divider-1': '', localadd: tr('Add to playlist'), localplay: tr('Play in browser'), 'divider-2': '', edit: tr('Edit')} + })); - App.commands.setHandler 'album:edit', (model) -> - loadedModel = App.request "album:entity", model.get('id') - App.execute "when:entity:fetched", loadedModel, => - new AlbumApp.Edit.Controller - model: loadedModel + return App.commands.setHandler('album:edit', function(model) { + const loadedModel = App.request("album:entity", model.get('id')); + return App.execute("when:entity:fetched", loadedModel, () => { + return new AlbumApp.Edit.Controller({ + model: loadedModel}); + }); + }); +}); diff --git a/src/js/apps/album/edit/edit_controller.js b/src/js/apps/album/edit/edit_controller.js index 7f60614f..b164b790 100644 --- a/src/js/apps/album/edit/edit_controller.js +++ b/src/js/apps/album/edit/edit_controller.js @@ -1,27 +1,37 @@ -@Kodi.module "AlbumApp.Edit", (Edit, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp.Edit", function(Edit, App, Backbone, Marionette, $, _) { - class Edit.Controller extends App.Controllers.Base + return Edit.Controller = class Controller extends App.Controllers.Base { - initialize: -> - @model = @getOption('model') - options = { - titleHtml: '' + tr('Edit') + '' + @model.escape('title') - form: @getStructure() - formState: @model.attributes - config: - attributes: {class: 'edit-form'} - editForm: true - tabs: true - callback: (data, formView) => - @saveCallback(data, formView) - } - form = App.request "form:popup:wrapper", options + initialize() { + let form; + this.model = this.getOption('model'); + const options = { + titleHtml: '' + tr('Edit') + '' + this.model.escape('title'), + form: this.getStructure(), + formState: this.model.attributes, + config: { + attributes: {class: 'edit-form'}, + editForm: true, + tabs: true, + callback: (data, formView) => { + return this.saveCallback(data, formView); + } + } + }; + return form = App.request("form:popup:wrapper", options); + } - getStructure: -> - [ + getStructure() { + return [ { - title: 'General' - id: 'general' + title: 'General', + id: 'general', children:[ {id: 'title', title: tr('Title'), type: 'textfield'}, {id: 'artist', title: tr('Artist'), type: 'textfield', format: 'array.string'}, @@ -30,10 +40,10 @@ {id: 'year', title: tr('Year'), type: 'number', format: 'integer', attributes: {class: 'half-width', step: 1, min: 0, max: 9999}}, {id: 'rating', title: tr('Rating'), type: 'number', format: 'float', attributes: {class: 'half-width', step: 0.1, min: 0, max: 10}, suffix: '
'}, ] - } + }, { - title: 'Tags' - id: 'tags' + title: 'Tags', + id: 'tags', children:[ {id: 'genre', title: tr('Genres'), type: 'textfield', format: 'array.string'}, {id: 'style', title: tr('Styles'), type: 'textfield', format: 'array.string'}, @@ -41,11 +51,16 @@ {id: 'mood', title: tr('Moods'), type: 'textarea', format: 'array.string'}, ] } - ] + ]; + } - ## Save the settings to Kodi - saveCallback: (data, formView) -> - controller = App.request "command:kodi:controller", 'audio', 'AudioLibrary' - controller.setAlbumDetails @model.get('id'), data, => - Kodi.vent.trigger 'entity:kodi:update', @model.get('uid') - Kodi.execute "notification:show", t.sprintf(tr("Updated %1$s details"), 'album') + //# Save the settings to Kodi + saveCallback(data, formView) { + const controller = App.request("command:kodi:controller", 'audio', 'AudioLibrary'); + return controller.setAlbumDetails(this.model.get('id'), data, () => { + Kodi.vent.trigger('entity:kodi:update', this.model.get('uid')); + return Kodi.execute("notification:show", t.sprintf(tr("Updated %1$s details"), 'album')); + }); + } + }; +}); diff --git a/src/js/apps/album/list/list_controller.js b/src/js/apps/album/list/list_controller.js index 43c77e0d..34350402 100644 --- a/src/js/apps/album/list/list_controller.js +++ b/src/js/apps/album/list/list_controller.js @@ -1,76 +1,91 @@ -@Kodi.module "AlbumApp.List", (List, App, Backbone, Marionette, $, _) -> - - API = - - bindTriggers: (view) -> - App.listenTo view, 'childview:album:play', (list, item) -> - App.execute 'album:action', 'play', item - App.listenTo view, 'childview:album:add', (list, item) -> - App.execute 'album:action', 'add', item - App.listenTo view, 'childview:album:localadd', (list, item) -> - App.execute 'album:action', 'localadd', item - App.listenTo view, 'childview:album:localplay', (list, item) -> - App.execute 'album:action', 'localplay', item - App.listenTo view, 'childview:album:edit', (parent, item) -> - App.execute 'album:edit', item.model - - getAlbumsList: (collection) -> - view = new List.Albums - collection: collection - API.bindTriggers(view) - view - - - ## Main controller - class List.Controller extends App.Controllers.Base - - initialize: -> - collection = App.request "album:entities" - App.execute "when:entity:fetched", collection, => - - ## Set available filters - collection.availableFilters = @getAvailableFilters() - - ## Top level menu path for filters - collection.sectionId = 'music' - - ## If present set initial filter via url - App.request 'filter:init', @getAvailableFilters() - - @layout = @getLayoutView collection - - ## Render subviews on show - @listenTo @layout, "show", => - @renderList collection - @getFiltersView collection - App.regionContent.show @layout - - getLayoutView: (collection) -> - new List.ListLayout - collection: collection - - ## Available sort and filter options - ## See filter_app.js for available options - getAvailableFilters: -> - sort: ['label', 'year', 'rating', 'artist', 'dateadded', 'random'] - filter: ['year', 'genre', 'style', 'albumlabel', 'thumbsUp'] - - ## Apply filter view and provide a handler for applying changes - getFiltersView: (collection) -> - filters = App.request 'filter:show', collection - @layout.regionSidebarFirst.show filters - ## Listen to when the filters change and re-render. - @listenTo filters, "filter:changed", => - @renderList collection - - ## Get the list view with filters applied. - renderList: (collection) -> - App.execute "loading:show:view", @layout.regionContent - filteredCollection = App.request 'filter:apply:entities', collection - view = API.getAlbumsList filteredCollection - @layout.regionContent.show view - - - ## handler for other modules to get a list view. - App.reqres.setHandler "album:list:view", (collection) -> - API.getAlbumsList collection +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp.List", function(List, App, Backbone, Marionette, $, _) { + + var API = { + + bindTriggers(view) { + App.listenTo(view, 'childview:album:play', (list, item) => App.execute('album:action', 'play', item)); + App.listenTo(view, 'childview:album:add', (list, item) => App.execute('album:action', 'add', item)); + App.listenTo(view, 'childview:album:localadd', (list, item) => App.execute('album:action', 'localadd', item)); + App.listenTo(view, 'childview:album:localplay', (list, item) => App.execute('album:action', 'localplay', item)); + return App.listenTo(view, 'childview:album:edit', (parent, item) => App.execute('album:edit', item.model)); + }, + + getAlbumsList(collection) { + const view = new List.Albums({ + collection}); + API.bindTriggers(view); + return view; + } + }; + + + //# Main controller + List.Controller = class Controller extends App.Controllers.Base { + + initialize() { + const collection = App.request("album:entities"); + return App.execute("when:entity:fetched", collection, () => { + + //# Set available filters + collection.availableFilters = this.getAvailableFilters(); + + //# Top level menu path for filters + collection.sectionId = 'music'; + + //# If present set initial filter via url + App.request('filter:init', this.getAvailableFilters()); + + this.layout = this.getLayoutView(collection); + + //# Render subviews on show + this.listenTo(this.layout, "show", () => { + this.renderList(collection); + return this.getFiltersView(collection); + }); + return App.regionContent.show(this.layout); + }); + } + + getLayoutView(collection) { + return new List.ListLayout({ + collection}); + } + + //# Available sort and filter options + //# See filter_app.js for available options + getAvailableFilters() { + return { + sort: ['label', 'year', 'rating', 'artist', 'dateadded', 'random'], + filter: ['year', 'genre', 'style', 'albumlabel', 'thumbsUp'] + }; + } + + //# Apply filter view and provide a handler for applying changes + getFiltersView(collection) { + const filters = App.request('filter:show', collection); + this.layout.regionSidebarFirst.show(filters); + //# Listen to when the filters change and re-render. + return this.listenTo(filters, "filter:changed", () => { + return this.renderList(collection); + }); + } + + //# Get the list view with filters applied. + renderList(collection) { + App.execute("loading:show:view", this.layout.regionContent); + const filteredCollection = App.request('filter:apply:entities', collection); + const view = API.getAlbumsList(filteredCollection); + return this.layout.regionContent.show(view); + } + }; + + + //# handler for other modules to get a list view. + return App.reqres.setHandler("album:list:view", collection => API.getAlbumsList(collection)); +}); diff --git a/src/js/apps/album/list/list_view.js b/src/js/apps/album/list/list_view.js index e5f4f3cd..c7cbf946 100644 --- a/src/js/apps/album/list/list_view.js +++ b/src/js/apps/album/list/list_view.js @@ -1,31 +1,64 @@ -@Kodi.module "AlbumApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.ListLayout extends App.Views.LayoutWithSidebarFirstView - className: "album-list with-filters" + let Cls = (List.ListLayout = class ListLayout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "album-list with-filters"; + } + }); + Cls.initClass(); - class List.AlbumTeaser extends App.Views.CardView - triggers: - "click .play" : "album:play" - "click .dropdown .add" : "album:add" - "click .dropdown .localadd" : "album:localadd" - "click .dropdown .localplay" : "album:localplay" - "click .dropdown .edit" : "album:edit" - initialize: -> - super arguments... - if @model? - @setMeta() - @model.set(App.request('album:action:items')) - setMeta: -> - if @model - @model.set subtitleHtml: @themeLink @model.get('artist'), helpers.url.get('artist', @model.get('artistid')) + Cls = (List.AlbumTeaser = class AlbumTeaser extends App.Views.CardView { + static initClass() { + this.prototype.triggers = { + "click .play" : "album:play", + "click .dropdown .add" : "album:add", + "click .dropdown .localadd" : "album:localadd", + "click .dropdown .localplay" : "album:localplay", + "click .dropdown .edit" : "album:edit" + }; + } + initialize() { + super.initialize(...arguments); + if (this.model != null) { + this.setMeta(); + return this.model.set(App.request('album:action:items')); + } + } + setMeta() { + if (this.model) { + return this.model.set({subtitleHtml: this.themeLink(this.model.get('artist'), helpers.url.get('artist', this.model.get('artistid')))}); + } + } + }); + Cls.initClass(); - class List.Empty extends App.Views.EmptyViewResults - tagName: "li" - className: "album-empty-result" + Cls = (List.Empty = class Empty extends App.Views.EmptyViewResults { + static initClass() { + this.prototype.tagName = "li"; + this.prototype.className = "album-empty-result"; + } + }); + Cls.initClass(); - class List.Albums extends App.Views.VirtualListView - childView: List.AlbumTeaser - emptyView: List.Empty - tagName: "ul" - sort: 'artist' - className: "card-grid--square" + return (function() { + Cls = (List.Albums = class Albums extends App.Views.VirtualListView { + static initClass() { + this.prototype.childView = List.AlbumTeaser; + this.prototype.emptyView = List.Empty; + this.prototype.tagName = "ul"; + this.prototype.sort = 'artist'; + this.prototype.className = "card-grid--square"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/album/show/show_controller.js b/src/js/apps/album/show/show_controller.js index 5894411d..d548f80d 100644 --- a/src/js/apps/album/show/show_controller.js +++ b/src/js/apps/album/show/show_controller.js @@ -1,100 +1,124 @@ -@Kodi.module "AlbumApp.Show", (Show, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp.Show", function(Show, App, Backbone, Marionette, $, _) { - API = + var API = { - bindTriggers: (view) -> - App.listenTo view, 'album:play', (item) -> - App.execute 'album:action', 'play', item - App.listenTo view, 'album:add', (item) -> - App.execute 'album:action', 'add', item - App.listenTo view, 'album:localadd', (item) -> - App.execute 'album:action', 'localadd', item - App.listenTo view, 'album:localplay', (item) -> - App.execute 'album:action', 'localplay', item - App.listenTo view, 'album:edit', (item) -> - App.execute 'album:edit', item.model + bindTriggers(view) { + App.listenTo(view, 'album:play', item => App.execute('album:action', 'play', item)); + App.listenTo(view, 'album:add', item => App.execute('album:action', 'add', item)); + App.listenTo(view, 'album:localadd', item => App.execute('album:action', 'localadd', item)); + App.listenTo(view, 'album:localplay', item => App.execute('album:action', 'localplay', item)); + return App.listenTo(view, 'album:edit', item => App.execute('album:edit', item.model)); + }, - ## Return a set of albums with songs. - ## Songs is expected to be an array of song collections - ## keyed by albumid. The only thing that should be calling this is artists. - getAlbumsFromSongs: (songs) -> - albumsCollectionView = new Show.WithSongsCollection() - ## What happens when we add a child to this mofo - albumsCollectionView.on "add:child", (albumView) => - App.execute "when:entity:fetched", album, => - model = albumView.model - ## Add the teaser. - teaser = new Show.AlbumTeaser model: model - API.bindTriggers teaser - albumView.regionMeta.show teaser - ## Add the songs. - songSet = _.findWhere songs, {albumid: model.get('albumid')} - songView = App.request "song:list:view", songSet.songs - albumView.regionSongs.show songView - ## Loop over albums/song collections - for albumSet in songs - ## Get the album. - album = App.request "album:entity", albumSet.albumid, success: (album) -> - albumsCollectionView.addChild album, Show.WithSongsLayout - ## Return the collection view - albumsCollectionView + //# Return a set of albums with songs. + //# Songs is expected to be an array of song collections + //# keyed by albumid. The only thing that should be calling this is artists. + getAlbumsFromSongs(songs) { + const albumsCollectionView = new Show.WithSongsCollection(); + //# What happens when we add a child to this mofo + albumsCollectionView.on("add:child", albumView => { + return App.execute("when:entity:fetched", album, () => { + const { + model + } = albumView; + //# Add the teaser. + const teaser = new Show.AlbumTeaser({model}); + API.bindTriggers(teaser); + albumView.regionMeta.show(teaser); + //# Add the songs. + const songSet = _.findWhere(songs, {albumid: model.get('albumid')}); + const songView = App.request("song:list:view", songSet.songs); + return albumView.regionSongs.show(songView); + }); + }); + //# Loop over albums/song collections + for (var albumSet of songs) { + //# Get the album. + var album = App.request("album:entity", albumSet.albumid, { success(album) { + return albumsCollectionView.addChild(album, Show.WithSongsLayout); + } + } + ); + } + //# Return the collection view + return albumsCollectionView; + } + }; - ## When viewing a full page we call the controller - class Show.Controller extends App.Controllers.Base + //# When viewing a full page we call the controller + Show.Controller = class Controller extends App.Controllers.Base { - ## The Album page. - initialize: (options) -> - id = parseInt options.id - album = App.request "album:entity", id - ## Fetch the artist - App.execute "when:entity:fetched", album, => - ## Get the layout. - @layout = @getLayoutView album - ## Ensure background removed when we leave. - @listenTo @layout, "destroy", => - App.execute "images:fanart:set", 'none' - ## Listen to the show of our layout. - @listenTo @layout, "show", => - @getMusic id - @getDetailsLayoutView album - ## Add the layout to content. - App.regionContent.show @layout + //# The Album page. + initialize(options) { + const id = parseInt(options.id); + const album = App.request("album:entity", id); + //# Fetch the artist + return App.execute("when:entity:fetched", album, () => { + //# Get the layout. + this.layout = this.getLayoutView(album); + //# Ensure background removed when we leave. + this.listenTo(this.layout, "destroy", () => { + return App.execute("images:fanart:set", 'none'); + }); + //# Listen to the show of our layout. + this.listenTo(this.layout, "show", () => { + this.getMusic(id); + return this.getDetailsLayoutView(album); + }); + //# Add the layout to content. + return App.regionContent.show(this.layout); + }); + } - ## Get the base layout - getLayoutView: (album) -> - new Show.PageLayout - model: album + //# Get the base layout + getLayoutView(album) { + return new Show.PageLayout({ + model: album}); + } - ## Build the details layout. - getDetailsLayoutView: (album) -> - headerLayout = new Show.HeaderLayout model: album - @listenTo headerLayout, "show", => - teaser = new Show.AlbumDetailTeaser model: album - API.bindTriggers teaser - detail = new Show.Details model: album - @listenTo detail, "show", => - API.bindTriggers detail - headerLayout.regionSide.show teaser - headerLayout.regionMeta.show detail - @layout.regionHeader.show headerLayout + //# Build the details layout. + getDetailsLayoutView(album) { + const headerLayout = new Show.HeaderLayout({model: album}); + this.listenTo(headerLayout, "show", () => { + const teaser = new Show.AlbumDetailTeaser({model: album}); + API.bindTriggers(teaser); + const detail = new Show.Details({model: album}); + this.listenTo(detail, "show", () => { + return API.bindTriggers(detail); + }); + headerLayout.regionSide.show(teaser); + return headerLayout.regionMeta.show(detail); + }); + return this.layout.regionHeader.show(headerLayout); + } - ## Get a list of all the music for this artist parsed into albums. - getMusic: (id) -> - options = - filter: {albumid: id} - ## Get all the songs and parse them into separate album collections. - songs = App.request "song:entities", options - App.execute "when:entity:fetched", songs, => - albumView = new Show.WithSongsLayout() - songView = App.request "song:list:view", songs - @listenTo albumView, "show", => - albumView.regionSongs.show songView - @layout.regionContent.show albumView + //# Get a list of all the music for this artist parsed into albums. + getMusic(id) { + const options = + {filter: {albumid: id}}; + //# Get all the songs and parse them into separate album collections. + const songs = App.request("song:entities", options); + return App.execute("when:entity:fetched", songs, () => { + const albumView = new Show.WithSongsLayout(); + const songView = App.request("song:list:view", songs); + this.listenTo(albumView, "show", () => { + return albumView.regionSongs.show(songView); + }); + return this.layout.regionContent.show(albumView); + }); + } + }; - ## Return a set of albums with songs. - App.reqres.setHandler "albums:withsongs:view", (songs) -> - API.getAlbumsFromSongs songs + //# Return a set of albums with songs. + return App.reqres.setHandler("albums:withsongs:view", songs => API.getAlbumsFromSongs(songs)); +}); diff --git a/src/js/apps/album/show/show_view.js b/src/js/apps/album/show/show_view.js index d760ad05..3367266e 100644 --- a/src/js/apps/album/show/show_view.js +++ b/src/js/apps/album/show/show_view.js @@ -1,48 +1,87 @@ -@Kodi.module "AlbumApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - ## Album with songs. - - class Show.WithSongsLayout extends App.Views.LayoutView - template: 'apps/album/show/album_with_songs' - className: 'album-wrapper' - regions: - regionMeta: '.region-album-meta' - regionSongs: '.region-album-songs' - - class Show.WithSongsCollection extends App.Views.CollectionView - childView: Show.WithSongsLayout - tagName: "div" - sort: 'year' - className: "albums-wrapper" - - ## Full page views. - - class Show.PageLayout extends App.Views.LayoutWithHeaderView - className: 'album-show detail-container' - - class Show.HeaderLayout extends App.Views.LayoutDetailsHeaderView - className: 'album-details' - - class Show.Details extends App.Views.DetailsItem - template: 'apps/album/show/details_meta' - triggers: - "click .play" : "album:play" - "click .add" : "album:add" - "click .localadd" : "album:localadd" - "click .localplay" : "album:localplay" - "click .edit" : "album:edit" - - class Show.AlbumTeaser extends App.AlbumApp.List.AlbumTeaser - tagName: "div" - initialize: -> - @setMeta() - @model.set(App.request('album:action:items')) - setMeta: -> - @model.set - subtitleHtml: @themeLink @model.get('year'), 'music/albums?year=' + @model.get('year') - attributes: -> - @watchedAttributes 'card-minimal' - - class Show.AlbumDetailTeaser extends Show.AlbumTeaser - attributes: -> - @watchedAttributes 'card-detail' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("AlbumApp.Show", function(Show, App, Backbone, Marionette, $, _) { + + //# Album with songs. + + let Cls = (Show.WithSongsLayout = class WithSongsLayout extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/album/show/album_with_songs'; + this.prototype.className = 'album-wrapper'; + this.prototype.regions = { + regionMeta: '.region-album-meta', + regionSongs: '.region-album-songs' + }; + } + }); + Cls.initClass(); + + Cls = (Show.WithSongsCollection = class WithSongsCollection extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = Show.WithSongsLayout; + this.prototype.tagName = "div"; + this.prototype.sort = 'year'; + this.prototype.className = "albums-wrapper"; + } + }); + Cls.initClass(); + + //# Full page views. + + Cls = (Show.PageLayout = class PageLayout extends App.Views.LayoutWithHeaderView { + static initClass() { + this.prototype.className = 'album-show detail-container'; + } + }); + Cls.initClass(); + + Cls = (Show.HeaderLayout = class HeaderLayout extends App.Views.LayoutDetailsHeaderView { + static initClass() { + this.prototype.className = 'album-details'; + } + }); + Cls.initClass(); + + Cls = (Show.Details = class Details extends App.Views.DetailsItem { + static initClass() { + this.prototype.template = 'apps/album/show/details_meta'; + this.prototype.triggers = { + "click .play" : "album:play", + "click .add" : "album:add", + "click .localadd" : "album:localadd", + "click .localplay" : "album:localplay", + "click .edit" : "album:edit" + }; + } + }); + Cls.initClass(); + + Cls = (Show.AlbumTeaser = class AlbumTeaser extends App.AlbumApp.List.AlbumTeaser { + static initClass() { + this.prototype.tagName = "div"; + } + initialize() { + this.setMeta(); + return this.model.set(App.request('album:action:items')); + } + setMeta() { + return this.model.set({ + subtitleHtml: this.themeLink(this.model.get('year'), 'music/albums?year=' + this.model.get('year'))}); + } + attributes() { + return this.watchedAttributes('card-minimal'); + } + }); + Cls.initClass(); + + return (Show.AlbumDetailTeaser = class AlbumDetailTeaser extends Show.AlbumTeaser { + attributes() { + return this.watchedAttributes('card-detail'); + } + }); +}); diff --git a/src/js/apps/artist/artist_app.js b/src/js/apps/artist/artist_app.js index 09591c23..a40084c1 100644 --- a/src/js/apps/artist/artist_app.js +++ b/src/js/apps/artist/artist_app.js @@ -1,51 +1,70 @@ -@Kodi.module "ArtistApp", (ArtistApp, App, Backbone, Marionette, $, _) -> - - class ArtistApp.Router extends App.Router.Base - appRoutes: - "music/artists" : "list" - "music/artist/:id" : "view" - - API = - - list: -> - new ArtistApp.List.Controller() - - view: (id) -> - new ArtistApp.Show.Controller - id: id - - action: (op, view) -> - model = view.model - playlist = App.request "command:kodi:controller", 'audio', 'PlayList' - switch op - when 'play' - App.execute "command:audio:play", 'artistid', model.get('artistid') - when 'add' - playlist.add 'artistid', model.get('artistid') - when 'localadd' - App.execute "localplaylist:addentity", 'artistid', model.get('artistid') - when 'localplay' - localPlaylist = App.request "command:local:controller", 'audio', 'PlayList' - localPlaylist.play 'artistid', model.get('artistid') - else - ## nothing - - - App.on "before:start", -> - new ArtistApp.Router - controller: API - - App.commands.setHandler 'artist:action', (op, model) -> - API.action op, model - - App.reqres.setHandler 'artist:action:items', -> - { - actions: {thumbs: tr('Thumbs up')} - menu: {add: tr('Queue in Kodi'), 'divider-1': '', localadd: tr('Add to playlist'), localplay: tr('Play in browser'), 'divider-1': '', edit: tr('Edit')} +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp", function(ArtistApp, App, Backbone, Marionette, $, _) { + + const Cls = (ArtistApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "music/artists" : "list", + "music/artist/:id" : "view" + }; + } + }); + Cls.initClass(); + + const API = { + + list() { + return new ArtistApp.List.Controller(); + }, + + view(id) { + return new ArtistApp.Show.Controller({ + id}); + }, + + action(op, view) { + const { + model + } = view; + const playlist = App.request("command:kodi:controller", 'audio', 'PlayList'); + switch (op) { + case 'play': + return App.execute("command:audio:play", 'artistid', model.get('artistid')); + case 'add': + return playlist.add('artistid', model.get('artistid')); + case 'localadd': + return App.execute("localplaylist:addentity", 'artistid', model.get('artistid')); + case 'localplay': + var localPlaylist = App.request("command:local:controller", 'audio', 'PlayList'); + return localPlaylist.play('artistid', model.get('artistid')); + default: + } } + }; + //# nothing + + + App.on("before:start", () => new ArtistApp.Router({ + controller: API})); + + App.commands.setHandler('artist:action', (op, model) => API.action(op, model)); + + App.reqres.setHandler('artist:action:items', () => ({ + actions: {thumbs: tr('Thumbs up')}, + menu: {add: tr('Queue in Kodi'), 'divider-1': '', localadd: tr('Add to playlist'), localplay: tr('Play in browser'), 'divider-1': '', edit: tr('Edit')} + })); - App.commands.setHandler 'artist:edit', (model) -> - loadedModel = App.request "artist:entity", model.get('id') - App.execute "when:entity:fetched", loadedModel, => - new ArtistApp.Edit.Controller - model: loadedModel + return App.commands.setHandler('artist:edit', function(model) { + const loadedModel = App.request("artist:entity", model.get('id')); + return App.execute("when:entity:fetched", loadedModel, () => { + return new ArtistApp.Edit.Controller({ + model: loadedModel}); + }); + }); +}); diff --git a/src/js/apps/artist/edit/edit_controller.js b/src/js/apps/artist/edit/edit_controller.js index 77d217fb..cff87eda 100644 --- a/src/js/apps/artist/edit/edit_controller.js +++ b/src/js/apps/artist/edit/edit_controller.js @@ -1,27 +1,37 @@ -@Kodi.module "ArtistApp.Edit", (Edit, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp.Edit", function(Edit, App, Backbone, Marionette, $, _) { - class Edit.Controller extends App.Controllers.Base + return Edit.Controller = class Controller extends App.Controllers.Base { - initialize: -> - @model = @getOption('model') - options = { - titleHtml: '' + tr('Edit') + '' + @model.escape('artist') - form: @getStructure() - formState: @model.attributes - config: - attributes: {class: 'edit-form'} - editForm: true - tabs: true - callback: (data, formView) => - @saveCallback(data, formView) - } - form = App.request "form:popup:wrapper", options + initialize() { + let form; + this.model = this.getOption('model'); + const options = { + titleHtml: '' + tr('Edit') + '' + this.model.escape('artist'), + form: this.getStructure(), + formState: this.model.attributes, + config: { + attributes: {class: 'edit-form'}, + editForm: true, + tabs: true, + callback: (data, formView) => { + return this.saveCallback(data, formView); + } + } + }; + return form = App.request("form:popup:wrapper", options); + } - getStructure: -> - [ + getStructure() { + return [ { - title: 'General' - id: 'general' + title: 'General', + id: 'general', children:[ {id: 'artist', title: tr('Title'), type: 'textfield'}, {id: 'description', title: tr('Description'), type: 'textarea'}, @@ -31,10 +41,10 @@ {id: 'died', title: tr('Died'), type: 'textfield', attributes: {class: 'half-width'}, suffix: '
'}, {id: 'yearsactive', title: tr('Years Active'), type: 'textfield', format: 'array.string'}, ] - } + }, { - title: 'Tags' - id: 'tags' + title: 'Tags', + id: 'tags', children:[ {id: 'genre', title: tr('Genres'), type: 'textfield', format: 'array.string'}, {id: 'style', title: tr('Styles'), type: 'textfield', format: 'array.string'}, @@ -42,11 +52,16 @@ {id: 'mood', title: tr('Moods'), type: 'textarea', format: 'array.string'}, ] } - ] + ]; + } - ## Save the settings to Kodi - saveCallback: (data, formView) -> - controller = App.request "command:kodi:controller", 'audio', 'AudioLibrary' - controller.setArtistDetails @model.get('id'), data, => - Kodi.vent.trigger 'entity:kodi:update', @model.get('uid') - Kodi.execute "notification:show", t.sprintf(tr("Updated %1$s details"), 'album') + //# Save the settings to Kodi + saveCallback(data, formView) { + const controller = App.request("command:kodi:controller", 'audio', 'AudioLibrary'); + return controller.setArtistDetails(this.model.get('id'), data, () => { + Kodi.vent.trigger('entity:kodi:update', this.model.get('uid')); + return Kodi.execute("notification:show", t.sprintf(tr("Updated %1$s details"), 'album')); + }); + } + }; +}); diff --git a/src/js/apps/artist/list/list_controller.js b/src/js/apps/artist/list/list_controller.js index 46c87bb6..f9eb25bc 100644 --- a/src/js/apps/artist/list/list_controller.js +++ b/src/js/apps/artist/list/list_controller.js @@ -1,76 +1,91 @@ -@Kodi.module "ArtistApp.List", (List, App, Backbone, Marionette, $, _) -> - - API = - - bindTriggers: (view) -> - App.listenTo view, 'childview:artist:play', (list, item) -> - App.execute 'artist:action', 'play', item - App.listenTo view, 'childview:artist:add', (list, item) -> - App.execute 'artist:action', 'add', item - App.listenTo view, 'childview:artist:localadd', (list, item) -> - App.execute 'artist:action', 'localadd', item - App.listenTo view, 'childview:artist:localplay', (list, item) -> - App.execute 'artist:action', 'localplay', item - App.listenTo view, 'childview:artist:edit', (parent, item) -> - App.execute 'artist:edit', item.model - - getArtistList: (collection) -> - view = new List.Artists - collection: collection - API.bindTriggers view - view - - - ## Main controller - class List.Controller extends App.Controllers.Base - - initialize: -> - collection = App.request "artist:entities" - App.execute "when:entity:fetched", collection, => - - ## Set available filters - collection.availableFilters = @getAvailableFilters() - - ## Top level menu path for filters - collection.sectionId = 'music' - - ## If present set initial filter via url - App.request 'filter:init', @getAvailableFilters() - - @layout = @getLayoutView collection - - @listenTo @layout, "show", => - @renderList collection - @getFiltersView collection - - App.regionContent.show @layout - - getLayoutView: (collection) -> - new List.ListLayout - collection: collection - - ## Available sort and filter options - ## See filter_app.js for available options - getAvailableFilters: -> - sort: ['label', 'random'] - filter: ['mood', 'genre', 'style', 'thumbsUp'] - - ## Apply filter view and provide a handler for applying changes - getFiltersView: (collection) -> - filters = App.request 'filter:show', collection - @layout.regionSidebarFirst.show filters - ## Listen to when the filters change and re-render. - @listenTo filters, "filter:changed", => - @renderList collection - - ## Get the list view with filters applied. - renderList: (collection) -> - App.execute "loading:show:view", @layout.regionContent - filteredCollection = App.request 'filter:apply:entities', collection - view = API.getArtistList filteredCollection - @layout.regionContent.show view - - - ## handler for other modules to get a list view. - App.reqres.setHandler "artist:list:view", (collection) -> - API.getArtistList collection +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp.List", function(List, App, Backbone, Marionette, $, _) { + + var API = { + + bindTriggers(view) { + App.listenTo(view, 'childview:artist:play', (list, item) => App.execute('artist:action', 'play', item)); + App.listenTo(view, 'childview:artist:add', (list, item) => App.execute('artist:action', 'add', item)); + App.listenTo(view, 'childview:artist:localadd', (list, item) => App.execute('artist:action', 'localadd', item)); + App.listenTo(view, 'childview:artist:localplay', (list, item) => App.execute('artist:action', 'localplay', item)); + return App.listenTo(view, 'childview:artist:edit', (parent, item) => App.execute('artist:edit', item.model)); + }, + + getArtistList(collection) { + const view = new List.Artists({ + collection}); + API.bindTriggers(view); + return view; + } + }; + + + //# Main controller + List.Controller = class Controller extends App.Controllers.Base { + + initialize() { + const collection = App.request("artist:entities"); + return App.execute("when:entity:fetched", collection, () => { + + //# Set available filters + collection.availableFilters = this.getAvailableFilters(); + + //# Top level menu path for filters + collection.sectionId = 'music'; + + //# If present set initial filter via url + App.request('filter:init', this.getAvailableFilters()); + + this.layout = this.getLayoutView(collection); + + this.listenTo(this.layout, "show", () => { + this.renderList(collection); + return this.getFiltersView(collection); + }); + + return App.regionContent.show(this.layout); + }); + } + + getLayoutView(collection) { + return new List.ListLayout({ + collection}); + } + + //# Available sort and filter options + //# See filter_app.js for available options + getAvailableFilters() { + return { + sort: ['label', 'random'], + filter: ['mood', 'genre', 'style', 'thumbsUp'] + }; + } + + //# Apply filter view and provide a handler for applying changes + getFiltersView(collection) { + const filters = App.request('filter:show', collection); + this.layout.regionSidebarFirst.show(filters); + //# Listen to when the filters change and re-render. + return this.listenTo(filters, "filter:changed", () => { + return this.renderList(collection); + }); + } + + //# Get the list view with filters applied. + renderList(collection) { + App.execute("loading:show:view", this.layout.regionContent); + const filteredCollection = App.request('filter:apply:entities', collection); + const view = API.getArtistList(filteredCollection); + return this.layout.regionContent.show(view); + } + }; + + + //# handler for other modules to get a list view. + return App.reqres.setHandler("artist:list:view", collection => API.getArtistList(collection)); +}); diff --git a/src/js/apps/artist/list/list_view.js b/src/js/apps/artist/list/list_view.js index 4f5b6dd5..ebe17d11 100644 --- a/src/js/apps/artist/list/list_view.js +++ b/src/js/apps/artist/list/list_view.js @@ -1,27 +1,58 @@ -@Kodi.module "ArtistApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.ListLayout extends App.Views.LayoutWithSidebarFirstView - className: "artist-list with-filters" + let Cls = (List.ListLayout = class ListLayout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "artist-list with-filters"; + } + }); + Cls.initClass(); - class List.ArtistTeaser extends App.Views.CardView - triggers: - "click .play" : "artist:play" - "click .dropdown .add" : "artist:add" - "click .dropdown .localadd" : "artist:localadd" - "click .dropdown .localplay" : "artist:localplay" - "click .dropdown .edit" : "artist:edit" + Cls = (List.ArtistTeaser = class ArtistTeaser extends App.Views.CardView { + static initClass() { + this.prototype.triggers = { + "click .play" : "artist:play", + "click .dropdown .add" : "artist:add", + "click .dropdown .localadd" : "artist:localadd", + "click .dropdown .localplay" : "artist:localplay", + "click .dropdown .edit" : "artist:edit" + }; + } - initialize: -> - super arguments... - if @model? - @model.set(App.request('album:action:items')) + initialize() { + super.initialize(...arguments); + if (this.model != null) { + return this.model.set(App.request('album:action:items')); + } + } + }); + Cls.initClass(); - class List.Empty extends App.Views.EmptyViewResults - tagName: "li" - className: "artist-empty-result" + Cls = (List.Empty = class Empty extends App.Views.EmptyViewResults { + static initClass() { + this.prototype.tagName = "li"; + this.prototype.className = "artist-empty-result"; + } + }); + Cls.initClass(); - class List.Artists extends App.Views.VirtualListView - childView: List.ArtistTeaser - emptyView: List.Empty - tagName: "ul" - className: "card-grid--wide" + return (function() { + Cls = (List.Artists = class Artists extends App.Views.VirtualListView { + static initClass() { + this.prototype.childView = List.ArtistTeaser; + this.prototype.emptyView = List.Empty; + this.prototype.tagName = "ul"; + this.prototype.className = "card-grid--wide"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/artist/show/show_controller.js b/src/js/apps/artist/show/show_controller.js index f372d949..8ca51416 100644 --- a/src/js/apps/artist/show/show_controller.js +++ b/src/js/apps/artist/show/show_controller.js @@ -1,71 +1,86 @@ -@Kodi.module "ArtistApp.Show", (Show, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp.Show", function(Show, App, Backbone, Marionette, $, _) { - API = + const API = { - bindTriggers: (view) -> - App.listenTo view, 'artist:play', (item) -> - App.execute 'artist:action', 'play', item - App.listenTo view, 'artist:add', (item) -> - App.execute 'artist:action', 'add', item - App.listenTo view, 'artist:localadd', (item) -> - App.execute 'artist:action', 'localadd', item - App.listenTo view, 'artist:localplay', (item) -> - App.execute 'artist:action', 'localplay', item - App.listenTo view, 'artist:edit', (item) -> - App.execute 'artist:edit', item.model + bindTriggers(view) { + App.listenTo(view, 'artist:play', item => App.execute('artist:action', 'play', item)); + App.listenTo(view, 'artist:add', item => App.execute('artist:action', 'add', item)); + App.listenTo(view, 'artist:localadd', item => App.execute('artist:action', 'localadd', item)); + App.listenTo(view, 'artist:localplay', item => App.execute('artist:action', 'localplay', item)); + return App.listenTo(view, 'artist:edit', item => App.execute('artist:edit', item.model)); + } + }; - class Show.Controller extends App.Controllers.Base + return Show.Controller = class Controller extends App.Controllers.Base { - ## The Artist page. - initialize: (options) -> - id = parseInt options.id - artist = App.request "artist:entity", id + //# The Artist page. + initialize(options) { + const id = parseInt(options.id); + const artist = App.request("artist:entity", id); - ## Fetch the artist - App.execute "when:entity:fetched", artist, => - ## Get the layout. - @layout = @getLayoutView artist - ## Ensure background removed when we leave. - @listenTo @layout, "destroy", => - App.execute "images:fanart:set", 'none' - ## Listen to the show of our layout. - @listenTo @layout, "show", => - @getMusic id - @getDetailsLayoutView artist - ## Add the layout to content. - App.regionContent.show @layout + //# Fetch the artist + return App.execute("when:entity:fetched", artist, () => { + //# Get the layout. + this.layout = this.getLayoutView(artist); + //# Ensure background removed when we leave. + this.listenTo(this.layout, "destroy", () => { + return App.execute("images:fanart:set", 'none'); + }); + //# Listen to the show of our layout. + this.listenTo(this.layout, "show", () => { + this.getMusic(id); + return this.getDetailsLayoutView(artist); + }); + //# Add the layout to content. + return App.regionContent.show(this.layout); + }); + } - ## Get the base layout - getLayoutView: (artist) -> - new Show.PageLayout - model: artist + //# Get the base layout + getLayoutView(artist) { + return new Show.PageLayout({ + model: artist}); + } - ## Build the details layout. - getDetailsLayoutView: (artist) -> - headerLayout = new Show.HeaderLayout model: artist - @listenTo headerLayout, "show", => - teaser = new Show.ArtistTeaser model: artist - API.bindTriggers teaser - detail = new Show.Details model: artist - @listenTo detail, "show", => - API.bindTriggers detail - headerLayout.regionSide.show teaser - headerLayout.regionMeta.show detail - @layout.regionHeader.show headerLayout + //# Build the details layout. + getDetailsLayoutView(artist) { + const headerLayout = new Show.HeaderLayout({model: artist}); + this.listenTo(headerLayout, "show", () => { + const teaser = new Show.ArtistTeaser({model: artist}); + API.bindTriggers(teaser); + const detail = new Show.Details({model: artist}); + this.listenTo(detail, "show", () => { + return API.bindTriggers(detail); + }); + headerLayout.regionSide.show(teaser); + return headerLayout.regionMeta.show(detail); + }); + return this.layout.regionHeader.show(headerLayout); + } - ## Get a list of all the music for this artist parsed into albums. - getMusic: (id) -> - # Might take a while so show loader - loading = App.request "loading:get:view", tr('Loading albums') - @layout.regionContent.show loading - # Set artist id for fetch - options = - filter: {artistid: id} - # Get all the songs and parse them into separate album collections. - songs = App.request "song:entities", options - App.execute "when:entity:fetched", songs, => - songsCollections = App.request "song:albumparse:entities", songs - albumsCollection = App.request "albums:withsongs:view", songsCollections - @layout.regionContent.show albumsCollection + //# Get a list of all the music for this artist parsed into albums. + getMusic(id) { + // Might take a while so show loader + const loading = App.request("loading:get:view", tr('Loading albums')); + this.layout.regionContent.show(loading); + // Set artist id for fetch + const options = + {filter: {artistid: id}}; + // Get all the songs and parse them into separate album collections. + const songs = App.request("song:entities", options); + return App.execute("when:entity:fetched", songs, () => { + const songsCollections = App.request("song:albumparse:entities", songs); + const albumsCollection = App.request("albums:withsongs:view", songsCollections); + return this.layout.regionContent.show(albumsCollection); + }); + } + }; +}); diff --git a/src/js/apps/artist/show/show_view.js b/src/js/apps/artist/show/show_view.js index ef39d96f..3cd052a8 100644 --- a/src/js/apps/artist/show/show_view.js +++ b/src/js/apps/artist/show/show_view.js @@ -1,23 +1,53 @@ -@Kodi.module "ArtistApp.Show", (Show, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ArtistApp.Show", function(Show, App, Backbone, Marionette, $, _) { - class Show.PageLayout extends App.Views.LayoutWithHeaderView - className: 'artist-show detail-container' + let Cls = (Show.PageLayout = class PageLayout extends App.Views.LayoutWithHeaderView { + static initClass() { + this.prototype.className = 'artist-show detail-container'; + } + }); + Cls.initClass(); - class Show.HeaderLayout extends App.Views.LayoutDetailsHeaderView - className: 'artist-details' + Cls = (Show.HeaderLayout = class HeaderLayout extends App.Views.LayoutDetailsHeaderView { + static initClass() { + this.prototype.className = 'artist-details'; + } + }); + Cls.initClass(); - class Show.Details extends App.Views.DetailsItem - template: 'apps/artist/show/details_meta' - triggers: - "click .play" : "artist:play" - "click .add" : "artist:add" - "click .localadd" : "artist:localadd" - "click .localplay" : "artist:localplay" - "click .edit" : "artist:edit" + Cls = (Show.Details = class Details extends App.Views.DetailsItem { + static initClass() { + this.prototype.template = 'apps/artist/show/details_meta'; + this.prototype.triggers = { + "click .play" : "artist:play", + "click .add" : "artist:add", + "click .localadd" : "artist:localadd", + "click .localplay" : "artist:localplay", + "click .edit" : "artist:edit" + }; + } + }); + Cls.initClass(); - class Show.ArtistTeaser extends App.ArtistApp.List.ArtistTeaser - tagName: "div" - initialize: -> - @model.set(actions: {thumbs: tr('Thumbs up')}) - attributes: -> - @watchedAttributes 'card-detail' + return (function() { + Cls = (Show.ArtistTeaser = class ArtistTeaser extends App.ArtistApp.List.ArtistTeaser { + static initClass() { + this.prototype.tagName = "div"; + } + initialize() { + return this.model.set({actions: {thumbs: tr('Thumbs up')}}); + } + attributes() { + return this.watchedAttributes('card-detail'); + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/audioStream/init.js b/src/js/apps/audioStream/init.js index 2a8a748f..042fa7e2 100644 --- a/src/js/apps/audioStream/init.js +++ b/src/js/apps/audioStream/init.js @@ -1,24 +1,31 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ -## Soundmanager config. -## Must be run before app init +//# Soundmanager config. +//# Must be run before app init soundManager.setup({ - url: 'lib/soundmanager/swf/' - flashVersion: 9 - preferFlash: true - useHTML5Audio: true - useFlashBlock: false - flashLoadTimeout: 3000 - debugMode: false - noSWFCache: true - debugFlash: false - flashPollingInterval: 1000 - html5PollingInterval: 1000 - onready: -> - $(window).trigger 'audiostream:ready' - ontimeout: -> - $(window).trigger 'audiostream:timeout' - soundManager.flashLoadTimeout = 0 # When restarting, wait indefinitely for flash - soundManager.onerror = {} # Prevent an infinite loop, in case it's not flashblock - soundManager.reboot() # Reboot -}) + url: 'lib/soundmanager/swf/', + flashVersion: 9, + preferFlash: true, + useHTML5Audio: true, + useFlashBlock: false, + flashLoadTimeout: 3000, + debugMode: false, + noSWFCache: true, + debugFlash: false, + flashPollingInterval: 1000, + html5PollingInterval: 1000, + onready() { + return $(window).trigger('audiostream:ready'); + }, + ontimeout() { + $(window).trigger('audiostream:timeout'); + soundManager.flashLoadTimeout = 0; // When restarting, wait indefinitely for flash + soundManager.onerror = {}; // Prevent an infinite loop, in case it's not flashblock + return soundManager.reboot(); + } // Reboot +}); diff --git a/src/js/apps/browser/browser_app.js b/src/js/apps/browser/browser_app.js index 463c57d3..b51d482a 100644 --- a/src/js/apps/browser/browser_app.js +++ b/src/js/apps/browser/browser_app.js @@ -1,23 +1,39 @@ -@Kodi.module "BrowserApp", (BrowserApp, App, Backbone, Marionette, $, _) -> - - class BrowserApp.Router extends App.Router.Base - appRoutes: - "browser" : "list" - "browser/:media/:id" : "view" - - API = - - list: -> - new BrowserApp.List.Controller - - view: (media, id) -> - new BrowserApp.List.Controller - media: media - id: id - - - App.on "before:start", -> - new BrowserApp.Router - controller: API +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("BrowserApp", function(BrowserApp, App, Backbone, Marionette, $, _) { + + const Cls = (BrowserApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "browser" : "list", + "browser/:media/:id" : "view" + }; + } + }); + Cls.initClass(); + + const API = { + + list() { + return new BrowserApp.List.Controller; + }, + + view(media, id) { + return new BrowserApp.List.Controller({ + media, + id + }); + } + }; + + + return App.on("before:start", () => new BrowserApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/browser/list/list_controller.js b/src/js/apps/browser/list/list_controller.js index 538d8499..7e4a9d55 100644 --- a/src/js/apps/browser/list/list_controller.js +++ b/src/js/apps/browser/list/list_controller.js @@ -1,174 +1,232 @@ -@Kodi.module "BrowserApp.List", (List, App, Backbone, Marionette, $, _) -> - - API = - - bindFileTriggers: (view) -> - App.listenTo view, 'childview:file:play', (set, item) => - playlist = App.request "command:kodi:controller", item.model.get('player'), 'PlayList' - playlist.play 'file', item.model.get('file') - App.listenTo view, 'childview:file:queue', (set, item) => - playlist = App.request "command:kodi:controller", item.model.get('player'), 'PlayList' - playlist.add 'file', item.model.get('file') - App.listenTo view, 'childview:file:download', (set, item) => - App.request("command:kodi:controller", 'auto', 'Files').downloadFile item.model.get('file') - - bindFolderTriggers: (view) -> - App.listenTo view, 'childview:folder:play', (set, item) => - App.request("command:kodi:controller", item.model.get('player'), 'PlayList').play 'directory', item.model.get('file') - App.listenTo view, 'childview:folder:queue', (set, item) => - App.request("command:kodi:controller", item.model.get('player'), 'PlayList').add 'directory', item.model.get('file') - - getFileListView: (collection) -> - fileView = new List.FileList - collection: collection - API.bindFileTriggers(fileView) - fileView - - getFolderListView: (collection) -> - folderView = new List.FolderList - collection: collection - App.listenTo folderView, 'childview:folder:open', (set, item) => - App.navigate item.model.get('url'), {trigger: true} - API.bindFolderTriggers folderView - folderView - - - - class List.Controller extends App.Controllers.Base - - sourceCollection: {} - backButtonModel: {} - - initialize: (options = {}) -> - @layout = @getLayout() - @listenTo @layout, "show", => - @getSources(options) - @getFolderLayout() - App.regionContent.show @layout - - getLayout: -> - new List.ListLayout() - - getFolderLayout: -> - options = {sortSettings: @getSort()} - @folderLayout = new List.FolderLayout options - @listenTo @folderLayout, 'browser:sort', (sort, $el) => - @setSort sort, $el - @listenTo @folderLayout, 'browser:play', (view) => - if @model - App.request("command:kodi:controller", @model.get('player'), 'PlayList').play 'directory', @model.get('file') - @listenTo @folderLayout, 'browser:queue', (view) => - if @model - App.request("command:kodi:controller", @model.get('player'), 'PlayList').add 'directory', @model.get('file') - @layout.regionContent.show @folderLayout - - setSort: (sort, $el) -> - sortSettings = @getSort() - if sortSettings.method is sort - sortSettings.order = if sortSettings.order is 'ascending' then 'descending' else 'ascending' - if $el - $el.removeClassStartsWith('order-').addClass('order-' + sortSettings.order).addClass 'active' - sortSettings.method = sort - if sortSettings.method - config.set 'app', 'browserSort', sortSettings - if @model - @getFolder @model - - getSort: -> - config.get('app', 'browserSort', {method: 'none', order: 'ascending'}) - - - ## Get the source lists - getSources: (options) -> - sources = App.request "file:source:entities", 'video' - App.execute "when:entity:fetched", sources, => - ## Store the sources collection for later - @sourceCollection = sources - ## Parse into sets - sets = App.request "file:source:media:entities", sources - setView = new List.SourcesSet({collection: sets}) - @layout.regionSidebarFirst.show setView - @listenTo setView, 'childview:childview:source:open', (set, item) => - @getFolder(item.model) - @loadFromUrl(options) - - loadFromUrl: (options) -> - if options.media and options.id - model = App.request "file:url:entity", options.media, options.id - @getFolder model - - getFolder: (model) -> - @model = model - ## Do a virtual navigate and load up the folder view - App.navigate model.get('url') - ## Get the collection - sortSettings = @getSort() - collection = App.request "file:entities", {file: model.get('file'), media: model.get('media'), sort: sortSettings} - pathCollection = App.request "file:path:entities", model.get('file'), @sourceCollection - @getPathList pathCollection - App.execute "when:entity:fetched", collection, => - ## parse and render - collections = App.request "file:parsed:entities", collection - @getFolderList(collections.directory) - @getFileList(collections.file) - - getFolderListView: (collection) -> - folderView = new List.FolderList - collection: collection - @listenTo folderView, 'childview:folder:open', (set, item) => - @getFolder item.model - API.bindFolderTriggers folderView - folderView - - getFolderList: (collection) -> - @folderLayout.regionFolders.show @getFolderListView(collection) - @getBackButton() - - getFileListView: (collection) -> - API.getFileListView collection - - getFileList: (collection) -> - @folderLayout.regionFiles.show @getFileListView(collection) - - getPathList: (collection) -> - pathView = new List.PathList - collection: collection - @folderLayout.regionPath.show pathView - @setBackModel collection - @listenTo pathView, 'childview:folder:open', (set, item) => - @getFolder item.model - - setBackModel: (pathCollection) -> - # Back button should be the second last model - if pathCollection.length >= 2 - @backButtonModel = pathCollection.models[pathCollection.length - 2] - else - @backButtonModel = {} - - getBackButton: -> - if @backButtonModel.attributes - backView = new List.Back - model: @backButtonModel - @folderLayout.regionBack.show backView - @listenTo backView, 'folder:open', (model) => - @getFolder model.model - else - @folderLayout.regionBack.empty() - - # Get view with a collection of files only - getFileViewByPath: (path, media, callback) -> - collection = App.request "file:entities", {file: path, media: media} - App.execute "when:entity:fetched", collection, => - view = @getFileListView collection - if callback - callback view - - - # Get view with a collection of files only - App.reqres.setHandler "browser:file:view", (collection) -> - API.getFileListView collection - - # Get view with a collection of files only - App.reqres.setHandler "browser:directory:view", (collection) -> - API.getFolderListView collection +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("BrowserApp.List", function(List, App, Backbone, Marionette, $, _) { + + var API = { + + bindFileTriggers(view) { + App.listenTo(view, 'childview:file:play', (set, item) => { + const playlist = App.request("command:kodi:controller", item.model.get('player'), 'PlayList'); + return playlist.play('file', item.model.get('file')); + }); + App.listenTo(view, 'childview:file:queue', (set, item) => { + const playlist = App.request("command:kodi:controller", item.model.get('player'), 'PlayList'); + return playlist.add('file', item.model.get('file')); + }); + return App.listenTo(view, 'childview:file:download', (set, item) => { + return App.request("command:kodi:controller", 'auto', 'Files').downloadFile(item.model.get('file')); + }); + }, + + bindFolderTriggers(view) { + App.listenTo(view, 'childview:folder:play', (set, item) => { + return App.request("command:kodi:controller", item.model.get('player'), 'PlayList').play('directory', item.model.get('file')); + }); + return App.listenTo(view, 'childview:folder:queue', (set, item) => { + return App.request("command:kodi:controller", item.model.get('player'), 'PlayList').add('directory', item.model.get('file')); + }); + }, + + getFileListView(collection) { + const fileView = new List.FileList({ + collection}); + API.bindFileTriggers(fileView); + return fileView; + }, + + getFolderListView(collection) { + const folderView = new List.FolderList({ + collection}); + App.listenTo(folderView, 'childview:folder:open', (set, item) => { + return App.navigate(item.model.get('url'), {trigger: true}); + }); + API.bindFolderTriggers(folderView); + return folderView; + } + }; + + + + const Cls = (List.Controller = class Controller extends App.Controllers.Base { + static initClass() { + + this.prototype.sourceCollection = {}; + this.prototype.backButtonModel = {}; + } + + initialize(options = {}) { + this.layout = this.getLayout(); + this.listenTo(this.layout, "show", () => { + this.getSources(options); + return this.getFolderLayout(); + }); + return App.regionContent.show(this.layout); + } + + getLayout() { + return new List.ListLayout(); + } + + getFolderLayout() { + const options = {sortSettings: this.getSort()}; + this.folderLayout = new List.FolderLayout(options); + this.listenTo(this.folderLayout, 'browser:sort', (sort, $el) => { + return this.setSort(sort, $el); + }); + this.listenTo(this.folderLayout, 'browser:play', view => { + if (this.model) { + return App.request("command:kodi:controller", this.model.get('player'), 'PlayList').play('directory', this.model.get('file')); + } + }); + this.listenTo(this.folderLayout, 'browser:queue', view => { + if (this.model) { + return App.request("command:kodi:controller", this.model.get('player'), 'PlayList').add('directory', this.model.get('file')); + } + }); + return this.layout.regionContent.show(this.folderLayout); + } + + setSort(sort, $el) { + const sortSettings = this.getSort(); + if (sortSettings.method === sort) { + sortSettings.order = sortSettings.order === 'ascending' ? 'descending' : 'ascending'; + } + if ($el) { + $el.removeClassStartsWith('order-').addClass('order-' + sortSettings.order).addClass('active'); + } + sortSettings.method = sort; + if (sortSettings.method) { + config.set('app', 'browserSort', sortSettings); + } + if (this.model) { + return this.getFolder(this.model); + } + } + + getSort() { + return config.get('app', 'browserSort', {method: 'none', order: 'ascending'}); + } + + + //# Get the source lists + getSources(options) { + const sources = App.request("file:source:entities", 'video'); + return App.execute("when:entity:fetched", sources, () => { + //# Store the sources collection for later + this.sourceCollection = sources; + //# Parse into sets + const sets = App.request("file:source:media:entities", sources); + const setView = new List.SourcesSet({collection: sets}); + this.layout.regionSidebarFirst.show(setView); + this.listenTo(setView, 'childview:childview:source:open', (set, item) => { + return this.getFolder(item.model); + }); + return this.loadFromUrl(options); + }); + } + + loadFromUrl(options) { + if (options.media && options.id) { + const model = App.request("file:url:entity", options.media, options.id); + return this.getFolder(model); + } + } + + getFolder(model) { + this.model = model; + //# Do a virtual navigate and load up the folder view + App.navigate(model.get('url')); + //# Get the collection + const sortSettings = this.getSort(); + const collection = App.request("file:entities", {file: model.get('file'), media: model.get('media'), sort: sortSettings}); + const pathCollection = App.request("file:path:entities", model.get('file'), this.sourceCollection); + this.getPathList(pathCollection); + return App.execute("when:entity:fetched", collection, () => { + //# parse and render + const collections = App.request("file:parsed:entities", collection); + this.getFolderList(collections.directory); + return this.getFileList(collections.file); + }); + } + + getFolderListView(collection) { + const folderView = new List.FolderList({ + collection}); + this.listenTo(folderView, 'childview:folder:open', (set, item) => { + return this.getFolder(item.model); + }); + API.bindFolderTriggers(folderView); + return folderView; + } + + getFolderList(collection) { + this.folderLayout.regionFolders.show(this.getFolderListView(collection)); + return this.getBackButton(); + } + + getFileListView(collection) { + return API.getFileListView(collection); + } + + getFileList(collection) { + return this.folderLayout.regionFiles.show(this.getFileListView(collection)); + } + + getPathList(collection) { + const pathView = new List.PathList({ + collection}); + this.folderLayout.regionPath.show(pathView); + this.setBackModel(collection); + return this.listenTo(pathView, 'childview:folder:open', (set, item) => { + return this.getFolder(item.model); + }); + } + + setBackModel(pathCollection) { + // Back button should be the second last model + if (pathCollection.length >= 2) { + return this.backButtonModel = pathCollection.models[pathCollection.length - 2]; + } else { + return this.backButtonModel = {}; + } + } + + getBackButton() { + if (this.backButtonModel.attributes) { + const backView = new List.Back({ + model: this.backButtonModel}); + this.folderLayout.regionBack.show(backView); + return this.listenTo(backView, 'folder:open', model => { + return this.getFolder(model.model); + }); + } else { + return this.folderLayout.regionBack.empty(); + } + } + + // Get view with a collection of files only + getFileViewByPath(path, media, callback) { + const collection = App.request("file:entities", {file: path, media}); + return App.execute("when:entity:fetched", collection, () => { + const view = this.getFileListView(collection); + if (callback) { + return callback(view); + } + }); + } + }); + Cls.initClass(); + + + // Get view with a collection of files only + App.reqres.setHandler("browser:file:view", collection => API.getFileListView(collection)); + + // Get view with a collection of files only + return App.reqres.setHandler("browser:directory:view", collection => API.getFolderListView(collection)); +}); diff --git a/src/js/apps/browser/list/list_view.js b/src/js/apps/browser/list/list_view.js index bbe8bdbd..c63afc4a 100644 --- a/src/js/apps/browser/list/list_view.js +++ b/src/js/apps/browser/list/list_view.js @@ -1,141 +1,224 @@ -@Kodi.module "BrowserApp.List", (List, App, Backbone, Marionette, $, _) -> - - class List.ListLayout extends App.Views.LayoutWithSidebarFirstView - className: "browser-page" - - - ### +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("BrowserApp.List", function(List, App, Backbone, Marionette, $, _) { + + let Cls = (List.ListLayout = class ListLayout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "browser-page"; + } + }); + Cls.initClass(); + + + /* Sources - ### - - class List.Source extends App.Views.ItemView - template: 'apps/browser/list/source' - tagName: 'li' - triggers: - 'click .source' : 'source:open' - attributes: -> - { - class: 'type-' + @model.get('sourcetype') - } - - ## Our composite view allows adding another view via the 'childViewContainer' el - ## which is in the template - class List.Sources extends App.Views.CompositeView - template: 'apps/browser/list/source_set' - childView: List.Source - tagName: "div" - childViewContainer: 'ul.sources' - className: "source-set" - initialize: -> - ## We need to tell the child view where to get its collection - @collection = @model.get('sources') - - class List.SourcesSet extends App.Views.CollectionView - childView: List.Sources - tagName: "div" - className: "sources-sets" - - - ### + */ + + Cls = (List.Source = class Source extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/browser/list/source'; + this.prototype.tagName = 'li'; + this.prototype.triggers = + {'click .source' : 'source:open'}; + } + attributes() { + return { + class: 'type-' + this.model.get('sourcetype') + }; + } + }); + Cls.initClass(); + + //# Our composite view allows adding another view via the 'childViewContainer' el + //# which is in the template + Cls = (List.Sources = class Sources extends App.Views.CompositeView { + static initClass() { + this.prototype.template = 'apps/browser/list/source_set'; + this.prototype.childView = List.Source; + this.prototype.tagName = "div"; + this.prototype.childViewContainer = 'ul.sources'; + this.prototype.className = "source-set"; + } + initialize() { + //# We need to tell the child view where to get its collection + return this.collection = this.model.get('sources'); + } + }); + Cls.initClass(); + + Cls = (List.SourcesSet = class SourcesSet extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = List.Sources; + this.prototype.tagName = "div"; + this.prototype.className = "sources-sets"; + } + }); + Cls.initClass(); + + + /* Folder - ### - - class List.FolderLayout extends App.Views.LayoutView - template: 'apps/browser/list/folder_layout' - className: "folder-page-wrapper" - regions: - regionPath: '.path' - regionFolders: '.folders' - regionFiles: '.files' - regionBack: '.back' - triggers: - 'click .play' : 'browser:play' - 'click .queue' : 'browser:queue' - events: - 'click .sorts li' : 'sortList' - sortList: (e) -> - $('.sorts li', @$el).removeClass 'active' - @trigger 'browser:sort', $(e.target).data('sort'), $(e.target) - onRender: -> - $('.sorts li', @$el).addClass 'order-' + @options.sortSettings.order - $('.sorts li[data-sort=' + @options.sortSettings.method + ']', @$el).addClass 'active' - - - class List.Item extends App.Views.ItemView - template: 'apps/browser/list/file' - tagName: 'li' - initialize: -> - # Parse title text - @model.set {labelHtml: @formatText(@model.get('label'))} - - onBeforeRender: -> - if !@model.get('labelHtml') - @model.set {labelHtml: @model.escape('label')} - - class List.Folder extends List.Item - className: 'folder' - triggers: - 'click .title' : 'folder:open' - 'dblclick .title' : 'file:play' - 'click .play' : 'folder:play' - 'click .queue' : 'folder:queue' - events: - "click .dropdown > i": "populateModelMenu" - initialize: -> - menu = {queue: tr('Queue in Kodi')} - @model.set({menu: menu}) - - class List.EmptyFiles extends App.Views.EmptyViewPage - tagName: 'li' - initialize: -> - @model.set({id: 'empty', content: t.gettext('no media in this folder')}) - - class List.File extends List.Item - className: 'file' - triggers: - 'click .play' : 'file:play' - 'dblclick .title' : 'file:play' - 'click .queue' : 'file:queue' - 'click .download' : 'file:download' - events: - "click .dropdown > i": "populateModelMenu" - initialize: -> - menu = {queue: tr('Queue in Kodi')} - if @model.get('filetype') is 'file' and @model.get('file').lastIndexOf('plugin://', 0) isnt 0 - menu.download = tr('Download') - @model.set({menu: menu}) - - - class List.FolderList extends App.Views.CollectionView - tagName: 'ul' - className: 'browser-folder-list' - childView: List.Folder - - class List.FileList extends App.Views.CollectionView - tagName: 'ul' - className: 'browser-file-list' - childView: List.File - emptyView: List.EmptyFiles - - ### + */ + + Cls = (List.FolderLayout = class FolderLayout extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/browser/list/folder_layout'; + this.prototype.className = "folder-page-wrapper"; + this.prototype.regions = { + regionPath: '.path', + regionFolders: '.folders', + regionFiles: '.files', + regionBack: '.back' + }; + this.prototype.triggers = { + 'click .play' : 'browser:play', + 'click .queue' : 'browser:queue' + }; + this.prototype.events = + {'click .sorts li' : 'sortList'}; + } + sortList(e) { + $('.sorts li', this.$el).removeClass('active'); + return this.trigger('browser:sort', $(e.target).data('sort'), $(e.target)); + } + onRender() { + $('.sorts li', this.$el).addClass('order-' + this.options.sortSettings.order); + return $('.sorts li[data-sort=' + this.options.sortSettings.method + ']', this.$el).addClass('active'); + } + }); + Cls.initClass(); + + + Cls = (List.Item = class Item extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/browser/list/file'; + this.prototype.tagName = 'li'; + } + initialize() { + // Parse title text + return this.model.set({labelHtml: this.formatText(this.model.get('label'))}); + } + + onBeforeRender() { + if (!this.model.get('labelHtml')) { + return this.model.set({labelHtml: this.model.escape('label')}); + } + } + }); + Cls.initClass(); + + Cls = (List.Folder = class Folder extends List.Item { + static initClass() { + this.prototype.className = 'folder'; + this.prototype.triggers = { + 'click .title' : 'folder:open', + 'dblclick .title' : 'file:play', + 'click .play' : 'folder:play', + 'click .queue' : 'folder:queue' + }; + this.prototype.events = + {"click .dropdown > i": "populateModelMenu"}; + } + initialize() { + const menu = {queue: tr('Queue in Kodi')}; + return this.model.set({menu}); + } + }); + Cls.initClass(); + + Cls = (List.EmptyFiles = class EmptyFiles extends App.Views.EmptyViewPage { + static initClass() { + this.prototype.tagName = 'li'; + } + initialize() { + return this.model.set({id: 'empty', content: t.gettext('no media in this folder')}); + } + }); + Cls.initClass(); + + Cls = (List.File = class File extends List.Item { + static initClass() { + this.prototype.className = 'file'; + this.prototype.triggers = { + 'click .play' : 'file:play', + 'dblclick .title' : 'file:play', + 'click .queue' : 'file:queue', + 'click .download' : 'file:download' + }; + this.prototype.events = + {"click .dropdown > i": "populateModelMenu"}; + } + initialize() { + const menu = {queue: tr('Queue in Kodi')}; + if ((this.model.get('filetype') === 'file') && (this.model.get('file').lastIndexOf('plugin://', 0) !== 0)) { + menu.download = tr('Download'); + } + return this.model.set({menu}); + } + }); + Cls.initClass(); + + + Cls = (List.FolderList = class FolderList extends App.Views.CollectionView { + static initClass() { + this.prototype.tagName = 'ul'; + this.prototype.className = 'browser-folder-list'; + this.prototype.childView = List.Folder; + } + }); + Cls.initClass(); + + Cls = (List.FileList = class FileList extends App.Views.CollectionView { + static initClass() { + this.prototype.tagName = 'ul'; + this.prototype.className = 'browser-file-list'; + this.prototype.childView = List.File; + this.prototype.emptyView = List.EmptyFiles; + } + }); + Cls.initClass(); + + /* Path - ### - - class List.Path extends App.Views.ItemView - template: 'apps/browser/list/path' - tagName: 'li' - triggers: - 'click .title' : 'folder:open' - - class List.PathList extends App.Views.CollectionView - tagName: 'ul' - childView: List.Path - - class List.Back extends App.Views.ItemView - template: 'apps/browser/list/back_button' - tagName: 'div' - className: 'back-button' - triggers: - 'click .title' : 'folder:open' - 'click i' : 'folder:open' + */ + + Cls = (List.Path = class Path extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/browser/list/path'; + this.prototype.tagName = 'li'; + this.prototype.triggers = + {'click .title' : 'folder:open'}; + } + }); + Cls.initClass(); + + Cls = (List.PathList = class PathList extends App.Views.CollectionView { + static initClass() { + this.prototype.tagName = 'ul'; + this.prototype.childView = List.Path; + } + }); + Cls.initClass(); + + return (function() { + Cls = (List.Back = class Back extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/browser/list/back_button'; + this.prototype.tagName = 'div'; + this.prototype.className = 'back-button'; + this.prototype.triggers = { + 'click .title' : 'folder:open', + 'click i' : 'folder:open' + }; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/cast/cast_app.js b/src/js/apps/cast/cast_app.js index 5e181e7e..85fd7e7f 100644 --- a/src/js/apps/cast/cast_app.js +++ b/src/js/apps/cast/cast_app.js @@ -1,21 +1,30 @@ -@Kodi.module "CastApp", (CastApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CastApp", function(CastApp, App, Backbone, Marionette, $, _) { - API = + const API = { - getCastCollection: (cast, origin) -> - App.request "cast:entities", cast, origin + getCastCollection(cast, origin) { + return App.request("cast:entities", cast, origin); + }, - getCastView: (collection) -> - view = new CastApp.List.CastList - collection: collection - App.listenTo view, 'childview:cast:google', (parent, child) -> - window.open('https://www.google.com/webhp?#q=' + encodeURIComponent(child.model.get('name'))) - App.listenTo view, 'childview:cast:imdb', (parent, child) -> - window.open('http://www.imdb.com/find?s=nm&q=' + encodeURIComponent(child.model.get('name'))) - view + getCastView(collection) { + const view = new CastApp.List.CastList({ + collection}); + App.listenTo(view, 'childview:cast:google', (parent, child) => window.open('https://www.google.com/webhp?#q=' + encodeURIComponent(child.model.get('name')))); + App.listenTo(view, 'childview:cast:imdb', (parent, child) => window.open('http://www.imdb.com/find?s=nm&q=' + encodeURIComponent(child.model.get('name')))); + return view; + } + }; - App.reqres.setHandler 'cast:list:view', (cast, origin) -> - collection = API.getCastCollection cast, origin - API.getCastView collection + return App.reqres.setHandler('cast:list:view', function(cast, origin) { + const collection = API.getCastCollection(cast, origin); + return API.getCastView(collection); + }); +}); diff --git a/src/js/apps/cast/list/list_view.js b/src/js/apps/cast/list/list_view.js index 3a774545..155a8b62 100644 --- a/src/js/apps/cast/list/list_view.js +++ b/src/js/apps/cast/list/list_view.js @@ -1,19 +1,42 @@ -@Kodi.module "CastApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CastApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.CastTeaser extends App.Views.ItemView - template: 'apps/cast/list/cast' - tagName: "li" - triggers: - "click .imdb" : "cast:imdb" - "click .google" : "cast:google" - onRender: -> - _.defer () -> - # Prevent broken images - defaultThumb = App.request "images:path:get", '' - $('img', @$el).on 'error', (e) -> - $(@).attr 'src', defaultThumb + let Cls = (List.CastTeaser = class CastTeaser extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/cast/list/cast'; + this.prototype.tagName = "li"; + this.prototype.triggers = { + "click .imdb" : "cast:imdb", + "click .google" : "cast:google" + }; + } + onRender() { + return _.defer(function() { + // Prevent broken images + const defaultThumb = App.request("images:path:get", ''); + return $('img', this.$el).on('error', function(e) { + return $(this).attr('src', defaultThumb); + }); + }); + } + }); + Cls.initClass(); - class List.CastList extends App.Views.CollectionView - childView: List.CastTeaser - tagName: "ul" - className: "cast-full" + return (function() { + Cls = (List.CastList = class CastList extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = List.CastTeaser; + this.prototype.tagName = "ul"; + this.prototype.className = "cast-full"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/category/category_app.js b/src/js/apps/category/category_app.js index 538b0efb..d14378d3 100644 --- a/src/js/apps/category/category_app.js +++ b/src/js/apps/category/category_app.js @@ -1,23 +1,37 @@ -@Kodi.module "CategoryApp", (CategoryApp, App, Backbone, Marionette, $, _) -> - - ## This is a generic app for category listings (eg Genres) - - class CategoryApp.Router extends App.Router.Base - appRoutes: - "music/genres" : "musicGenres" - - - API = - - musicGenres: -> - new CategoryApp.List.Controller - entityKey: 'genre:entities' - media: 'audio' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CategoryApp", function(CategoryApp, App, Backbone, Marionette, $, _) { + + //# This is a generic app for category listings (eg Genres) + + const Cls = (CategoryApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = + {"music/genres" : "musicGenres"}; + } + }); + Cls.initClass(); + + + const API = { + + musicGenres() { + return new CategoryApp.List.Controller({ + entityKey: 'genre:entities', + media: 'audio', subNavParent: 'music' + }); + } + }; - App.on "before:start", -> - new CategoryApp.Router - controller: API + return App.on("before:start", () => new CategoryApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/category/list/list_controller.js b/src/js/apps/category/list/list_controller.js index dc2cfe36..04076f37 100644 --- a/src/js/apps/category/list/list_controller.js +++ b/src/js/apps/category/list/list_controller.js @@ -1,29 +1,43 @@ -@Kodi.module "CategoryApp.List", (List, App, Backbone, Marionette, $, _) -> - - - ## Main controller - class List.Controller extends App.Controllers.Base - - initialize: (options) -> - collection = App.request @getOption('entityKey'), @getOption('media') - App.execute "when:entity:fetched", collection, => - - @layout = @getLayoutView collection - @listenTo @layout, "show", => - @renderList collection - @getSubNav() - - App.regionContent.show @layout - - getLayoutView: (collection) -> - new List.Layout - collection: collection - - renderList: (collection) -> - view = new List.CategoryList - collection: collection - @layout.regionContent.show view - - getSubNav: -> - subNav = App.request "navMain:children:show", @getOption('subNavParent'), 'Sections' - @layout.regionSidebarFirst.show subNav +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CategoryApp.List", function(List, App, Backbone, Marionette, $, _) { + + + //# Main controller + return List.Controller = class Controller extends App.Controllers.Base { + + initialize(options) { + const collection = App.request(this.getOption('entityKey'), this.getOption('media')); + return App.execute("when:entity:fetched", collection, () => { + + this.layout = this.getLayoutView(collection); + this.listenTo(this.layout, "show", () => { + this.renderList(collection); + return this.getSubNav(); + }); + + return App.regionContent.show(this.layout); + }); + } + + getLayoutView(collection) { + return new List.Layout({ + collection}); + } + + renderList(collection) { + const view = new List.CategoryList({ + collection}); + return this.layout.regionContent.show(view); + } + + getSubNav() { + const subNav = App.request("navMain:children:show", this.getOption('subNavParent'), 'Sections'); + return this.layout.regionSidebarFirst.show(subNav); + } + }; +}); diff --git a/src/js/apps/category/list/list_view.js b/src/js/apps/category/list/list_view.js index dc2f8790..13bbbdde 100644 --- a/src/js/apps/category/list/list_view.js +++ b/src/js/apps/category/list/list_view.js @@ -1,14 +1,37 @@ -@Kodi.module "CategoryApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CategoryApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.Layout extends App.Views.LayoutWithSidebarFirstView - className: "category-list" + let Cls = (List.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "category-list"; + } + }); + Cls.initClass(); - class List.Item extends App.Views.CardView - template: 'apps/category/list/item' - tagName: "li" - className: "card category" + Cls = (List.Item = class Item extends App.Views.CardView { + static initClass() { + this.prototype.template = 'apps/category/list/item'; + this.prototype.tagName = "li"; + this.prototype.className = "card category"; + } + }); + Cls.initClass(); - class List.CategoryList extends App.Views.CollectionView - childView: List.Item - tagName: "ul" - className: "card-grid--square" + return (function() { + Cls = (List.CategoryList = class CategoryList extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = List.Item; + this.prototype.tagName = "ul"; + this.prototype.className = "card-grid--square"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/command/command_app.js b/src/js/apps/command/command_app.js index 790f8c09..f6866ad9 100644 --- a/src/js/apps/command/command_app.js +++ b/src/js/apps/command/command_app.js @@ -1,81 +1,90 @@ -@Kodi.module "CommandApp", (CommandApp, App, Backbone, Marionette, $, _) -> - - API = - # Return current playlist controller. - currentAudioPlaylistController: -> - stateObj = App.request "state:current" - App.request "command:" + stateObj.getPlayer() + ":controller", 'audio', 'PlayList' - - # Return current playlist controller. - currentVideoPlayerController: -> - stateObj = App.request "state:current" - # Switch method depending on player - method = if stateObj.getPlayer() is 'local' then 'VideoPlayer' else 'PlayList' - App.request "command:" + stateObj.getPlayer() + ":controller", 'video', method - - ### +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp", function(CommandApp, App, Backbone, Marionette, $, _) { + + const API = { + // Return current playlist controller. + currentAudioPlaylistController() { + const stateObj = App.request("state:current"); + return App.request("command:" + stateObj.getPlayer() + ":controller", 'audio', 'PlayList'); + }, + + // Return current playlist controller. + currentVideoPlayerController() { + const stateObj = App.request("state:current"); + // Switch method depending on player + const method = stateObj.getPlayer() === 'local' ? 'VideoPlayer' : 'PlayList'; + return App.request("command:" + stateObj.getPlayer() + ":controller", 'video', method); + } + }; + + /* Kodi. - ### + */ - ## Kodi: Execute a command - App.reqres.setHandler "command:kodi:player", (method, params, callback) -> - commander = new CommandApp.Kodi.Player('auto') - commander.sendCommand method, params, callback + //# Kodi: Execute a command + App.reqres.setHandler("command:kodi:player", function(method, params, callback) { + const commander = new CommandApp.Kodi.Player('auto'); + return commander.sendCommand(method, params, callback); + }); - ## Kodi: Get a controller for a specific player type and media - App.reqres.setHandler "command:kodi:controller", (media = 'auto', controller) -> - new CommandApp.Kodi[controller](media) + //# Kodi: Get a controller for a specific player type and media + App.reqres.setHandler("command:kodi:controller", (media = 'auto', controller) => new (CommandApp.Kodi[controller])(media)); - ### + /* Local. - ### + */ - ## Local: Execute a command - App.reqres.setHandler "command:local:player", (method, params, callback) -> - commander = new CommandApp.Local.Player('audio') - commander.sendCommand method, params, callback + //# Local: Execute a command + App.reqres.setHandler("command:local:player", function(method, params, callback) { + const commander = new CommandApp.Local.Player('audio'); + return commander.sendCommand(method, params, callback); + }); - ## Local: Get a controller for a specific player type and media - App.reqres.setHandler "command:local:controller", (media = 'auto', controller) -> - new CommandApp.Local[controller](media) + //# Local: Get a controller for a specific player type and media + App.reqres.setHandler("command:local:controller", (media = 'auto', controller) => new (CommandApp.Local[controller])(media)); - ### + /* Wrappers single command for playing in kodi and local. - ### - - ## Play Audio in kodi or local depending on active player. - App.commands.setHandler "command:audio:play", (type, value) -> - API.currentAudioPlaylistController().play type, value - - ## Queue Audio in kodi or local depending on active player. - App.commands.setHandler "command:audio:add", (type, value) -> - API.currentAudioPlaylistController().add type, value - - ## Play Video in kodi or local depending on active player. - App.commands.setHandler "command:video:play", (model, type, resume = 0, callback) -> - value = model.get(type) - API.currentVideoPlayerController().play type, value, model, resume, (resp) -> - # Problem: Home OSD to display when you 'add to playlist and play' when it is not empty - # This might cause other issues but tested ok for me, so hack implemented! - # TODO: Investigate, feels like a Kodi bug, but maybe not also. - stateObj = App.request "state:current" - if stateObj.getPlayer() is 'kodi' - # If player is kodi, force full screen to full. This hides the home OSD. - kodiVideo = App.request "command:kodi:controller", 'video', 'GUI' - kodiVideo.setFullScreen true, callback - - ### + */ + + //# Play Audio in kodi or local depending on active player. + App.commands.setHandler("command:audio:play", (type, value) => API.currentAudioPlaylistController().play(type, value)); + + //# Queue Audio in kodi or local depending on active player. + App.commands.setHandler("command:audio:add", (type, value) => API.currentAudioPlaylistController().add(type, value)); + + //# Play Video in kodi or local depending on active player. + App.commands.setHandler("command:video:play", function(model, type, resume = 0, callback) { + const value = model.get(type); + return API.currentVideoPlayerController().play(type, value, model, resume, function(resp) { + // Problem: Home OSD to display when you 'add to playlist and play' when it is not empty + // This might cause other issues but tested ok for me, so hack implemented! + // TODO: Investigate, feels like a Kodi bug, but maybe not also. + const stateObj = App.request("state:current"); + if (stateObj.getPlayer() === 'kodi') { + // If player is kodi, force full screen to full. This hides the home OSD. + const kodiVideo = App.request("command:kodi:controller", 'video', 'GUI'); + return kodiVideo.setFullScreen(true, callback); + } + }); + }); + + /* Commands that are generally used by settings pages. - ### + */ - ## Clean audio library. - App.commands.setHandler "command:kodi:audio:clean", () -> - App.request("command:kodi:controller", 'auto', 'AudioLibrary').clean() + //# Clean audio library. + App.commands.setHandler("command:kodi:audio:clean", () => App.request("command:kodi:controller", 'auto', 'AudioLibrary').clean()); - ## Clean audio library. - App.commands.setHandler "command:kodi:video:clean", () -> - App.request("command:kodi:controller", 'auto', 'VideoLibrary').clean() + //# Clean audio library. + App.commands.setHandler("command:kodi:video:clean", () => App.request("command:kodi:controller", 'auto', 'VideoLibrary').clean()); - ## Startup tasks. - App.addInitializer -> + //# Startup tasks. + return App.addInitializer(function() {}); +}); diff --git a/src/js/apps/command/kodi/_base/_base.js b/src/js/apps/command/kodi/_base/_base.js index 44a8dc17..71c2baa8 100644 --- a/src/js/apps/command/kodi/_base/_base.js +++ b/src/js/apps/command/kodi/_base/_base.js @@ -1,52 +1,82 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> - - class Api.Base extends Marionette.Object - - ajaxOptions: {} - - initialize: (options = {}) -> - $.jsonrpc.defaultUrl = helpers.url.baseKodiUrl "Base" - @setOptions(options) - - setOptions: (options) -> - @ajaxOptions = options - - multipleCommands: (commands, callback, fail) -> - obj = $.jsonrpc commands, @ajaxOptions - obj.fail (error) => - @doCallback fail, error - @onError commands, error - obj.done (response) => - response = @parseResponse commands, response - @triggerMethod "response:ready", response - if callback? - @doCallback callback, response - obj - - singleCommand: (command, params, callback, fail) -> - command = {method: command, url: helpers.url.baseKodiUrl(command)} - if params? and (params.length > 0 or _.isObject(params)) - command.params = params - obj = @multipleCommands [command], callback, fail - obj - - parseResponse: (commands, response) -> - results = [] - for i, result of response - if result.result or result.result is false - results.push result.result - else - @onError commands[i], result - if commands.length is 1 and results.length is 1 - results = results[0] - results - - paramObj: (key, val) -> - helpers.global.paramObj key, val - - doCallback: (callback, response) -> - if callback? - callback response - - onError: (commands, error) -> - helpers.debug.rpcError commands, error +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => (function() { + const Cls = (Api.Base = class Base extends Marionette.Object { + static initClass() { + + this.prototype.ajaxOptions = {}; + } + + initialize(options = {}) { + $.jsonrpc.defaultUrl = helpers.url.baseKodiUrl("Base"); + return this.setOptions(options); + } + + setOptions(options) { + return this.ajaxOptions = options; + } + + multipleCommands(commands, callback, fail) { + const obj = $.jsonrpc(commands, this.ajaxOptions); + obj.fail(error => { + this.doCallback(fail, error); + return this.onError(commands, error); + }); + obj.done(response => { + response = this.parseResponse(commands, response); + this.triggerMethod("response:ready", response); + if (callback != null) { + return this.doCallback(callback, response); + } + }); + return obj; + } + + singleCommand(command, params, callback, fail) { + command = {method: command, url: helpers.url.baseKodiUrl(command)}; + if ((params != null) && ((params.length > 0) || _.isObject(params))) { + command.params = params; + } + const obj = this.multipleCommands([command], callback, fail); + return obj; + } + + parseResponse(commands, response) { + let results = []; + for (var i in response) { + var result = response[i]; + if (result.result || (result.result === false)) { + results.push(result.result); + } else { + this.onError(commands[i], result); + } + } + if ((commands.length === 1) && (results.length === 1)) { + results = results[0]; + } + return results; + } + + paramObj(key, val) { + return helpers.global.paramObj(key, val); + } + + doCallback(callback, response) { + if (callback != null) { + return callback(response); + } + } + + onError(commands, error) { + return helpers.debug.rpcError(commands, error); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/_base/api.js b/src/js/apps/command/kodi/_base/api.js index 9e60c1dc..d0f35b74 100644 --- a/src/js/apps/command/kodi/_base/api.js +++ b/src/js/apps/command/kodi/_base/api.js @@ -1,116 +1,172 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> - - - ## Base commander with shared functionality. - class Api.Commander extends Api.Base - - playerActive: 0 ## default to audio - playerName: 'music' - playerForced: false ## If false will check active player before a command - - ## Applies to player and playlists. - playerIds: - audio: 0 - video: 1 - - setPlayer: (player) -> - if player is 'audio' or player is 'video' - @playerActive = @playerIds[player] - @playerName = player - @playerForced = true - - getPlayer: -> - @playerActive - - getPlayerName: -> - @playerName - - ## get the player name via the id (eg return audio, video) - playerIdToName: (playerId) -> - playerName - for name, id of @playerIds when id is playerId - playerName = name - playerName - - - ## Namespace should be added in each extending class - commandNameSpace: 'JSONRPC' - - ## Namespace can be overridden when called - getCommand: (command, namespace = @commandNameSpace) -> - namespace + '.' + command - - ## Send a command - sendCommand: (command, params, callback, fail) -> - @singleCommand @getCommand(command), params, ((resp) => - @doCallback callback, resp - ), (err) => - @doCallback fail, err - - - ## Player commander. - class Api.Player extends Api.Commander - - commandNameSpace: 'Player' - playlistApi: {} - - initialize: (media = 'audio') -> - @setPlayer media - @playlistApi = App.request "playlist:kodi:entity:api" - - getParams: (params = [], callback) -> - if @playerForced - defaultParams = [@playerActive] - @doCallback callback, defaultParams.concat(params) - else - @getActivePlayers (activeId) => - defaultParams = [activeId] - @doCallback callback, defaultParams.concat(params) - - getActivePlayers: (callback) -> - @singleCommand @getCommand("GetActivePlayers"), {}, (resp) => - if resp.length > 0 - @playerActive = resp[0].playerid - @playerName = @playerIdToName(@playerActive) - @triggerMethod "player:ready", @playerActive - @doCallback callback, @playerActive - else - @doCallback callback, @playerActive - - sendCommand: (command, params = [], callback, fail) -> - @getParams params, (playerParams) => - @singleCommand @getCommand(command), playerParams, ((resp) => - @doCallback callback, resp - ), (err) => - @doCallback fail, err - - playEntity: (type, value, options = {}, callback) -> - params = {'item': @paramObj(type, value), 'options': options} - if type is 'position' - params.item.playlistid = @getPlayer() - @singleCommand @getCommand('Open', 'Player'), params, (resp) => - if not App.request 'sockets:active' - # App.request 'player:kodi:timer', 'start' - App.request 'state:kodi:update' - @doCallback callback, resp - - setPartyMode: (op = 'toggle', callback) -> - @sendCommand 'SetPartymode', [op], (resp) => - @doCallback callback, resp - - getPlaying: (callback) -> - obj = {active: false, properties: false, item: false} - @singleCommand @getCommand('GetActivePlayers'), {}, (resp) => - if resp.length > 0 - obj.active = resp[0] ## Only use the first active player (cant think of 2 running at the same time?) - commands = [] - itemFields = helpers.entities.getFields(@playlistApi.fields, 'full') - playerFields = ["playlistid", "speed", "position", "totaltime", "time", "percentage", "shuffled", "repeat", "canrepeat", "canshuffle", "canseek", "partymode"] - commands.push {method: @getCommand('GetProperties'), params: [obj.active.playerid, playerFields]} - commands.push {method: @getCommand('GetItem'), params: [obj.active.playerid, itemFields]} - @multipleCommands commands, (playing) => - obj.properties = playing[0] - obj.item = playing[1].item - @doCallback callback, obj - else - @doCallback callback, false ## nothing playing +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", function(Api, App, Backbone, Marionette, $, _) { + + + //# Base commander with shared functionality. + let Cls = (Api.Commander = class Commander extends Api.Base { + static initClass() { + + this.prototype.playerActive = 0; //# default to audio + this.prototype.playerName = 'music'; + this.prototype.playerForced = false; //# If false will check active player before a command + + //# Applies to player and playlists. + this.prototype.playerIds = { + audio: 0, + video: 1 + }; + + + //# Namespace should be added in each extending class + this.prototype.commandNameSpace = 'JSONRPC'; + } + + setPlayer(player) { + if ((player === 'audio') || (player === 'video')) { + this.playerActive = this.playerIds[player]; + this.playerName = player; + return this.playerForced = true; + } + } + + getPlayer() { + return this.playerActive; + } + + getPlayerName() { + return this.playerName; + } + + //# get the player name via the id (eg return audio, video) + playerIdToName(playerId) { + let playerName; + playerName; + for (var name in this.playerIds) { + var id = this.playerIds[name]; + if (id === playerId) { + playerName = name; + } + } + return playerName; + } + + //# Namespace can be overridden when called + getCommand(command, namespace = this.commandNameSpace) { + return namespace + '.' + command; + } + + //# Send a command + sendCommand(command, params, callback, fail) { + return this.singleCommand(this.getCommand(command), params, (resp => { + return this.doCallback(callback, resp); + } + ), err => { + return this.doCallback(fail, err); + }); + } + }); + Cls.initClass(); + + + //# Player commander. + return (function() { + Cls = (Api.Player = class Player extends Api.Commander { + static initClass() { + + this.prototype.commandNameSpace = 'Player'; + this.prototype.playlistApi = {}; + } + + initialize(media = 'audio') { + this.setPlayer(media); + return this.playlistApi = App.request("playlist:kodi:entity:api"); + } + + getParams(params = [], callback) { + let defaultParams; + if (this.playerForced) { + defaultParams = [this.playerActive]; + return this.doCallback(callback, defaultParams.concat(params)); + } else { + return this.getActivePlayers(activeId => { + defaultParams = [activeId]; + return this.doCallback(callback, defaultParams.concat(params)); + }); + } + } + + getActivePlayers(callback) { + return this.singleCommand(this.getCommand("GetActivePlayers"), {}, resp => { + if (resp.length > 0) { + this.playerActive = resp[0].playerid; + this.playerName = this.playerIdToName(this.playerActive); + this.triggerMethod("player:ready", this.playerActive); + return this.doCallback(callback, this.playerActive); + } else { + return this.doCallback(callback, this.playerActive); + } + }); + } + + sendCommand(command, params = [], callback, fail) { + return this.getParams(params, playerParams => { + return this.singleCommand(this.getCommand(command), playerParams, (resp => { + return this.doCallback(callback, resp); + } + ), err => { + return this.doCallback(fail, err); + }); + }); + } + + playEntity(type, value, options = {}, callback) { + const params = {'item': this.paramObj(type, value), 'options': options}; + if (type === 'position') { + params.item.playlistid = this.getPlayer(); + } + return this.singleCommand(this.getCommand('Open', 'Player'), params, resp => { + if (!App.request('sockets:active')) { + // App.request 'player:kodi:timer', 'start' + App.request('state:kodi:update'); + } + return this.doCallback(callback, resp); + }); + } + + setPartyMode(op = 'toggle', callback) { + return this.sendCommand('SetPartymode', [op], resp => { + return this.doCallback(callback, resp); + }); + } + + getPlaying(callback) { + const obj = {active: false, properties: false, item: false}; + return this.singleCommand(this.getCommand('GetActivePlayers'), {}, resp => { + if (resp.length > 0) { + obj.active = resp[0]; //# Only use the first active player (cant think of 2 running at the same time?) + const commands = []; + const itemFields = helpers.entities.getFields(this.playlistApi.fields, 'full'); + const playerFields = ["playlistid", "speed", "position", "totaltime", "time", "percentage", "shuffled", "repeat", "canrepeat", "canshuffle", "canseek", "partymode"]; + commands.push({method: this.getCommand('GetProperties'), params: [obj.active.playerid, playerFields]}); + commands.push({method: this.getCommand('GetItem'), params: [obj.active.playerid, itemFields]}); + return this.multipleCommands(commands, playing => { + obj.properties = playing[0]; + obj.item = playing[1].item; + return this.doCallback(callback, obj); + }); + } else { + return this.doCallback(callback, false); + } + }); + } + }); + Cls.initClass(); + return Cls; + })(); +}); //# nothing playing diff --git a/src/js/apps/command/kodi/helpers/addon.js b/src/js/apps/command/kodi/helpers/addon.js index f5d4b350..d90ebecd 100644 --- a/src/js/apps/command/kodi/helpers/addon.js +++ b/src/js/apps/command/kodi/helpers/addon.js @@ -1,47 +1,74 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Application commander. +(function() { + const Cls = (Api.AddOn = class AddOn extends Api.Commander { + constructor(...args) { + super(...args); + this.getEnabledAddons = this.getEnabledAddons.bind(this); + this.getAllAddons = this.getAllAddons.bind(this); + } - ## Application commander. - class Api.AddOn extends Api.Commander + static initClass() { - commandNameSpace: 'Addons' + this.prototype.commandNameSpace = 'Addons'; - addonAllFields: [ - "name", - "version", - "summary", - "description", - "path", - "author", - "thumbnail", - "disclaimer", - "fanart", - "dependencies", - "broken", - "extrainfo", - "rating", - "enabled" - ] + this.prototype.addonAllFields = [ + "name", + "version", + "summary", + "description", + "path", + "author", + "thumbnail", + "disclaimer", + "fanart", + "dependencies", + "broken", + "extrainfo", + "rating", + "enabled" + ]; + } - # Get an array of addons from the api - getAddons: (type = "unknown", enabled = true, fields = [], callback) -> - @singleCommand @getCommand('GetAddons'), [type, "unknown", enabled, fields], (resp) => - @doCallback callback, resp.addons + // Get an array of addons from the api + getAddons(type = "unknown", enabled = true, fields = [], callback) { + return this.singleCommand(this.getCommand('GetAddons'), [type, "unknown", enabled, fields], resp => { + return this.doCallback(callback, resp.addons); + }); + } - # If load set then get all the addon fields else get basics - getEnabledAddons: (load = true, callback) => - fields = if load then @addonAllFields else ["name"] - @getAddons "unknown", true, fields, (resp) => - @doCallback callback, resp + // If load set then get all the addon fields else get basics + getEnabledAddons(load = true, callback) { + const fields = load ? this.addonAllFields : ["name"]; + return this.getAddons("unknown", true, fields, resp => { + return this.doCallback(callback, resp); + }); + } - # If load set then get all the addon fields else get basics - getAllAddons: (callback) => - @getAddons "unknown", "all", @addonAllFields, (resp) => - @doCallback callback, resp + // If load set then get all the addon fields else get basics + getAllAddons(callback) { + return this.getAddons("unknown", "all", this.addonAllFields, resp => { + return this.doCallback(callback, resp); + }); + } - # Execute an addon - executeAddon: (addonId, params = {}, callback) -> - opts = {addonid: addonId} - if not _.isEmpty params - opts.params = params - @singleCommand @getCommand('ExecuteAddon'), opts, (resp) => - @doCallback callback, resp.addons + // Execute an addon + executeAddon(addonId, params = {}, callback) { + const opts = {addonid: addonId}; + if (!_.isEmpty(params)) { + opts.params = params; + } + return this.singleCommand(this.getCommand('ExecuteAddon'), opts, resp => { + return this.doCallback(callback, resp.addons); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/application.js b/src/js/apps/command/kodi/helpers/application.js index ef3c3c9b..cf479371 100644 --- a/src/js/apps/command/kodi/helpers/application.js +++ b/src/js/apps/command/kodi/helpers/application.js @@ -1,23 +1,43 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Application commander. +(function() { + const Cls = (Api.Application = class Application extends Api.Commander { + static initClass() { - ## Application commander. - class Api.Application extends Api.Commander + this.prototype.commandNameSpace = 'Application'; + } - commandNameSpace: 'Application' + getProperties(callback) { + return this.singleCommand(this.getCommand('GetProperties'), [["volume", "muted", "version"]], resp => { + return this.doCallback(callback, resp); + }); + } - getProperties: (callback) -> - @singleCommand @getCommand('GetProperties'), [["volume", "muted", "version"]], (resp) => - @doCallback callback, resp + setVolume(volume, callback) { + return this.singleCommand(this.getCommand('SetVolume'), [volume], resp => { + return this.doCallback(callback, resp); + }); + } - setVolume: (volume, callback) -> - @singleCommand @getCommand('SetVolume'), [volume], (resp) => - @doCallback callback, resp + toggleMute(callback) { + const stateObj = App.request("state:kodi"); + return this.singleCommand(this.getCommand('SetMute'), [!stateObj.getState('muted')], resp => { + return this.doCallback(callback, resp); + }); + } - toggleMute: (callback) -> - stateObj = App.request "state:kodi" - @singleCommand @getCommand('SetMute'), [!stateObj.getState('muted')], (resp) => - @doCallback callback, resp - - quit: (callback) -> - @singleCommand @getCommand('Quit'), [], (resp) => - @doCallback callback, resp + quit(callback) { + return this.singleCommand(this.getCommand('Quit'), [], resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/audiolibrary.js b/src/js/apps/command/kodi/helpers/audiolibrary.js index 72de8d66..ae3197b2 100644 --- a/src/js/apps/command/kodi/helpers/audiolibrary.js +++ b/src/js/apps/command/kodi/helpers/audiolibrary.js @@ -1,37 +1,59 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Audio Library +(function() { + const Cls = (Api.AudioLibrary = class AudioLibrary extends Api.Commander { + static initClass() { - ## Audio Library - class Api.AudioLibrary extends Api.Commander + this.prototype.commandNameSpace = 'AudioLibrary'; + } - commandNameSpace: 'AudioLibrary' + //# Set a album value + setAlbumDetails(id, fields = {}, callback) { + let params = {albumid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetAlbumDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a album value - setAlbumDetails: (id, fields = {}, callback) -> - params = {albumid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetAlbumDetails'), params, (resp) => - @doCallback callback, resp + //# Set a artist value + setArtistDetails(id, fields = {}, callback) { + let params = {artistid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetArtistDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a artist value - setArtistDetails: (id, fields = {}, callback) -> - params = {artistid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetArtistDetails'), params, (resp) => - @doCallback callback, resp + //# Set a song value + setSongDetails(id, fields = {}, callback) { + let params = {songid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetSongDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a song value - setSongDetails: (id, fields = {}, callback) -> - params = {songid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetSongDetails'), params, (resp) => - @doCallback callback, resp + //# Scan library + scan(callback) { + return this.singleCommand(this.getCommand('Scan'), resp => { + return this.doCallback(callback, resp); + }); + } - ## Scan library - scan: (callback) -> - @singleCommand @getCommand('Scan'), (resp) => - @doCallback callback, resp - - ## Clean library - clean: (callback) -> - @singleCommand @getCommand('Clean'), {showdialogs: false}, (resp) => - @doCallback callback, resp + //# Clean library + clean(callback) { + return this.singleCommand(this.getCommand('Clean'), {showdialogs: false}, resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/file.js b/src/js/apps/command/kodi/helpers/file.js index 17fdb29e..2db3d982 100644 --- a/src/js/apps/command/kodi/helpers/file.js +++ b/src/js/apps/command/kodi/helpers/file.js @@ -1,29 +1,44 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Input commander +(function() { + const Cls = (Api.Files = class Files extends Api.Commander { + static initClass() { + this.prototype.commandNameSpace = 'Files'; + } - ## Input commander - class Api.Files extends Api.Commander + //# Prepare a file for download + prepareDownload(file, callback) { + return this.singleCommand(this.getCommand('PrepareDownload'), [file], resp => { + return this.doCallback(callback, resp); + }); + } - commandNameSpace: 'Files' + //# Returns a download path for a file + downloadPath(file, callback) { + return this.prepareDownload(file, resp => { + return this.doCallback(callback, resp.details.path); + }); + } - ## Prepare a file for download - prepareDownload: (file, callback) -> - @singleCommand @getCommand('PrepareDownload'), [file], (resp) => - @doCallback callback, resp + //# Callback for a download button, will initiate a download + downloadFile(file) { + const dl = window.open('about:blank', 'download'); + return this.downloadPath(file, path => dl.location = path); + } - ## Returns a download path for a file - downloadPath: (file, callback) -> - @prepareDownload file, (resp) => - @doCallback callback, resp.details.path - - ## Callback for a download button, will initiate a download - downloadFile: (file) -> - dl = window.open('about:blank', 'download') - @downloadPath file, (path) -> - dl.location = path - - ## Callback for video stream popup - videoStream: (file, background = '', player = 'html5') -> - st = helpers.global.localVideoPopup 'about:blank' - @downloadPath file, (path) -> - st.location = "videoPlayer.html?player=" + player + '&src=' + encodeURIComponent(path) + '&bg=' + encodeURIComponent(background) + //# Callback for video stream popup + videoStream(file, background = '', player = 'html5') { + const st = helpers.global.localVideoPopup('about:blank'); + return this.downloadPath(file, path => st.location = "videoPlayer.html?player=" + player + '&src=' + encodeURIComponent(path) + '&bg=' + encodeURIComponent(background)); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/gui.js b/src/js/apps/command/kodi/helpers/gui.js index cb7e2d14..97ab041e 100644 --- a/src/js/apps/command/kodi/helpers/gui.js +++ b/src/js/apps/command/kodi/helpers/gui.js @@ -1,15 +1,31 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# GUI +(function() { + const Cls = (Api.GUI = class GUI extends Api.Commander { + static initClass() { - ## GUI - class Api.GUI extends Api.Commander + this.prototype.commandNameSpace = 'GUI'; + } - commandNameSpace: 'GUI' + setFullScreen(fullscreen = true, callback) { + return this.sendCommand("SetFullscreen", [fullscreen], resp => { + return this.doCallback(callback, resp); + }); + } - setFullScreen: (fullscreen = true, callback) -> - @sendCommand "SetFullscreen", [fullscreen], (resp) => - @doCallback callback, resp - - ## See http://kodi.wiki/view/JSON-RPC_API/v6#GUI.Window for types - activateWindow: (window, params = [], callback) -> - @sendCommand "ActivateWindow", [window, params], (resp) => - @doCallback callback, resp + //# See http://kodi.wiki/view/JSON-RPC_API/v6#GUI.Window for types + activateWindow(window, params = [], callback) { + return this.sendCommand("ActivateWindow", [window, params], resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/input.js b/src/js/apps/command/kodi/helpers/input.js index c11b52bd..5115b7f0 100644 --- a/src/js/apps/command/kodi/helpers/input.js +++ b/src/js/apps/command/kodi/helpers/input.js @@ -1,19 +1,35 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Input commander +(function() { + const Cls = (Api.Input = class Input extends Api.Commander { + static initClass() { + this.prototype.commandNameSpace = 'Input'; + } - ## Input commander - class Api.Input extends Api.Commander + //# Send a text string + sendText(text, callback) { + return this.singleCommand(this.getCommand('SendText'), [text], resp => { + return this.doCallback(callback, resp); + }); + } - commandNameSpace: 'Input' - - ## Send a text string - sendText: (text, callback) -> - @singleCommand @getCommand('SendText'), [text], (resp) => - @doCallback callback, resp - - ## Set a single input - sendInput: (type, params = [], callback) -> - @singleCommand @getCommand(type), params, (resp) => - @doCallback callback, resp - if not App.request 'sockets:active' - App.request 'state:kodi:update', callback + //# Set a single input + sendInput(type, params = [], callback) { + return this.singleCommand(this.getCommand(type), params, resp => { + this.doCallback(callback, resp); + if (!App.request('sockets:active')) { + return App.request('state:kodi:update', callback); + } + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/playlist.js b/src/js/apps/command/kodi/helpers/playlist.js index c2137e99..e94dc0f6 100644 --- a/src/js/apps/command/kodi/helpers/playlist.js +++ b/src/js/apps/command/kodi/helpers/playlist.js @@ -1,133 +1,186 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> - - ## Playlist requires some player functionality but is also its - ## own thing so it extends the player. - class Api.PlayList extends Api.Player - - commandNameSpace: 'Playlist' - - ## Play an item. Rules: - ## - If in the playlist already, play that item - ## - If currently playing, insert it next and play - ## - If not playing clear playlist, add and play - ## - If resume > 0 will resume from that point - play: (type, value, model, resume = 0, callback) -> - # Get items in the playlist - @getItems (currentPlaylist) => - # If item is already in th playlist, play that - plItem = {type: type.replace('id', ''), id: value} - inPlaylist = if currentPlaylist.items then _.findWhere(currentPlaylist.items, plItem) else false - if inPlaylist - @playPosition inPlaylist.position, resume, callback - else - # Item needs to be added to playlist - stateObj = App.request "state:kodi" - ## If playing, queue up next. - if stateObj.isPlaying(@getPlayerName()) - pos = if currentPlaylist.items then (stateObj.getPlaying('position') + 1) else 0 - @insertAndPlay type, value, pos, resume, callback - else - @clear => - @insertAndPlay type, value, 0, resume, callback - - ## Add a collection of models wrapper, will clear if not playing - addCollection: (collection, position = 0, callback) -> - stateObj = App.request "state:kodi" - ## If playing, queue up next. - if stateObj.isPlaying(@getPlayerName()) - position = (stateObj.getPlaying('position') + 1) - @addCollectionItems collection, position, callback - else - @clear => - @addCollectionItems collection, position, callback - position - - ## Add a collection of models - addCollectionItems: (collection, position = 0, callback) -> - App.execute "notification:show", t.gettext("Adding items to the queue") - models = collection.getRawCollection() - player = @getPlayer() - commands = [] - ## build a set of commands so we can add all the models with one request. - for i, model of models - pos = parseInt(position) + parseInt(i) - type = if model.type is 'file' then 'file' else model.type + 'id' - params = [player, pos, @paramObj(type, model[type])] - commands.push {method: @getCommand('Insert'), params: params} - @multipleCommands commands, (resp) => - @doCallback callback, resp - @refreshPlaylistView() - - # Add a collection of models. - playCollection: (collection, position = 0) -> - pos = @addCollection collection, position, (resp) => - @playEntity 'position', parseInt(pos), {}, => - @refreshPlaylistView() - - ## Add a item to the end of the playlist - add: (type, value) -> - @playlistSize (size) => - @insert type, value, size - - ## Remove an item from the list - remove: (position, callback) -> - @singleCommand @getCommand('Remove'), [@getPlayer(), parseInt(position)], (resp) => - @refreshPlaylistView() - @doCallback callback, resp - - ## Clear a playlist. - clear: (callback) -> - @singleCommand @getCommand('Clear'), [@getPlayer()], (resp) => - @doCallback callback, resp - - ## Insert a song at a position - insert: (type, value, position = 0, callback) -> - @singleCommand @getCommand('Insert'), [@getPlayer(), parseInt(position), @paramObj(type,value)], (resp) => - @refreshPlaylistView() - @doCallback callback, resp - - ## Get items in a playlist - getItems: (callback) -> - @singleCommand @getCommand('GetItems'), [@getPlayer(), ['title']], (resp) => - @doCallback callback, @parseItems(resp) - - ## Add position to each item in the playlist - parseItems: (resp) -> - if resp.items - resp.items = _.map resp.items, (item, idx) -> - item.position = parseInt(idx) - item - resp - - ## Insert a song at a position and play it - insertAndPlay: (type, value, position = 0, resume = 0, callback) -> - @insert type, value, position, (resp) => - @playPosition position, resume, callback - - ## Play a position in the playlist with optional resume - playPosition: (position = 0, resume = 0, callback) -> - @playEntity 'position', parseInt(position), {}, => - if resume > 0 - # Seek to resume point if not 0. Setting option {resume: true} does not work :( - App.execute "player:kodi:progress:update", resume - @doCallback callback - - ## Get the size of the current playlist - playlistSize: (callback) -> - @getItems (resp) => - position = if resp.items? then resp.items.length else 0 - @doCallback callback, position - - ## Refresh playlist - refreshPlaylistView: -> - wsActive = App.request "sockets:active" - if not wsActive - App.execute "playlist:refresh", 'kodi', @playerName - - ## Move Item - moveItem: (media, id, position1, position2, callback) -> - idProp = if media is 'file' then 'file' else media + 'id' - @singleCommand @getCommand('Remove'), [@getPlayer(), parseInt(position1)], (resp) => - @insert idProp, id, position2, => - @doCallback callback, position2 +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Playlist requires some player functionality but is also its +//# own thing so it extends the player. +(function() { + const Cls = (Api.PlayList = class PlayList extends Api.Player { + static initClass() { + + this.prototype.commandNameSpace = 'Playlist'; + } + + //# Play an item. Rules: + //# - If in the playlist already, play that item + //# - If currently playing, insert it next and play + //# - If not playing clear playlist, add and play + //# - If resume > 0 will resume from that point + play(type, value, model, resume = 0, callback) { + // Get items in the playlist + return this.getItems(currentPlaylist => { + // If item is already in th playlist, play that + const plItem = {type: type.replace('id', ''), id: value}; + const inPlaylist = currentPlaylist.items ? _.findWhere(currentPlaylist.items, plItem) : false; + if (inPlaylist) { + return this.playPosition(inPlaylist.position, resume, callback); + } else { + // Item needs to be added to playlist + const stateObj = App.request("state:kodi"); + //# If playing, queue up next. + if (stateObj.isPlaying(this.getPlayerName())) { + const pos = currentPlaylist.items ? (stateObj.getPlaying('position') + 1) : 0; + return this.insertAndPlay(type, value, pos, resume, callback); + } else { + return this.clear(() => { + return this.insertAndPlay(type, value, 0, resume, callback); + }); + } + } + }); + } + + //# Add a collection of models wrapper, will clear if not playing + addCollection(collection, position = 0, callback) { + const stateObj = App.request("state:kodi"); + //# If playing, queue up next. + if (stateObj.isPlaying(this.getPlayerName())) { + position = (stateObj.getPlaying('position') + 1); + this.addCollectionItems(collection, position, callback); + } else { + this.clear(() => { + return this.addCollectionItems(collection, position, callback); + }); + } + return position; + } + + //# Add a collection of models + addCollectionItems(collection, position = 0, callback) { + App.execute("notification:show", t.gettext("Adding items to the queue")); + const models = collection.getRawCollection(); + const player = this.getPlayer(); + const commands = []; + //# build a set of commands so we can add all the models with one request. + for (var i in models) { + var model = models[i]; + var pos = parseInt(position) + parseInt(i); + var type = model.type === 'file' ? 'file' : model.type + 'id'; + var params = [player, pos, this.paramObj(type, model[type])]; + commands.push({method: this.getCommand('Insert'), params}); + } + return this.multipleCommands(commands, resp => { + this.doCallback(callback, resp); + return this.refreshPlaylistView(); + }); + } + + // Add a collection of models. + playCollection(collection, position = 0) { + let pos; + return pos = this.addCollection(collection, position, resp => { + this.playEntity('position', parseInt(pos), {}, () => {}); + return this.refreshPlaylistView(); + }); + } + + //# Add a item to the end of the playlist + add(type, value) { + return this.playlistSize(size => { + return this.insert(type, value, size); + }); + } + + //# Remove an item from the list + remove(position, callback) { + return this.singleCommand(this.getCommand('Remove'), [this.getPlayer(), parseInt(position)], resp => { + this.refreshPlaylistView(); + return this.doCallback(callback, resp); + }); + } + + //# Clear a playlist. + clear(callback) { + return this.singleCommand(this.getCommand('Clear'), [this.getPlayer()], resp => { + return this.doCallback(callback, resp); + }); + } + + //# Insert a song at a position + insert(type, value, position = 0, callback) { + return this.singleCommand(this.getCommand('Insert'), [this.getPlayer(), parseInt(position), this.paramObj(type,value)], resp => { + this.refreshPlaylistView(); + return this.doCallback(callback, resp); + }); + } + + //# Get items in a playlist + getItems(callback) { + return this.singleCommand(this.getCommand('GetItems'), [this.getPlayer(), ['title']], resp => { + return this.doCallback(callback, this.parseItems(resp)); + }); + } + + //# Add position to each item in the playlist + parseItems(resp) { + if (resp.items) { + resp.items = _.map(resp.items, function(item, idx) { + item.position = parseInt(idx); + return item; + }); + } + return resp; + } + + //# Insert a song at a position and play it + insertAndPlay(type, value, position = 0, resume = 0, callback) { + return this.insert(type, value, position, resp => { + return this.playPosition(position, resume, callback); + }); + } + + //# Play a position in the playlist with optional resume + playPosition(position = 0, resume = 0, callback) { + return this.playEntity('position', parseInt(position), {}, () => { + if (resume > 0) { + // Seek to resume point if not 0. Setting option {resume: true} does not work :( + App.execute("player:kodi:progress:update", resume); + } + return this.doCallback(callback); + }); + } + + //# Get the size of the current playlist + playlistSize(callback) { + return this.getItems(resp => { + const position = (resp.items != null) ? resp.items.length : 0; + return this.doCallback(callback, position); + }); + } + + //# Refresh playlist + refreshPlaylistView() { + const wsActive = App.request("sockets:active"); + if (!wsActive) { + return App.execute("playlist:refresh", 'kodi', this.playerName); + } + } + + //# Move Item + moveItem(media, id, position1, position2, callback) { + const idProp = media === 'file' ? 'file' : media + 'id'; + return this.singleCommand(this.getCommand('Remove'), [this.getPlayer(), parseInt(position1)], resp => { + return this.insert(idProp, id, position2, () => { + return this.doCallback(callback, position2); + }); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/pvr.js b/src/js/apps/command/kodi/helpers/pvr.js index cbb1599a..5f9d4eeb 100644 --- a/src/js/apps/command/kodi/helpers/pvr.js +++ b/src/js/apps/command/kodi/helpers/pvr.js @@ -1,31 +1,51 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# PVR +(function() { + const Cls = (Api.PVR = class PVR extends Api.Commander { + static initClass() { - ## PVR - class Api.PVR extends Api.Commander + this.prototype.commandNameSpace = 'PVR'; + } - commandNameSpace: 'PVR' + //# Start recording a channel + setRecord(id, fields = {}, callback) { + let params = {channel: id, record: 'toggle'}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('Record'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Start recording a channel - setRecord: (id, fields = {}, callback) -> - params = {channel: id, record: 'toggle'} - params = _.extend params, fields - @singleCommand @getCommand('Record'), params, (resp) => - @doCallback callback, resp + //# Toggle timer on a broadcast + toggleTimer(id, timerRule = false, callback) { + const params = {broadcastid: id, timerrule: timerRule}; + return this.singleCommand(this.getCommand('ToggleTimer'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Toggle timer on a broadcast - toggleTimer: (id, timerRule = false, callback) -> - params = {broadcastid: id, timerrule: timerRule} - @singleCommand @getCommand('ToggleTimer'), params, (resp) => - @doCallback callback, resp + //# Add timer on a broadcast + addTimer(id, timerRule = false, callback) { + const params = {broadcastid: id, timerrule: timerRule}; + return this.singleCommand(this.getCommand('AddTimer'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Add timer on a broadcast - addTimer: (id, timerRule = false, callback) -> - params = {broadcastid: id, timerrule: timerRule} - @singleCommand @getCommand('AddTimer'), params, (resp) => - @doCallback callback, resp - - ## Remove a timer id - deleteTimer: (id, callback) -> - params = {timerid: id} - @singleCommand @getCommand('DeleteTimer'), params, (resp) => - @doCallback callback, resp + //# Remove a timer id + deleteTimer(id, callback) { + const params = {timerid: id}; + return this.singleCommand(this.getCommand('DeleteTimer'), params, resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/settings.js b/src/js/apps/command/kodi/helpers/settings.js index c60e91b8..d142a8e9 100644 --- a/src/js/apps/command/kodi/helpers/settings.js +++ b/src/js/apps/command/kodi/helpers/settings.js @@ -1,10 +1,24 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# GUI +(function() { + const Cls = (Api.Settings = class Settings extends Api.Commander { + static initClass() { - ## GUI - class Api.Settings extends Api.Commander + this.prototype.commandNameSpace = 'Settings'; + } - commandNameSpace: 'Settings' - - getSettingValue: (value, callback) -> - @sendCommand "getSettingValue", [value], (resp) => - @doCallback callback, resp.value + getSettingValue(value, callback) { + return this.sendCommand("getSettingValue", [value], resp => { + return this.doCallback(callback, resp.value); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/system.js b/src/js/apps/command/kodi/helpers/system.js index 4a69bb8b..1ff9aa27 100644 --- a/src/js/apps/command/kodi/helpers/system.js +++ b/src/js/apps/command/kodi/helpers/system.js @@ -1,27 +1,49 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Application commander. +(function() { + const Cls = (Api.System = class System extends Api.Commander { + static initClass() { - ## Application commander. - class Api.System extends Api.Commander + this.prototype.commandNameSpace = 'System'; + } - commandNameSpace: 'System' + getProperties(callback) { + const properties = ["canshutdown", "cansuspend", "canhibernate", "canreboot"]; + return this.singleCommand(this.getCommand('GetProperties'), [properties], resp => { + return this.doCallback(callback, resp); + }); + } - getProperties: (callback) -> - properties = ["canshutdown", "cansuspend", "canhibernate", "canreboot"] - @singleCommand @getCommand('GetProperties'), [properties], (resp) => - @doCallback callback, resp + hibernate(callback) { + return this.singleCommand(this.getCommand('Hibernate'), [], resp => { + return this.doCallback(callback, resp); + }); + } - hibernate: (callback) -> - @singleCommand @getCommand('Hibernate'), [], (resp) => - @doCallback callback, resp + reboot(callback) { + return this.singleCommand(this.getCommand('Reboot'), [], resp => { + return this.doCallback(callback, resp); + }); + } - reboot: (callback) -> - @singleCommand @getCommand('Reboot'), [], (resp) => - @doCallback callback, resp + shutdown(callback) { + return this.singleCommand(this.getCommand('Shutdown'), [], resp => { + return this.doCallback(callback, resp); + }); + } - shutdown: (callback) -> - @singleCommand @getCommand('Shutdown'), [], (resp) => - @doCallback callback, resp - - suspend: (callback) -> - @singleCommand @getCommand('Suspend'), [], (resp) => - @doCallback callback, resp + suspend(callback) { + return this.singleCommand(this.getCommand('Suspend'), [], resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/kodi/helpers/videolibrary.js b/src/js/apps/command/kodi/helpers/videolibrary.js index a4bb6206..bccf73da 100644 --- a/src/js/apps/command/kodi/helpers/videolibrary.js +++ b/src/js/apps/command/kodi/helpers/videolibrary.js @@ -1,86 +1,126 @@ -@Kodi.module "CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Kodi", (Api, App, Backbone, Marionette, $, _) => //# Video Library +(function() { + const Cls = (Api.VideoLibrary = class VideoLibrary extends Api.Commander { + static initClass() { - ## Video Library - class Api.VideoLibrary extends Api.Commander + this.prototype.commandNameSpace = 'VideoLibrary'; + } - commandNameSpace: 'VideoLibrary' + //# Set a episode value + setEpisodeDetails(id, fields = {}, callback) { + let params = {episodeid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetEpisodeDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a episode value - setEpisodeDetails: (id, fields = {}, callback) -> - params = {episodeid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetEpisodeDetails'), params, (resp) => - @doCallback callback, resp + //# Set a movie value + setMovieDetails(id, fields = {}, callback) { + let params = {movieid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetMovieDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a movie value - setMovieDetails: (id, fields = {}, callback) -> - params = {movieid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetMovieDetails'), params, (resp) => - @doCallback callback, resp + //# Set a tvshow value + setTVShowDetails(id, fields = {}, callback) { + let params = {tvshowid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetTVShowDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a tvshow value - setTVShowDetails: (id, fields = {}, callback) -> - params = {tvshowid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetTVShowDetails'), params, (resp) => - @doCallback callback, resp + //# Set a music video value + setMusicVideoDetails(id, fields = {}, callback) { + let params = {musicvideoid: id}; + params = _.extend(params, fields); + return this.singleCommand(this.getCommand('SetMusicVideoDetails'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Set a music video value - setMusicVideoDetails: (id, fields = {}, callback) -> - params = {musicvideoid: id} - params = _.extend params, fields - @singleCommand @getCommand('SetMusicVideoDetails'), params, (resp) => - @doCallback callback, resp + //# Scan library + scan(callback) { + return this.singleCommand(this.getCommand('Scan'), resp => { + return this.doCallback(callback, resp); + }); + } - ## Scan library - scan: (callback) -> - @singleCommand @getCommand('Scan'), (resp) => - @doCallback callback, resp + //# Clean library + clean(callback) { + return this.singleCommand(this.getCommand('Clean'), {showdialogs: false}, resp => { + return this.doCallback(callback, resp); + }); + } - ## Clean library - clean: (callback) -> - @singleCommand @getCommand('Clean'), {showdialogs: false}, (resp) => - @doCallback callback, resp + //# Toggle watched on a collection. op is 'watched' or 'unwatched' + toggleWatchedCollection(collection, op, callback) { + for (var i in collection.models) { + var model = collection.models[i]; + this.toggleWatched(model, op); + } + return this.doCallback(callback, true); + } - ## Toggle watched on a collection. op is 'watched' or 'unwatched' - toggleWatchedCollection: (collection, op, callback) -> - for i, model of collection.models - @toggleWatched model, op - @doCallback callback, true + //# Toggle watched status. op is 'watched' or 'unwatched' + toggleWatched(model, op = 'auto', callback) { + let setPlaycount; + if (op === 'auto') { + setPlaycount = model.get('playcount') > 0 ? 0 : 1; + } else if (op === 'watched') { + setPlaycount = 1; + } else if (op === 'unwatched') { + setPlaycount = 0; + } + const fields = helpers.global.paramObj('playcount', setPlaycount); + if (model.get('type') === 'movie') { + this.setMovieDetails(model.get('id'), fields, () => { + App.vent.trigger('entity:kodi:update', model.get('uid')); + return this.doCallback(callback, setPlaycount); + }); + } + if (model.get('type') === 'episode') { + return this.setEpisodeDetails(model.get('id'), fields, () => { + App.vent.trigger('entity:kodi:update', model.get('uid')); + return this.doCallback(callback, setPlaycount); + }); + } + } - ## Toggle watched status. op is 'watched' or 'unwatched' - toggleWatched: (model, op = 'auto', callback) -> - if op is 'auto' - setPlaycount = if model.get('playcount') > 0 then 0 else 1 - else if op is 'watched' - setPlaycount = 1 - else if op is 'unwatched' - setPlaycount = 0 - fields = helpers.global.paramObj 'playcount', setPlaycount - if model.get('type') is 'movie' - @setMovieDetails model.get('id'), fields, => - App.vent.trigger 'entity:kodi:update', model.get('uid') - @doCallback callback, setPlaycount - if model.get('type') is 'episode' - @setEpisodeDetails model.get('id'), fields, => - App.vent.trigger 'entity:kodi:update', model.get('uid') - @doCallback callback, setPlaycount + //# Refresh a movie + refreshMovie(id, params, callback) { + params = _.extend({movieid: id, ignorenfo: false}, params); + return this.singleCommand(this.getCommand('RefreshMovie'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Refresh a movie - refreshMovie: (id, params, callback) -> - params = _.extend {movieid: id, ignorenfo: false}, params - @singleCommand @getCommand('RefreshMovie'), params, (resp) => - @doCallback callback, resp + //# Refresh a tvshow + refreshTVShow(id, params, callback) { + params = _.extend({tvshowid: id, ignorenfo: false}, params); + return this.singleCommand(this.getCommand('RefreshTVShow'), params, resp => { + return this.doCallback(callback, resp); + }); + } - ## Refresh a tvshow - refreshTVShow: (id, params, callback) -> - params = _.extend {tvshowid: id, ignorenfo: false}, params - @singleCommand @getCommand('RefreshTVShow'), params, (resp) => - @doCallback callback, resp - - ## Refresh an episode - refreshEpisode: (id, params, callback) -> - params = _.extend {episodeid: id, ignorenfo: false}, params - @singleCommand @getCommand('RefreshEpisode'), params, (resp) => - @doCallback callback, resp + //# Refresh an episode + refreshEpisode(id, params, callback) { + params = _.extend({episodeid: id, ignorenfo: false}, params); + return this.singleCommand(this.getCommand('RefreshEpisode'), params, resp => { + return this.doCallback(callback, resp); + }); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/command/local/_base/_base.js b/src/js/apps/command/local/_base/_base.js index 2a2a14c1..04394bd9 100644 --- a/src/js/apps/command/local/_base/_base.js +++ b/src/js/apps/command/local/_base/_base.js @@ -1,206 +1,261 @@ -@Kodi.module "CommandApp.Local", (Api, App, Backbone, Marionette, $, _) -> - - class Api.Base extends Marionette.Object - - localLoad: (model, callback) -> - - ## Local state obj - stateObj = App.request "state:local" - - ## If no valid model passed tell the UI we have stopped - if not model? - stateObj.setPlaying 'playing', false - @localStateUpdate() - return - - ## Unique browser playback id - stateObj.setState 'currentPlaybackId', 'browser-' + model.get('id') - - ## Get the download path for the file. - files = App.request "command:kodi:controller", 'video', 'Files' - files.downloadPath model.get('file'), (path) => - - ## Clone soundmanager - sm = soundManager; - - ## Stop anything currently playing - @localStop() - - ## Create a sm object and load it into the state - stateObj.setState 'localPlay', sm.createSound - id: stateObj.getState('currentPlaybackId') - url: path - autoplay: false - autoLoad: true - stream: true - volume: stateObj.getState('volume') - onerror: -> - console.log 'SM ERROR!' - onplay: => - stateObj.setPlayer 'local' - stateObj.setPlaying 'playing', true - stateObj.setPlaying 'paused', false - stateObj.setPlaying 'playState', 'playing' - stateObj.setPlaying 'position', model.get('position') - stateObj.setPlaying 'itemChanged', true - stateObj.setPlaying 'item', model.attributes - stateObj.setPlaying 'totaltime', helpers.global.secToTime( model.get('duration') ) - ## Set volume - ## Trigger listeners - @localStateUpdate() - onstop: => - stateObj.setPlaying 'playing', false - ## trigger listeners (remove classes, etc) - @localStateUpdate() - onpause: => - stateObj.setPlaying 'paused', true - stateObj.setPlaying 'playState', 'paused' - ## trigger listeners - @localStateUpdate() - onresume: => - stateObj.setPlaying 'paused', false - stateObj.setPlaying 'playState', 'playing' - ## trigger listeners - @localStateUpdate() - onfinish: => - @localFinished() - whileplaying: -> - pos = parseInt(@position) / 1000 - dur = parseInt( model.get('duration') ) ## @duration is also available (represents loaded not total) - percentage = Math.round((pos / dur) * 100) - stateObj.setPlaying 'time', helpers.global.secToTime(pos) - stateObj.setPlaying 'percentage', percentage - App.execute 'player:local:progress:update', percentage, helpers.global.secToTime(pos) - - ## stuff after load - @doCallback callback - - - ## What to do when finished. - localFinished: -> - @localGoTo('next') - - ## Wrapper for playing current item. - localPlay: -> - @localCommand 'play' - - ## Wrapper for stopping current item. - localStop: -> - @localCommand 'stop' - - ## Wrapper for pausing current item. - localPause: -> - @localCommand 'pause' - - localPlayPause: -> - stateObj = App.request "state:local" - if stateObj.getPlaying 'paused' - @localCommand 'play' - else - @localCommand 'pause' - - ## Set volume - localSetVolume: (volume) -> - @localCommand 'setVolume', volume - - ## Wrapper for calling a command on the current soundmanager sound. - localCommand: (command, param) -> - stateObj = App.request "state:local" - currentItem = stateObj.getState 'localPlay' - if currentItem isnt false - currentItem[command](param) - @localStateUpdate() - - ## Go to next/prev item adhering to repeat and shuffle - localGoTo: (param) -> - ## Get current playlist and state - collection = App.request "localplayer:get:entities" - stateObj = App.request "state:local" - currentPos = stateObj.getPlaying 'position' - posToPlay = false - ## Need songs to continue. - if collection.length > 0 - ## Repeat this item - if stateObj.getState('repeat') is 'one' - posToPlay = currentPos - else if stateObj.getState('shuffled') is true - ## Shuffle - ## TODO: store what positions have been played so we dont repeat - posToPlay = helpers.global.getRandomInt 0, collection.length - 1 - else - ## Next action - if param is 'next' - ## repeat all, back to the start - if currentPos is collection.length - 1 and stateObj.getState('repeat') is 'all' - posToPlay = 0 - else if currentPos < collection.length - ## Standard next - posToPlay = currentPos + 1 - @localStateNext() - ## Prev action - if param is 'previous' - ## repeat all, go to the end - if currentPos is 0 and stateObj.getState('repeat') is 'all' - posToPlay = collection.length - 1 - else if currentPos > 0 - ## Standard prev - posToPlay = currentPos - 1 - ## Check we have a position to play, if so, play it. - if posToPlay isnt false - model = collection.findWhere {position: parseInt(posToPlay)} - @localLoad model, => - @localPlay() - @localStateUpdate() - - ## Seek to a percentage in the song - localSeek: (param) -> - stateObj = App.request "state:local" - localPlay = stateObj.getState 'localPlay' - if localPlay isnt false - newPos = (param.percentage / 100) * localPlay.duration - sound = soundManager.getSoundById stateObj.getState('currentPlaybackId') - sound.setPosition newPos - - ## Set repeat state (cycle is available). - localRepeat: (param) -> - stateObj = App.request "state:local" - if param isnt 'cycle' - stateObj.setState('repeat', param) - else - newState = false - states = ['off', 'all', 'one'] - for i, state of states - i = parseInt(i) - if newState isnt false - continue - if stateObj.getState('repeat') is state - if i isnt (states.length - 1) - key = i + 1 - newState = states[key] - else - newState = 'off' - stateObj.setState('repeat', newState) - - ## Toggle shuffle - localShuffle: -> - stateObj = App.request "state:local" - currentShuffle = stateObj.getState 'shuffled' - stateObj.setState 'shuffled', !currentShuffle - - ## Triggers when something changes in the player. - localStateUpdate: -> - App.vent.trigger "state:local:changed" - - ## Trigger when we have moved to the next song - localStateNext: -> - App.vent.trigger "state:local:next" - - paramObj: (key, val) -> - helpers.global.paramObj key, val - - doCallback: (callback, response) -> - if typeof callback is 'function' - callback response - - onError: (commands, error) -> - helpers.debug.rpcError commands, error +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Local", function(Api, App, Backbone, Marionette, $, _) { + + return Api.Base = class Base extends Marionette.Object { + + localLoad(model, callback) { + + //# Local state obj + const stateObj = App.request("state:local"); + + //# If no valid model passed tell the UI we have stopped + if ((model == null)) { + stateObj.setPlaying('playing', false); + this.localStateUpdate(); + return; + } + + //# Unique browser playback id + stateObj.setState('currentPlaybackId', 'browser-' + model.get('id')); + + //# Get the download path for the file. + const files = App.request("command:kodi:controller", 'video', 'Files'); + return files.downloadPath(model.get('file'), path => { + + //# Clone soundmanager + const sm = soundManager; + + //# Stop anything currently playing + this.localStop(); + + //# Create a sm object and load it into the state + stateObj.setState('localPlay', sm.createSound({ + id: stateObj.getState('currentPlaybackId'), + url: path, + autoplay: false, + autoLoad: true, + stream: true, + volume: stateObj.getState('volume'), + onerror() { + return console.log('SM ERROR!'); + }, + onplay: () => { + stateObj.setPlayer('local'); + stateObj.setPlaying('playing', true); + stateObj.setPlaying('paused', false); + stateObj.setPlaying('playState', 'playing'); + stateObj.setPlaying('position', model.get('position')); + stateObj.setPlaying('itemChanged', true); + stateObj.setPlaying('item', model.attributes); + stateObj.setPlaying('totaltime', helpers.global.secToTime( model.get('duration') )); + //# Set volume + //# Trigger listeners + return this.localStateUpdate(); + }, + onstop: () => { + stateObj.setPlaying('playing', false); + //# trigger listeners (remove classes, etc) + return this.localStateUpdate(); + }, + onpause: () => { + stateObj.setPlaying('paused', true); + stateObj.setPlaying('playState', 'paused'); + //# trigger listeners + return this.localStateUpdate(); + }, + onresume: () => { + stateObj.setPlaying('paused', false); + stateObj.setPlaying('playState', 'playing'); + //# trigger listeners + return this.localStateUpdate(); + }, + onfinish: () => { + return this.localFinished(); + }, + whileplaying() { + const pos = parseInt(this.position) / 1000; + const dur = parseInt( model.get('duration') ); //# @duration is also available (represents loaded not total) + const percentage = Math.round((pos / dur) * 100); + stateObj.setPlaying('time', helpers.global.secToTime(pos)); + stateObj.setPlaying('percentage', percentage); + return App.execute('player:local:progress:update', percentage, helpers.global.secToTime(pos)); + } + }) + ); + + //# stuff after load + return this.doCallback(callback); + }); + } + + + //# What to do when finished. + localFinished() { + return this.localGoTo('next'); + } + + //# Wrapper for playing current item. + localPlay() { + return this.localCommand('play'); + } + + //# Wrapper for stopping current item. + localStop() { + return this.localCommand('stop'); + } + + //# Wrapper for pausing current item. + localPause() { + return this.localCommand('pause'); + } + + localPlayPause() { + const stateObj = App.request("state:local"); + if (stateObj.getPlaying('paused')) { + return this.localCommand('play'); + } else { + return this.localCommand('pause'); + } + } + + //# Set volume + localSetVolume(volume) { + return this.localCommand('setVolume', volume); + } + + //# Wrapper for calling a command on the current soundmanager sound. + localCommand(command, param) { + const stateObj = App.request("state:local"); + const currentItem = stateObj.getState('localPlay'); + if (currentItem !== false) { + currentItem[command](param); + } + return this.localStateUpdate(); + } + + //# Go to next/prev item adhering to repeat and shuffle + localGoTo(param) { + //# Get current playlist and state + const collection = App.request("localplayer:get:entities"); + const stateObj = App.request("state:local"); + const currentPos = stateObj.getPlaying('position'); + let posToPlay = false; + //# Need songs to continue. + if (collection.length > 0) { + //# Repeat this item + if (stateObj.getState('repeat') === 'one') { + posToPlay = currentPos; + } else if (stateObj.getState('shuffled') === true) { + //# Shuffle + //# TODO: store what positions have been played so we dont repeat + posToPlay = helpers.global.getRandomInt(0, collection.length - 1); + } else { + //# Next action + if (param === 'next') { + //# repeat all, back to the start + if ((currentPos === (collection.length - 1)) && (stateObj.getState('repeat') === 'all')) { + posToPlay = 0; + } else if (currentPos < collection.length) { + //# Standard next + posToPlay = currentPos + 1; + } + this.localStateNext(); + } + //# Prev action + if (param === 'previous') { + //# repeat all, go to the end + if ((currentPos === 0) && (stateObj.getState('repeat') === 'all')) { + posToPlay = collection.length - 1; + } else if (currentPos > 0) { + //# Standard prev + posToPlay = currentPos - 1; + } + } + } + } + //# Check we have a position to play, if so, play it. + if (posToPlay !== false) { + const model = collection.findWhere({position: parseInt(posToPlay)}); + return this.localLoad(model, () => { + this.localPlay(); + return this.localStateUpdate(); + }); + } + } + + //# Seek to a percentage in the song + localSeek(param) { + const stateObj = App.request("state:local"); + const localPlay = stateObj.getState('localPlay'); + if (localPlay !== false) { + const newPos = (param.percentage / 100) * localPlay.duration; + const sound = soundManager.getSoundById(stateObj.getState('currentPlaybackId')); + return sound.setPosition(newPos); + } + } + + //# Set repeat state (cycle is available). + localRepeat(param) { + const stateObj = App.request("state:local"); + if (param !== 'cycle') { + return stateObj.setState('repeat', param); + } else { + let newState = false; + const states = ['off', 'all', 'one']; + for (var i in states) { + var state = states[i]; + i = parseInt(i); + if (newState !== false) { + continue; + } + if (stateObj.getState('repeat') === state) { + if (i !== (states.length - 1)) { + var key = i + 1; + newState = states[key]; + } else { + newState = 'off'; + } + } + } + return stateObj.setState('repeat', newState); + } + } + + //# Toggle shuffle + localShuffle() { + const stateObj = App.request("state:local"); + const currentShuffle = stateObj.getState('shuffled'); + return stateObj.setState('shuffled', !currentShuffle); + } + + //# Triggers when something changes in the player. + localStateUpdate() { + return App.vent.trigger("state:local:changed"); + } + + //# Trigger when we have moved to the next song + localStateNext() { + return App.vent.trigger("state:local:next"); + } + + paramObj(key, val) { + return helpers.global.paramObj(key, val); + } + + doCallback(callback, response) { + if (typeof callback === 'function') { + return callback(response); + } + } + + onError(commands, error) { + return helpers.debug.rpcError(commands, error); + } + }; +}); diff --git a/src/js/apps/command/local/_base/api.js b/src/js/apps/command/local/_base/api.js index dd11e74b..d6375b9b 100644 --- a/src/js/apps/command/local/_base/api.js +++ b/src/js/apps/command/local/_base/api.js @@ -1,43 +1,63 @@ -@Kodi.module "CommandApp.Local", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Local", function(Api, App, Backbone, Marionette, $, _) { - ## Base commander with shared functionality. - class Api.Commander extends Api.Base - ## See Api.Base for soundmanager abstraction + //# Base commander with shared functionality. + Api.Commander = class Commander extends Api.Base {}; + //# See Api.Base for soundmanager abstraction - ## Player commander. - class Api.Player extends Api.Commander + //# Player commander. + return Api.Player = class Player extends Api.Commander { - playEntity: (type = 'position', position, callback) -> - collection = App.request "localplayer:get:entities" - model = collection.findWhere {position: position} - @localLoad model, => - @localPlay() - ## Start playback of playlist position x - @doCallback callback, position + playEntity(type = 'position', position, callback) { + const collection = App.request("localplayer:get:entities"); + const model = collection.findWhere({position}); + return this.localLoad(model, () => { + this.localPlay(); + //# Start playback of playlist position x + return this.doCallback(callback, position); + }); + } - ## Mimics Kodi Player Commands. - sendCommand: (command, param) -> - switch command - when 'GoTo' - @localGoTo param - when 'PlayPause' - @localPlayPause() - when 'Seek' - @localSeek param - when 'SetRepeat' - ## param can be 'cycle', 'off', 'all' or 'one' - @localRepeat param - when 'SetShuffle' - ## Toggles shuffle - @localShuffle() - when 'Stop' - @localStop() - else - ## nothing - @localStateUpdate() + //# Mimics Kodi Player Commands. + sendCommand(command, param) { + switch (command) { + case 'GoTo': + this.localGoTo(param); + break; + case 'PlayPause': + this.localPlayPause(); + break; + case 'Seek': + this.localSeek(param); + break; + case 'SetRepeat': + //# param can be 'cycle', 'off', 'all' or 'one' + this.localRepeat(param); + break; + case 'SetShuffle': + //# Toggles shuffle + this.localShuffle(); + break; + case 'Stop': + this.localStop(); + break; + default: + } + //# nothing + return this.localStateUpdate(); + } - ## Start, stop, toggle local party mode - setPartyMode: (op = 'toggle', callback) -> - App.execute 'playlist:local:partymode', op, (resp) => - @doCallback callback, resp + //# Start, stop, toggle local party mode + setPartyMode(op = 'toggle', callback) { + return App.execute('playlist:local:partymode', op, resp => { + return this.doCallback(callback, resp); + }); + } + }; +}); diff --git a/src/js/apps/command/local/helpers/application.js b/src/js/apps/command/local/helpers/application.js index af4db812..51728213 100644 --- a/src/js/apps/command/local/helpers/application.js +++ b/src/js/apps/command/local/helpers/application.js @@ -1,33 +1,45 @@ -@Kodi.module "CommandApp.Local", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Local", function(Api, App, Backbone, Marionette, $, _) { - ## Application commander. - class Api.Application extends Api.Commander + //# Application commander. + return Api.Application = class Application extends Api.Commander { - getProperties: (callback) -> - stateObj = App.request "state:local" - resp = { - volume: stateObj.getState 'volume' - muted: stateObj.getState 'muted' - } - @doCallback callback, resp + getProperties(callback) { + const stateObj = App.request("state:local"); + const resp = { + volume: stateObj.getState('volume'), + muted: stateObj.getState('muted') + }; + return this.doCallback(callback, resp); + } - setVolume: (volume, callback) -> - stateObj = App.request "state:local" - stateObj.setState 'volume', volume - @localSetVolume(volume) - @doCallback callback, volume + setVolume(volume, callback) { + const stateObj = App.request("state:local"); + stateObj.setState('volume', volume); + this.localSetVolume(volume); + return this.doCallback(callback, volume); + } - toggleMute: (callback) -> - stateObj = App.request "state:local" - volume = 0 - if stateObj.getState 'muted' - ## unmute (last vol) - volume = stateObj.getState('lastVolume') - stateObj.setState 'muted', false - else - ## set mute - stateObj.setState 'lastVolume', stateObj.getState('volume') - stateObj.setState 'muted', true - volume = 0 - @localSetVolume(volume) - @doCallback callback, volume + toggleMute(callback) { + const stateObj = App.request("state:local"); + let volume = 0; + if (stateObj.getState('muted')) { + //# unmute (last vol) + volume = stateObj.getState('lastVolume'); + stateObj.setState('muted', false); + } else { + //# set mute + stateObj.setState('lastVolume', stateObj.getState('volume')); + stateObj.setState('muted', true); + volume = 0; + } + this.localSetVolume(volume); + return this.doCallback(callback, volume); + } + }; +}); diff --git a/src/js/apps/command/local/helpers/playlist.js b/src/js/apps/command/local/helpers/playlist.js index 9c25b19b..7bae03b7 100644 --- a/src/js/apps/command/local/helpers/playlist.js +++ b/src/js/apps/command/local/helpers/playlist.js @@ -1,143 +1,201 @@ -@Kodi.module "CommandApp.Local", (Api, App, Backbone, Marionette, $, _) -> - - - ## Playlist requires some player functionality but is also its - ## own thing so it extends the player. - class Api.PlayList extends Api.Player - - ## Play an item. - play: (type, value, resume = 0) -> - @getSongs type, value, (songs) => - @playCollection songs - - ## Queue an item. - add: (type, value) -> - @getSongs type, value, (songs) => - @addCollection songs - - ## Play a collection of song models. - playCollection: (models) -> - models = @itemsJson models - ## TODO: Add logic for if something is already playing (like kodi controller) - @clear => - @insertAndPlay models, 0 - - ## Add a item to the end of the playlist - addCollection: (models) -> - models = @itemsJson models - @playlistSize (size) => - @insert models, size - - ## Remove an item from the list - remove: (position, callback) -> - @getItems (collection) => - raw = @itemsJson collection - ret = [] - for pos, item of raw - if parseInt(pos) isnt parseInt(position) - ret.push item - @clear => - collection = @addItems ret - @doCallback callback, collection - - ## Clear a playlist. - clear: (callback) -> - collection = App.execute "localplayer:clear:entities" - @refreshPlaylistView() - @doCallback callback, collection - - ## Insert a song at a position models can be a sing model or an array. Expects raw json (not collection) - insert: (models, position = 0, callback) -> - @getItems (collection) => - raw = @itemsJson collection - if raw.length is 0 - ## Empty list - ret = _.flatten( [models] ) - else if parseInt(position) >= raw.length - ## Adding to the end of a list - ret = raw - for model in _.flatten( [models] ) - ret.push model - else - ## Insert in the middle of a list - ret = [] - for pos, item of raw - if parseInt(pos) is parseInt(position) - for model in _.flatten( [models] ) - ret.push model - ret.push item - @clear => - collection = @addItems ret - @doCallback callback, collection - - ## Add items to the end of a list - addItems: (items) -> - App.request "localplayer:item:add:entities", items - @updatePlayingPosition items - @refreshPlaylistView() - items - - ## Get the songs in a collection based on type type/value. - getSongs: (type, value, callback) -> - ## If a single song. - if type is 'songid' - App.request "song:byid:entities", [value], (songs) => - @doCallback callback, songs.getRawCollection() - else - ## Else it's a filtered collection (artist, album, etc) - songs = App.request "song:entities", {filter: helpers.global.paramObj(type, value)} - App.execute "when:entity:fetched", songs, => - @doCallback callback, songs.getRawCollection() - - ## Get items in a playlist - getItems: (callback) -> - collection = App.request "localplayer:get:entities" - @doCallback callback, collection - - ## If collection, normalise to JSON, if JSON pass through. - itemsJson: (collection) -> - items = if _.isArray(collection) then collection else collection.toJSON() - items - - ## Insert a song at a position and play it - insertAndPlay: (models, position = 0, callback) -> - @insert models, position, (resp) => - @playEntity 'position', parseInt(position), {}, => - @doCallback callback, position - - ## Get the size of the current playlist - playlistSize: (callback) -> - @getItems (resp) => - @doCallback callback, resp.length - - ## Refresh playlist - refreshPlaylistView: -> - App.execute "playlist:refresh", 'local', 'audio' - - ## Move Item - moveItem: (media, id, position1, position2, callback) -> - @getItems (collection) => - raw = collection.getRawCollection() - item = raw[position1] - @remove position1, => - @insert item, position2, => - @doCallback callback, position2 - - ## After items in playlist have changed, this updates the playing position - ## TODO: Make this less buggy, does weird things when tracks changed in party mode - updatePlayingPosition: (collection) -> - stateObj = App.request "state:local" - if stateObj.isPlaying() - model = stateObj.getPlaying('item') - if model.uid - set = false - pos = 0 - for i, m of @itemsJson(collection) - if set is true - continue - if m.uid is model.uid - pos = parseInt(i) - set = true - model.position = pos - stateObj.setPlaying 'item', model - stateObj.setPlaying 'position', pos +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Local", function(Api, App, Backbone, Marionette, $, _) { + + + //# Playlist requires some player functionality but is also its + //# own thing so it extends the player. + return Api.PlayList = class PlayList extends Api.Player { + + //# Play an item. + play(type, value, resume = 0) { + return this.getSongs(type, value, songs => { + return this.playCollection(songs); + }); + } + + //# Queue an item. + add(type, value) { + return this.getSongs(type, value, songs => { + return this.addCollection(songs); + }); + } + + //# Play a collection of song models. + playCollection(models) { + models = this.itemsJson(models); + //# TODO: Add logic for if something is already playing (like kodi controller) + return this.clear(() => { + return this.insertAndPlay(models, 0); + }); + } + + //# Add a item to the end of the playlist + addCollection(models) { + models = this.itemsJson(models); + return this.playlistSize(size => { + return this.insert(models, size); + }); + } + + //# Remove an item from the list + remove(position, callback) { + return this.getItems(collection => { + const raw = this.itemsJson(collection); + const ret = []; + for (var pos in raw) { + var item = raw[pos]; + if (parseInt(pos) !== parseInt(position)) { + ret.push(item); + } + } + return this.clear(() => { + collection = this.addItems(ret); + return this.doCallback(callback, collection); + }); + }); + } + + //# Clear a playlist. + clear(callback) { + const collection = App.execute("localplayer:clear:entities"); + this.refreshPlaylistView(); + return this.doCallback(callback, collection); + } + + //# Insert a song at a position models can be a sing model or an array. Expects raw json (not collection) + insert(models, position = 0, callback) { + return this.getItems(collection => { + let model, ret; + const raw = this.itemsJson(collection); + if (raw.length === 0) { + //# Empty list + ret = _.flatten( [models] ); + } else if (parseInt(position) >= raw.length) { + //# Adding to the end of a list + ret = raw; + for (model of _.flatten( [models] )) { + ret.push(model); + } + } else { + //# Insert in the middle of a list + ret = []; + for (var pos in raw) { + var item = raw[pos]; + if (parseInt(pos) === parseInt(position)) { + for (model of _.flatten( [models] )) { + ret.push(model); + } + } + ret.push(item); + } + } + return this.clear(() => { + collection = this.addItems(ret); + return this.doCallback(callback, collection); + }); + }); + } + + //# Add items to the end of a list + addItems(items) { + App.request("localplayer:item:add:entities", items); + this.updatePlayingPosition(items); + this.refreshPlaylistView(); + return items; + } + + //# Get the songs in a collection based on type type/value. + getSongs(type, value, callback) { + //# If a single song. + if (type === 'songid') { + return App.request("song:byid:entities", [value], songs => { + return this.doCallback(callback, songs.getRawCollection()); + }); + } else { + //# Else it's a filtered collection (artist, album, etc) + const songs = App.request("song:entities", {filter: helpers.global.paramObj(type, value)}); + return App.execute("when:entity:fetched", songs, () => { + return this.doCallback(callback, songs.getRawCollection()); + }); + } + } + + //# Get items in a playlist + getItems(callback) { + const collection = App.request("localplayer:get:entities"); + return this.doCallback(callback, collection); + } + + //# If collection, normalise to JSON, if JSON pass through. + itemsJson(collection) { + const items = _.isArray(collection) ? collection : collection.toJSON(); + return items; + } + + //# Insert a song at a position and play it + insertAndPlay(models, position = 0, callback) { + return this.insert(models, position, resp => { + return this.playEntity('position', parseInt(position), {}, () => { + return this.doCallback(callback, position); + }); + }); + } + + //# Get the size of the current playlist + playlistSize(callback) { + return this.getItems(resp => { + return this.doCallback(callback, resp.length); + }); + } + + //# Refresh playlist + refreshPlaylistView() { + return App.execute("playlist:refresh", 'local', 'audio'); + } + + //# Move Item + moveItem(media, id, position1, position2, callback) { + return this.getItems(collection => { + const raw = collection.getRawCollection(); + const item = raw[position1]; + return this.remove(position1, () => { + return this.insert(item, position2, () => { + return this.doCallback(callback, position2); + }); + }); + }); + } + + //# After items in playlist have changed, this updates the playing position + //# TODO: Make this less buggy, does weird things when tracks changed in party mode + updatePlayingPosition(collection) { + const stateObj = App.request("state:local"); + if (stateObj.isPlaying()) { + const model = stateObj.getPlaying('item'); + if (model.uid) { + let set = false; + let pos = 0; + const object = this.itemsJson(collection); + for (var i in object) { + var m = object[i]; + if (set === true) { + continue; + } + if (m.uid === model.uid) { + pos = parseInt(i); + set = true; + } + } + model.position = pos; + stateObj.setPlaying('item', model); + return stateObj.setPlaying('position', pos); + } + } + } + }; +}); diff --git a/src/js/apps/command/local/helpers/videoplayer.js b/src/js/apps/command/local/helpers/videoplayer.js index 6cd57b42..a61512c1 100644 --- a/src/js/apps/command/local/helpers/videoplayer.js +++ b/src/js/apps/command/local/helpers/videoplayer.js @@ -1,17 +1,27 @@ -@Kodi.module "CommandApp.Local", (Api, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("CommandApp.Local", function(Api, App, Backbone, Marionette, $, _) { - class Api.VideoPlayer extends Api.Player + return Api.VideoPlayer = class VideoPlayer extends Api.Player { - # files controller - getKodiFilesController: -> - new App.CommandApp.Kodi.Files + // files controller + getKodiFilesController() { + return new App.CommandApp.Kodi.Files; + } - # Play wrapper to match kodi controller - play: (type, value, model) -> - @videoStream model.get('file'), model.get('fanart') + // Play wrapper to match kodi controller + play(type, value, model) { + return this.videoStream(model.get('file'), model.get('fanart')); + } - # Callback for video stream popup - videoStream: (file, background = '', player = 'html5') -> - st = helpers.global.localVideoPopup 'about:blank' - @getKodiFilesController().downloadPath file, (path) -> - st.location = "videoPlayer.html?player=" + player + '&src=' + encodeURIComponent(path) + '&bg=' + encodeURIComponent(background) + // Callback for video stream popup + videoStream(file, background = '', player = 'html5') { + const st = helpers.global.localVideoPopup('about:blank'); + return this.getKodiFilesController().downloadPath(file, path => st.location = "videoPlayer.html?player=" + player + '&src=' + encodeURIComponent(path) + '&bg=' + encodeURIComponent(background)); + } + }; +}); diff --git a/src/js/apps/epg/epg_app.js b/src/js/apps/epg/epg_app.js index f227bd66..36cad3b0 100644 --- a/src/js/apps/epg/epg_app.js +++ b/src/js/apps/epg/epg_app.js @@ -1,41 +1,60 @@ -@Kodi.module "EPGApp", (EPGApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("EPGApp", function(EPGApp, App, Backbone, Marionette, $, _) { - class EPGApp.Router extends App.Router.Base - appRoutes: - "pvr/tv/:channelid" : "tv" - "pvr/radio/:channelid" : "radio" + const Cls = (EPGApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "pvr/tv/:channelid" : "tv", + "pvr/radio/:channelid" : "radio" + }; + } + }); + Cls.initClass(); - API = + const API = { - tv: (channelid) -> - new EPGApp.List.Controller - channelid: channelid + tv(channelid) { + return new EPGApp.List.Controller({ + channelid, type: "tv" + }); + }, - radio: (channelid) -> - new EPGApp.List.Controller - channelid: channelid + radio(channelid) { + return new EPGApp.List.Controller({ + channelid, type: "radio" + }); + }, - action: (op, view) -> - model = view.model - player = App.request "command:kodi:controller", 'auto', 'Player' - pvr = App.request "command:kodi:controller", 'auto', 'PVR' - switch op - when 'play' - player.playEntity 'channelid', model.get('channelid') - when 'record' - pvr.setRecord model.get('channelid'), {}, -> - App.execute "notification:show", tr("Channel recording toggled") - when 'timer' - pvr.toggleTimer model.get('id') - else - # nothing + action(op, view) { + const { + model + } = view; + const player = App.request("command:kodi:controller", 'auto', 'Player'); + const pvr = App.request("command:kodi:controller", 'auto', 'PVR'); + switch (op) { + case 'play': + return player.playEntity('channelid', model.get('channelid')); + case 'record': + return pvr.setRecord(model.get('channelid'), {}, () => App.execute("notification:show", tr("Channel recording toggled"))); + case 'timer': + return pvr.toggleTimer(model.get('id')); + default: + } + } + }; + // nothing - ## This is shared with a channel action (sidebar) - App.commands.setHandler 'broadcast:action', (op, view) -> - API.action op, view + //# This is shared with a channel action (sidebar) + App.commands.setHandler('broadcast:action', (op, view) => API.action(op, view)); - App.on "before:start", -> - new EPGApp.Router - controller: API + return App.on("before:start", () => new EPGApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/epg/list/list_controller.js b/src/js/apps/epg/list/list_controller.js index 0df025ae..1b2a51b5 100644 --- a/src/js/apps/epg/list/list_controller.js +++ b/src/js/apps/epg/list/list_controller.js @@ -1,60 +1,73 @@ -@Kodi.module "EPGApp.List", (List, App, Backbone, Marionette, $, _) -> - - API = - - bindTriggers: (view) -> - App.listenTo view, 'childview:broadcast:play', (parent, child) -> - App.execute 'broadcast:action', 'play', child - App.listenTo view, 'childview:broadcast:record', (parent, child) -> - App.execute 'broadcast:action', 'record', child - App.listenTo view, 'childview:broadcast:timer', (parent, child) -> - App.execute 'broadcast:action', 'timer', child - - bindChannelTriggers: (view) -> - App.listenTo view, 'broadcast:play', (child) -> - App.execute 'broadcast:action', 'play', child - App.listenTo view, 'broadcast:record', (child) -> - App.execute 'broadcast:action', 'record', child - App.listenTo view, 'broadcast:timer', (child) -> - App.execute 'broadcast:action', 'timer', child - - ## Main controller - class List.Controller extends App.Controllers.Base - - initialize: (options) -> - model = App.request 'channel:entity', options.channelid - App.execute "when:entity:fetched", model, => - collection = App.request "broadcast:entities", options.channelid - - ## When fetched. - App.execute "when:entity:fetched", collection, => - - ## Get and setup the layout - @layout = @getLayoutView collection - @listenTo @layout, "show", => - @getSubNav model - @getChannelActions model - @renderProgrammes collection - - ## Render the layout - App.regionContent.show @layout - - getLayoutView: (collection) -> - new List.Layout - collection: collection - - renderProgrammes: (collection) -> - view = new List.EPGList - collection: collection - API.bindTriggers view - @layout.regionContent.show view - - getSubNav: (model) -> - subNav = App.request "navMain:children:show", 'pvr/tv', 'PVR' - @layout.regionSidebarFirst.show subNav - - getChannelActions: (model) -> - view = new List.ChannelActions - model: model - API.bindChannelTriggers view - @layout.appendSidebarView 'channel-actions', view +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("EPGApp.List", function(List, App, Backbone, Marionette, $, _) { + + const API = { + + bindTriggers(view) { + App.listenTo(view, 'childview:broadcast:play', (parent, child) => App.execute('broadcast:action', 'play', child)); + App.listenTo(view, 'childview:broadcast:record', (parent, child) => App.execute('broadcast:action', 'record', child)); + return App.listenTo(view, 'childview:broadcast:timer', (parent, child) => App.execute('broadcast:action', 'timer', child)); + }, + + bindChannelTriggers(view) { + App.listenTo(view, 'broadcast:play', child => App.execute('broadcast:action', 'play', child)); + App.listenTo(view, 'broadcast:record', child => App.execute('broadcast:action', 'record', child)); + return App.listenTo(view, 'broadcast:timer', child => App.execute('broadcast:action', 'timer', child)); + } + }; + + //# Main controller + return List.Controller = class Controller extends App.Controllers.Base { + + initialize(options) { + const model = App.request('channel:entity', options.channelid); + return App.execute("when:entity:fetched", model, () => { + const collection = App.request("broadcast:entities", options.channelid); + + //# When fetched. + return App.execute("when:entity:fetched", collection, () => { + + //# Get and setup the layout + this.layout = this.getLayoutView(collection); + this.listenTo(this.layout, "show", () => { + this.getSubNav(model); + this.getChannelActions(model); + return this.renderProgrammes(collection); + }); + + //# Render the layout + return App.regionContent.show(this.layout); + }); + }); + } + + getLayoutView(collection) { + return new List.Layout({ + collection}); + } + + renderProgrammes(collection) { + const view = new List.EPGList({ + collection}); + API.bindTriggers(view); + return this.layout.regionContent.show(view); + } + + getSubNav(model) { + const subNav = App.request("navMain:children:show", 'pvr/tv', 'PVR'); + return this.layout.regionSidebarFirst.show(subNav); + } + + getChannelActions(model) { + const view = new List.ChannelActions({ + model}); + API.bindChannelTriggers(view); + return this.layout.appendSidebarView('channel-actions', view); + } + }; +}); diff --git a/src/js/apps/epg/list/list_view.js b/src/js/apps/epg/list/list_view.js index 8512bf92..315cf43b 100644 --- a/src/js/apps/epg/list/list_view.js +++ b/src/js/apps/epg/list/list_view.js @@ -1,50 +1,84 @@ -@Kodi.module "EPGApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("EPGApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.Layout extends App.Views.LayoutWithSidebarFirstView - className: "epg-page" + let Cls = (List.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "epg-page"; + } + }); + Cls.initClass(); - class List.ChannelActions extends App.Views.ItemView - template: 'apps/epg/list/channel' - className: 'nav-sub' - triggers: - 'click .play' : 'broadcast:play' - events: - 'click .record' : 'toggleRecord' - toggleRecord: -> - console.log $('.airing') - $('.airing').toggleClass 'has-timer' - @trigger 'broadcast:record', @ + Cls = (List.ChannelActions = class ChannelActions extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/epg/list/channel'; + this.prototype.className = 'nav-sub'; + this.prototype.triggers = + {'click .play' : 'broadcast:play'}; + this.prototype.events = + {'click .record' : 'toggleRecord'}; + } + toggleRecord() { + console.log($('.airing')); + $('.airing').toggleClass('has-timer'); + return this.trigger('broadcast:record', this); + } + }); + Cls.initClass(); - class List.ProgrammeList extends App.Views.ItemView - template: 'apps/epg/list/programme' - tagName: "li" - className: "pvr-card card" - onRender: -> - ## Add a class to indicate the programme has finished - if @model.attributes.wasactive then @$el.addClass("aired") - if @model.attributes.isactive then @$el.addClass("airing") - if @model.attributes.hastimer then @$el.addClass("has-timer") - triggers: - 'click .play' : 'broadcast:play' - events: - 'click .record' : 'toggleRecord' - 'click .toggle-timer' : 'toggleTimer' - toggleRecord: -> - @$el.toggleClass 'has-timer' - @trigger 'broadcast:record', @ - toggleTimer: -> - @$el.toggleClass 'has-timer' - @trigger 'broadcast:timer', @ + Cls = (List.ProgrammeList = class ProgrammeList extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/epg/list/programme'; + this.prototype.tagName = "li"; + this.prototype.className = "pvr-card card"; + this.prototype.triggers = + {'click .play' : 'broadcast:play'}; + this.prototype.events = { + 'click .record' : 'toggleRecord', + 'click .toggle-timer' : 'toggleTimer' + }; + } + onRender() { + //# Add a class to indicate the programme has finished + if (this.model.attributes.wasactive) { this.$el.addClass("aired"); } + if (this.model.attributes.isactive) { this.$el.addClass("airing"); } + if (this.model.attributes.hastimer) { return this.$el.addClass("has-timer"); } + } + toggleRecord() { + this.$el.toggleClass('has-timer'); + return this.trigger('broadcast:record', this); + } + toggleTimer() { + this.$el.toggleClass('has-timer'); + return this.trigger('broadcast:timer', this); + } + }); + Cls.initClass(); - class List.EPGList extends App.Views.CollectionView - childView: List.ProgrammeList - tagName: "ul" - className: "programmes" - emptyView: App.Views.EmptyViewResults - emptyViewOptions: - emptyKey: 'EPG data' - onShow: -> - $airing = @$el.find('.airing') - if $airing.length - $(window).scrollTop($airing.offset().top-150) + return (function() { + Cls = (List.EPGList = class EPGList extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = List.ProgrammeList; + this.prototype.tagName = "ul"; + this.prototype.className = "programmes"; + this.prototype.emptyView = App.Views.EmptyViewResults; + this.prototype.emptyViewOptions = + {emptyKey: 'EPG data'}; + } + onShow() { + const $airing = this.$el.find('.airing'); + if ($airing.length) { + return $(window).scrollTop($airing.offset().top-150); + } + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/external/external_app.js b/src/js/apps/external/external_app.js index 6c04761f..7350c15e 100644 --- a/src/js/apps/external/external_app.js +++ b/src/js/apps/external/external_app.js @@ -1,2 +1,7 @@ -@Kodi.module "ExternalApp", (ExternalApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ExternalApp", function(ExternalApp, App, Backbone, Marionette, $, _) {}); diff --git a/src/js/apps/external/youtube/youtube_controller.js b/src/js/apps/external/youtube/youtube_controller.js index 68658475..9e45857c 100644 --- a/src/js/apps/external/youtube/youtube_controller.js +++ b/src/js/apps/external/youtube/youtube_controller.js @@ -1,38 +1,50 @@ -@Kodi.module "ExternalApp.Youtube", (Youtube, App, Backbone, Marionette, $, _) -> - - API = - - getSearchView: (query, viewName, title = '', options = {}, callback) -> - App.execute "youtube:search:entities", query, options, (collection) -> - view = new Youtube[viewName] - collection: collection - title: title - App.listenTo view, 'childview:youtube:play', (parent, item) -> - if item.model.get('addonEnabled') - API.playKodi item.model.get('id') - else - API.playLocal item.model.get('id') - App.listenTo view, 'childview:youtube:localplay', (parent, item) -> - API.playLocal item.model.get('id') - callback view - - playLocal: (id) -> - localPlayer = "videoPlayer.html?yt=" + id - helpers.global.localVideoPopup localPlayer, 530 - - playKodi: (id) -> - playlist = App.request "command:kodi:controller", 'video', 'PlayList' - playlist.play 'file', 'plugin://plugin.video.youtube/play/?video_id=' + id - - - App.commands.setHandler "youtube:search:view", (query, callback) -> - API.getSearchView query, 'List', '', {}, callback - - App.commands.setHandler "youtube:search:popup", (query) -> - API.getSearchView query, 'List', '', {}, (view) -> - $footer = $('', {class: 'btn btn-primary', href: 'https://www.youtube.com/results?search_query=' + query, target: '_blank'}) - $footer.html('More videos') - App.execute "ui:modal:show", _.escape(query), view.render().$el, $footer - - App.commands.setHandler "youtube:list:view", (query, title, options = {}, callback) -> - API.getSearchView query, 'CardList', title, options, callback +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ExternalApp.Youtube", function(Youtube, App, Backbone, Marionette, $, _) { + + var API = { + + getSearchView(query, viewName, title = '', options = {}, callback) { + return App.execute("youtube:search:entities", query, options, function(collection) { + const view = new (Youtube[viewName])({ + collection, + title + }); + App.listenTo(view, 'childview:youtube:play', function(parent, item) { + if (item.model.get('addonEnabled')) { + return API.playKodi(item.model.get('id')); + } else { + return API.playLocal(item.model.get('id')); + } + }); + App.listenTo(view, 'childview:youtube:localplay', (parent, item) => API.playLocal(item.model.get('id'))); + return callback(view); + }); + }, + + playLocal(id) { + const localPlayer = "videoPlayer.html?yt=" + id; + return helpers.global.localVideoPopup(localPlayer, 530); + }, + + playKodi(id) { + const playlist = App.request("command:kodi:controller", 'video', 'PlayList'); + return playlist.play('file', 'plugin://plugin.video.youtube/play/?video_id=' + id); + } + }; + + + App.commands.setHandler("youtube:search:view", (query, callback) => API.getSearchView(query, 'List', '', {}, callback)); + + App.commands.setHandler("youtube:search:popup", query => API.getSearchView(query, 'List', '', {}, function(view) { + const $footer = $('', {class: 'btn btn-primary', href: 'https://www.youtube.com/results?search_query=' + query, target: '_blank'}); + $footer.html('More videos'); + return App.execute("ui:modal:show", _.escape(query), view.render().$el, $footer); + })); + + return App.commands.setHandler("youtube:list:view", (query, title, options = {}, callback) => API.getSearchView(query, 'CardList', title, options, callback)); +}); diff --git a/src/js/apps/external/youtube/youtube_view.js b/src/js/apps/external/youtube/youtube_view.js index d4027359..63f2cacb 100644 --- a/src/js/apps/external/youtube/youtube_view.js +++ b/src/js/apps/external/youtube/youtube_view.js @@ -1,35 +1,70 @@ -@Kodi.module "ExternalApp.Youtube", (Youtube, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("ExternalApp.Youtube", function(Youtube, App, Backbone, Marionette, $, _) { - class Youtube.Item extends App.Views.ItemView - template: 'apps/external/youtube/youtube' - tagName: 'li' - triggers: - 'click .play': 'youtube:play' - 'click .localplay': 'youtube:localplay' - events: - 'click .action': 'closeModal' - closeModal: -> - App.execute "ui:modal:close" + let Cls = (Youtube.Item = class Item extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/external/youtube/youtube'; + this.prototype.tagName = 'li'; + this.prototype.triggers = { + 'click .play': 'youtube:play', + 'click .localplay': 'youtube:localplay' + }; + this.prototype.events = + {'click .action': 'closeModal'}; + } + closeModal() { + return App.execute("ui:modal:close"); + } + }); + Cls.initClass(); - class Youtube.List extends App.Views.CollectionView - childView: Youtube.Item - tagName: 'ul' - className: 'youtube-list' + Cls = (Youtube.List = class List extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = Youtube.Item; + this.prototype.tagName = 'ul'; + this.prototype.className = 'youtube-list'; + } + }); + Cls.initClass(); - class Youtube.Card extends App.Views.CardView - triggers: - 'click .play': 'youtube:play' - 'click .localplay': 'youtube:localplay' - initialize: -> - @getMeta() - getMeta: -> - if @model - @model.set {subtitleHtml: @themeLink 'YouTube', @model.get('url'), {external: true}} - if @model.get('addonEnabled') - @model.set {menu: {localplay: 'Local play'}} - onRender: () -> - @makeLinksExternal() + Cls = (Youtube.Card = class Card extends App.Views.CardView { + static initClass() { + this.prototype.triggers = { + 'click .play': 'youtube:play', + 'click .localplay': 'youtube:localplay' + }; + } + initialize() { + return this.getMeta(); + } + getMeta() { + if (this.model) { + this.model.set({subtitleHtml: this.themeLink('YouTube', this.model.get('url'), {external: true})}); + if (this.model.get('addonEnabled')) { + return this.model.set({menu: {localplay: 'Local play'}}); + } + } + } + onRender() { + return this.makeLinksExternal(); + } + }); + Cls.initClass(); - class Youtube.CardList extends App.Views.SetCompositeView - childView: Youtube.Card - className: "section-content card-grid--musicvideo" + return (function() { + Cls = (Youtube.CardList = class CardList extends App.Views.SetCompositeView { + static initClass() { + this.prototype.childView = Youtube.Card; + this.prototype.className = "section-content card-grid--musicvideo"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/filter/filter_app.js b/src/js/apps/filter/filter_app.js index f2481a79..a632db4f 100644 --- a/src/js/apps/filter/filter_app.js +++ b/src/js/apps/filter/filter_app.js @@ -1,495 +1,572 @@ -@Kodi.module "FilterApp", (FilterApp, App, Backbone, Marionette, $, _) -> - - API = - - ### +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("FilterApp", function(FilterApp, App, Backbone, Marionette, $, _) { + + var API = { + + /* Settings/fields - ### + */ sortFields: [ { - alias: 'title' - type: 'string' - defaultSort: true - defaultOrder: 'asc' + alias: 'title', + type: 'string', + defaultSort: true, + defaultOrder: 'asc', key: 'title' - } + }, { - alias: 'title' - type: 'string' - defaultSort: true - defaultOrder: 'asc' + alias: 'title', + type: 'string', + defaultSort: true, + defaultOrder: 'asc', key: 'label' - } + }, { - alias: 'year' - type: 'number' - key: 'year' + alias: 'year', + type: 'number', + key: 'year', defaultOrder: 'desc' - } + }, { - alias: 'date added' - type: 'string' - key: 'dateadded' + alias: 'date added', + type: 'string', + key: 'dateadded', defaultOrder: 'desc' - } + }, { - alias: 'rating' - type: 'float' - key: 'rating' + alias: 'rating', + type: 'float', + key: 'rating', defaultOrder: 'desc' - } + }, { - alias: 'artist' - type: 'string' - key: 'artist' + alias: 'artist', + type: 'string', + key: 'artist', defaultOrder: 'asc' - } + }, { - alias: 'random' - type: 'other' - key: 'random' + alias: 'random', + type: 'other', + key: 'random', defaultOrder: 'asc' - } + }, { - alias: 'album' - type: 'string' - key: 'album' + alias: 'album', + type: 'string', + key: 'album', defaultOrder: 'asc' } - ] + ], - ## See applyFilter() for how filterCallback are handled. + //# See applyFilter() for how filterCallback are handled. filterFields: [ { - alias: 'year' - type: 'number' - key: 'year' + alias: 'year', + type: 'number', + key: 'year', sortOrder: 'desc', filterCallback: 'multiple' - } + }, { - alias: 'genre' - type: 'array' - key: 'genre' + alias: 'genre', + type: 'array', + key: 'genre', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'mood' - type: 'array' - key: 'mood' + alias: 'mood', + type: 'array', + key: 'mood', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'style' - type: 'array' - key: 'style' + alias: 'style', + type: 'array', + key: 'style', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'unwatched' - type: "boolean" - key: 'unwatched' + alias: 'unwatched', + type: "boolean", + key: 'unwatched', sortOrder: 'asc', filterCallback: 'unwatched' - } + }, { - alias: 'watched' - type: "boolean" - key: 'watched' + alias: 'watched', + type: "boolean", + key: 'watched', sortOrder: 'asc', filterCallback: 'watched' - } + }, { - alias: 'in progress' - type: "boolean" - key: 'inprogress' + alias: 'in progress', + type: "boolean", + key: 'inprogress', sortOrder: 'asc', filterCallback: 'inprogress' - } + }, { - alias: 'writer' - type: 'array' - key: 'writer' + alias: 'writer', + type: 'array', + key: 'writer', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'director' - type: 'array' - key: 'director' + alias: 'director', + type: 'array', + key: 'director', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'tag' - type: 'array' - key: 'tag' + alias: 'tag', + type: 'array', + key: 'tag', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'actor' - type: 'object' - property: 'name' - key: 'cast' + alias: 'actor', + type: 'object', + property: 'name', + key: 'cast', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'set' - type: 'string' - property: 'set' - key: 'set' + alias: 'set', + type: 'string', + property: 'set', + key: 'set', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'rated' - type: 'string' - property: 'mpaa' - key: 'mpaa' + alias: 'rated', + type: 'string', + property: 'mpaa', + key: 'mpaa', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'studio' - type: 'array' - property: 'studio' - key: 'studio' + alias: 'studio', + type: 'array', + property: 'studio', + key: 'studio', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'label' - type: 'string' - property: 'albumlabel' - key: 'albumlabel' + alias: 'label', + type: 'string', + property: 'albumlabel', + key: 'albumlabel', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'Thumbs up' - type: "boolean" - key: 'thumbsUp' + alias: 'Thumbs up', + type: "boolean", + key: 'thumbsUp', sortOrder: 'asc', filterCallback: 'thumbsup' - } + }, { - alias: 'album' - type: 'string' - key: 'album' + alias: 'album', + type: 'string', + key: 'album', sortOrder: 'asc', filterCallback: 'multiple' - } + }, { - alias: 'artist' - type: 'array' - key: 'artist' + alias: 'artist', + type: 'array', + key: 'artist', sortOrder: 'asc', filterCallback: 'multiple' } - ] - - ## Wrapper for returning the available fields for sort/filter - ## Available fields are defined in the entity controller and passed - ## to the filter view where they are stored in cache. - getFilterFields: (type) -> - key = type + 'Fields' - fields = API[key] - ## Get available and only return fields available to this entity - availableFilters = API.getAvailable() - available = availableFilters[type] - ret = [] - for field in fields - if helpers.global.inArray field.key, available - ret.push field - ret - - - ### + ], + + //# Wrapper for returning the available fields for sort/filter + //# Available fields are defined in the entity controller and passed + //# to the filter view where they are stored in cache. + getFilterFields(type) { + const key = type + 'Fields'; + const fields = API[key]; + //# Get available and only return fields available to this entity + const availableFilters = API.getAvailable(); + const available = availableFilters[type]; + const ret = []; + for (var field of fields) { + if (helpers.global.inArray(field.key, available)) { + ret.push(field); + } + } + return ret; + }, + + + /* Storage - ### - - ## Store filters namespace - storeFiltersNamespace: 'filter:store:' - - getStoreNameSpace: (type) -> - API.storeFiltersNamespace + type - - ## Memory store the current filters - setStoreFilters: (filters = {}, type = 'filters') -> - store = {} - store[helpers.url.path()] = filters - helpers.cache.set(API.getStoreNameSpace(type), store) - App.vent.trigger('filter:changed', filters); - - ## Get the current filters for this page - getStoreFilters: (type = 'filters') -> - store = helpers.cache.get(API.getStoreNameSpace(type), {}) - path = helpers.url.path() - filters = if store[path] then store[path] else {} - ret = {} - if not _.isEmpty filters - for key, val of filters when val.length > 0 - ret[key] = val - ret - - ## Update a given key with new values - updateStoreFiltersKey: (key, values = []) -> - filters = API.getStoreFilters() - filters[key] = values - API.setStoreFilters filters - filters - - ## Get a specific key values - getStoreFiltersKey: (key) -> - filters = API.getStoreFilters() - filter = if filters[key] then filters[key] else [] - filter - - ## Set current sort. - setStoreSort: (method, order = 'asc') -> - sort = {method: method, order: order} - API.setStoreFilters(sort, 'sort') - - ## Get current sort. - getStoreSort: -> - sort = API.getStoreFilters('sort') - if not sort.method - defaults = _.findWhere(API.getFilterFields('sort'), {defaultSort: true}); - sort = {method: defaults.key, order: defaults.defaultOrder} - sort - - ## Set available filters - setAvailable: (available) -> - API.setStoreFilters(available, 'available') - - ## Get available filters - getAvailable: -> - API.getStoreFilters('available') - - - ### + */ + + //# Store filters namespace + storeFiltersNamespace: 'filter:store:', + + getStoreNameSpace(type) { + return API.storeFiltersNamespace + type; + }, + + //# Memory store the current filters + setStoreFilters(filters = {}, type = 'filters') { + const store = {}; + store[helpers.url.path()] = filters; + helpers.cache.set(API.getStoreNameSpace(type), store); + return App.vent.trigger('filter:changed', filters); + }, + + //# Get the current filters for this page + getStoreFilters(type = 'filters') { + const store = helpers.cache.get(API.getStoreNameSpace(type), {}); + const path = helpers.url.path(); + const filters = store[path] ? store[path] : {}; + const ret = {}; + if (!_.isEmpty(filters)) { + for (var key in filters) { + var val = filters[key]; + if (val.length > 0) { + ret[key] = val; + } + } + } + return ret; + }, + + //# Update a given key with new values + updateStoreFiltersKey(key, values = []) { + const filters = API.getStoreFilters(); + filters[key] = values; + API.setStoreFilters(filters); + return filters; + }, + + //# Get a specific key values + getStoreFiltersKey(key) { + const filters = API.getStoreFilters(); + const filter = filters[key] ? filters[key] : []; + return filter; + }, + + //# Set current sort. + setStoreSort(method, order = 'asc') { + const sort = {method, order}; + return API.setStoreFilters(sort, 'sort'); + }, + + //# Get current sort. + getStoreSort() { + let sort = API.getStoreFilters('sort'); + if (!sort.method) { + const defaults = _.findWhere(API.getFilterFields('sort'), {defaultSort: true}); + sort = {method: defaults.key, order: defaults.defaultOrder}; + } + return sort; + }, + + //# Set available filters + setAvailable(available) { + return API.setStoreFilters(available, 'available'); + }, + + //# Get available filters + getAvailable() { + return API.getStoreFilters('available'); + }, + + + /* Parsing - ### - - ## Swap the order. - toggleOrder: (order) -> - order = if order is 'asc' then 'desc' else 'asc' - order - - ## Parse the defaults with context of the current page - parseSortable: (items) -> - ## Set the current state - params = API.getStoreSort false, 'asc' - ## loop over the items and set the active and toggle order if active - for i, item of items - items[i].active = false - items[i].order = item.defaultOrder - if params.method and item.key is params.method - items[i].active = true - items[i].order = @toggleOrder params.order - else if item.defaultSort and params.method is false - items[i].active = true - items - - ## Parse the active state int the current filters - parseFilterable: (items) -> - active = API.getFilterActive() - for i, val of items - activeItem = _.findWhere(active, {key: val.key}); - items[i].active = activeItem != undefined - items - - ## Extract the available options for a given filter from the attached collection. - getFilterOptions: (key, collection) -> - values = App.request 'filter:store:key:get', key - ## Filter settings for this key. - s = API.getFilterSettings(key) - items = [] - ## Get the properties requested - collectionItems = collection.pluck(key) - ## Deal with more complex nested properties (e.g. cast) - if s.filterCallback is 'multiple' and s.type is 'object' - ## Limit to first 5 for each otherwise it kills the browser. - limited = [] - for item in collectionItems - for i, data of item - if i < 5 - limited.push data[s.property] - collectionItems = limited - ## Reduce the list to an array of unique items. - _.map _.uniq(_.flatten(collectionItems)), (val) -> - items.push {key: key, value: val, active: helpers.global.inArray(val,values)} - items - - - ### + */ + + //# Swap the order. + toggleOrder(order) { + order = order === 'asc' ? 'desc' : 'asc'; + return order; + }, + + //# Parse the defaults with context of the current page + parseSortable(items) { + //# Set the current state + const params = API.getStoreSort(false, 'asc'); + //# loop over the items and set the active and toggle order if active + for (var i in items) { + var item = items[i]; + items[i].active = false; + items[i].order = item.defaultOrder; + if (params.method && (item.key === params.method)) { + items[i].active = true; + items[i].order = this.toggleOrder(params.order); + } else if (item.defaultSort && (params.method === false)) { + items[i].active = true; + } + } + return items; + }, + + //# Parse the active state int the current filters + parseFilterable(items) { + const active = API.getFilterActive(); + for (var i in items) { + var val = items[i]; + var activeItem = _.findWhere(active, {key: val.key}); + items[i].active = activeItem !== undefined; + } + return items; + }, + + //# Extract the available options for a given filter from the attached collection. + getFilterOptions(key, collection) { + const values = App.request('filter:store:key:get', key); + //# Filter settings for this key. + const s = API.getFilterSettings(key); + const items = []; + //# Get the properties requested + let collectionItems = collection.pluck(key); + //# Deal with more complex nested properties (e.g. cast) + if ((s.filterCallback === 'multiple') && (s.type === 'object')) { + //# Limit to first 5 for each otherwise it kills the browser. + const limited = []; + for (var item of collectionItems) { + for (var i in item) { + var data = item[i]; + if (i < 5) { + limited.push(data[s.property]); + } + } + } + collectionItems = limited; + } + //# Reduce the list to an array of unique items. + _.map(_.uniq(_.flatten(collectionItems)), val => items.push({key, value: val, active: helpers.global.inArray(val,values)})); + return items; + }, + + + /* Apply filters - ### - - ## Apply filters to a collection. - applyFilters: (collection) -> - sort = API.getStoreSort() - collection.sortCollection sort.method, sort.order - filteredCollection = new App.Entities.Filtered collection - for key, values of API.getStoreFilters() when values.length > 0 - filteredCollection = API.applyFilter filteredCollection, key, values - filteredCollection - - ## Apply a single filter key - ## See entities/_base/filtered.js for custom filter methods - applyFilter: (collection, key, vals) -> - ## Get the filter settings available for this key and switch on the callback. - s = API.getFilterSettings(key) - switch s.filterCallback - ## If multiple values allowed - when 'multiple' - if s.type is 'array' - collection.filterByMultipleArray(key, vals) ## data is an array - else if s.type is 'object' - collection.filterByMultipleObject(key, s.property, vals) ## data is an array of objects - else - collection.filterByMultiple(key, vals) ## data is not array - when 'unwatched' - collection.filterByUnwatched() - when 'watched' - collection.filterByWatched() - when 'inprogress' - collection.filterByInProgress() - when 'thumbsup' - collection.filterByThumbsUp() - else - collection - collection - - ## Get settings for a given filter - getFilterSettings: (key, availableOnly = true) -> - filters = if availableOnly is true then API.getFilterFields('filter') else API.filterFields - _.findWhere(filters, {key: key}) - - ## Get the active filters. - getFilterActive: -> - items = [] - for key, values of API.getStoreFilters() when values.length > 0 - items.push {key: key, values: values} - items - - - - ### + */ + + //# Apply filters to a collection. + applyFilters(collection) { + const sort = API.getStoreSort(); + collection.sortCollection(sort.method, sort.order); + let filteredCollection = new App.Entities.Filtered(collection); + const object = API.getStoreFilters(); + for (var key in object) { + var values = object[key]; + if (values.length > 0) { + filteredCollection = API.applyFilter(filteredCollection, key, values); + } + } + return filteredCollection; + }, + + //# Apply a single filter key + //# See entities/_base/filtered.js for custom filter methods + applyFilter(collection, key, vals) { + //# Get the filter settings available for this key and switch on the callback. + const s = API.getFilterSettings(key); + switch (s.filterCallback) { + //# If multiple values allowed + case 'multiple': + if (s.type === 'array') { + collection.filterByMultipleArray(key, vals); //# data is an array + } else if (s.type === 'object') { + collection.filterByMultipleObject(key, s.property, vals); //# data is an array of objects + } else { + collection.filterByMultiple(key, vals); //# data is not array + } + break; + case 'unwatched': + collection.filterByUnwatched(); + break; + case 'watched': + collection.filterByWatched(); + break; + case 'inprogress': + collection.filterByInProgress(); + break; + case 'thumbsup': + collection.filterByThumbsUp(); + break; + default: + collection; + } + return collection; + }, + + //# Get settings for a given filter + getFilterSettings(key, availableOnly = true) { + const filters = availableOnly === true ? API.getFilterFields('filter') : API.filterFields; + return _.findWhere(filters, {key}); + }, + + //# Get the active filters. + getFilterActive() { + const items = []; + const object = API.getStoreFilters(); + for (var key in object) { + var values = object[key]; + if (values.length > 0) { + items.push({key, values}); + } + } + return items; + } + }; + + + + /* Handlers. - ### - - ## Views and collections. - - ## Return the filters view - App.reqres.setHandler 'filter:show', (collection) -> - API.setAvailable collection.availableFilters - filters = new FilterApp.Show.Controller - refCollection: collection - view = filters.getFilterView() - view - - ## Return the filter options collection - App.reqres.setHandler 'filter:options', (key, collection) -> - ## Get the options collection based on values in the collection. - options = API.getFilterOptions key, collection - optionsCollection = App.request 'filter:filters:options:entities', options - ## Set the order of the options collection. - filterSettings = API.getFilterSettings(key) - optionsCollection.sortCollection('value', filterSettings.sortOrder) - ## Return collection - optionsCollection - - ## Get an active filter collection. - App.reqres.setHandler 'filter:active', -> - App.request 'filter:active:entities', API.getFilterActive() - - ## Apply filters to a collection. - App.reqres.setHandler 'filter:apply:entities', (collection) -> - API.setAvailable collection.availableFilters - newCollection = API.applyFilters collection - App.vent.trigger 'filter:filtering:stop' - newCollection - - ## Get a sortable collection - App.reqres.setHandler 'filter:sortable:entities', -> - App.request 'filter:sort:entities', API.parseSortable(API.getFilterFields('sort')) - - ## Get a filter collection - App.reqres.setHandler 'filter:filterable:entities', -> - App.request 'filter:filters:entities', API.parseFilterable(API.getFilterFields('filter')) - - ## Set a filter using a url param eg ?director=name - App.reqres.setHandler 'filter:init', (availableFilters) -> - params = helpers.url.params() - if not _.isEmpty params - # Clear existing filters first - API.setStoreFilters {} - # Set sort, no validation here, wrong param might break something - if params.sort - order = if params.order then params.order else 'asc' - API.setStoreSort params.sort, order - # Set Filter - for key in availableFilters.filter - # is one of the params an available filter - if params[key] - values = API.getStoreFiltersKey key - filterSettings = API.getFilterSettings key, false - # If the filter doesn't exist, add and save. - if not helpers.global.inArray params[key], values - if filterSettings.type is 'number' - values.push parseInt params[key] - else - values.push decodeURIComponent(params[key]) - API.updateStoreFiltersKey key, values - - ## Storage. - - ## Store a filter set - App.reqres.setHandler 'filter:store:set', (filters) -> - API.setStoreFilters filters - filters - - ## Get a Stored a filter set - App.reqres.setHandler 'filter:store:get', -> - API.getStoreFilters() - - ## Get a Stored a filter set for a given key - App.reqres.setHandler 'filter:store:key:get', (key) -> - API.getStoreFiltersKey key - - ## Update a key in a stored filter set. - App.reqres.setHandler 'filter:store:key:update', (key, values = []) -> - API.updateStoreFiltersKey key, values - - ## Toggle a value in a key and return the updated values - ## This feels long winded, maybe one day refactor/compress. - App.reqres.setHandler 'filter:store:key:toggle', (key, value) -> - values = API.getStoreFiltersKey key - ret = [] - ## Remove. - if _.indexOf(values, value) > -1 - newValues = [] - for i in values when i isnt value - newValues.push i - ret = newValues - else - ## Add. - values.push value - ret = values - API.updateStoreFiltersKey key, ret - ret - - ## Store a sort - App.reqres.setHandler 'filter:sort:store:set', (method, order = 'asc') -> - API.setStoreSort method, order - - ## Get a sort, fallback to default - App.reqres.setHandler 'filter:sort:store:get', -> - API.getStoreSort() + */ + + //# Views and collections. + + //# Return the filters view + App.reqres.setHandler('filter:show', function(collection) { + API.setAvailable(collection.availableFilters); + const filters = new FilterApp.Show.Controller({ + refCollection: collection}); + const view = filters.getFilterView(); + return view; + }); + + //# Return the filter options collection + App.reqres.setHandler('filter:options', function(key, collection) { + //# Get the options collection based on values in the collection. + const options = API.getFilterOptions(key, collection); + const optionsCollection = App.request('filter:filters:options:entities', options); + //# Set the order of the options collection. + const filterSettings = API.getFilterSettings(key); + optionsCollection.sortCollection('value', filterSettings.sortOrder); + //# Return collection + return optionsCollection; + }); + + //# Get an active filter collection. + App.reqres.setHandler('filter:active', () => App.request('filter:active:entities', API.getFilterActive())); + + //# Apply filters to a collection. + App.reqres.setHandler('filter:apply:entities', function(collection) { + API.setAvailable(collection.availableFilters); + const newCollection = API.applyFilters(collection); + App.vent.trigger('filter:filtering:stop'); + return newCollection; + }); + + //# Get a sortable collection + App.reqres.setHandler('filter:sortable:entities', () => App.request('filter:sort:entities', API.parseSortable(API.getFilterFields('sort')))); + + //# Get a filter collection + App.reqres.setHandler('filter:filterable:entities', () => App.request('filter:filters:entities', API.parseFilterable(API.getFilterFields('filter')))); + + //# Set a filter using a url param eg ?director=name + App.reqres.setHandler('filter:init', function(availableFilters) { + const params = helpers.url.params(); + if (!_.isEmpty(params)) { + // Clear existing filters first + API.setStoreFilters({}); + // Set sort, no validation here, wrong param might break something + if (params.sort) { + const order = params.order ? params.order : 'asc'; + API.setStoreSort(params.sort, order); + } + // Set Filter + return (() => { + const result = []; + for (var key of availableFilters.filter) { + // is one of the params an available filter + if (params[key]) { + var values = API.getStoreFiltersKey(key); + var filterSettings = API.getFilterSettings(key, false); + // If the filter doesn't exist, add and save. + if (!helpers.global.inArray(params[key], values)) { + if (filterSettings.type === 'number') { + values.push(parseInt(params[key])); + } else { + values.push(decodeURIComponent(params[key])); + } + result.push(API.updateStoreFiltersKey(key, values)); + } else { + result.push(undefined); + } + } else { + result.push(undefined); + } + } + return result; + })(); + } + }); + + //# Storage. + + //# Store a filter set + App.reqres.setHandler('filter:store:set', function(filters) { + API.setStoreFilters(filters); + return filters; + }); + + //# Get a Stored a filter set + App.reqres.setHandler('filter:store:get', () => API.getStoreFilters()); + + //# Get a Stored a filter set for a given key + App.reqres.setHandler('filter:store:key:get', key => API.getStoreFiltersKey(key)); + + //# Update a key in a stored filter set. + App.reqres.setHandler('filter:store:key:update', (key, values = []) => API.updateStoreFiltersKey(key, values)); + + //# Toggle a value in a key and return the updated values + //# This feels long winded, maybe one day refactor/compress. + App.reqres.setHandler('filter:store:key:toggle', function(key, value) { + const values = API.getStoreFiltersKey(key); + let ret = []; + //# Remove. + if (_.indexOf(values, value) > -1) { + const newValues = []; + for (var i of values) { + if (i !== value) { + newValues.push(i); + } + } + ret = newValues; + } else { + //# Add. + values.push(value); + ret = values; + } + API.updateStoreFiltersKey(key, ret); + return ret; + }); + + //# Store a sort + App.reqres.setHandler('filter:sort:store:set', (method, order = 'asc') => API.setStoreSort(method, order)); + + //# Get a sort, fallback to default + return App.reqres.setHandler('filter:sort:store:get', () => API.getStoreSort()); +}); diff --git a/src/js/apps/filter/show/show_controller.js b/src/js/apps/filter/show/show_controller.js index 944f11d2..f39ad286 100644 --- a/src/js/apps/filter/show/show_controller.js +++ b/src/js/apps/filter/show/show_controller.js @@ -1,146 +1,181 @@ -@Kodi.module "FilterApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - class Show.Controller extends App.Controllers.Base - - getFilterView: -> - collection = @getOption('refCollection') - @layoutFilters = @getLayoutView collection - - ## Render subviews. - @listenTo @layoutFilters, "show", => - @getSort() - @getFilters() - @getActive() - @getSections() - - ## Change panes. - @listenTo @layoutFilters, 'filter:layout:close:filters', => - @stateChange('normal') - @listenTo @layoutFilters, 'filter:layout:close:options', => - @stateChange('filters') - @listenTo @layoutFilters, 'filter:layout:open:filters', => - @stateChange('filters') - @listenTo @layoutFilters, 'filter:layout:open:options', => - @stateChange('options') - - ## Return layout view. - @layoutFilters - - - ## Get the base layout - getLayoutView: (collection) -> - new Show.FilterLayout - collection: collection - - - getSort: -> - sortCollection = App.request 'filter:sortable:entities' - sortView = new Show.SortList - collection: sortCollection - @layoutFilters.regionSort.show sortView - ## Listen to click. - App.listenTo sortView, "childview:filter:sortable:select", (parentview, childview) => - App.request 'filter:sort:store:set', childview.model.get('key'), childview.model.get('order') - @layoutFilters.trigger 'filter:changed' - @getSort() - - - getFilters: (clearOptions = true) -> - filterCollection = App.request 'filter:filterable:entities' - filtersView = new Show.FilterList - collection: filterCollection - ## On filterable click. - App.listenTo filtersView, "childview:filter:filterable:select", (parentview, childview) => - key = childview.model.get('key') - if childview.model.get('type') is 'boolean' ## No options - App.request 'filter:store:key:toggle', key, childview.model.get('alias') - @triggerChange() - else - @getFilterOptions key - @stateChange('options') - ## Render the filters. - @layoutFilters.regionFiltersList.show filtersView - ## Empty the options ready for a change. - if clearOptions - @layoutFilters.regionFiltersOptions.empty() - - - getActive: -> - activeCollection = App.request 'filter:active' - optionsView = new Show.ActiveList - collection: activeCollection - @layoutFilters.regionFiltersActive.show optionsView - ## Get a new filtered collection and the current keys. - App.listenTo optionsView, "childview:filter:option:remove", (parentview, childview) => - key = childview.model.get('key') - App.request 'filter:store:key:update', key, [] - @triggerChange() - ## Bind to new and open filter pane - App.listenTo optionsView, "childview:filter:add", (parentview, childview) => - @stateChange('filters') - ## Add/remove filter bar - @getFilterBar() - - getFilterOptions: (key) -> - ## Create the options list view and add to dom - optionsCollection = App.request 'filter:options', key, @getOption('refCollection') - optionsView = new Show.OptionList - collection: optionsCollection - @layoutFilters.regionFiltersOptions.show optionsView - ## Get a new filtered collection and the current keys. - App.listenTo optionsView, "childview:filter:option:select", (parentview, childview) => - value = childview.model.get('value') - childview.view.$el.find('.option').toggleClass('active') - App.request 'filter:store:key:toggle', key, value - @triggerChange(false) ## dont clear options. - ## Deselect all - App.listenTo optionsView, 'filter:option:deselectall', (parentview) => - parentview.view.$el.find('.option').removeClass('active') - App.request 'filter:store:key:update', key, [] - @triggerChange(false) ## dont clear options. - - ## When something has changed. rerender the actives and notify other watchers. - triggerChange: (clearOptions = true) -> - App.vent.trigger 'filter:filtering:start' - @getFilters(clearOptions) - @getActive() - App.navigate helpers.url.path() - @layoutFilters.trigger 'filter:changed' - - - ## Deal with the filters bar showing all active filters - getFilterBar: -> - currentFilters = App.request 'filter:store:get' - list = _.flatten _.values(currentFilters) - $wrapper = $('.layout-container') - $list = $('.region-content-top', $wrapper) - if list.length > 0 - bar = new Show.FilterBar({filters: list}) - $list.html bar.render().$el - $wrapper.addClass('filters-active') - App.listenTo bar, 'filter:remove:all', => - App.request 'filter:store:set', {} - @triggerChange() - @stateChange('normal') - else - $wrapper.removeClass('filters-active') - - - ## state changes (slide the filter panes in and out) - stateChange: (state = 'normal') -> - $wrapper = @layoutFilters.$el.find('.filters-container') - switch state - when 'filters' - $wrapper.removeClass('show-options').addClass('show-filters') - when 'options' - $wrapper.addClass('show-options').removeClass('show-filters') - else - $wrapper.removeClass('show-options').removeClass('show-filters') - - - ## Populate the sections with structure from mainNav. - getSections: -> - collection = @getOption('refCollection') - if collection.sectionId - nav = App.request "navMain:children:show", collection.sectionId, 'Sections' - @layoutFilters.regionNavSection.show nav +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("FilterApp.Show", function(Show, App, Backbone, Marionette, $, _) { + + return Show.Controller = class Controller extends App.Controllers.Base { + + getFilterView() { + const collection = this.getOption('refCollection'); + this.layoutFilters = this.getLayoutView(collection); + + //# Render subviews. + this.listenTo(this.layoutFilters, "show", () => { + this.getSort(); + this.getFilters(); + this.getActive(); + return this.getSections(); + }); + + //# Change panes. + this.listenTo(this.layoutFilters, 'filter:layout:close:filters', () => { + return this.stateChange('normal'); + }); + this.listenTo(this.layoutFilters, 'filter:layout:close:options', () => { + return this.stateChange('filters'); + }); + this.listenTo(this.layoutFilters, 'filter:layout:open:filters', () => { + return this.stateChange('filters'); + }); + this.listenTo(this.layoutFilters, 'filter:layout:open:options', () => { + return this.stateChange('options'); + }); + + //# Return layout view. + return this.layoutFilters; + } + + + //# Get the base layout + getLayoutView(collection) { + return new Show.FilterLayout({ + collection}); + } + + + getSort() { + const sortCollection = App.request('filter:sortable:entities'); + const sortView = new Show.SortList({ + collection: sortCollection}); + this.layoutFilters.regionSort.show(sortView); + //# Listen to click. + return App.listenTo(sortView, "childview:filter:sortable:select", (parentview, childview) => { + App.request('filter:sort:store:set', childview.model.get('key'), childview.model.get('order')); + this.layoutFilters.trigger('filter:changed'); + return this.getSort(); + }); + } + + + getFilters(clearOptions = true) { + const filterCollection = App.request('filter:filterable:entities'); + const filtersView = new Show.FilterList({ + collection: filterCollection}); + //# On filterable click. + App.listenTo(filtersView, "childview:filter:filterable:select", (parentview, childview) => { + const key = childview.model.get('key'); + if (childview.model.get('type') === 'boolean') { //# No options + App.request('filter:store:key:toggle', key, childview.model.get('alias')); + return this.triggerChange(); + } else { + this.getFilterOptions(key); + return this.stateChange('options'); + } + }); + //# Render the filters. + this.layoutFilters.regionFiltersList.show(filtersView); + //# Empty the options ready for a change. + if (clearOptions) { + return this.layoutFilters.regionFiltersOptions.empty(); + } + } + + + getActive() { + const activeCollection = App.request('filter:active'); + const optionsView = new Show.ActiveList({ + collection: activeCollection}); + this.layoutFilters.regionFiltersActive.show(optionsView); + //# Get a new filtered collection and the current keys. + App.listenTo(optionsView, "childview:filter:option:remove", (parentview, childview) => { + const key = childview.model.get('key'); + App.request('filter:store:key:update', key, []); + return this.triggerChange(); + }); + //# Bind to new and open filter pane + App.listenTo(optionsView, "childview:filter:add", (parentview, childview) => { + return this.stateChange('filters'); + }); + //# Add/remove filter bar + return this.getFilterBar(); + } + + getFilterOptions(key) { + //# Create the options list view and add to dom + const optionsCollection = App.request('filter:options', key, this.getOption('refCollection')); + const optionsView = new Show.OptionList({ + collection: optionsCollection}); + this.layoutFilters.regionFiltersOptions.show(optionsView); + //# Get a new filtered collection and the current keys. + App.listenTo(optionsView, "childview:filter:option:select", (parentview, childview) => { + const value = childview.model.get('value'); + childview.view.$el.find('.option').toggleClass('active'); + App.request('filter:store:key:toggle', key, value); + return this.triggerChange(false); + }); //# dont clear options. + //# Deselect all + return App.listenTo(optionsView, 'filter:option:deselectall', parentview => { + parentview.view.$el.find('.option').removeClass('active'); + App.request('filter:store:key:update', key, []); + return this.triggerChange(false); + }); //# dont clear options. + } + + //# When something has changed. rerender the actives and notify other watchers. + triggerChange(clearOptions = true) { + App.vent.trigger('filter:filtering:start'); + this.getFilters(clearOptions); + this.getActive(); + App.navigate(helpers.url.path()); + return this.layoutFilters.trigger('filter:changed'); + } + + + //# Deal with the filters bar showing all active filters + getFilterBar() { + const currentFilters = App.request('filter:store:get'); + const list = _.flatten(_.values(currentFilters)); + const $wrapper = $('.layout-container'); + const $list = $('.region-content-top', $wrapper); + if (list.length > 0) { + const bar = new Show.FilterBar({filters: list}); + $list.html(bar.render().$el); + $wrapper.addClass('filters-active'); + return App.listenTo(bar, 'filter:remove:all', () => { + App.request('filter:store:set', {}); + this.triggerChange(); + return this.stateChange('normal'); + }); + } else { + return $wrapper.removeClass('filters-active'); + } + } + + + //# state changes (slide the filter panes in and out) + stateChange(state = 'normal') { + const $wrapper = this.layoutFilters.$el.find('.filters-container'); + switch (state) { + case 'filters': + return $wrapper.removeClass('show-options').addClass('show-filters'); + case 'options': + return $wrapper.addClass('show-options').removeClass('show-filters'); + default: + return $wrapper.removeClass('show-options').removeClass('show-filters'); + } + } + + + //# Populate the sections with structure from mainNav. + getSections() { + const collection = this.getOption('refCollection'); + if (collection.sectionId) { + const nav = App.request("navMain:children:show", collection.sectionId, 'Sections'); + return this.layoutFilters.regionNavSection.show(nav); + } + } + }; +}); diff --git a/src/js/apps/filter/show/show_view.js b/src/js/apps/filter/show/show_view.js index 0d2da711..309f8d72 100644 --- a/src/js/apps/filter/show/show_view.js +++ b/src/js/apps/filter/show/show_view.js @@ -1,130 +1,207 @@ -@Kodi.module "FilterApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - ### +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("FilterApp.Show", function(Show, App, Backbone, Marionette, $, _) { + + /* Base. - ### - - class Show.FilterLayout extends App.Views.LayoutView - template: 'apps/filter/show/filters_ui' - className: "side-bar" - regions: - regionSort: '.sort-options' - regionFiltersActive: '.filters-active' - regionFiltersList: '.filters-list' - regionFiltersOptions: '.filter-options-list' - regionNavSection: '.nav-section' - triggers: - 'click .close-filters' : 'filter:layout:close:filters' - 'click .close-options' : 'filter:layout:close:options' - 'click .open-filters' : 'filter:layout:open:filters' - - class Show.ListItem extends App.Views.ItemView - template: 'apps/filter/show/list_item' - tagName: 'li' - - class Show.List extends App.Views.CollectionView - childView: Show.ListItem - tagName: "ul" - className: "selection-list" - - - ### + */ + + let Cls = (Show.FilterLayout = class FilterLayout extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/filter/show/filters_ui'; + this.prototype.className = "side-bar"; + this.prototype.regions = { + regionSort: '.sort-options', + regionFiltersActive: '.filters-active', + regionFiltersList: '.filters-list', + regionFiltersOptions: '.filter-options-list', + regionNavSection: '.nav-section' + }; + this.prototype.triggers = { + 'click .close-filters' : 'filter:layout:close:filters', + 'click .close-options' : 'filter:layout:close:options', + 'click .open-filters' : 'filter:layout:open:filters' + }; + } + }); + Cls.initClass(); + + Cls = (Show.ListItem = class ListItem extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/filter/show/list_item'; + this.prototype.tagName = 'li'; + } + }); + Cls.initClass(); + + Cls = (Show.List = class List extends App.Views.CollectionView { + static initClass() { + this.prototype.childView = Show.ListItem; + this.prototype.tagName = "ul"; + this.prototype.className = "selection-list"; + } + }); + Cls.initClass(); + + + /* Extends. - ### - - - ## Sort. - - class Show.SortListItem extends Show.ListItem - triggers: - "click .sortable": "filter:sortable:select" - initialize: -> - classes = ['option', 'sortable'] - if @model.get('active') is true - classes.push 'active' - classes.push 'order-' + @model.get('order') - tag = @themeTag('span', {'class': classes.join(' ')}, t.gettext(@model.get('alias'))) - @model.set(title: tag) - - class Show.SortList extends Show.List - childView: Show.SortListItem - - - ## Filter - - class Show.FilterListItem extends Show.ListItem - triggers: - "click .filterable": "filter:filterable:select" - initialize: -> - classes = ['option', 'option filterable'] - if @model.get('active') - classes.push 'active' - tag = @themeTag('span', {'class': classes.join(' ')}, t.gettext(@model.get('alias'))) - @model.set(title: tag) - - - class Show.FilterList extends Show.List - childView: Show.FilterListItem - - - ## Filter option. - - class Show.OptionListItem extends Show.ListItem - triggers: - "click .filterable-option" : "filter:option:select" - initialize: -> - classes = ['option', 'option filterable-option'] - if @model.get('active') - classes.push 'active' - tag = @themeTag('span', {'class': classes.join(' ')}, @model.get('value')) - @model.set(title: tag) - - class Show.OptionList extends App.Views.CompositeView - template: 'apps/filter/show/filter_options' - activeValues: [] - childView: Show.OptionListItem - childViewContainer: 'ul.selection-list' - onRender: -> - ## hide filter search if < 10 items - if @collection.length <= 10 - $('.options-search-wrapper', @$el).addClass('hidden') - ## Filter options via search box. - $('.options-search', @$el).filterList() - triggers: - 'click .deselect-all': 'filter:option:deselectall' - - - ## Active Filters. - - class Show.ActiveListItem extends Show.ListItem - triggers: - "click .filterable-remove" : "filter:option:remove" - initialize: -> - tooltip = t.gettext('Remove') + ' ' + @model.escape('key') + ' ' + t.gettext('filter') - text = @themeTag('span', {'class': 'text'}, @model.get('values').join(', ')) - tag = @themeTag('span', {'class': 'filter-btn filterable-remove', title: tooltip}, text) - @model.set(title: tag) - - class Show.ActiveNewListItem extends Show.ListItem - triggers: - "click .filterable-add" : "filter:add" - initialize: -> - tag = @themeTag('span', {'class': 'filter-btn filterable-add'}, t.gettext('Add filter')) - @model.set(title: tag) - - class Show.ActiveList extends Show.List - childView: Show.ActiveListItem - emptyView: Show.ActiveNewListItem - className: "active-list" - - - ## Filters bar - - class Show.FilterBar extends App.Views.ItemView - template: 'apps/filter/show/filters_bar' - className: "filters-active-bar" - onRender: -> - if @options.filters - $('.filters-active-all', @$el).text( @options.filters.join(', ') ) - triggers: - 'click .remove': 'filter:remove:all' + */ + + + //# Sort. + + Cls = (Show.SortListItem = class SortListItem extends Show.ListItem { + static initClass() { + this.prototype.triggers = + {"click .sortable": "filter:sortable:select"}; + } + initialize() { + const classes = ['option', 'sortable']; + if (this.model.get('active') === true) { + classes.push('active'); + } + classes.push('order-' + this.model.get('order')); + const tag = this.themeTag('span', {'class': classes.join(' ')}, t.gettext(this.model.get('alias'))); + return this.model.set({title: tag}); + } + }); + Cls.initClass(); + + Cls = (Show.SortList = class SortList extends Show.List { + static initClass() { + this.prototype.childView = Show.SortListItem; + } + }); + Cls.initClass(); + + + //# Filter + + Cls = (Show.FilterListItem = class FilterListItem extends Show.ListItem { + static initClass() { + this.prototype.triggers = + {"click .filterable": "filter:filterable:select"}; + } + initialize() { + const classes = ['option', 'option filterable']; + if (this.model.get('active')) { + classes.push('active'); + } + const tag = this.themeTag('span', {'class': classes.join(' ')}, t.gettext(this.model.get('alias'))); + return this.model.set({title: tag}); + } + }); + Cls.initClass(); + + + Cls = (Show.FilterList = class FilterList extends Show.List { + static initClass() { + this.prototype.childView = Show.FilterListItem; + } + }); + Cls.initClass(); + + + //# Filter option. + + Cls = (Show.OptionListItem = class OptionListItem extends Show.ListItem { + static initClass() { + this.prototype.triggers = + {"click .filterable-option" : "filter:option:select"}; + } + initialize() { + const classes = ['option', 'option filterable-option']; + if (this.model.get('active')) { + classes.push('active'); + } + const tag = this.themeTag('span', {'class': classes.join(' ')}, this.model.get('value')); + return this.model.set({title: tag}); + } + }); + Cls.initClass(); + + Cls = (Show.OptionList = class OptionList extends App.Views.CompositeView { + static initClass() { + this.prototype.template = 'apps/filter/show/filter_options'; + this.prototype.activeValues = []; + this.prototype.childView = Show.OptionListItem; + this.prototype.childViewContainer = 'ul.selection-list'; + this.prototype.triggers = + {'click .deselect-all': 'filter:option:deselectall'}; + } + onRender() { + //# hide filter search if < 10 items + if (this.collection.length <= 10) { + $('.options-search-wrapper', this.$el).addClass('hidden'); + } + //# Filter options via search box. + return $('.options-search', this.$el).filterList(); + } + }); + Cls.initClass(); + + + //# Active Filters. + + Cls = (Show.ActiveListItem = class ActiveListItem extends Show.ListItem { + static initClass() { + this.prototype.triggers = + {"click .filterable-remove" : "filter:option:remove"}; + } + initialize() { + const tooltip = t.gettext('Remove') + ' ' + this.model.escape('key') + ' ' + t.gettext('filter'); + const text = this.themeTag('span', {'class': 'text'}, this.model.get('values').join(', ')); + const tag = this.themeTag('span', {'class': 'filter-btn filterable-remove', title: tooltip}, text); + return this.model.set({title: tag}); + } + }); + Cls.initClass(); + + Cls = (Show.ActiveNewListItem = class ActiveNewListItem extends Show.ListItem { + static initClass() { + this.prototype.triggers = + {"click .filterable-add" : "filter:add"}; + } + initialize() { + const tag = this.themeTag('span', {'class': 'filter-btn filterable-add'}, t.gettext('Add filter')); + return this.model.set({title: tag}); + } + }); + Cls.initClass(); + + Cls = (Show.ActiveList = class ActiveList extends Show.List { + static initClass() { + this.prototype.childView = Show.ActiveListItem; + this.prototype.emptyView = Show.ActiveNewListItem; + this.prototype.className = "active-list"; + } + }); + Cls.initClass(); + + + //# Filters bar + + return (function() { + Cls = (Show.FilterBar = class FilterBar extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/filter/show/filters_bar'; + this.prototype.className = "filters-active-bar"; + this.prototype.triggers = + {'click .remove': 'filter:remove:all'}; + } + onRender() { + if (this.options.filters) { + return $('.filters-active-all', this.$el).text( this.options.filters.join(', ') ); + } + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/help/help_app.js b/src/js/apps/help/help_app.js index 9f011085..5f12b64e 100644 --- a/src/js/apps/help/help_app.js +++ b/src/js/apps/help/help_app.js @@ -1,59 +1,78 @@ -@Kodi.module "HelpApp", (HelpApp, App, Backbone, Marionette, $, _) -> - - class HelpApp.Router extends App.Router.Base - appRoutes: - "help" : "helpOverview" - "help/overview" : "helpOverview" - "help/:id" : "helpPage" - - API = - - helpOverview: -> - new App.HelpApp.Overview.Controller() - - helpPage: (id) -> - new HelpApp.Show.Controller - id: id - - # Get a html page with jQuery ajax - getPage: (id, lang = 'en', callback) -> - content = $.get("lang/#{lang}/#{id}.html") - content.fail (error) -> - if lang != 'en' - API.getPage id, 'en', callback - content.done (data) -> - callback data - content - - # Get second level nav - getSubNav: -> - collection = App.request "navMain:array:entities", @getSideBarStructure() - App.request "navMain:collection:show", collection, t.gettext('Help topics') - - # Get second level nav structure - # TODO: refactor into navMain - getSideBarStructure: -> - [ - {title: t.gettext('About'), path: 'help'} - {title: t.gettext('Readme'), path: 'help/app-readme'} - {title: t.gettext('Changelog'), path: 'help/app-changelog'} - {title: t.gettext('Keyboard'), path: 'help/keybind-readme'} - {title: t.gettext('Add-ons'), path: 'help/addons'} - {title: t.gettext('Developers'), path: 'help/developers'} - {title: t.gettext('Translations'), path: 'help/lang-readme'} +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("HelpApp", function(HelpApp, App, Backbone, Marionette, $, _) { + + const Cls = (HelpApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "help" : "helpOverview", + "help/overview" : "helpOverview", + "help/:id" : "helpPage" + }; + } + }); + Cls.initClass(); + + var API = { + + helpOverview() { + return new App.HelpApp.Overview.Controller(); + }, + + helpPage(id) { + return new HelpApp.Show.Controller({ + id}); + }, + + // Get a html page with jQuery ajax + getPage(id, lang = 'en', callback) { + const content = $.get(`lang/${lang}/${id}.html`); + content.fail(function(error) { + if (lang !== 'en') { + return API.getPage(id, 'en', callback); + } + }); + content.done(data => callback(data)); + return content; + }, + + // Get second level nav + getSubNav() { + const collection = App.request("navMain:array:entities", this.getSideBarStructure()); + return App.request("navMain:collection:show", collection, t.gettext('Help topics')); + }, + + // Get second level nav structure + // TODO: refactor into navMain + getSideBarStructure() { + return [ + {title: t.gettext('About'), path: 'help'}, + {title: t.gettext('Readme'), path: 'help/app-readme'}, + {title: t.gettext('Changelog'), path: 'help/app-changelog'}, + {title: t.gettext('Keyboard'), path: 'help/keybind-readme'}, + {title: t.gettext('Add-ons'), path: 'help/addons'}, + {title: t.gettext('Developers'), path: 'help/developers'}, + {title: t.gettext('Translations'), path: 'help/lang-readme'}, {title: t.gettext('License'), path: 'help/license'} - ] + ]; + } + }; - # Subnav for help - App.reqres.setHandler 'help:subnav', -> - API.getSubNav() + // Subnav for help + App.reqres.setHandler('help:subnav', () => API.getSubNav()); - # Get a page via jQuery, use current language - App.reqres.setHandler 'help:page', (id, callback) -> - lang = config.getLocal 'lang', 'en' - API.getPage id, lang, callback + // Get a page via jQuery, use current language + App.reqres.setHandler('help:page', function(id, callback) { + const lang = config.getLocal('lang', 'en'); + return API.getPage(id, lang, callback); + }); - ## Start the router. - App.on "before:start", -> - new HelpApp.Router - controller: API + //# Start the router. + return App.on("before:start", () => new HelpApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/help/overview/overview_controller.js b/src/js/apps/help/overview/overview_controller.js index 70f1e80d..42993ef2 100644 --- a/src/js/apps/help/overview/overview_controller.js +++ b/src/js/apps/help/overview/overview_controller.js @@ -1,79 +1,103 @@ -@Kodi.module "HelpApp.Overview", (Overview, App, Backbone, Marionette, $, _) -> - - class Overview.Controller extends App.Controllers.Base - - initialize: (options) -> - - # Load the page - App.request "help:page", 'help-overview', (data) => - - @layout = @getLayoutView data - @listenTo @layout, "show", => - @getSideBar() - @getPage data - - # Render layout - App.regionContent.show @layout - - getPage: (data) -> - @pageView = new Overview.Page - data: data - @listenTo @pageView, "show", => - @getReport() - - @layout.regionContent.show @pageView - - getSideBar: -> - subNav = App.request "help:subnav" - @layout.regionSidebarFirst.show subNav - - getLayoutView: -> - new Overview.Layout() - - getReport: -> - - # jQuery obj for page view - @$pageView = @pageView.$el - - @getReportChorusVersion() - @getReportKodiVersion() - @getReportWebsocketsActive() - @getReportLocalAudio() - - # We might have just called to early, bind to available event just in case. - App.vent.on "sockets:available", => - @getReportWebsocketsActive() - App.vent.on "state:initialized", => - @getReportKodiVersion() - - # - # Callbacks for getting/setting report values below. - # TODO: Refactor... Shouldn't be using jQuery to insert content - # - - # Chorus version. - getReportChorusVersion: -> - $.get "addon.xml", (data) => - $('.report-chorus-version > span', @$pageView).text $('addon', data).attr('version') - - # Kodi version - getReportKodiVersion: -> - state = App.request "state:kodi" - kodiVersion = state.getState('version') - $('.report-kodi-version > span', @$pageView).text kodiVersion.major + '.' + kodiVersion.minor - - # Web sockets. - getReportWebsocketsActive: -> - wsActive = App.request "sockets:active" - $ws = $('.report-websockets', @$pageView) - if wsActive - $('span', $ws).text tr("Remote control is set up correctly") - $ws.removeClass 'warning' - else - $('span', $ws).html tr("You need to 'Allow remote control' for Kodi. You can do that") + ' ' + tr('here') + '' - $ws.addClass 'warning' - - # Local audio - getReportLocalAudio: -> - localAudio = if soundManager.useHTML5Audio then "HTML 5" else "Flash" - $('.report-local-audio > span', @$pageView) .text localAudio +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("HelpApp.Overview", function(Overview, App, Backbone, Marionette, $, _) { + + return Overview.Controller = class Controller extends App.Controllers.Base { + + initialize(options) { + + // Load the page + return App.request("help:page", 'help-overview', data => { + + this.layout = this.getLayoutView(data); + this.listenTo(this.layout, "show", () => { + this.getSideBar(); + return this.getPage(data); + }); + + // Render layout + return App.regionContent.show(this.layout); + }); + } + + getPage(data) { + this.pageView = new Overview.Page({ + data}); + this.listenTo(this.pageView, "show", () => { + return this.getReport(); + }); + + return this.layout.regionContent.show(this.pageView); + } + + getSideBar() { + const subNav = App.request("help:subnav"); + return this.layout.regionSidebarFirst.show(subNav); + } + + getLayoutView() { + return new Overview.Layout(); + } + + getReport() { + + // jQuery obj for page view + this.$pageView = this.pageView.$el; + + this.getReportChorusVersion(); + this.getReportKodiVersion(); + this.getReportWebsocketsActive(); + this.getReportLocalAudio(); + + // We might have just called to early, bind to available event just in case. + App.vent.on("sockets:available", () => { + return this.getReportWebsocketsActive(); + }); + return App.vent.on("state:initialized", () => { + return this.getReportKodiVersion(); + }); + } + + // + // Callbacks for getting/setting report values below. + // TODO: Refactor... Shouldn't be using jQuery to insert content + // + + // Chorus version. + getReportChorusVersion() { + return $.get("addon.xml", data => { + return $('.report-chorus-version > span', this.$pageView).text($('addon', data).attr('version')); + }); + } + + // Kodi version + getReportKodiVersion() { + const state = App.request("state:kodi"); + const kodiVersion = state.getState('version'); + return $('.report-kodi-version > span', this.$pageView).text(kodiVersion.major + '.' + kodiVersion.minor); + } + + // Web sockets. + getReportWebsocketsActive() { + const wsActive = App.request("sockets:active"); + const $ws = $('.report-websockets', this.$pageView); + if (wsActive) { + $('span', $ws).text(tr("Remote control is set up correctly")); + return $ws.removeClass('warning'); + } else { + $('span', $ws).html(tr("You need to 'Allow remote control' for Kodi. You can do that") + ' ' + tr('here') + ''); + return $ws.addClass('warning'); + } + } + + // Local audio + getReportLocalAudio() { + const localAudio = soundManager.useHTML5Audio ? "HTML 5" : "Flash"; + return $('.report-local-audio > span', this.$pageView) .text(localAudio); + } + }; +}); diff --git a/src/js/apps/help/overview/overview_view.js b/src/js/apps/help/overview/overview_view.js index a7dcc19a..39d71d16 100644 --- a/src/js/apps/help/overview/overview_view.js +++ b/src/js/apps/help/overview/overview_view.js @@ -1,22 +1,42 @@ -# View for the API Browser. -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "HelpApp.Overview", (Overview, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// View for the API Browser. +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("HelpApp.Overview", function(Overview, App, Backbone, Marionette, $, _) { - class Overview.Page extends App.Views.CompositeView - className: "help--overview" - template: 'apps/help/overview/overview' - tagName: "div" - onRender: -> - # Set the data/header. - $('.help--overview--header', @$el).html @options.data + let Cls = (Overview.Page = class Page extends App.Views.CompositeView { + static initClass() { + this.prototype.className = "help--overview"; + this.prototype.template = 'apps/help/overview/overview'; + this.prototype.tagName = "div"; + } + onRender() { + // Set the data/header. + return $('.help--overview--header', this.$el).html(this.options.data); + } + }); + Cls.initClass(); - class Overview.Layout extends App.Views.LayoutWithSidebarFirstView - className: "help--page help--overview page-wrapper" + return (function() { + Cls = (Overview.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "help--page help--overview page-wrapper"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/help/show/show_controller.js b/src/js/apps/help/show/show_controller.js index 911b442e..5524ef4f 100644 --- a/src/js/apps/help/show/show_controller.js +++ b/src/js/apps/help/show/show_controller.js @@ -1,29 +1,44 @@ -@Kodi.module "HelpApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - # Main controller - class Show.Controller extends App.Controllers.Base - - initialize: (options) -> - - # Load the page - App.request "help:page", options.id, (data) => - - @layout = @getLayoutView data - @listenTo @layout, "show", => - @getSideBar() - - # Render layout - App.regionContent.show @layout - - # If a page view is overridden set that to the content. - if options.pageView - @layout.regionContent.show options.pageView - - getSideBar: -> - subNav = App.request "help:subnav" - @layout.regionSidebarFirst.show subNav - - getLayoutView: (data) -> - new Show.Layout - data: data - pageView: @options.pageView +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("HelpApp.Show", function(Show, App, Backbone, Marionette, $, _) { + + // Main controller + return Show.Controller = class Controller extends App.Controllers.Base { + + initialize(options) { + + // Load the page + return App.request("help:page", options.id, data => { + + this.layout = this.getLayoutView(data); + this.listenTo(this.layout, "show", () => { + return this.getSideBar(); + }); + + // Render layout + App.regionContent.show(this.layout); + + // If a page view is overridden set that to the content. + if (options.pageView) { + return this.layout.regionContent.show(options.pageView); + } + }); + } + + getSideBar() { + const subNav = App.request("help:subnav"); + return this.layout.regionSidebarFirst.show(subNav); + } + + getLayoutView(data) { + return new Show.Layout({ + data, + pageView: this.options.pageView + }); + } + }; +}); diff --git a/src/js/apps/help/show/show_view.js b/src/js/apps/help/show/show_view.js index 425f4622..f42c8179 100644 --- a/src/js/apps/help/show/show_view.js +++ b/src/js/apps/help/show/show_view.js @@ -1,16 +1,29 @@ -# View for the API Browser. -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "HelpApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - class Show.Layout extends App.Views.LayoutWithSidebarFirstView - className: "help--page page-wrapper" - onRender: -> - # Set the data. - $(@regionContent.el, @$el).html @options.data +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// View for the API Browser. +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("HelpApp.Show", (Show, App, Backbone, Marionette, $, _) => (function() { + const Cls = (Show.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "help--page page-wrapper"; + } + onRender() { + // Set the data. + return $(this.regionContent.el, this.$el).html(this.options.data); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/images/images_app.js b/src/js/apps/images/images_app.js index 3a6f8ca3..1231ba7e 100644 --- a/src/js/apps/images/images_app.js +++ b/src/js/apps/images/images_app.js @@ -1,78 +1,101 @@ -@Kodi.module "Images", (Images, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("Images", function(Images, App, Backbone, Marionette, $, _) { - API = + var API = { - imagesPath: 'images/' + imagesPath: 'images/', - defaultFanartPath: 'fanart_default/' + defaultFanartPath: 'fanart_default/', defaultFanartFiles: [ - 'cans.jpg' - 'guitar.jpg' - 'speaker.jpg' + 'cans.jpg', + 'guitar.jpg', + 'speaker.jpg', 'turntable.jpg', 'amp.jpg', 'concert.jpg', 'tweeter.jpg', - ] + ], - getDefaultThumbnail: -> - API.imagesPath + 'thumbnail_default.png' + getDefaultThumbnail() { + return API.imagesPath + 'thumbnail_default.png'; + }, - getRandomFanart: -> - rand = helpers.global.getRandomInt(0, API.defaultFanartFiles.length - 1) - file = API.defaultFanartFiles[rand] - path = API.imagesPath + API.defaultFanartPath + file - path + getRandomFanart() { + const rand = helpers.global.getRandomInt(0, API.defaultFanartFiles.length - 1); + const file = API.defaultFanartFiles[rand]; + const path = API.imagesPath + API.defaultFanartPath + file; + return path; + }, - parseRawPath: (rawPath) -> - path = if config.getLocal 'reverseProxy' then 'image/' + encodeURIComponent(rawPath) else '/image/' + encodeURIComponent(rawPath) - path + parseRawPath(rawPath) { + const path = config.getLocal('reverseProxy') ? 'image/' + encodeURIComponent(rawPath) : '/image/' + encodeURIComponent(rawPath); + return path; + }, - ## set background fanart, string to 'none' removes fanart - setFanartBackground: (path, region) -> - $body = App.getRegion(region).$el - if path isnt 'none' - if not path - path = @getRandomFanart() - $body.css('background-image', 'url(' + path + ')') - else - $body.removeAttr('style') + //# set background fanart, string to 'none' removes fanart + setFanartBackground(path, region) { + const $body = App.getRegion(region).$el; + if (path !== 'none') { + if (!path) { + path = this.getRandomFanart(); + } + return $body.css('background-image', 'url(' + path + ')'); + } else { + return $body.removeAttr('style'); + } + }, - getImageUrl: (rawPath, type = 'thumbnail', useFallback = true) -> - path = '' - if not rawPath? or rawPath is '' - switch type - when 'fanart' then path = API.getRandomFanart() - else path = API.getDefaultThumbnail() - else if type is 'trailer' - path = API.getTrailerUrl(rawPath) - else - path = API.parseRawPath(rawPath) - path + getImageUrl(rawPath, type = 'thumbnail', useFallback = true) { + let path = ''; + if ((rawPath == null) || (rawPath === '')) { + switch (type) { + case 'fanart': path = API.getRandomFanart(); break; + default: path = API.getDefaultThumbnail(); + } + } else if (type === 'trailer') { + path = API.getTrailerUrl(rawPath); + } else { + path = API.parseRawPath(rawPath); + } + return path; + }, - getTrailerUrl: (rawpath) -> - trailer = helpers.url.parseTrailerUrl (rawpath) - trailer.img + getTrailerUrl(rawpath) { + const trailer = helpers.url.parseTrailerUrl((rawpath)); + return trailer.img; + } + }; - ## Handler to set the background fanart pic. - App.commands.setHandler "images:fanart:set", (path, region = 'regionFanart') -> - API.setFanartBackground path, region + //# Handler to set the background fanart pic. + App.commands.setHandler("images:fanart:set", (path, region = 'regionFanart') => API.setFanartBackground(path, region)); - ## Handler to return a parsed image path. - App.reqres.setHandler "images:path:get", (rawPath = '', type = 'thumbnail') -> - API.getImageUrl(rawPath, type) + //# Handler to return a parsed image path. + App.reqres.setHandler("images:path:get", (rawPath = '', type = 'thumbnail') => API.getImageUrl(rawPath, type)); - ## Handler to apply correct paths to a model, expects to be called - ## on the model attributes, typically during a model.parse() - App.reqres.setHandler "images:path:entity", (model) -> - if model.thumbnail? - model.thumbnailOriginal = model.thumbnail - model.thumbnail = API.getImageUrl(model.thumbnail, 'thumbnail') - if model.fanart? - model.fanartOriginal = model.fanart - model.fanart = API.getImageUrl(model.fanart, 'fanart') - if model.cast? and model.cast.length > 0 - for i, person of model.cast - model.cast[i].thumbnail = API.getImageUrl(person.thumbnail, 'thumbnail') - model + //# Handler to apply correct paths to a model, expects to be called + //# on the model attributes, typically during a model.parse() + return App.reqres.setHandler("images:path:entity", function(model) { + if (model.thumbnail != null) { + model.thumbnailOriginal = model.thumbnail; + model.thumbnail = API.getImageUrl(model.thumbnail, 'thumbnail'); + } + if (model.fanart != null) { + model.fanartOriginal = model.fanart; + model.fanart = API.getImageUrl(model.fanart, 'fanart'); + } + if ((model.cast != null) && (model.cast.length > 0)) { + for (var i in model.cast) { + var person = model.cast[i]; + model.cast[i].thumbnail = API.getImageUrl(person.thumbnail, 'thumbnail'); + } + } + return model; + }); +}); diff --git a/src/js/apps/input/input_app.js b/src/js/apps/input/input_app.js index f6ed33c2..7985ac2e 100644 --- a/src/js/apps/input/input_app.js +++ b/src/js/apps/input/input_app.js @@ -1,163 +1,193 @@ -@Kodi.module "InputApp", (InputApp, App, Backbone, Marionette, $, _) -> - - - class InputApp.Router extends App.Router.Base - appRoutes: - "remote" : "remotePage" - - - API = - - initKeyBind: -> - $(document).keydown (e) => - @keyBind e - - ## The input controller - inputController: -> - App.request "command:kodi:controller", 'auto', 'Input' - - ## Do an input command - doInput: (type) -> - @inputController().sendInput type, [] - - ## Do an action - ## http://kodi.wiki/view/JSON-RPC_API/v6#Input.Action - doAction: (action) -> - @inputController().sendInput 'ExecuteAction', [action] - - ## Send a player command. - doCommand: (command, params, callback) -> - App.request 'command:kodi:player', command, params, => - @pollingUpdate(callback) - - ## Get the Kodi application controller - appController: -> - App.request "command:kodi:controller", 'auto', 'Application' - - ## Wrapper for requesting a state update if no sockets - pollingUpdate: (callback) -> - if not App.request 'sockets:active' - App.request 'state:kodi:update', callback - - ## Toggle remote visibility and path - toggleRemote: (open = 'auto') -> - $body = $('body') - rClass = 'section-remote' - if open is 'auto' - open = ($body.hasClass(rClass)) - if open - window.history.back() - helpers.backscroll.scrollToLast() - else - helpers.backscroll.setLast() - App.navigate("remote", {trigger: true}); - - ## Page callback, open remote and clear content. - remotePage: -> - @toggleRemote('auto'); - App.regionContent.empty() - - ## The input binds - keyBind: (e) -> - - # Get settings - kodiControl = config.getLocal('keyboardControl') is 'kodi' - remotePage = $('body').hasClass('page-remote') - - ## Don't do anything if forms in use or if we have a local only setting - if $(e.target).is("input, textarea, select") - return - - ## Don't do anything for white listed commands like CTRL, ALT, SHIFT, etc - whiteListCommands = [17, 16, 91, 18, 70] - if helpers.global.inArray e.which, whiteListCommands - return - - # If no Kodi control and not on the remote page - if not kodiControl and not remotePage - return - - # If all keyboard controls are for kodi or on the remote page - if kodiControl or remotePage - e.preventDefault() - - ## Get stateObj - consider changing this to be current and work with local too? - stateObj = App.request "state:kodi" - - ## Respond to key code - switch e.which - when 37, 72 # left, h - @doInput "Left" - when 38, 75 # up, k - @doInput "Up" - when 39, 76 # right, l - @doInput "Right" - when 40, 74 # down, j - @doInput "Down" - when 8 # backspace - @doInput "Back" - when 13 # enter - @doInput "Select" - when 67 # c (context) - @doInput "ContextMenu" - when 107, 187, 61 # + (vol up) - vol = stateObj.getState('volume') + 5 - @appController().setVolume ((if vol > 100 then 100 else Math.ceil(vol))) - when 109, 189, 173 # - (vol down) - vol = stateObj.getState('volume') - 5 - @appController().setVolume ((if vol < 0 then 0 else Math.ceil(vol))) - when 77 # m (mute) - @appController().toggleMute() - when 32 # spacebar (play/pause) - @doCommand "PlayPause", "toggle" - when 88 # x (stop) - @doCommand "Stop" - when 84 # t (toggle subtitles) - @doAction "showsubtitles" - when 9 # tab (close osd) - @doAction "close" - when 190 # > (next) - @doCommand "GoTo", "next" - when 188 # < (prev) - @doCommand "GoTo", "previous" - when 220, 160 # Backslash, ^ (firefox) (fullscreen) - @doAction "fullscreen" - when 79 # o (osd) - @doAction "osd" - else # return everything else here - - - App.commands.setHandler "input:textbox", (msg) -> - App.execute "ui:textinput:show", "Input required", {msg: msg}, (text) -> - API.inputController().sendText(text) - App.execute "notification:show", t.gettext('Sent text') + ' "' + text + '" ' + t.gettext('to Kodi') - - App.commands.setHandler "input:textbox:close", -> - App.execute "ui:modal:close" - - App.commands.setHandler "input:send", (action) -> - API.doInput action - - App.commands.setHandler "input:remote:toggle", -> - API.toggleRemote() - - App.commands.setHandler "input:action", (action) -> - API.doAction(action) - - App.commands.setHandler "input:resume", (model, idKey) -> - controller = new InputApp.Resume.Controller() - controller.resumePlay model, idKey - - ## Startup tasks. - App.addInitializer -> - - ## Render remote - controller = new InputApp.Remote.Controller() - - ## Bind to the keyboard inputs - API.initKeyBind() - - ## Start the router. - App.on "before:start", -> - new InputApp.Router - controller: API +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("InputApp", function(InputApp, App, Backbone, Marionette, $, _) { + + + const Cls = (InputApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = + {"remote" : "remotePage"}; + } + }); + Cls.initClass(); + + + const API = { + + initKeyBind() { + return $(document).keydown(e => { + return this.keyBind(e); + }); + }, + + //# The input controller + inputController() { + return App.request("command:kodi:controller", 'auto', 'Input'); + }, + + //# Do an input command + doInput(type) { + return this.inputController().sendInput(type, []); + }, + + //# Do an action + //# http://kodi.wiki/view/JSON-RPC_API/v6#Input.Action + doAction(action) { + return this.inputController().sendInput('ExecuteAction', [action]); + }, + + //# Send a player command. + doCommand(command, params, callback) { + return App.request('command:kodi:player', command, params, () => { + return this.pollingUpdate(callback); + }); + }, + + //# Get the Kodi application controller + appController() { + return App.request("command:kodi:controller", 'auto', 'Application'); + }, + + //# Wrapper for requesting a state update if no sockets + pollingUpdate(callback) { + if (!App.request('sockets:active')) { + return App.request('state:kodi:update', callback); + } + }, + + //# Toggle remote visibility and path + toggleRemote(open = 'auto') { + const $body = $('body'); + const rClass = 'section-remote'; + if (open === 'auto') { + open = ($body.hasClass(rClass)); + } + if (open) { + window.history.back(); + return helpers.backscroll.scrollToLast(); + } else { + helpers.backscroll.setLast(); + return App.navigate("remote", {trigger: true}); + } + }, + + //# Page callback, open remote and clear content. + remotePage() { + this.toggleRemote('auto'); + return App.regionContent.empty(); + }, + + //# The input binds + keyBind(e) { + + // Get settings + const kodiControl = config.getLocal('keyboardControl') === 'kodi'; + const remotePage = $('body').hasClass('page-remote'); + + //# Don't do anything if forms in use or if we have a local only setting + if ($(e.target).is("input, textarea, select")) { + return; + } + + //# Don't do anything for white listed commands like CTRL, ALT, SHIFT, etc + const whiteListCommands = [17, 16, 91, 18, 70]; + if (helpers.global.inArray(e.which, whiteListCommands)) { + return; + } + + // If no Kodi control and not on the remote page + if (!kodiControl && !remotePage) { + return; + } + + // If all keyboard controls are for kodi or on the remote page + if (kodiControl || remotePage) { + e.preventDefault(); + } + + //# Get stateObj - consider changing this to be current and work with local too? + const stateObj = App.request("state:kodi"); + + //# Respond to key code + switch (e.which) { + case 37: case 72: // left, h + return this.doInput("Left"); + case 38: case 75: // up, k + return this.doInput("Up"); + case 39: case 76: // right, l + return this.doInput("Right"); + case 40: case 74: // down, j + return this.doInput("Down"); + case 8: // backspace + return this.doInput("Back"); + case 13: // enter + return this.doInput("Select"); + case 67: // c (context) + return this.doInput("ContextMenu"); + case 107: case 187: case 61: // + (vol up) + var vol = stateObj.getState('volume') + 5; + return this.appController().setVolume(((vol > 100 ? 100 : Math.ceil(vol)))); + case 109: case 189: case 173: // - (vol down) + vol = stateObj.getState('volume') - 5; + return this.appController().setVolume(((vol < 0 ? 0 : Math.ceil(vol)))); + case 77: // m (mute) + return this.appController().toggleMute(); + case 32: // spacebar (play/pause) + return this.doCommand("PlayPause", "toggle"); + case 88: // x (stop) + return this.doCommand("Stop"); + case 84: // t (toggle subtitles) + return this.doAction("showsubtitles"); + case 9: // tab (close osd) + return this.doAction("close"); + case 190: // > (next) + return this.doCommand("GoTo", "next"); + case 188: // < (prev) + return this.doCommand("GoTo", "previous"); + case 220: case 160: // Backslash, ^ (firefox) (fullscreen) + return this.doAction("fullscreen"); + case 79: // o (osd) + return this.doAction("osd"); + default: + } + } // return everything else here + }; + + + App.commands.setHandler("input:textbox", msg => App.execute("ui:textinput:show", "Input required", {msg}, function(text) { + API.inputController().sendText(text); + return App.execute("notification:show", t.gettext('Sent text') + ' "' + text + '" ' + t.gettext('to Kodi')); + })); + + App.commands.setHandler("input:textbox:close", () => App.execute("ui:modal:close")); + + App.commands.setHandler("input:send", action => API.doInput(action)); + + App.commands.setHandler("input:remote:toggle", () => API.toggleRemote()); + + App.commands.setHandler("input:action", action => API.doAction(action)); + + App.commands.setHandler("input:resume", function(model, idKey) { + const controller = new InputApp.Resume.Controller(); + return controller.resumePlay(model, idKey); + }); + + //# Startup tasks. + App.addInitializer(function() { + + //# Render remote + const controller = new InputApp.Remote.Controller(); + + //# Bind to the keyboard inputs + return API.initKeyBind(); + }); + + //# Start the router. + return App.on("before:start", () => new InputApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/input/remote/remote_controller.js b/src/js/apps/input/remote/remote_controller.js index 3cc03424..1f7caf24 100644 --- a/src/js/apps/input/remote/remote_controller.js +++ b/src/js/apps/input/remote/remote_controller.js @@ -1,67 +1,92 @@ -@Kodi.module "InputApp.Remote", (Remote, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("InputApp.Remote", function(Remote, App, Backbone, Marionette, $, _) { - class Remote.Controller extends App.Controllers.Base + return Remote.Controller = class Controller extends App.Controllers.Base { - initialize: -> - ## Watch the shell and render when ready. - App.vent.on "shell:ready", (options) => - @getRemote() + initialize() { + //# Watch the shell and render when ready. + return App.vent.on("shell:ready", options => { + return this.getRemote(); + }); + } - getRemote: -> - view = new Remote.Control() - @listenTo view, "remote:input", (type) -> - App.execute "input:send", type - @listenTo view, "remote:player", (type) -> - App.request 'command:kodi:player', type, [] - @listenTo view, "remote:info", -> - # If playing show osd - if App.request("state:kodi").isPlaying() - App.execute 'input:action', 'osd' - else - App.execute "input:send", 'Info' - @listenTo view, "remote:power", => - @getShutdownMenu() - App.regionRemote.show view + getRemote() { + const view = new Remote.Control(); + this.listenTo(view, "remote:input", type => App.execute("input:send", type)); + this.listenTo(view, "remote:player", type => App.request('command:kodi:player', type, [])); + this.listenTo(view, "remote:info", function() { + // If playing show osd + if (App.request("state:kodi").isPlaying()) { + return App.execute('input:action', 'osd'); + } else { + return App.execute("input:send", 'Info'); + } + }); + this.listenTo(view, "remote:power", () => { + return this.getShutdownMenu(); + }); + App.regionRemote.show(view); - ## Change the fanart when the state changes. - App.vent.on "state:changed", (state) -> - stateObj = App.request "state:current" - if stateObj.isPlayingItemChanged() - playingItem = stateObj.getPlaying 'item' - fanart = App.request "images:path:get", playingItem.fanart, 'fanart' - $('#remote-background').css('background-image', 'url(' + playingItem.fanart + ')') + //# Change the fanart when the state changes. + return App.vent.on("state:changed", function(state) { + const stateObj = App.request("state:current"); + if (stateObj.isPlayingItemChanged()) { + const playingItem = stateObj.getPlaying('item'); + const fanart = App.request("images:path:get", playingItem.fanart, 'fanart'); + return $('#remote-background').css('background-image', 'url(' + playingItem.fanart + ')'); + } + }); + } - getShutdownMenu: -> - system = App.request "command:kodi:controller", 'auto', 'System' - system.getProperties (props) -> - actions = [] - optionalActions = ['shutdown', 'reboot', 'suspend', 'hibernate'] - actions.push {id: 'quit', title: 'Quit Kodi'} - for action in optionalActions - prop = 'can' + action - if props[prop] - actions.push {id: action, title: action} - # Build modal with options - model = new Backbone.Model {id: 1, actions: actions} - view = new Remote.System {model: model} - $content = view.render().$el - # Open modal and bind actions - App.execute "ui:modal:show", tr('Shutdown menu'), $content, '', false, 'system' - App.listenTo view, 'system:action', (action) => - switch action - when 'quit' - App.request("command:kodi:controller", 'auto', 'Application').quit() - when 'shutdown' - system.shutdown() - when 'reboot' - system.reboot() - when 'suspend' - system.suspend() - when 'hibernate' - system.hibernate() - else - # nothing - App.execute "ui:modal:close" + getShutdownMenu() { + const system = App.request("command:kodi:controller", 'auto', 'System'); + return system.getProperties(function(props) { + const actions = []; + const optionalActions = ['shutdown', 'reboot', 'suspend', 'hibernate']; + actions.push({id: 'quit', title: 'Quit Kodi'}); + for (var action of optionalActions) { + var prop = 'can' + action; + if (props[prop]) { + actions.push({id: action, title: action}); + } + } + // Build modal with options + const model = new Backbone.Model({id: 1, actions}); + const view = new Remote.System({model}); + const $content = view.render().$el; + // Open modal and bind actions + App.execute("ui:modal:show", tr('Shutdown menu'), $content, '', false, 'system'); + return App.listenTo(view, 'system:action', action => { + switch (action) { + case 'quit': + App.request("command:kodi:controller", 'auto', 'Application').quit(); + break; + case 'shutdown': + system.shutdown(); + break; + case 'reboot': + system.reboot(); + break; + case 'suspend': + system.suspend(); + break; + case 'hibernate': + system.hibernate(); + break; + default: + } + // nothing + return App.execute("ui:modal:close"); + }); + }); + } + }; +}); diff --git a/src/js/apps/input/remote/remote_view.js b/src/js/apps/input/remote/remote_view.js index b54b1584..f24dbe7d 100644 --- a/src/js/apps/input/remote/remote_view.js +++ b/src/js/apps/input/remote/remote_view.js @@ -1,35 +1,60 @@ -@Kodi.module "InputApp.Remote", (Remote, App, Backbone, Marionette, $, _) -> - - class Remote.Control extends App.Views.ItemView - template: 'apps/input/remote/remote_control' - events: - 'click .input-button': 'inputClick' - 'click .player-button': 'playerClick' - 'click .close-remote': 'closeRemote' - triggers: - 'click .power-button': 'remote:power' - 'click .info-button': 'remote:info' - - inputClick: (e) -> - type = $(e.target).data('type') - @trigger 'remote:input', type - - playerClick: (e) -> - type = $(e.target).data('type') - @trigger 'remote:player', type - - closeRemote: (e) -> - App.execute "input:remote:toggle" - - class Remote.Landing extends App.Views.ItemView - - - class Remote.System extends App.Views.ItemView - template: 'apps/input/remote/system' - className: 'system-menu' - events: - 'click li': 'doAction' - doAction: (e) -> - action = $(e.target).data('action') - @trigger 'system:action', action +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("InputApp.Remote", function(Remote, App, Backbone, Marionette, $, _) { + + let Cls = (Remote.Control = class Control extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/input/remote/remote_control'; + this.prototype.events = { + 'click .input-button': 'inputClick', + 'click .player-button': 'playerClick', + 'click .close-remote': 'closeRemote' + }; + this.prototype.triggers = { + 'click .power-button': 'remote:power', + 'click .info-button': 'remote:info' + }; + + Remote.Landing = class Landing extends App.Views.ItemView {}; + } + + inputClick(e) { + const type = $(e.target).data('type'); + return this.trigger('remote:input', type); + } + + playerClick(e) { + const type = $(e.target).data('type'); + return this.trigger('remote:player', type); + } + + closeRemote(e) { + return App.execute("input:remote:toggle"); + } + }); + Cls.initClass(); + + + return (function() { + Cls = (Remote.System = class System extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/input/remote/system'; + this.prototype.className = 'system-menu'; + this.prototype.events = + {'click li': 'doAction'}; + } + doAction(e) { + const action = $(e.target).data('action'); + return this.trigger('system:action', action); + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/input/resume/resume_controller.js b/src/js/apps/input/resume/resume_controller.js index 8e75916c..24e8ac92 100644 --- a/src/js/apps/input/resume/resume_controller.js +++ b/src/js/apps/input/resume/resume_controller.js @@ -1,43 +1,52 @@ -@Kodi.module "InputApp.Resume", (Resume, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("InputApp.Resume", (Resume, App, Backbone, Marionette, $, _) => Resume.Controller = class Controller extends App.Controllers.Base { - class Resume.Controller extends App.Controllers.Base + //# Ask to resume playback if the model has a resume position + //# Currently only supports Kodi playback + resumePlay(model, idKey) { + const stateObj = App.request("state:current"); + const title = t.gettext('Resume playback'); + const resume = model.get('resume'); + let percent = 0; + const options = []; - ## Ask to resume playback if the model has a resume position - ## Currently only supports Kodi playback - resumePlay: (model, idKey) -> - stateObj = App.request "state:current" - title = t.gettext('Resume playback') - resume = model.get('resume') - percent = 0 - options = [] + // If resume position position + if ((parseInt(resume.position) > 0) && (stateObj.getPlayer() === 'kodi')) { + // Get percent + percent = helpers.global.getPercent(resume.position, resume.total); - # If resume position position - if parseInt(resume.position) > 0 and stateObj.getPlayer() is 'kodi' - # Get percent - percent = helpers.global.getPercent(resume.position, resume.total) + // Build strings + const time_string = helpers.global.formatTime(helpers.global.secToTime(resume.position)); + const complete_string = helpers.global.round(percent, 0) + '% ' + t.gettext('complete'); + const resume_string = t.gettext('Resume from') + ' ' + time_string + ' ' + complete_string + ''; + const start_string = t.gettext('Start from the beginning'); - # Build strings - time_string = helpers.global.formatTime(helpers.global.secToTime(resume.position)) - complete_string = helpers.global.round(percent, 0) + '% ' + t.gettext('complete') - resume_string = t.gettext('Resume from') + ' ' + time_string + ' ' + complete_string + '' - start_string = t.gettext('Start from the beginning') + // build options as an array of jQuery objects + const items = [{title: resume_string, percent}, {title: start_string, percent: 0}]; + for (var item of items) { + var $el = $('') + .attr('data-percent', item.percent) + .html(item.title) + .click(function(e){ + // Callback for option click + return App.execute("command:video:play", model, idKey, $(this).data('percent')); + }); + options.push($el); + } - # build options as an array of jQuery objects - items = [{title: resume_string, percent: percent}, {title: start_string, percent: 0}] - for item in items - $el = $('') - .attr('data-percent', item.percent) - .html(item.title) - .click (e)-> - # Callback for option click - App.execute "command:video:play", model, idKey, $(@).data('percent') - options.push $el + // Open options in a modal + return App.execute("ui:modal:options", title, options); + } else { + // No resume point or resume is 0% + return App.execute("command:video:play", model, idKey, 0); + } + } - # Open options in a modal - App.execute "ui:modal:options", title, options - else - # No resume point or resume is 0% - App.execute "command:video:play", model, idKey, 0 - - initialize: -> - # Something. + initialize() {} +}); + // Something. diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_controller.js b/src/js/apps/lab/apiBrowser/apiBrowser_controller.js index 378b90b6..340bcf2b 100644 --- a/src/js/apps/lab/apiBrowser/apiBrowser_controller.js +++ b/src/js/apps/lab/apiBrowser/apiBrowser_controller.js @@ -1,70 +1,89 @@ -# Controller for the API Browser. -# -# An app that allows you to get all the methods from the api -# and execute them -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "LabApp.apiBrowser", (apiBrowser, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// Controller for the API Browser. +// +// An app that allows you to get all the methods from the api +// and execute them +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("LabApp.apiBrowser", function(apiBrowser, App, Backbone, Marionette, $, _) { - # Main controller - class apiBrowser.Controller extends App.Controllers.Base + // Main controller + return apiBrowser.Controller = class Controller extends App.Controllers.Base { - initialize: -> - collection = App.request "introspect:entities" - App.execute "when:entity:fetched", collection, => - collection.dictionary = App.request "introspect:dictionary" + initialize() { + const collection = App.request("introspect:entities"); + return App.execute("when:entity:fetched", collection, () => { + collection.dictionary = App.request("introspect:dictionary"); - @layout = @getLayoutView collection + this.layout = this.getLayoutView(collection); - @listenTo @layout, "show", => - @renderList collection - if @options.method - @renderPage @options.method, collection - else - @renderLanding() + this.listenTo(this.layout, "show", () => { + this.renderList(collection); + if (this.options.method) { + return this.renderPage(this.options.method, collection); + } else { + return this.renderLanding(); + } + }); - App.regionContent.show @layout + return App.regionContent.show(this.layout); + }); + } - getLayoutView: (collection) -> - new apiBrowser.Layout - collection: collection + getLayoutView(collection) { + return new apiBrowser.Layout({ + collection}); + } - renderList: (collection) -> - view = new apiBrowser.apiMethods - collection: collection - @listenTo view, 'childview:lab:apibrowser:method:view', (item) => - @renderPage(item.model.get('id'), collection) - @layout.regionSidebarFirst.show view + renderList(collection) { + const view = new apiBrowser.apiMethods({ + collection}); + this.listenTo(view, 'childview:lab:apibrowser:method:view', item => { + return this.renderPage(item.model.get('id'), collection); + }); + return this.layout.regionSidebarFirst.show(view); + } - renderPage: (id, collection) -> - model = App.request "introspect:entity", id, collection - pageView = new apiBrowser.apiMethodPage - model: model - helpers.debug.msg "Params/Returns for #{model.get('method')}:", 'info', [model.get('params'), model.get('returns')] - @listenTo pageView, 'lab:apibrowser:execute', (item) => - input = $('.api-method--params').val(); - params = JSON.parse input - method = item.model.get 'method' + renderPage(id, collection) { + const model = App.request("introspect:entity", id, collection); + const pageView = new apiBrowser.apiMethodPage({ + model}); + helpers.debug.msg(`Params/Returns for ${model.get('method')}:`, 'info', [model.get('params'), model.get('returns')]); + this.listenTo(pageView, 'lab:apibrowser:execute', item => { + const input = $('.api-method--params').val(); + const params = JSON.parse(input); + const method = item.model.get('method'); - # Notify - helpers.debug.msg "Parameters for: #{method}", 'info', params + // Notify + helpers.debug.msg(`Parameters for: ${method}`, 'info', params); - # Execute the method - api = App.request "command:kodi:controller", "auto", "Commander" - api.singleCommand method, params, (response) => - helpers.debug.msg "Response for: #{method}", 'info', response - output = prettyPrint response - $('#api-result').html(output).prepend($('

Response (check the console for more)

')); + // Execute the method + const api = App.request("command:kodi:controller", "auto", "Commander"); + return api.singleCommand(method, params, response => { + helpers.debug.msg(`Response for: ${method}`, 'info', response); + const output = prettyPrint(response); + return $('#api-result').html(output).prepend($('

Response (check the console for more)

')); + }); + }); - App.navigate "lab/api-browser/#{model.get('method')}" - @layout.regionContent.show pageView + App.navigate(`lab/api-browser/${model.get('method')}`); + return this.layout.regionContent.show(pageView); + } - renderLanding: -> - view = new apiBrowser.apiBrowserLanding() - @layout.regionContent.show view + renderLanding() { + const view = new apiBrowser.apiBrowserLanding(); + return this.layout.regionContent.show(view); + } + }; +}); diff --git a/src/js/apps/lab/apiBrowser/apiBrowser_view.js b/src/js/apps/lab/apiBrowser/apiBrowser_view.js index c701761f..a2277e24 100644 --- a/src/js/apps/lab/apiBrowser/apiBrowser_view.js +++ b/src/js/apps/lab/apiBrowser/apiBrowser_view.js @@ -1,54 +1,88 @@ -# View for the API Browser. -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "LabApp.apiBrowser", (apiBrowser, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// View for the API Browser. +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("LabApp.apiBrowser", function(apiBrowser, App, Backbone, Marionette, $, _) { - class apiBrowser.Layout extends App.Views.LayoutWithSidebarFirstView - className: "api-browser--page page-wrapper" + let Cls = (apiBrowser.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "api-browser--page page-wrapper"; + } + }); + Cls.initClass(); - # A single api method item - class apiBrowser.apiMethodItem extends App.Views.ItemView - className: "api-browser--method" - template: 'apps/lab/apiBrowser/api_method_item' - tagName: "li" - triggers: - 'click .api-method--item' : 'lab:apibrowser:method:view' + // A single api method item + Cls = (apiBrowser.apiMethodItem = class apiMethodItem extends App.Views.ItemView { + static initClass() { + this.prototype.className = "api-browser--method"; + this.prototype.template = 'apps/lab/apiBrowser/api_method_item'; + this.prototype.tagName = "li"; + this.prototype.triggers = + {'click .api-method--item' : 'lab:apibrowser:method:view'}; + } + }); + Cls.initClass(); - # List of api methods - class apiBrowser.apiMethods extends App.Views.CompositeView - template: 'apps/lab/apiBrowser/api_method_list' - childView: apiBrowser.apiMethodItem - childViewContainer: 'ul.items' - tagName: "div" - className: "api-browser--methods" - onRender: -> - $('#api-search', @$el).filterList { - items: '.api-browser--methods .api-browser--method' + // List of api methods + Cls = (apiBrowser.apiMethods = class apiMethods extends App.Views.CompositeView { + static initClass() { + this.prototype.template = 'apps/lab/apiBrowser/api_method_list'; + this.prototype.childView = apiBrowser.apiMethodItem; + this.prototype.childViewContainer = 'ul.items'; + this.prototype.tagName = "div"; + this.prototype.className = "api-browser--methods"; + } + onRender() { + return $('#api-search', this.$el).filterList({ + items: '.api-browser--methods .api-browser--method', textSelector: '.method' - } + }); + } + }); + Cls.initClass(); - # A single api page - class apiBrowser.apiMethodPage extends App.Views.ItemView - className: "api-browser--page" - template: 'apps/lab/apiBrowser/api_method_page' - tagName: "div" - triggers: - 'click #send-command' : 'lab:apibrowser:execute' - regions: - 'apiResult' : '#api-result' - onShow: -> - $('.api-method--params', @$el).html prettyPrint(@model.get('params')) - if @model.get('type') is 'method' - $('.api-method--return', @$el).html prettyPrint(@model.get('returns')) + // A single api page + Cls = (apiBrowser.apiMethodPage = class apiMethodPage extends App.Views.ItemView { + static initClass() { + this.prototype.className = "api-browser--page"; + this.prototype.template = 'apps/lab/apiBrowser/api_method_page'; + this.prototype.tagName = "div"; + this.prototype.triggers = + {'click #send-command' : 'lab:apibrowser:execute'}; + this.prototype.regions = + {'apiResult' : '#api-result'}; + } + onShow() { + $('.api-method--params', this.$el).html(prettyPrint(this.model.get('params'))); + if (this.model.get('type') === 'method') { + return $('.api-method--return', this.$el).html(prettyPrint(this.model.get('returns'))); + } + } + }); + Cls.initClass(); - # Api browser landing (home) - class apiBrowser.apiBrowserLanding extends App.Views.ItemView - className: "api-browser--landing" - template: 'apps/lab/apiBrowser/api_browser_landing' - tagName: "div" + // Api browser landing (home) + return (function() { + Cls = (apiBrowser.apiBrowserLanding = class apiBrowserLanding extends App.Views.ItemView { + static initClass() { + this.prototype.className = "api-browser--landing"; + this.prototype.template = 'apps/lab/apiBrowser/api_browser_landing'; + this.prototype.tagName = "div"; + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/lab/iconBrowser/iconBrowser_view.js b/src/js/apps/lab/iconBrowser/iconBrowser_view.js index ee5980bd..fd0cac82 100644 --- a/src/js/apps/lab/iconBrowser/iconBrowser_view.js +++ b/src/js/apps/lab/iconBrowser/iconBrowser_view.js @@ -1,13 +1,38 @@ -@Kodi.module "LabApp.IconBrowser", (lab, App, Backbone, Marionette, $, _) -> - - class lab.IconsPage extends App.Views.LayoutView - template: 'apps/lab/iconBrowser/icon_browser_page' - tagName: "div" - className: "icon-browser page" - onRender: -> - for type in ['material', 'custom'] - $ctx = $('#icons-' + type, @$el) - set = type + 'Icons' - for icoClass, name of @options[set] - $ico = $('
  • ' + name + '' + icoClass + '
  • ') - $ctx.append $ico +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LabApp.IconBrowser", (lab, App, Backbone, Marionette, $, _) => (function() { + const Cls = (lab.IconsPage = class IconsPage extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/lab/iconBrowser/icon_browser_page'; + this.prototype.tagName = "div"; + this.prototype.className = "icon-browser page"; + } + onRender() { + return (() => { + const result = []; + for (var type of ['material', 'custom']) { + var $ctx = $('#icons-' + type, this.$el); + var set = type + 'Icons'; + result.push((() => { + const result1 = []; + for (var icoClass in this.options[set]) { + var name = this.options[set][icoClass]; + var $ico = $('
  • ' + name + '' + icoClass + '
  • '); + result1.push($ctx.append($ico)); + } + return result1; + })()); + } + return result; + })(); + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/lab/lab/lab_view.js b/src/js/apps/lab/lab/lab_view.js index 2eb00a80..d35c6016 100644 --- a/src/js/apps/lab/lab/lab_view.js +++ b/src/js/apps/lab/lab/lab_view.js @@ -1,27 +1,47 @@ -# View for the Lab. -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "LabApp.lab", (lab, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// View for the Lab. +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("LabApp.lab", function(lab, App, Backbone, Marionette, $, _) { - # A single lab item - class lab.labItem extends App.Views.ItemView - className: "lab--item" - template: 'apps/lab/lab/lab_item' - tagName: "div" + // A single lab item + let Cls = (lab.labItem = class labItem extends App.Views.ItemView { + static initClass() { + this.prototype.className = "lab--item"; + this.prototype.template = 'apps/lab/lab/lab_item'; + this.prototype.tagName = "div"; + } + }); + Cls.initClass(); - # List of lab items - class lab.labItems extends App.Views.CollectionView - tagName: "div" - className: "lab--items page" - childView: lab.labItem - onRender: -> - @$el.prepend $('

    ').text( t.gettext('Experimental code, use at own risk') ) - @$el.prepend $('

    ').text( t.gettext('The lab') ) - @$el.addClass('page-secondary') + // List of lab items + return (function() { + Cls = (lab.labItems = class labItems extends App.Views.CollectionView { + static initClass() { + this.prototype.tagName = "div"; + this.prototype.className = "lab--items page"; + this.prototype.childView = lab.labItem; + } + onRender() { + this.$el.prepend($('

    ').text( t.gettext('Experimental code, use at own risk') )); + this.$el.prepend($('

    ').text( t.gettext('The lab') )); + return this.$el.addClass('page-secondary'); + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/lab/lab_app.js b/src/js/apps/lab/lab_app.js index 8fd80819..3c26e77d 100644 --- a/src/js/apps/lab/lab_app.js +++ b/src/js/apps/lab/lab_app.js @@ -1,73 +1,94 @@ -# Lab App handles new experimental features. -# -# Each sub module should have its own folder with controller, view, etc. -# Global Lab features here. -# -# @param [Object] This app object -# @param [Object] The full application object -# @param [Object] Backbone -# @param [Object] Marionette -# @param [Object] jQuery -# @param [Object] lodash (underscore) -# -@Kodi.module "LabApp", (LabApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +// Lab App handles new experimental features. +// +// Each sub module should have its own folder with controller, view, etc. +// Global Lab features here. +// +// @param [Object] This app object +// @param [Object] The full application object +// @param [Object] Backbone +// @param [Object] Marionette +// @param [Object] jQuery +// @param [Object] lodash (underscore) +// +this.Kodi.module("LabApp", function(LabApp, App, Backbone, Marionette, $, _) { - # Create our LabApp router. - class LabApp.Router extends App.Router.Base - appRoutes: - "lab" : "labLanding" - "lab/api-browser" : "apiBrowser" - "lab/api-browser/:method" : "apiBrowser" - "lab/screenshot" : "screenShot" - "lab/icon-browser" : "iconBrowser" + // Create our LabApp router. + const Cls = (LabApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "lab" : "labLanding", + "lab/api-browser" : "apiBrowser", + "lab/api-browser/:method" : "apiBrowser", + "lab/screenshot" : "screenShot", + "lab/icon-browser" : "iconBrowser" + }; + } + }); + Cls.initClass(); - # Lab API controller. - API = + // Lab API controller. + const API = { - labLanding: -> - view = new LabApp.lab.labItems - collection: new App.Entities.NavMainCollection @labItems() - App.regionContent.show view + labLanding() { + const view = new LabApp.lab.labItems({ + collection: new App.Entities.NavMainCollection(this.labItems())}); + return App.regionContent.show(view); + }, - # TODO Make dynamic, some sort of hook or registry. - labItems: -> - [ + // TODO Make dynamic, some sort of hook or registry. + labItems() { + return [ { - title: 'API browser' - description: 'Execute any API command.' + title: 'API browser', + description: 'Execute any API command.', path: 'lab/api-browser' - } + }, { - title: 'Screenshot' - description: 'Take a screenshot of Kodi right now.' + title: 'Screenshot', + description: 'Take a screenshot of Kodi right now.', path: 'lab/screenshot' - } + }, { - title: 'Icon browser' - description: 'View all the icons available to Chorus.' + title: 'Icon browser', + description: 'View all the icons available to Chorus.', path: 'lab/icon-browser' } - ] + ]; + }, - # Open the api explorer. - apiBrowser: (method = false)-> - new LabApp.apiBrowser.Controller - method: method + // Open the api explorer. + apiBrowser(method = false){ + return new LabApp.apiBrowser.Controller({ + method}); + }, - screenShot: -> - App.execute "input:action", 'screenshot' - App.execute "notification:show", t.gettext("Screenshot saved to your screenshots folder") - App.navigate "#lab", {trigger: true} + screenShot() { + App.execute("input:action", 'screenshot'); + App.execute("notification:show", t.gettext("Screenshot saved to your screenshots folder")); + return App.navigate("#lab", {trigger: true}); + }, - iconBrowser: -> - $.getJSON 'lib/icons/mdi.json', (mdiIcons) => - $.getJSON 'lib/icons/icomoon.json', (customIcons) => - console.log mdiIcons, customIcons - view = new LabApp.IconBrowser.IconsPage - materialIcons: mdiIcons - customIcons: customIcons - App.regionContent.show view + iconBrowser() { + return $.getJSON('lib/icons/mdi.json', mdiIcons => { + return $.getJSON('lib/icons/icomoon.json', customIcons => { + console.log(mdiIcons, customIcons); + const view = new LabApp.IconBrowser.IconsPage({ + materialIcons: mdiIcons, + customIcons + }); + return App.regionContent.show(view); + }); + }); + } + }; - App.on "before:start", -> - new LabApp.Router - controller: API + return App.on("before:start", () => new LabApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/landing/landing_app.js b/src/js/apps/landing/landing_app.js index 2129e145..b727e614 100644 --- a/src/js/apps/landing/landing_app.js +++ b/src/js/apps/landing/landing_app.js @@ -1,169 +1,193 @@ -@Kodi.module "LandingApp", (LandingApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LandingApp", function(LandingApp, App, Backbone, Marionette, $, _) { - class LandingApp.Router extends App.Router.Base - appRoutes: - "music" : "landingPage" - "music/top" : "landingPage" - "movies/recent" : "landingPage" - "tvshows/recent" : "landingPage" - "music/genre/:filter" : "filteredPage" + const Cls = (LandingApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "music" : "landingPage", + "music/top" : "landingPage", + "movies/recent" : "landingPage", + "tvshows/recent" : "landingPage", + "music/genre/:filter" : "filteredPage" + }; + } + }); + Cls.initClass(); - API = + var API = { - ## This defines what we will see on each landing page - ## Example of a complex filter using rules - ## {"and": [{'operator': 'is', 'field': 'playcount', 'value': '0'}, {'operator': 'is', 'field': 'year', 'value': '2015'}]} - landingSettings: - music: - subnavId: 'music' + //# This defines what we will see on each landing page + //# Example of a complex filter using rules + //# {"and": [{'operator': 'is', 'field': 'playcount', 'value': '0'}, {'operator': 'is', 'field': 'year', 'value': '2015'}]} + landingSettings: { + music: { + subnavId: 'music', sections: [ { - title: 'Recently added albums' - entity: 'album' - sort: 'dateadded' - order: 'descending' - limit: 14 + title: 'Recently added albums', + entity: 'album', + sort: 'dateadded', + order: 'descending', + limit: 14, moreLink: 'music/albums?sort=dateadded&order=desc' - } + }, { - title: 'Recently played albums' - entity: 'album' - sort: 'lastplayed' - order: 'descending' + title: 'Recently played albums', + entity: 'album', + sort: 'lastplayed', + order: 'descending', limit: 14 - } + }, { - title: 'Random albums' - entity: 'album' - sort: 'random' - order: 'descending' - limit: 14 + title: 'Random albums', + entity: 'album', + sort: 'random', + order: 'descending', + limit: 14, moreLink: 'music/albums?sort=random' } ] - musictop: - subnavId: 'music' + }, + musictop: { + subnavId: 'music', sections: [ { - title: 'Top Albums' - entity: 'album' - sort: 'playcount' - order: 'descending' - limit: 56 + title: 'Top Albums', + entity: 'album', + sort: 'playcount', + order: 'descending', + limit: 56, filter: {'operator': 'greaterthan', 'field': 'playcount', 'value': '0'} - } + }, { - title: 'Top Songs' - entity: 'song' - sort: 'playcount' - order: 'descending' - limit: 100 + title: 'Top Songs', + entity: 'song', + sort: 'playcount', + order: 'descending', + limit: 100, filter: {'operator': 'greaterthan', 'field': 'playcount', 'value': '0'} } ] - moviesrecent: - subnavId: 'movies/recent' + }, + moviesrecent: { + subnavId: 'movies/recent', sections: [ { - title: 'Continue watching' - entity: 'movie' - sort: 'lastplayed' - order: 'descending' + title: 'Continue watching', + entity: 'movie', + sort: 'lastplayed', + order: 'descending', limit: 14, - filter: {'operator': 'true', 'field': 'inprogress', 'value': ''} + filter: {'operator': 'true', 'field': 'inprogress', 'value': ''}, moreLink: 'movies?sort=dateadded&order=desc&inprogress=in progress' - } + }, { - title: 'Recently added' - entity: 'movie' - sort: 'dateadded' - order: 'descending' - limit: 14 - filter: {'operator': 'is', 'field': 'playcount', 'value': '0'} + title: 'Recently added', + entity: 'movie', + sort: 'dateadded', + order: 'descending', + limit: 14, + filter: {'operator': 'is', 'field': 'playcount', 'value': '0'}, moreLink: 'movies?sort=dateadded&order=desc&unwatched=unwatched' - } + }, { - title: 'Random movies' - entity: 'movie' - sort: 'random' - order: 'descending' - limit: 14 + title: 'Random movies', + entity: 'movie', + sort: 'random', + order: 'descending', + limit: 14, moreLink: 'movies?sort=random' } ] - tvshowsrecent: - subnavId: 'tvshows/recent' + }, + tvshowsrecent: { + subnavId: 'tvshows/recent', sections: [ { - title: 'Continue watching' - entity: 'tvshow' - sort: 'lastplayed' - order: 'descending' - limit: 14 - filter: {'operator': 'true', 'field': 'inprogress', 'value': ''} - moreLink: 'tvshows?sort=dateadded&order=desc&inprogress=in progress' + title: 'Continue watching', + entity: 'tvshow', + sort: 'lastplayed', + order: 'descending', + limit: 14, + filter: {'operator': 'true', 'field': 'inprogress', 'value': ''}, + moreLink: 'tvshows?sort=dateadded&order=desc&inprogress=in progress', preventSelect: true - } + }, { - title: 'Recently added' - entity: 'episode' - sort: 'dateadded' - order: 'descending' - limit: 12 + title: 'Recently added', + entity: 'episode', + sort: 'dateadded', + order: 'descending', + limit: 12, filter: {'operator': 'is', 'field': 'playcount', 'value': '0'} } ] + } + }, - ## Filtered sections require an argument passed and are used for pages such as genere - ## Key name should be "arg0 + arg1", filter should be "arg2" - ## Filter gets replaced in sections[i].filter.value and prepended to moreLink - filteredSettings: - musicgenre: - subnavId: 'music' + //# Filtered sections require an argument passed and are used for pages such as genere + //# Key name should be "arg0 + arg1", filter should be "arg2" + //# Filter gets replaced in sections[i].filter.value and prepended to moreLink + filteredSettings: { + musicgenre: { + subnavId: 'music', sections: [ { - title: '%1$s Artists' - entity: 'artist' - sort: 'title' - order: 'ascending' - limit: 500 + title: '%1$s Artists', + entity: 'artist', + sort: 'title', + order: 'ascending', + limit: 500, filter: {'operator': 'is', 'field': 'genre', 'value': '[FILTER]'} - } + }, { - title: '%1$s Albums' - entity: 'album' - sort: 'title' - order: 'ascending' - limit: 500 + title: '%1$s Albums', + entity: 'album', + sort: 'title', + order: 'ascending', + limit: 500, filter: {'operator': 'is', 'field': 'genre', 'value': '[FILTER]'} - } + }, { - title: '%1$s Songs' - entity: 'song' - sort: 'title' - order: 'ascending' - limit: 1000 + title: '%1$s Songs', + entity: 'song', + sort: 'title', + order: 'ascending', + limit: 1000, filter: {'operator': 'is', 'field': 'genre', 'value': '[FILTER]'} } ] + } + }, - landingPage: () -> - type = helpers.url.arg(0) + helpers.url.arg(1) - settings = API.landingSettings[type] - new LandingApp.Show.Controller - settings: settings + landingPage() { + const type = helpers.url.arg(0) + helpers.url.arg(1); + const settings = API.landingSettings[type]; + return new LandingApp.Show.Controller({ + settings, filter: false + }); + }, - filteredPage: (filter) -> - type = helpers.url.arg(0) + helpers.url.arg(1) - settings = API.filteredSettings[type] - new LandingApp.Show.Controller - settings: settings + filteredPage(filter) { + const type = helpers.url.arg(0) + helpers.url.arg(1); + const settings = API.filteredSettings[type]; + return new LandingApp.Show.Controller({ + settings, filter: decodeURIComponent(filter) + }); + } + }; - ## Register controller - App.on "before:start", -> - new LandingApp.Router - controller: API + //# Register controller + return App.on("before:start", () => new LandingApp.Router({ + controller: API})); +}); diff --git a/src/js/apps/landing/show/landing_controller.js b/src/js/apps/landing/show/landing_controller.js index 4ed8acf2..936087fb 100644 --- a/src/js/apps/landing/show/landing_controller.js +++ b/src/js/apps/landing/show/landing_controller.js @@ -1,83 +1,126 @@ -@Kodi.module "LandingApp.Show", (Show, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LandingApp.Show", function(Show, App, Backbone, Marionette, $, _) { - class Show.Controller extends App.Controllers.Base + return Show.Controller = class Controller extends App.Controllers.Base { - initialize: (options) -> - @fanarts = [] - @rendered = 0 - @settings = options.settings - @layout = @getLayoutView() - $('body').addClass 'landing-loading' - @listenTo @layout, "show", => - @content = @getContentView() - @listenTo @content, "show", => - window.scroll(0, 350) - @getSections @settings.sections - @getSubNav @settings.subnavId - @layout.regionContent.show @content + constructor(...args) { + super(...args); + this.getSections = this.getSections.bind(this); + this.renderSection = this.renderSection.bind(this); + } - App.regionContent.show @layout + initialize(options) { + this.fanarts = []; + this.rendered = 0; + this.settings = options.settings; + this.layout = this.getLayoutView(); + $('body').addClass('landing-loading'); + this.listenTo(this.layout, "show", () => { + this.content = this.getContentView(); + this.listenTo(this.content, "show", () => { + window.scroll(0, 350); + this.getSections(this.settings.sections); + return this.getSubNav(this.settings.subnavId); + }); + return this.layout.regionContent.show(this.content); + }); - getLayoutView: -> - new Show.Layout() + return App.regionContent.show(this.layout); + } - getContentView: -> - new Show.Page() + getLayoutView() { + return new Show.Layout(); + } - getSubNav: (subnavId) -> - subNav = App.request "navMain:children:show", subnavId, 'Sections' - @layout.regionSidebarFirst.show subNav + getContentView() { + return new Show.Page(); + } - getSections: (sections) => - for i, section of sections - section.idx = parseInt(i) + 1 - @getSection section + getSubNav(subnavId) { + const subNav = App.request("navMain:children:show", subnavId, 'Sections'); + return this.layout.regionSidebarFirst.show(subNav); + } - getSection: (section) -> - section = @addFilterValue section - opts = - sort: {method: section.sort, order: section.order} - limit: {start: 0, end: section.limit} - addFields: ['fanart'] - cache: false - success: (collection) => - @rendered++ - if collection.length > 0 - @renderSection section, collection - @getFanArts collection - if section.filter - opts.filter = section.filter - App.request "#{section.entity}:entities", opts + getSections(sections) { + return (() => { + const result = []; + for (var i in sections) { + var section = sections[i]; + section.idx = parseInt(i) + 1; + result.push(this.getSection(section)); + } + return result; + })(); + } - renderSection: (section, collection) => - view = App.request "#{section.entity}:list:view", collection, true - setView = new Show.ListSet - section: section - filter: @getOption('filter') - App.listenTo setView, "show", => - setView.regionCollection.show view - App.listenTo setView, 'landing:set:more', (viewItem) -> - App.navigate viewItem.model.get('section').moreLink, {trigger: true} - if @content["regionSection#{section.idx}"] - @content["regionSection#{section.idx}"].show setView + getSection(section) { + section = this.addFilterValue(section); + const opts = { + sort: {method: section.sort, order: section.order}, + limit: {start: 0, end: section.limit}, + addFields: ['fanart'], + cache: false, + success: collection => { + this.rendered++; + if (collection.length > 0) { + this.renderSection(section, collection); + return this.getFanArts(collection); + } + } + }; + if (section.filter) { + opts.filter = section.filter; + } + return App.request(`${section.entity}:entities`, opts); + } - addFilterValue: (section) -> - filterVal = @getOption('filter') - if filterVal isnt false - if section.filter and section.filter.value - # TODO: Deal with complex nested rules that us 'and' or 'or' - section.filter.value = filterVal - section + renderSection(section, collection) { + const view = App.request(`${section.entity}:list:view`, collection, true); + const setView = new Show.ListSet({ + section, + filter: this.getOption('filter') + }); + App.listenTo(setView, "show", () => { + return setView.regionCollection.show(view); + }); + App.listenTo(setView, 'landing:set:more', viewItem => App.navigate(viewItem.model.get('section').moreLink, {trigger: true})); + if (this.content[`regionSection${section.idx}`]) { + return this.content[`regionSection${section.idx}`].show(setView); + } + } - getFanArts: (collection) -> - $hero = $("#landing-hero") - for item in collection.toJSON() - if item.fanart and item.fanart isnt '' - @fanarts.push item - if $hero.is(':visible') and @rendered is @settings.sections.length and @fanarts.length > 0 - randomModel = @fanarts[Math.floor(Math.random() * @fanarts.length)]; + addFilterValue(section) { + const filterVal = this.getOption('filter'); + if (filterVal !== false) { + if (section.filter && section.filter.value) { + // TODO: Deal with complex nested rules that us 'and' or 'or' + section.filter.value = filterVal; + } + } + return section; + } + + getFanArts(collection) { + const $hero = $("#landing-hero"); + for (var item of collection.toJSON()) { + if (item.fanart && (item.fanart !== '')) { + this.fanarts.push(item); + } + } + if ($hero.is(':visible') && (this.rendered === this.settings.sections.length) && (this.fanarts.length > 0)) { + const randomModel = this.fanarts[Math.floor(Math.random() * this.fanarts.length)]; $hero .css('background-image', 'url(' + randomModel.fanart + ')') - .attr('href', '#' + randomModel.url).attr('title', randomModel.title) - $('body').removeClass 'landing-loading' + .attr('href', '#' + randomModel.url).attr('title', randomModel.title); + return $('body').removeClass('landing-loading'); + } + } + }; +}); diff --git a/src/js/apps/landing/show/landing_view.js b/src/js/apps/landing/show/landing_view.js index bcd33c6b..fc00b72a 100644 --- a/src/js/apps/landing/show/landing_view.js +++ b/src/js/apps/landing/show/landing_view.js @@ -1,34 +1,66 @@ -@Kodi.module "LandingApp.Show", (Show, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LandingApp.Show", function(Show, App, Backbone, Marionette, $, _) { - class Show.Layout extends App.Views.LayoutWithSidebarFirstView - className: "landing-page" + let Cls = (Show.Layout = class Layout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "landing-page"; + } + }); + Cls.initClass(); - class Show.Page extends App.Views.LayoutView - template: "apps/landing/show/landing_page" - className: "landing-content" - regions: - regionHero: '#landing-hero' - regionSection1: '#landing-section-1' - regionSection2: '#landing-section-2' - regionSection3: '#landing-section-3' - regionSection4: '#landing-section-4' - regionSection5: '#landing-section-5' - regionSection6: '#landing-section-6' - - class Show.ListSet extends App.Views.SetLayoutView - className: 'landing-set' - triggers: - 'click .more' : 'landing:set:more' - initialize: () -> - @setOptions() - @createModel() - setOptions: () -> - @options.menu = {} - if @options.filter isnt false and @options.section.title - @options.title = t.sprintf(tr(@options.section.title), @options.filter) - else if @options.section.title - @options.title = tr(@options.section.title) - if @options.section.moreLink - @options.menu.more = tr 'More like this' - if @options.section.preventSelect - @options.noMenuDefault = true + return (function() { + Cls = (Show.Page = class Page extends App.Views.LayoutView { + static initClass() { + this.prototype.template = "apps/landing/show/landing_page"; + this.prototype.className = "landing-content"; + this.prototype.regions = { + regionHero: '#landing-hero', + regionSection1: '#landing-section-1', + regionSection2: '#landing-section-2', + regionSection3: '#landing-section-3', + regionSection4: '#landing-section-4', + regionSection5: '#landing-section-5', + regionSection6: '#landing-section-6' + }; + + (function() { + Cls = (Show.ListSet = class ListSet extends App.Views.SetLayoutView { + static initClass() { + this.prototype.className = 'landing-set'; + this.prototype.triggers = + {'click .more' : 'landing:set:more'}; + } + initialize() { + this.setOptions(); + return this.createModel(); + } + setOptions() { + this.options.menu = {}; + if ((this.options.filter !== false) && this.options.section.title) { + this.options.title = t.sprintf(tr(this.options.section.title), this.options.filter); + } else if (this.options.section.title) { + this.options.title = tr(this.options.section.title); + } + if (this.options.section.moreLink) { + this.options.menu.more = tr('More like this'); + } + if (this.options.section.preventSelect) { + return this.options.noMenuDefault = true; + } + } + }); + Cls.initClass(); + return Cls; + })(); + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/loading/loading_app.js b/src/js/apps/loading/loading_app.js index 82e04422..4f80b389 100644 --- a/src/js/apps/loading/loading_app.js +++ b/src/js/apps/loading/loading_app.js @@ -1,21 +1,30 @@ -@Kodi.module "LoadingApp", (LoadingApp, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LoadingApp", function(LoadingApp, App, Backbone, Marionette, $, _) { - API = + const API = { - getLoaderView: (msgTextHtml = 'Just a sec...', inline = false) -> - new LoadingApp.Show.Page - textHtml: msgTextHtml - # Inline is used when the loader is not full page - inline: inline + getLoaderView(msgTextHtml = 'Just a sec...', inline = false) { + return new LoadingApp.Show.Page({ + textHtml: msgTextHtml, + // Inline is used when the loader is not full page + inline + }); + } + }; - App.commands.setHandler "loading:show:view", (region, msgTextHtml) -> - view = API.getLoaderView msgTextHtml - region.show view + App.commands.setHandler("loading:show:view", function(region, msgTextHtml) { + const view = API.getLoaderView(msgTextHtml); + return region.show(view); + }); - ## Replace whole page with loader. - App.commands.setHandler "loading:show:page", -> - App.execute "loading:show:view", App.regionContent + //# Replace whole page with loader. + App.commands.setHandler("loading:show:page", () => App.execute("loading:show:view", App.regionContent)); - ## Get a loader view - App.reqres.setHandler "loading:get:view", (msgText, inline = true) -> - API.getLoaderView msgText, inline + //# Get a loader view + return App.reqres.setHandler("loading:get:view", (msgText, inline = true) => API.getLoaderView(msgText, inline)); +}); diff --git a/src/js/apps/loading/show/loading_view.js b/src/js/apps/loading/show/loading_view.js index 26647e7b..db9da7ec 100644 --- a/src/js/apps/loading/show/loading_view.js +++ b/src/js/apps/loading/show/loading_view.js @@ -1,11 +1,26 @@ -@Kodi.module "LoadingApp.Show", (Show, App, Backbone, Marionette, $, _) -> - - class Show.Page extends Backbone.Marionette.ItemView - template: "apps/loading/show/loading_page" - onRender: -> - @$el.find('h2').html @options.textHtml - attributes: -> - if @options.inline - { +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("LoadingApp.Show", (Show, App, Backbone, Marionette, $, _) => (function() { + const Cls = (Show.Page = class Page extends Backbone.Marionette.ItemView { + static initClass() { + this.prototype.template = "apps/loading/show/loading_page"; + } + onRender() { + return this.$el.find('h2').html(this.options.textHtml); + } + attributes() { + if (this.options.inline) { + return { class: 'loader-inline' - } + }; + } + } + }); + Cls.initClass(); + return Cls; +})()); diff --git a/src/js/apps/localPlaylist/list/list_controller.js b/src/js/apps/localPlaylist/list/list_controller.js index 99262730..002fc1f0 100644 --- a/src/js/apps/localPlaylist/list/list_controller.js +++ b/src/js/apps/localPlaylist/list/list_controller.js @@ -1,97 +1,125 @@ -@Kodi.module "localPlaylistApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("localPlaylistApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.Controller extends App.Controllers.Base + return List.Controller = class Controller extends App.Controllers.Base { - initialize: (options) -> - id = options.id - playlists = App.request "localplaylist:entities" - @layout = @getLayoutView playlists + initialize(options) { + const { + id + } = options; + const playlists = App.request("localplaylist:entities"); + this.layout = this.getLayoutView(playlists); - @listenTo @layout, "show", => - @getListsView(playlists) - @getItems(id) + this.listenTo(this.layout, "show", () => { + this.getListsView(playlists); + return this.getItems(id); + }); - App.regionContent.show @layout + return App.regionContent.show(this.layout); + } - ## Get the layout - getLayoutView: (collection) -> - new List.ListLayout - collection: collection + //# Get the layout + getLayoutView(collection) { + return new List.ListLayout({ + collection}); + } - ## Get the sidebar list - getListsView: (playlists) -> - @sideLayout = new List.SideLayout() - view = new List.Lists - collection: playlists - App.listenTo @sideLayout, "show", => - if playlists.length > 0 - @sideLayout.regionLists.show view - App.listenTo @sideLayout, 'lists:new', -> - App.execute "localplaylist:newlist" - @layout.regionSidebarFirst.show @sideLayout + //# Get the sidebar list + getListsView(playlists) { + this.sideLayout = new List.SideLayout(); + const view = new List.Lists({ + collection: playlists}); + App.listenTo(this.sideLayout, "show", () => { + if (playlists.length > 0) { + return this.sideLayout.regionLists.show(view); + } + }); + App.listenTo(this.sideLayout, 'lists:new', () => App.execute("localplaylist:newlist")); + return this.layout.regionSidebarFirst.show(this.sideLayout); + } - ## Get items then render - getItems: (id) -> - playlist = App.request "localplaylist:entity", id - collection = App.request "localplaylist:item:entities", id - @itemLayout = new List.Layout - list: playlist - App.listenTo @itemLayout, "show", => - if collection.length > 0 - media = playlist.get('media') - view = App.request "#{media}:list:view", collection, true - @itemLayout.regionListItems.show view - @bindRemove id, view - @initSortable id, view - @bindLayout id - @layout.regionContent.show @itemLayout + //# Get items then render + getItems(id) { + const playlist = App.request("localplaylist:entity", id); + const collection = App.request("localplaylist:item:entities", id); + this.itemLayout = new List.Layout({ + list: playlist}); + App.listenTo(this.itemLayout, "show", () => { + if (collection.length > 0) { + const media = playlist.get('media'); + const view = App.request(`${media}:list:view`, collection, true); + this.itemLayout.regionListItems.show(view); + this.bindRemove(id, view); + return this.initSortable(id, view); + } + }); + this.bindLayout(id); + return this.layout.regionContent.show(this.itemLayout); + } - ## Binds to layout - bindLayout: (id) -> - collection = App.request "localplaylist:item:entities", id - App.listenTo @itemLayout, 'list:clear', -> - App.execute "localplaylist:clear:entities", id - App.execute "localplaylist:reload", id - App.listenTo @itemLayout, 'list:delete', -> - App.execute "localplaylist:clear:entities", id - App.execute "localplaylist:remove:entity", id - App.navigate "playlists", {trigger: true} - App.listenTo @itemLayout, 'list:rename', -> - App.execute "localplaylist:rename", id - App.listenTo @itemLayout, 'list:play', -> - kodiPlaylist = App.request "command:kodi:controller", 'audio', 'PlayList' - kodiPlaylist.playCollection(collection) - App.listenTo @itemLayout, 'list:localplay', -> - localPlaylist = App.request "command:local:controller", 'audio', 'PlayList' - localPlaylist.playCollection(collection) - App.listenTo @itemLayout, 'list:export', -> - App.execute "playlist:export", collection + //# Binds to layout + bindLayout(id) { + const collection = App.request("localplaylist:item:entities", id); + App.listenTo(this.itemLayout, 'list:clear', function() { + App.execute("localplaylist:clear:entities", id); + return App.execute("localplaylist:reload", id); + }); + App.listenTo(this.itemLayout, 'list:delete', function() { + App.execute("localplaylist:clear:entities", id); + App.execute("localplaylist:remove:entity", id); + return App.navigate("playlists", {trigger: true}); + }); + App.listenTo(this.itemLayout, 'list:rename', () => App.execute("localplaylist:rename", id)); + App.listenTo(this.itemLayout, 'list:play', function() { + const kodiPlaylist = App.request("command:kodi:controller", 'audio', 'PlayList'); + return kodiPlaylist.playCollection(collection); + }); + App.listenTo(this.itemLayout, 'list:localplay', function() { + const localPlaylist = App.request("command:local:controller", 'audio', 'PlayList'); + return localPlaylist.playCollection(collection); + }); + return App.listenTo(this.itemLayout, 'list:export', () => App.execute("playlist:export", collection)); + } - ## Binds to items - bindRemove: (id, view) -> - App.listenTo view, 'childview:song:remove', (parent, viewItem) => - # Update the order, exclude removed item - @updateOrder id, view.$el, [parent.$el.data('id')] + //# Binds to items + bindRemove(id, view) { + return App.listenTo(view, 'childview:song:remove', (parent, viewItem) => { + // Update the order, exclude removed item + return this.updateOrder(id, view.$el, [parent.$el.data('id')]); + }); + } - ## Bind sortable - initSortable: (id, view) -> - self = @ - $('tbody', view.$el).sortable({ - onEnd: (e) => - self.updateOrder id, @el + //# Bind sortable + initSortable(id, view) { + const self = this; + return $('tbody', view.$el).sortable({ + onEnd: e => { + return self.updateOrder(id, this.el); + } }); + } - ## Rebuild the order of items after sort or item removal, excluded items - ## will get removed from the collection - updateOrder: (playlistId, $ctx, exclude = []) -> - order = [] - pos = 0 - $('tr', $ctx).each (i, d) -> - id = $(d).data('id') - if helpers.global.inArray(id, exclude) - $(d).remove() - else - order.push id - $(d).data('id', pos) - pos++ - App.request "localplaylist:item:updateorder", playlistId, order + //# Rebuild the order of items after sort or item removal, excluded items + //# will get removed from the collection + updateOrder(playlistId, $ctx, exclude = []) { + const order = []; + let pos = 0; + $('tr', $ctx).each(function(i, d) { + const id = $(d).data('id'); + if (helpers.global.inArray(id, exclude)) { + return $(d).remove(); + } else { + order.push(id); + $(d).data('id', pos); + return pos++; + } + }); + return App.request("localplaylist:item:updateorder", playlistId, order); + } + }; +}); diff --git a/src/js/apps/localPlaylist/list/list_view.js b/src/js/apps/localPlaylist/list/list_view.js index 371178e1..fbe24a8c 100644 --- a/src/js/apps/localPlaylist/list/list_view.js +++ b/src/js/apps/localPlaylist/list/list_view.js @@ -1,64 +1,111 @@ -@Kodi.module "localPlaylistApp.List", (List, App, Backbone, Marionette, $, _) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("localPlaylistApp.List", function(List, App, Backbone, Marionette, $, _) { - class List.ListLayout extends App.Views.LayoutWithSidebarFirstView - className: "local-playlist-list" + let Cls = (List.ListLayout = class ListLayout extends App.Views.LayoutWithSidebarFirstView { + static initClass() { + this.prototype.className = "local-playlist-list"; + } + }); + Cls.initClass(); - class List.SideLayout extends App.Views.LayoutView - template: 'apps/localPlaylist/list/playlist_sidebar_layout' - tagName: 'div' - className: 'side-inner' - regions: - regionLists: '.current-lists' - triggers: - 'click .new-list' : 'lists:new' + Cls = (List.SideLayout = class SideLayout extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist_sidebar_layout'; + this.prototype.tagName = 'div'; + this.prototype.className = 'side-inner'; + this.prototype.regions = + {regionLists: '.current-lists'}; + this.prototype.triggers = + {'click .new-list' : 'lists:new'}; + } + }); + Cls.initClass(); - class List.List extends App.Views.ItemView - template: 'apps/localPlaylist/list/playlist' - tagName: "li" - initialize: -> - path = helpers.url.get 'playlist', @model.get('id') - @model.set(title: @model.get('name'), path: path) - if path is helpers.url.path() - @model.set(active: true) + Cls = (List.List = class List extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist'; + this.prototype.tagName = "li"; + } + initialize() { + const path = helpers.url.get('playlist', this.model.get('id')); + this.model.set({title: this.model.get('name'), path}); + if (path === helpers.url.path()) { + return this.model.set({active: true}); + } + } + }); + Cls.initClass(); - class List.Lists extends App.Views.CompositeView - template: 'apps/localPlaylist/list/playlist_list' - childView: List.List - tagName: "div" - childViewContainer: 'ul.lists' - onRender: -> - $('h3', @$el).text( t.gettext('Playlists') ) + Cls = (List.Lists = class Lists extends App.Views.CompositeView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist_list'; + this.prototype.childView = List.List; + this.prototype.tagName = "div"; + this.prototype.childViewContainer = 'ul.lists'; + } + onRender() { + return $('h3', this.$el).text( t.gettext('Playlists') ); + } + }); + Cls.initClass(); - class List.Selection extends App.Views.ItemView - template: 'apps/localPlaylist/list/playlist' - tagName: "li" - initialize: -> - @model.set(title: @model.get('name')) - triggers: - 'click .item' : 'item:selected' + Cls = (List.Selection = class Selection extends App.Views.ItemView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist'; + this.prototype.tagName = "li"; + this.prototype.triggers = + {'click .item' : 'item:selected'}; + } + initialize() { + return this.model.set({title: this.model.get('name')}); + } + }); + Cls.initClass(); - class List.SelectionList extends App.Views.CompositeView - template: 'apps/localPlaylist/list/playlist_list' - childView: List.Selection - tagName: "div" - className: 'playlist-selection-list' - childViewContainer: 'ul.lists' - onRender: -> - $('h3', @$el).text( t.gettext('Existing playlists') ) + Cls = (List.SelectionList = class SelectionList extends App.Views.CompositeView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist_list'; + this.prototype.childView = List.Selection; + this.prototype.tagName = "div"; + this.prototype.className = 'playlist-selection-list'; + this.prototype.childViewContainer = 'ul.lists'; + } + onRender() { + return $('h3', this.$el).text( t.gettext('Existing playlists') ); + } + }); + Cls.initClass(); - class List.Layout extends App.Views.LayoutView - template: 'apps/localPlaylist/list/playlist_layout' - tagName: 'div' - className: 'local-playlist' - regions: - regionListItems: '.item-container' - triggers: - 'click .local-playlist-header .rename' : 'list:rename' - 'click .local-playlist-header .clear' : 'list:clear' - 'click .local-playlist-header .delete' : 'list:delete' - 'click .local-playlist-header .play' : 'list:play' - 'click .local-playlist-header .localplay' : 'list:localplay' - 'click .local-playlist-header .export' : 'list:export' - onRender: -> - if @options and @options.list - $('h2', @$el).text( @options.list.get('name') ) + return (function() { + Cls = (List.Layout = class Layout extends App.Views.LayoutView { + static initClass() { + this.prototype.template = 'apps/localPlaylist/list/playlist_layout'; + this.prototype.tagName = 'div'; + this.prototype.className = 'local-playlist'; + this.prototype.regions = + {regionListItems: '.item-container'}; + this.prototype.triggers = { + 'click .local-playlist-header .rename' : 'list:rename', + 'click .local-playlist-header .clear' : 'list:clear', + 'click .local-playlist-header .delete' : 'list:delete', + 'click .local-playlist-header .play' : 'list:play', + 'click .local-playlist-header .localplay' : 'list:localplay', + 'click .local-playlist-header .export' : 'list:export' + }; + } + onRender() { + if (this.options && this.options.list) { + return $('h2', this.$el).text( this.options.list.get('name') ); + } + } + }); + Cls.initClass(); + return Cls; + })(); +}); diff --git a/src/js/apps/localPlaylist/localPlaylist_app.js b/src/js/apps/localPlaylist/localPlaylist_app.js index e079b3eb..34ed9831 100644 --- a/src/js/apps/localPlaylist/localPlaylist_app.js +++ b/src/js/apps/localPlaylist/localPlaylist_app.js @@ -1,119 +1,151 @@ -@Kodi.module "localPlaylistApp", (localPlaylistApp, App, Backbone, Marionette, $, _) -> - - class localPlaylistApp.Router extends App.Router.Base - appRoutes: - "playlists" : "list" - "playlist/:id" : "list" - - - ### +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * DS208: Avoid top-level this + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +this.Kodi.module("localPlaylistApp", function(localPlaylistApp, App, Backbone, Marionette, $, _) { + + const Cls = (localPlaylistApp.Router = class Router extends App.Router.Base { + static initClass() { + this.prototype.appRoutes = { + "playlists" : "list", + "playlist/:id" : "list" + }; + } + }); + Cls.initClass(); + + + /* Main functionality. - ### - - API = - - playlistNameMsg: 'Give your playlist a name' - - ## if no id, find the first list, else id is 0 - list: (id) -> - if id is null - lists = App.request "localplaylist:entities" - items = lists.getRawCollection() - if _.isEmpty lists - id = 0 - else - item = _.min items, (list) -> list.id - id = item.id - App.navigate helpers.url.get('playlist', id) - new localPlaylistApp.List.Controller - id: id - - ## Wrapper for adding to a new or existing list. - addToList: (entityType, id) -> - playlists = App.request "localplaylist:entities" - if not playlists or playlists.length is 0 - @createNewList(entityType, id) - else - view = new localPlaylistApp.List.SelectionList - collection: playlists - $content = view.render().$el - ## New list button - $new = $('