diff --git a/package-lock.json b/package-lock.json index d92bf27e..81768fd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,20 +26,20 @@ "dev": true }, "@babel/core": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.15.tgz", - "integrity": "sha512-6GXmNYeNjS2Uz+uls5jalOemgIhnTMeaXo+yBUA72kC2uX/8VW6XyhVIo2L8/q0goKQA3EVKx0KOQpVKSeWadQ==", + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.16.tgz", + "integrity": "sha512-sXHpixBiWWFti0AV2Zq7avpTasr6sIAu7Y396c608541qAU2ui4a193m0KSQmfPSKFZLnQ3cvlKDOm3XkuXm3Q==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.13.9", - "@babel/helper-compilation-targets": "^7.13.13", + "@babel/generator": "^7.13.16", + "@babel/helper-compilation-targets": "^7.13.16", "@babel/helper-module-transforms": "^7.13.14", - "@babel/helpers": "^7.13.10", - "@babel/parser": "^7.13.15", + "@babel/helpers": "^7.13.16", + "@babel/parser": "^7.13.16", "@babel/template": "^7.12.13", "@babel/traverse": "^7.13.15", - "@babel/types": "^7.13.14", + "@babel/types": "^7.13.16", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -58,16 +58,28 @@ } }, "@babel/generator": { - "version": "7.13.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", - "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.16.tgz", + "integrity": "sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg==", "dev": true, "requires": { - "@babel/types": "^7.13.0", + "@babel/types": "^7.13.16", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, + "@babel/helper-compilation-targets": { + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", + "integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.15", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + } + }, "@babel/helper-function-name": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", @@ -170,9 +182,9 @@ } }, "@babel/parser": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz", - "integrity": "sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ==", + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.16.tgz", + "integrity": "sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw==", "dev": true }, "@babel/template": { @@ -187,32 +199,50 @@ } }, "@babel/traverse": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz", - "integrity": "sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.17.tgz", + "integrity": "sha512-BMnZn0R+X6ayqm3C3To7o1j7Q020gWdqdyP50KEoVqaCO2c/Im7sYZSmVgvefp8TTMQ+9CtwuBp0Z1CZ8V3Pvg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.13.9", + "@babel/generator": "^7.13.16", "@babel/helper-function-name": "^7.12.13", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.13.15", - "@babel/types": "^7.13.14", + "@babel/parser": "^7.13.16", + "@babel/types": "^7.13.17", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.13.14", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", - "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.17.tgz", + "integrity": "sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", - "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, + "browserslist": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.4.tgz", + "integrity": "sha512-d7rCxYV8I9kj41RH8UKYnvDYCRENUlHRgyXy/Rhr/1BaeLGfiCptEdFE8MIrvGfWbBFNjVYx76SQWvNX1j+/cQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001208", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.712", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + } + }, + "caniuse-lite": { + "version": "1.0.30001214", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001214.tgz", + "integrity": "sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg==", + "dev": true + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -223,6 +253,24 @@ "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } + }, + "electron-to-chromium": { + "version": "1.3.718", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.718.tgz", + "integrity": "sha512-CikzdUSShGXwjq1pcW740wK8j+KbazgHZiwzlHICejDaczM6OVsPcrZmBHPwzj9i2rj5twg20MBwp+cYZwldYA==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true } } }, @@ -1401,14 +1449,14 @@ } }, "@babel/helpers": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", - "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.17.tgz", + "integrity": "sha512-Eal4Gce4kGijo1/TGJdqp3WuhllaMLSrW6XcL0ulyUAQOuxHcCafZE8KHg9857gcTehsm/v7RcOx2+jp0Ryjsg==", "dev": true, "requires": { "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.0" + "@babel/traverse": "^7.13.17", + "@babel/types": "^7.13.17" }, "dependencies": { "@babel/code-frame": { @@ -1421,12 +1469,12 @@ } }, "@babel/generator": { - "version": "7.13.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", - "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.16.tgz", + "integrity": "sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg==", "dev": true, "requires": { - "@babel/types": "^7.13.0", + "@babel/types": "^7.13.16", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -1478,9 +1526,9 @@ } }, "@babel/parser": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz", - "integrity": "sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ==", + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.16.tgz", + "integrity": "sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw==", "dev": true }, "@babel/template": { @@ -1495,29 +1543,28 @@ } }, "@babel/traverse": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz", - "integrity": "sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.17.tgz", + "integrity": "sha512-BMnZn0R+X6ayqm3C3To7o1j7Q020gWdqdyP50KEoVqaCO2c/Im7sYZSmVgvefp8TTMQ+9CtwuBp0Z1CZ8V3Pvg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.13.9", + "@babel/generator": "^7.13.16", "@babel/helper-function-name": "^7.12.13", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.13.15", - "@babel/types": "^7.13.14", + "@babel/parser": "^7.13.16", + "@babel/types": "^7.13.17", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.13.14", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", - "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.17.tgz", + "integrity": "sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", - "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, @@ -3170,9 +3217,9 @@ } }, "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", + "version": "0.0.47", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.47.tgz", + "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", "dev": true }, "@types/fs-extra": { @@ -6094,9 +6141,9 @@ } }, "core-js": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz", - "integrity": "sha512-pwCxEXnj27XG47mu7SXAwhLP3L5CrlvCB91ANUkIz40P27kUcvNfSdvyZJ9CLHiVoKSp+TTChMQMSKQEH/IQxA==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.2.tgz", + "integrity": "sha512-W+2oVYeNghuBr3yTzZFQ5rfmjZtYB/Ubg87R5YOmlGrIb+Uw9f7qjUbhsj+/EkXhcV7eOD3jiM4+sgraX3FZUw==", "dev": true }, "core-js-compat": { @@ -6340,23 +6387,22 @@ } }, "css-loader": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.1.tgz", - "integrity": "sha512-YCyRzlt/jgG1xanXZDG/DHqAueOtXFHeusP9TS478oP1J++JSKOyEgGW1GHVoCj/rkS+GWOlBwqQJBr9yajQ9w==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.4.tgz", + "integrity": "sha512-OFYGyINCKkdQsTrSYxzGSFnGS4gNjcXkKkQgWxK138jgnPt+lepxdjSZNc8sHAl5vP3DhsJUxufWIjOwI8PMMw==", "dev": true, "requires": { "camelcase": "^6.2.0", - "cssesc": "^3.0.0", "icss-utils": "^5.1.0", "loader-utils": "^2.0.0", - "postcss": "^8.2.8", + "postcss": "^8.2.10", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.1.0", "schema-utils": "^3.0.0", - "semver": "^7.3.4" + "semver": "^7.3.5" }, "dependencies": { "ajv": { @@ -7291,20 +7337,30 @@ } }, "electron-devtools-installer": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-3.1.1.tgz", - "integrity": "sha512-g2D4J6APbpsiIcnLkFMyKZ6bOpEJ0Ltcc2m66F7oKUymyGAt628OWeU9nRZoh1cNmUs/a6Cls2UfOmsZtE496Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-3.2.0.tgz", + "integrity": "sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ==", "dev": true, "requires": { "rimraf": "^3.0.2", "semver": "^7.2.1", + "tslib": "^2.1.0", "unzip-crx-3": "^0.2.0" }, "dependencies": { "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", "dev": true } } @@ -7495,9 +7551,9 @@ } }, "enhanced-resolve": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", - "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.0.tgz", + "integrity": "sha512-Sl3KRpJA8OpprrtaIswVki3cWPiPKxXuFxJXBp+zNb6s6VwNWwFRUdtmzd2ReUut8n+sCPx7QCtQ7w5wfJhSgQ==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -10355,9 +10411,9 @@ } }, "jszip": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", - "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", + "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", "dev": true, "requires": { "lie": "~3.3.0", @@ -10773,9 +10829,9 @@ } }, "markdown-it": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.5.tgz", - "integrity": "sha512-9KB992Yy2TedaoKETgZPL2n3bmqqZxzUsZ4fxe2ho+/AYuQUz+iDKpfjLgKbg/lHcG6cGOj+L3gDrn9S2CxoRg==", + "version": "12.0.6", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz", + "integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==", "dev": true, "requires": { "argparse": "^2.0.1", @@ -10928,9 +10984,9 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.4.1.tgz", - "integrity": "sha512-COAGbpAsU0ioFzj+/RRfO5Qv177L1Z/XAx2EmCF33b8GDDqKygMffBTws2lit8iaPdrbKEY5P+zsseBUCREZWQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.5.0.tgz", + "integrity": "sha512-SIbuLMv6jsk1FnLIU5OUG/+VMGUprEjM1+o2trOAx8i5KOKMrhyezb1dJ4Ugsykb8Jgq8/w5NEopy6escV9G7g==", "dev": true, "requires": { "loader-utils": "^2.0.0", @@ -12757,14 +12813,12 @@ }, "dependencies": { "postcss-selector-parser": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", - "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.5.tgz", + "integrity": "sha512-aFYPoYmXbZ1V6HZaSvat08M97A8HqO6Pjz+PiNpw/DhuRrC72XWAdp3hL6wusDCN31sSmcZyMGa2hZEuX+Xfhg==", "dev": true, "requires": { "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1", "util-deprecate": "^1.0.2" } } @@ -16709,20 +16763,20 @@ } }, "webpack": { - "version": "5.33.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.33.2.tgz", - "integrity": "sha512-X4b7F1sYBmJx8mlh2B7mV5szEkE0jYNJ2y3akgAP0ERi0vLCG1VvdsIxt8lFd4st6SUy0lf7W0CCQS566MBpJg==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.35.0.tgz", + "integrity": "sha512-au3gu55yYF/h6NXFr0KZPZAYxS6Nlc595BzYPke8n0CSff5WXcoixtjh5LC/8mXunkRKxhymhXmBY0+kEbR6jg==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", + "@types/estree": "^0.0.47", "@webassemblyjs/ast": "1.11.0", "@webassemblyjs/wasm-edit": "1.11.0", "@webassemblyjs/wasm-parser": "1.11.0", "acorn": "^8.0.4", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", + "enhanced-resolve": "^5.8.0", "es-module-lexer": "^0.4.0", "eslint-scope": "^5.1.1", "events": "^3.2.0", @@ -16777,15 +16831,15 @@ } }, "caniuse-lite": { - "version": "1.0.30001208", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz", - "integrity": "sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==", + "version": "1.0.30001214", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001214.tgz", + "integrity": "sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg==", "dev": true }, "electron-to-chromium": { - "version": "1.3.717", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.717.tgz", - "integrity": "sha512-OfzVPIqD1MkJ7fX+yTl2nKyOE4FReeVfMCzzxQS+Kp43hZYwHwThlGP+EGIZRXJsxCM7dqo8Y65NOX/HP12iXQ==", + "version": "1.3.718", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.718.tgz", + "integrity": "sha512-CikzdUSShGXwjq1pcW740wK8j+KbazgHZiwzlHICejDaczM6OVsPcrZmBHPwzj9i2rj5twg20MBwp+cYZwldYA==", "dev": true }, "escalade": { diff --git a/package.json b/package.json index f25afcd0..1c434980 100644 --- a/package.json +++ b/package.json @@ -155,7 +155,7 @@ }, "homepage": "https://github.com/lyswhut/lx-music-desktop#readme", "devDependencies": { - "@babel/core": "^7.13.15", + "@babel/core": "^7.13.16", "@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-modules-umd": "^7.13.0", @@ -170,14 +170,14 @@ "chalk": "^4.1.0", "changelog-parser": "^2.8.0", "copy-webpack-plugin": "^8.1.1", - "core-js": "^3.10.1", + "core-js": "^3.10.2", "cross-env": "^7.0.3", - "css-loader": "^5.2.1", + "css-loader": "^5.2.4", "del": "^6.0.0", "electron": "^9.4.4", "electron-builder": "^22.10.5", "electron-debug": "^3.2.0", - "electron-devtools-installer": "^3.1.1", + "electron-devtools-installer": "^3.2.0", "eslint": "^7.24.0", "eslint-config-standard": "^14.1.1", "eslint-formatter-friendly": "^7.0.0", @@ -193,8 +193,8 @@ "less": "^4.1.1", "less-loader": "^8.1.1", "less-plugin-clean-css": "^1.5.1", - "markdown-it": "^12.0.5", - "mini-css-extract-plugin": "^1.4.1", + "markdown-it": "^12.0.6", + "mini-css-extract-plugin": "^1.5.0", "optimize-css-assets-webpack-plugin": "^5.0.4", "postcss": "^8.2.10", "postcss-loader": "^5.2.0", @@ -211,7 +211,7 @@ "url-loader": "^4.1.1", "vue-loader": "^15.9.6", "vue-template-compiler": "^2.6.12", - "webpack": "^5.33.2", + "webpack": "^5.35.0", "webpack-cli": "^4.6.0", "webpack-dev-server": "^3.11.2", "webpack-hot-middleware": "^2.25.0", diff --git a/publish/changeLog.md b/publish/changeLog.md index ebe19a67..0dc82fc3 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -3,6 +3,7 @@ - 新增启动参数`-dhmkh`,此参数将禁用Chromium的Hardware Media Key Handling特性,用于解决漫步者部分型号耳机与本程序冲突导致耳机意外关机的问题 - 新增Windows arm64位免安装版的构建 - 新增黑色皮肤“黑灯瞎火”,有关于皮肤配色的建议欢迎反馈 +- 新增自动换源下载功能,默认关闭,当无法从歌曲的原始源下载时,将尝试切换到其他源下载,注:此功能不100%保证换源后的歌曲版本与原版一致 ### 优化 diff --git a/src/common/defaultSetting.js b/src/common/defaultSetting.js index b2830f2d..43455c0b 100644 --- a/src/common/defaultSetting.js +++ b/src/common/defaultSetting.js @@ -2,7 +2,7 @@ const path = require('path') const os = require('os') const defaultSetting = { - version: '1.0.40', + version: '1.0.41', player: { togglePlayMethod: 'listLoop', highQuality: false, @@ -45,6 +45,7 @@ const defaultSetting = { isDownloadLrc: false, isEmbedPic: true, isEmbedLyric: false, + isUseOtherSource: false, }, leaderboard: { source: 'kw', diff --git a/src/renderer/lang/en-us/view/setting.json b/src/renderer/lang/en-us/view/setting.json index 66cfb238..89512278 100644 --- a/src/renderer/lang/en-us/view/setting.json +++ b/src/renderer/lang/en-us/view/setting.json @@ -73,6 +73,7 @@ "download_name1": "Title - Artist", "download_name2": "Artist - Title", "download_name3": "Title only", + "download_use_other_source": "Automatically change the source to download (when the song cannot be downloaded from the original source, try to switch to another source to download. Note: this function does not 100% guarantee that the version of the song after the source is changed is the same as the original version)", "download_select_save_path": "Select the save path", "hot_key": "Shortcut Key Settings", diff --git a/src/renderer/lang/zh-cn/view/setting.json b/src/renderer/lang/zh-cn/view/setting.json index 9b33455c..60bb62bc 100644 --- a/src/renderer/lang/zh-cn/view/setting.json +++ b/src/renderer/lang/zh-cn/view/setting.json @@ -73,6 +73,7 @@ "download_name1": "歌名 - 歌手", "download_name2": "歌手 - 歌名", "download_name3": "歌名", + "download_use_other_source": "自动换源下载(当无法从歌曲的原始源下载时,尝试切换到其他源下载,注:此功能不100%保证换源后的歌曲版本与原版一致)", "download_select_save_path": "选择歌曲保存路径", "hot_key": "快捷键设置", diff --git a/src/renderer/lang/zh-tw/view/setting.json b/src/renderer/lang/zh-tw/view/setting.json index 78ecffba..384d8e72 100644 --- a/src/renderer/lang/zh-tw/view/setting.json +++ b/src/renderer/lang/zh-tw/view/setting.json @@ -73,6 +73,7 @@ "download_name1": "歌名 - 歌手", "download_name2": "歌手 - 歌名", "download_name3": "歌名", + "download_use_other_source": "自動換源下載(當無法從歌曲的原始源下載時,嘗試切換到其他源下載,注:此功能不100%保證換源後的歌曲版本與原版一致)", "download_select_save_path": "選擇歌曲保存路徑", "hot_key": "快捷鍵設置", diff --git a/src/renderer/store/modules/download.js b/src/renderer/store/modules/download.js index d4e3c2f8..f424398e 100644 --- a/src/renderer/store/modules/download.js +++ b/src/renderer/store/modules/download.js @@ -3,7 +3,15 @@ import fs from 'fs' import path from 'path' import music from '../../utils/music' import { getMusicType } from '../../utils/music/utils' -import { setMeta, saveLrc, getLyric, setLyric, getMusicUrl, setMusicUrl } from '../../utils' +import { + setMeta, + saveLrc, + getLyric as getLyricFromStorage, + setLyric, + getMusicUrl as getMusicUrlFormStorage, + setMusicUrl, + assertApiSupport, +} from '../../utils' // state const state = { @@ -147,8 +155,33 @@ const pauseTasks = async(store, list, runs = []) => { await pauseTasks(store, list, runs) } -const getUrl = async(downloadInfo, isRefresh) => { - const cachedUrl = await getMusicUrl(downloadInfo.musicInfo, downloadInfo.type) +const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMusic) { + // console.log(musicInfo.source) + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getMusicUrl(musicInfo, type).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source) || !assertApiSupport(musicInfo.source)) retryedSource.push(musicInfo.source) + return this.dispatch('list/getOtherSource', originMusic).then(otherSource => { + console.log('find otherSource', otherSource) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return handleGetMusicUrl.call(this, item, type, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} + +const getMusicUrl = async function(downloadInfo, isUseOtherSource, isRefresh) { + const cachedUrl = await getMusicUrlFormStorage(downloadInfo.musicInfo, downloadInfo.type) if (!downloadInfo.musicInfo._types[downloadInfo.type]) { // 兼容旧版酷我源搜索列表过滤128k音质的bug if (!(downloadInfo.musicInfo.source == 'kw' && downloadInfo.type == '128k')) throw new Error('该歌曲没有可下载的音频') @@ -157,11 +190,62 @@ const getUrl = async(downloadInfo, isRefresh) => { } return cachedUrl && !isRefresh ? cachedUrl - : music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise.then(({ url }) => { + : ( + isUseOtherSource + ? handleGetMusicUrl.call(this, downloadInfo.musicInfo, downloadInfo.type) + : music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise + ).then(({ url }) => { setMusicUrl(downloadInfo.musicInfo, downloadInfo.type, url) return url }) } +const getPic = function(musicInfo, retryedSource = [], originMusic) { + // console.log(musicInfo.source) + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getPic(musicInfo).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) + return this.dispatch('list/getOtherSource', originMusic).then(otherSource => { + console.log('find otherSource', otherSource) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return getPic.call(this, item, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} +const getLyric = function(musicInfo, retryedSource = [], originMusic) { + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getLyric(musicInfo).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) + return this.dispatch('list/getOtherSource', originMusic).then(otherSource => { + console.log('find otherSource', otherSource) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return getLyric.call(this, item, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} // 修复 1.1.x版本 酷狗源歌词格式 const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[00:(\d\d:\d\d.\d+\]))/gm, '[$1') : lrc @@ -172,22 +256,30 @@ const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[0 * @param {*} filePath * @param {*} isEmbedPic // 是否嵌入图片 */ -const saveMeta = (downloadInfo, filePath, isEmbedPic, isEmbedLyric) => { +const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic, isEmbedLyric) { if (downloadInfo.type === 'ape') return const tasks = [ isEmbedPic ? downloadInfo.musicInfo.img ? Promise.resolve(downloadInfo.musicInfo.img) - : music[downloadInfo.musicInfo.source].getPic(downloadInfo.musicInfo).promise.catch(err => { + : ( + isUseOtherSource + ? getPic.call(this, downloadInfo.musicInfo) + : music[downloadInfo.musicInfo.source].getPic(downloadInfo.musicInfo).promise + ).catch(err => { console.log(err) return null }) : Promise.resolve(), isEmbedLyric - ? getLyric(downloadInfo.musicInfo).then(lrcInfo => { + ? getLyricFromStorage(downloadInfo.musicInfo).then(lrcInfo => { return lrcInfo.lyric ? Promise.resolve({ lyric: lrcInfo.lyric, tlyric: lrcInfo.tlyric || '' }) - : music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise.then(({ lyric, tlyric, lxlyric }) => { + : ( + isUseOtherSource + ? getLyric.call(this, downloadInfo.musicInfo) + : music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise + ).then(({ lyric, tlyric, lxlyric }) => { setLyric(downloadInfo.musicInfo, { lyric, tlyric, lxlyric }) return { lyric, tlyric, lxlyric } }).catch(err => { @@ -231,9 +323,9 @@ const downloadLyric = (downloadInfo, filePath) => { }) } -const refreshUrl = function(commit, downloadInfo) { +const refreshUrl = function(commit, downloadInfo, isUseOtherSource) { commit('setStatusText', { downloadInfo, text: '链接失效,正在刷新链接' }) - getUrl(downloadInfo, true).then(url => { + getMusicUrl.call(this, downloadInfo, isUseOtherSource, true).then(url => { commit('updateUrl', { downloadInfo, url }) commit('setStatusText', { downloadInfo, text: '链接刷新成功' }) const dl = dls[downloadInfo.key] @@ -341,7 +433,7 @@ const actions = { commit('onCompleted', downloadInfo) dispatch('startTask') - saveMeta(downloadInfo, downloadInfo.filePath, rootState.setting.download.isEmbedPic, rootState.setting.download.isEmbedLyric) + saveMeta.call(_this, downloadInfo, downloadInfo.filePath, rootState.setting.download.isUseOtherSource, rootState.setting.download.isEmbedPic, rootState.setting.download.isEmbedLyric) if (rootState.setting.download.isDownloadLrc) downloadLyric(downloadInfo, downloadInfo.filePath) console.log('on complate') }, @@ -358,7 +450,8 @@ const actions = { return } if (err.code == 'ENOTFOUND') { - refreshUrl.call(_this, commit, downloadInfo) + commit('onError', { downloadInfo, errorMsg: '链接失效' }) + refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource) } else { console.log('Download failed, Attempting Retry') dls[downloadInfo.key].start() @@ -375,7 +468,13 @@ const actions = { case 401: case 403: case 410: - refreshUrl.call(_this, commit, downloadInfo) + commit('onError', { downloadInfo, errorMsg: '链接失效' }) + refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource) + break + default: + dls[downloadInfo.key].start() + commit('setStatusText', { downloadInfo, text: '正在重试' }) + break } }, onStart() { @@ -394,7 +493,7 @@ const actions = { commit('setStatusText', { downloadInfo, text: '获取URL中...' }) let p = options.url ? Promise.resolve() - : getUrl(downloadInfo).then(url => { + : getMusicUrl.call(this, downloadInfo, rootState.setting.download.isUseOtherSource).then(url => { commit('updateUrl', { downloadInfo, url }) if (!url) return Promise.reject(new Error('获取URL失败')) options.url = url diff --git a/src/renderer/store/modules/player.js b/src/renderer/store/modules/player.js index b4d1798a..36a0a502 100644 --- a/src/renderer/store/modules/player.js +++ b/src/renderer/store/modules/player.js @@ -68,16 +68,16 @@ const filterList = async({ playedList, listInfo, savePath, commit }) => { const getPic = function(musicInfo, retryedSource = [], originMusic) { // console.log(musicInfo.source) + if (!originMusic) originMusic = musicInfo let reqPromise try { reqPromise = music[musicInfo.source].getPic(musicInfo).promise } catch (err) { reqPromise = Promise.reject(err) } - return reqPromise.promise.catch(err => { + return reqPromise.catch(err => { if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) - return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => { - if (!originMusic) originMusic = musicInfo + return this.dispatch('list/getOtherSource', originMusic).then(otherSource => { console.log('find otherSource', otherSource) if (otherSource.length) { for (const item of otherSource) { @@ -91,16 +91,16 @@ const getPic = function(musicInfo, retryedSource = [], originMusic) { }) } const getLyric = function(musicInfo, retryedSource = [], originMusic) { + if (!originMusic) originMusic = musicInfo let reqPromise try { reqPromise = music[musicInfo.source].getLyric(musicInfo).promise } catch (err) { reqPromise = Promise.reject(err) } - return reqPromise.promise.catch(err => { + return reqPromise.catch(err => { if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) - return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => { - if (!originMusic) originMusic = musicInfo + return this.dispatch('list/getOtherSource', originMusic).then(otherSource => { console.log('find otherSource', otherSource) if (otherSource.length) { for (const item of otherSource) { diff --git a/src/renderer/views/Setting.vue b/src/renderer/views/Setting.vue index 963de0bb..323329c8 100644 --- a/src/renderer/views/Setting.vue +++ b/src/renderer/views/Setting.vue @@ -122,6 +122,11 @@ div(:class="$style.main") span.auto-hidden.hover(:tips="$t('view.setting.download_path_open_label')" :class="$style.savePath" @click="handleOpenDir(current_setting.download.savePath)") {{current_setting.download.savePath}} p material-btn(:class="$style.btn" min @click="handleChangeSavePath") {{$t('view.setting.download_path_change_btn')}} + dd + h3#download_name {{$t('view.setting.download_use_other_source')}} + div + material-checkbox(id="setting_download_isUseOtherSource" v-model="current_setting.download.isUseOtherSource" :label="$t('view.setting.is_enable')") + div dd(:tips="$t('view.setting.download_name_title')") h3#download_name {{$t('view.setting.download_name')}} div