diff --git a/Gulpfile.js b/Gulpfile.js
index 51dfd58..a78cc58 100644
--- a/Gulpfile.js
+++ b/Gulpfile.js
@@ -18,7 +18,7 @@ var uglify = require("gulp-uglify");
var deporder = require("gulp-deporder");
var changed = require("gulp-changed");
var imagemin = require("gulp-imagemin");
-var minifyCss = require("gulp-minify-css");
+var minifyCss = require("gulp-clean-css");
var ghPages = require("gulp-gh-pages");
var babel = require('gulp-babel');
diff --git a/package-lock.json b/package-lock.json
index e5b2c06..cfe9b42 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,11 +16,11 @@
"gulp-autoprefixer": "^8.0.0",
"gulp-babel": "^8.0.0",
"gulp-changed": "^3.2.0",
+ "gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-deporder": "^1.2.0",
"gulp-gh-pages": "^0.6.0-6",
"gulp-imagemin": "^7",
- "gulp-minify-css": "^1.2.4",
"gulp-rename": "^1.4.0",
"gulp-sass": "^5.1.0",
"gulp-sourcemaps": "^2.6.5",
@@ -54,6 +54,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
@@ -1808,15 +1809,6 @@
"node": ">=8"
}
},
- "node_modules/amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
- "dev": true,
- "engines": {
- "node": ">=0.4.2"
- }
- },
"node_modules/ansi-colors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
@@ -2031,15 +2023,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/array-differ": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
- "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/array-each": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
@@ -2134,15 +2117,6 @@
"node": ">=8"
}
},
- "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,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/assign-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -2391,15 +2365,6 @@
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
"dev": true
},
- "node_modules/beeper": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
- "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/bin-build": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bin-build/-/bin-build-3.0.0.tgz",
@@ -2975,42 +2940,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
- "node_modules/bufferstreams": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz",
- "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=",
- "dev": true,
- "dependencies": {
- "readable-stream": "^1.0.33"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/bufferstreams/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/bufferstreams/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": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.1",
- "isarray": "0.0.1",
- "string_decoder": "~0.10.x"
- }
- },
- "node_modules/bufferstreams/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/bytes": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
@@ -3275,34 +3204,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/clean-css": {
- "version": "3.4.28",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
- "integrity": "sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==",
- "dev": true,
- "dependencies": {
- "commander": "2.8.x",
- "source-map": "0.4.x"
- },
- "bin": {
- "cleancss": "bin/cleancss"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/clean-css/node_modules/source-map": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
- "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
- "dev": true,
- "dependencies": {
- "amdefine": ">=0.0.4"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -3851,15 +3752,6 @@
"type": "^1.0.1"
}
},
- "node_modules/dateformat": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
- "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
"node_modules/debug": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
@@ -4288,39 +4180,6 @@
"node": ">=4"
}
},
- "node_modules/duplexer2": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
- "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
- "dev": true,
- "dependencies": {
- "readable-stream": "~1.1.9"
- }
- },
- "node_modules/duplexer2/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/duplexer2/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": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.1",
- "isarray": "0.0.1",
- "string_decoder": "~0.10.x"
- }
- },
- "node_modules/duplexer2/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/duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@@ -6482,6 +6341,8 @@
"resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
"integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==",
"dev": true,
+ "license": "MIT",
+ "peer": true,
"dependencies": {
"glob-watcher": "^5.0.3",
"gulp-cli": "^2.2.0",
@@ -6652,6 +6513,52 @@
"xtend": "~4.0.1"
}
},
+ "node_modules/gulp-clean-css": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.3.0.tgz",
+ "integrity": "sha512-mGyeT3qqFXTy61j0zOIciS4MkYziF2U594t2Vs9rUnpkEHqfu6aDITMp8xOvZcvdX61Uz3y1mVERRYmjzQF5fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clean-css": "4.2.3",
+ "plugin-error": "1.0.1",
+ "through2": "3.0.1",
+ "vinyl-sourcemaps-apply": "0.2.1"
+ }
+ },
+ "node_modules/gulp-clean-css/node_modules/clean-css": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
+ "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "source-map": "~0.6.0"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
+ "node_modules/gulp-clean-css/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,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-clean-css/node_modules/through2": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
+ "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "2 || 3"
+ }
+ },
"node_modules/gulp-cli": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
@@ -6987,21 +6894,6 @@
"node": ">=8"
}
},
- "node_modules/gulp-minify-css": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/gulp-minify-css/-/gulp-minify-css-1.2.4.tgz",
- "integrity": "sha512-byBqFQM/HrZoUVYihu/03iYH4m7U5TjSGhr6/7JvpMHh9+woewsCtEp6Noif2VXB+idDoM4ECd9sw+St+KFqsg==",
- "deprecated": "Please use gulp-clean-css",
- "dev": true,
- "dependencies": {
- "clean-css": "^3.3.3",
- "gulp-util": "^3.0.5",
- "object-assign": "^4.0.1",
- "readable-stream": "^2.0.0",
- "vinyl-bufferstream": "^1.0.1",
- "vinyl-sourcemaps-apply": "^0.2.0"
- }
- },
"node_modules/gulp-rename": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz",
@@ -7106,148 +6998,6 @@
"xtend": "~4.0.1"
}
},
- "node_modules/gulp-util": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
- "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==",
- "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5",
- "dev": true,
- "dependencies": {
- "array-differ": "^1.0.0",
- "array-uniq": "^1.0.2",
- "beeper": "^1.0.0",
- "chalk": "^1.0.0",
- "dateformat": "^2.0.0",
- "fancy-log": "^1.1.0",
- "gulplog": "^1.0.0",
- "has-gulplog": "^0.1.0",
- "lodash._reescape": "^3.0.0",
- "lodash._reevaluate": "^3.0.0",
- "lodash._reinterpolate": "^3.0.0",
- "lodash.template": "^3.0.0",
- "minimist": "^1.1.0",
- "multipipe": "^0.1.2",
- "object-assign": "^3.0.0",
- "replace-ext": "0.0.1",
- "through2": "^2.0.0",
- "vinyl": "^0.5.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/gulp-util/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,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/gulp-util/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"
- }
- },
- "node_modules/gulp-util/node_modules/chalk": {
- "version": "1.1.3",
- "resolved": "https://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/gulp-util/node_modules/clone": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
- "dev": true,
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/gulp-util/node_modules/clone-stats": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
- "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
- "dev": true
- },
- "node_modules/gulp-util/node_modules/object-assign": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
- "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/gulp-util/node_modules/replace-ext": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
- "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/gulp-util/node_modules/strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/gulp-util/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,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/gulp-util/node_modules/through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
- "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
- "dev": true,
- "dependencies": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
- }
- },
- "node_modules/gulp-util/node_modules/vinyl": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
- "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
- "dev": true,
- "dependencies": {
- "clone": "^1.0.0",
- "clone-stats": "^0.0.1",
- "replace-ext": "0.0.1"
- },
- "engines": {
- "node": ">= 0.9"
- }
- },
"node_modules/gulplog": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
@@ -8618,60 +8368,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
- "node_modules/lodash._basecopy": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
- "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
- "dev": true
- },
- "node_modules/lodash._basetostring": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
- "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
- "dev": true
- },
- "node_modules/lodash._basevalues": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
- "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
- "dev": true
- },
- "node_modules/lodash._getnative": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
- "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
- "dev": true
- },
- "node_modules/lodash._isiterateecall": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
- "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
- "dev": true
- },
- "node_modules/lodash._reescape": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
- "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
- "dev": true
- },
- "node_modules/lodash._reevaluate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
- "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
- "dev": true
- },
- "node_modules/lodash._reinterpolate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
- "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
- "dev": true
- },
- "node_modules/lodash._root": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
- "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
- "dev": true
- },
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -8684,77 +8380,12 @@
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
- "node_modules/lodash.escape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
- "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
- "dev": true,
- "dependencies": {
- "lodash._root": "^3.0.0"
- }
- },
- "node_modules/lodash.isarguments": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
- "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
- "dev": true
- },
- "node_modules/lodash.isarray": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
- "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
- "dev": true
- },
"node_modules/lodash.isfinite": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
"integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==",
"dev": true
},
- "node_modules/lodash.keys": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
- "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
- "dev": true,
- "dependencies": {
- "lodash._getnative": "^3.0.0",
- "lodash.isarguments": "^3.0.0",
- "lodash.isarray": "^3.0.0"
- }
- },
- "node_modules/lodash.restparam": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
- "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
- "dev": true
- },
- "node_modules/lodash.template": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
- "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==",
- "dev": true,
- "dependencies": {
- "lodash._basecopy": "^3.0.0",
- "lodash._basetostring": "^3.0.0",
- "lodash._basevalues": "^3.0.0",
- "lodash._isiterateecall": "^3.0.0",
- "lodash._reinterpolate": "^3.0.0",
- "lodash.escape": "^3.0.0",
- "lodash.keys": "^3.0.0",
- "lodash.restparam": "^3.0.0",
- "lodash.templatesettings": "^3.0.0"
- }
- },
- "node_modules/lodash.templatesettings": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
- "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
- "dev": true,
- "dependencies": {
- "lodash._reinterpolate": "^3.0.0",
- "lodash.escape": "^3.0.0"
- }
- },
"node_modules/logalot": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz",
@@ -9496,15 +9127,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
- "node_modules/multipipe": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
- "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
- "dev": true,
- "dependencies": {
- "duplexer2": "0.0.2"
- }
- },
"node_modules/mute-stdout": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz",
@@ -10459,6 +10081,7 @@
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
"integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
"dev": true,
+ "peer": true,
"dependencies": {
"nanoid": "^3.1.30",
"picocolors": "^1.0.0",
@@ -13100,15 +12723,6 @@
"node": ">= 0.10"
}
},
- "node_modules/vinyl-bufferstream": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz",
- "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=",
- "dev": true,
- "dependencies": {
- "bufferstreams": "1.0.1"
- }
- },
"node_modules/vinyl-fs": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
@@ -13395,6 +13009,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
"dev": true,
+ "peer": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
@@ -14645,12 +14260,6 @@
"indent-string": "^4.0.0"
}
},
- "amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
- "dev": true
- },
"ansi-colors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
@@ -14805,12 +14414,6 @@
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
"dev": true
},
- "array-differ": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
- "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
- "dev": true
- },
"array-each": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
@@ -14882,12 +14485,6 @@
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true
},
- "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
- },
"assign-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -15072,12 +14669,6 @@
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
"dev": true
},
- "beeper": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
- "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=",
- "dev": true
- },
"bin-build": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bin-build/-/bin-build-3.0.0.tgz",
@@ -15554,41 +15145,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
- "bufferstreams": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz",
- "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=",
- "dev": true,
- "requires": {
- "readable-stream": "^1.0.33"
- },
- "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
- }
- }
- },
"bytes": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
@@ -15792,27 +15348,6 @@
}
}
},
- "clean-css": {
- "version": "3.4.28",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
- "integrity": "sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==",
- "dev": true,
- "requires": {
- "commander": "2.8.x",
- "source-map": "0.4.x"
- },
- "dependencies": {
- "source-map": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
- "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
- "dev": true,
- "requires": {
- "amdefine": ">=0.0.4"
- }
- }
- }
- },
"clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -16271,12 +15806,6 @@
"type": "^1.0.1"
}
},
- "dateformat": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
- "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
- "dev": true
- },
"debug": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
@@ -16621,41 +16150,6 @@
}
}
},
- "duplexer2": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
- "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
- "dev": true,
- "requires": {
- "readable-stream": "~1.1.9"
- },
- "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
- }
- }
- },
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@@ -18414,6 +17908,7 @@
"resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
"integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==",
"dev": true,
+ "peer": true,
"requires": {
"glob-watcher": "^5.0.3",
"gulp-cli": "^2.2.0",
@@ -18541,6 +18036,44 @@
}
}
},
+ "gulp-clean-css": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.3.0.tgz",
+ "integrity": "sha512-mGyeT3qqFXTy61j0zOIciS4MkYziF2U594t2Vs9rUnpkEHqfu6aDITMp8xOvZcvdX61Uz3y1mVERRYmjzQF5fg==",
+ "dev": true,
+ "requires": {
+ "clean-css": "4.2.3",
+ "plugin-error": "1.0.1",
+ "through2": "3.0.1",
+ "vinyl-sourcemaps-apply": "0.2.1"
+ },
+ "dependencies": {
+ "clean-css": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
+ "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ }
+ },
+ "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
+ },
+ "through2": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
+ "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2 || 3"
+ }
+ }
+ }
+ },
"gulp-cli": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
@@ -18817,20 +18350,6 @@
}
}
},
- "gulp-minify-css": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/gulp-minify-css/-/gulp-minify-css-1.2.4.tgz",
- "integrity": "sha512-byBqFQM/HrZoUVYihu/03iYH4m7U5TjSGhr6/7JvpMHh9+woewsCtEp6Noif2VXB+idDoM4ECd9sw+St+KFqsg==",
- "dev": true,
- "requires": {
- "clean-css": "^3.3.3",
- "gulp-util": "^3.0.5",
- "object-assign": "^4.0.1",
- "readable-stream": "^2.0.0",
- "vinyl-bufferstream": "^1.0.1",
- "vinyl-sourcemaps-apply": "^0.2.0"
- }
- },
"gulp-rename": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz",
@@ -18926,119 +18445,6 @@
}
}
},
- "gulp-util": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
- "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==",
- "dev": true,
- "requires": {
- "array-differ": "^1.0.0",
- "array-uniq": "^1.0.2",
- "beeper": "^1.0.0",
- "chalk": "^1.0.0",
- "dateformat": "^2.0.0",
- "fancy-log": "^1.1.0",
- "gulplog": "^1.0.0",
- "has-gulplog": "^0.1.0",
- "lodash._reescape": "^3.0.0",
- "lodash._reevaluate": "^3.0.0",
- "lodash._reinterpolate": "^3.0.0",
- "lodash.template": "^3.0.0",
- "minimist": "^1.1.0",
- "multipipe": "^0.1.2",
- "object-assign": "^3.0.0",
- "replace-ext": "0.0.1",
- "through2": "^2.0.0",
- "vinyl": "^0.5.0"
- },
- "dependencies": {
- "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
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- }
- },
- "clone": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
- "dev": true
- },
- "clone-stats": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
- "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
- "dev": true
- },
- "object-assign": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
- "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
- "dev": true
- },
- "replace-ext": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
- "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
- "dev": true
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- },
- "through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
- "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
- "dev": true,
- "requires": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
- }
- },
- "vinyl": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
- "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
- "dev": true,
- "requires": {
- "clone": "^1.0.0",
- "clone-stats": "^0.0.1",
- "replace-ext": "0.0.1"
- }
- }
- }
- },
"gulplog": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
@@ -20064,60 +19470,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
- "lodash._basecopy": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
- "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
- "dev": true
- },
- "lodash._basetostring": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
- "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
- "dev": true
- },
- "lodash._basevalues": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
- "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
- "dev": true
- },
- "lodash._getnative": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
- "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
- "dev": true
- },
- "lodash._isiterateecall": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
- "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
- "dev": true
- },
- "lodash._reescape": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
- "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
- "dev": true
- },
- "lodash._reevaluate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
- "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
- "dev": true
- },
- "lodash._reinterpolate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
- "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
- "dev": true
- },
- "lodash._root": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
- "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
- "dev": true
- },
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -20130,77 +19482,12 @@
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
- "lodash.escape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
- "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
- "dev": true,
- "requires": {
- "lodash._root": "^3.0.0"
- }
- },
- "lodash.isarguments": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
- "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
- "dev": true
- },
- "lodash.isarray": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
- "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
- "dev": true
- },
"lodash.isfinite": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
"integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==",
"dev": true
},
- "lodash.keys": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
- "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
- "dev": true,
- "requires": {
- "lodash._getnative": "^3.0.0",
- "lodash.isarguments": "^3.0.0",
- "lodash.isarray": "^3.0.0"
- }
- },
- "lodash.restparam": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
- "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
- "dev": true
- },
- "lodash.template": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
- "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==",
- "dev": true,
- "requires": {
- "lodash._basecopy": "^3.0.0",
- "lodash._basetostring": "^3.0.0",
- "lodash._basevalues": "^3.0.0",
- "lodash._isiterateecall": "^3.0.0",
- "lodash._reinterpolate": "^3.0.0",
- "lodash.escape": "^3.0.0",
- "lodash.keys": "^3.0.0",
- "lodash.restparam": "^3.0.0",
- "lodash.templatesettings": "^3.0.0"
- }
- },
- "lodash.templatesettings": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
- "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
- "dev": true,
- "requires": {
- "lodash._reinterpolate": "^3.0.0",
- "lodash.escape": "^3.0.0"
- }
- },
"logalot": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz",
@@ -20804,15 +20091,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
- "multipipe": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
- "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
- "dev": true,
- "requires": {
- "duplexer2": "0.0.2"
- }
- },
"mute-stdout": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz",
@@ -21537,6 +20815,7 @@
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
"integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
"dev": true,
+ "peer": true,
"requires": {
"nanoid": "^3.1.30",
"picocolors": "^1.0.0",
@@ -23660,15 +22939,6 @@
"replace-ext": "^1.0.0"
}
},
- "vinyl-bufferstream": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz",
- "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=",
- "dev": true,
- "requires": {
- "bufferstreams": "1.0.1"
- }
- },
"vinyl-fs": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
diff --git a/package.json b/package.json
index 5136f65..8a19b6e 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"gulp-deporder": "^1.2.0",
"gulp-gh-pages": "^0.6.0-6",
"gulp-imagemin": "^7",
- "gulp-minify-css": "^1.2.4",
+ "gulp-clean-css": "^4.3.0",
"gulp-rename": "^1.4.0",
"gulp-sass": "^5.1.0",
"gulp-sourcemaps": "^2.6.5",
diff --git a/src/assets/js/api/api.js b/src/assets/js/api/api.js
index 2526d91..96e1db3 100644
--- a/src/assets/js/api/api.js
+++ b/src/assets/js/api/api.js
@@ -1,10 +1,17 @@
/*requires:
api/lastfm.js
+api/musicbrainz.js
*/
var api = api || {};
var superCount = 0;
+// Queue for artists that need MusicBrainz fallback lookup
+var musicbrainzFallbackQueue = [];
+var musicbrainzProcessingActive = false;
+var musicbrainzProcessedCount = 0;
+var musicbrainzFoundCount = 0;
+
(function (window, document) {
let getHardcodedCountries = () => new Promise((res, rej) =>
d3.json("assets/data/artist-countries.json", (err, data) =>
@@ -71,8 +78,51 @@ var superCount = 0;
})
.map(countryData);
- /**
- * Tries to find out the country for a specified artist.
+ /**
+ * Convert country name to country data
+ * @param {String} countryName - Country name (e.g., "United States", "Sweden")
+ * @returns {Object|null} Country data object with id, name, etc., or null if not found
+ */
+ api.convertCountryNameToCountry = function(countryName) {
+ if (!countryName) return null;
+
+ var countryNameLower = countryName.toLowerCase();
+ var countryMatch = cname[countryNameLower];
+
+ if (countryMatch && countryMatch.length > 0) {
+ var country = countryMatch[0];
+ return {
+ id: country.id,
+ name: country.mainName,
+ country: country.mainName,
+ tag: country.tag || country.mainName.toLowerCase(),
+ mainName: country.mainName
+ };
+ }
+
+ // Try to find by matching any of the names array
+ var country = countryData.find(function(d) {
+ return d.names.some(function(name) {
+ return name.toLowerCase() === countryNameLower;
+ });
+ });
+
+ if (country) {
+ return {
+ id: country.id,
+ name: country.mainName,
+ country: country.mainName,
+ tag: country.tag || country.mainName.toLowerCase(),
+ mainName: country.mainName
+ };
+ }
+
+ console.warn("Unknown country name:", countryName);
+ return null;
+ };
+
+ /**
+ * Tries to find out the country for a specified artist.
* @param {String} artist Name of the artist to get country for
* @param {Function} callback Callback function, called when the search is over (whether a country's been found or not)
* The callback function takes one argument, this object:
@@ -165,6 +215,27 @@ var superCount = 0;
console.info("Potentially incorrect country for '" + artist + "': " + bestTag.country + ", using the tag '" + bestTag.tag + "'");
}
+ // If no country found from Last.fm tags, queue for MusicBrainz fallback
+ if (!bestTag.id && !bestTag.country) {
+ // Last.fm succeeded but no country tag found - queue for MusicBrainz fallback
+ var playcount = STORED_ARTISTS[artist] ? STORED_ARTISTS[artist].playcount : 0;
+ musicbrainzFallbackQueue.push({
+ artist: artist,
+ url: STORED_ARTISTS[artist] ? STORED_ARTISTS[artist].url : null,
+ playcount: playcount
+ });
+
+ // Sort queue by playcount (highest first) to prioritize artists with most scrobbles
+ musicbrainzFallbackQueue.sort(function(a, b) {
+ return (b.playcount || 0) - (a.playcount || 0);
+ });
+
+ // Start processing if not already active
+ if (!musicbrainzProcessingActive) {
+ api.startMusicBrainzProcessing();
+ }
+ }
+
callback(Object.assign({ "artist": artist, }, bestTag));
});
}
@@ -385,4 +456,198 @@ var superCount = 0;
api.lastfm.send("user.getFriends", [["user", SESSION.name]], callback);
}
+ /**
+ * Get the queue of artists that need MusicBrainz fallback lookup
+ * @returns {Array} Array of artist objects
+ */
+ api.getMusicBrainzFallbackQueue = function() {
+ return musicbrainzFallbackQueue;
+ };
+
+ /**
+ * Check if an artist is currently in the MusicBrainz fallback queue
+ * @param {String} artistName - Name of the artist to check
+ * @returns {Boolean} True if artist is in queue
+ */
+ api.isArtistInMusicBrainzQueue = function(artistName) {
+ return musicbrainzFallbackQueue.some(function(item) {
+ return item.artist === artistName;
+ });
+ };
+
+ /**
+ * Queue multiple artists for MusicBrainz fallback lookup
+ * @param {Array} artists - Array of artist objects with artist, url, playcount properties
+ */
+ api.queueArtistsForMusicBrainz = function(artists) {
+ if (!artists || !Array.isArray(artists)) {
+ return;
+ }
+
+ var queuedCount = 0;
+ artists.forEach(function(art) {
+ // Skip if already has a country
+ if (STORED_ARTISTS[art.artist] && STORED_ARTISTS[art.artist].country && STORED_ARTISTS[art.artist].country.id) {
+ return;
+ }
+
+ // Skip if already in queue
+ if (api.isArtistInMusicBrainzQueue(art.artist)) {
+ return;
+ }
+
+ // Add to queue
+ musicbrainzFallbackQueue.push({
+ artist: art.artist,
+ url: art.url || (STORED_ARTISTS[art.artist] ? STORED_ARTISTS[art.artist].url : null),
+ playcount: art.playcount || (STORED_ARTISTS[art.artist] ? STORED_ARTISTS[art.artist].playcount : 0)
+ });
+ queuedCount++;
+ });
+
+ if (queuedCount > 0) {
+ // Sort queue by playcount (highest first)
+ musicbrainzFallbackQueue.sort(function(a, b) {
+ return (b.playcount || 0) - (a.playcount || 0);
+ });
+
+ // Start processing if not already active
+ if (!musicbrainzProcessingActive) {
+ api.startMusicBrainzProcessing();
+ }
+ }
+ };
+
+ /**
+ * Clear the MusicBrainz fallback queue
+ */
+ api.clearMusicBrainzFallbackQueue = function() {
+ musicbrainzFallbackQueue = [];
+ };
+
+ /**
+ * Start processing MusicBrainz fallbacks continuously
+ * Processes artists as they're added to the queue, prioritizing by scrobbles
+ */
+ api.startMusicBrainzProcessing = function() {
+ if (musicbrainzProcessingActive) {
+ return; // Already processing
+ }
+
+ musicbrainzProcessingActive = true;
+ musicbrainzProcessedCount = 0;
+ musicbrainzFoundCount = 0;
+
+ // Process next item in queue
+ var processNext = function() {
+ // Sort queue by playcount (highest first) to prioritize artists with most scrobbles
+ musicbrainzFallbackQueue.sort(function(a, b) {
+ return (b.playcount || 0) - (a.playcount || 0);
+ });
+
+ if (musicbrainzFallbackQueue.length === 0) {
+ // Queue is empty, stop processing
+ musicbrainzProcessingActive = false;
+ return;
+ }
+
+ // Get next item from queue (highest playcount)
+ var queueItem = musicbrainzFallbackQueue.shift();
+
+ var processResult = function(result) {
+ musicbrainzProcessedCount++;
+
+ if (result.error) {
+ if (result.error === "rate_limit") {
+ // Retry after longer delay - put back in queue
+ musicbrainzFallbackQueue.unshift(queueItem);
+ setTimeout(function() {
+ api.musicbrainz.queueRequest(queueItem.artist, processResult);
+ }, 2000);
+ return;
+ }
+ // Other errors: not_found, no_country, api_error - just skip
+ // Process next item after delay
+ setTimeout(processNext, 1100);
+ return;
+ }
+
+ if (result.countryName) {
+ // Convert country name to country data
+ var countryData = api.convertCountryNameToCountry(result.countryName);
+
+ if (countryData) {
+ musicbrainzFoundCount++;
+
+ // Update STORED_ARTISTS
+ STORED_ARTISTS[result.artist] = STORED_ARTISTS[result.artist] || {};
+ STORED_ARTISTS[result.artist].country = {
+ id: countryData.id,
+ name: countryData.name
+ };
+
+ // Remove artist from no-countries list
+ if (typeof noCountries !== 'undefined' && typeof noCountries.removeArtist === 'function') {
+ noCountries.removeArtist(result.artist);
+ }
+
+ // Create artist object for countryCountObj
+ var artistObj = {
+ artist: result.artist,
+ id: countryData.id,
+ country: countryData.name,
+ url: queueItem.url || STORED_ARTISTS[result.artist].url || "",
+ playcount: queueItem.playcount || STORED_ARTISTS[result.artist].playcount || 0
+ };
+
+ // Update countryCountObj (only if SESSION.name is available)
+ if (typeof SESSION !== 'undefined' && SESSION.name) {
+ var countryId = countryData.id.toString();
+ if (!countryCountObj[countryId]) { countryCountObj[countryId] = {}; }
+ if (!countryCountObj[countryId][SESSION.name]) { countryCountObj[countryId][SESSION.name] = []; }
+ var exists = countryCountObj[countryId][SESSION.name].some(function(a) { return a.artist === result.artist; });
+ if (!exists) {
+ countryCountObj[countryId][SESSION.name].push(artistObj);
+ var newArtistsByCountry = {};
+ newArtistsByCountry[countryId] = [artistObj];
+ map.addArtists(newArtistsByCountry);
+ localforage.setItem("artists", STORED_ARTISTS);
+ window.localStorage.countryCountObj = JSON.stringify(countryCountObj);
+ }
+ }
+ }
+ }
+
+ // Process next item after delay (respect rate limit)
+ setTimeout(processNext, 1100);
+
+ // Trigger update of no-countries list to reflect queue changes
+ // Use setTimeout to avoid calling during render
+ setTimeout(function() {
+ if (typeof noCountries !== 'undefined' && typeof noCountries.updateList === 'function') {
+ noCountries.updateList();
+ }
+ }, 0);
+ };
+
+ // Queue the request (MusicBrainz module handles rate limiting)
+ api.musicbrainz.queueRequest(queueItem.artist, processResult);
+ };
+
+ // Start processing
+ processNext();
+ };
+
+ /**
+ * Process artists in the MusicBrainz fallback queue
+ * This is kept for backwards compatibility but now just calls startMusicBrainzProcessing
+ * @param {Function} progressCallback - Optional callback for progress updates (not used in new implementation)
+ */
+ api.processMusicBrainzFallbacks = function(progressCallback) {
+ // Just start processing if not already active
+ if (!musicbrainzProcessingActive) {
+ api.startMusicBrainzProcessing();
+ }
+ };
+
})(window, document);
diff --git a/src/assets/js/api/musicbrainz.js b/src/assets/js/api/musicbrainz.js
new file mode 100644
index 0000000..bc78038
--- /dev/null
+++ b/src/assets/js/api/musicbrainz.js
@@ -0,0 +1,241 @@
+var api = api || {};
+
+api.musicbrainz = (function() {
+ var requestQueue = [];
+ var isProcessing = false;
+ var lastRequestTime = 0;
+ var MIN_REQUEST_INTERVAL = 1000; // 1 second minimum between requests
+
+ // Mapping for common subdivisions to countries
+ var subdivisionToCountry = {
+ "England": "United Kingdom",
+ "Scotland": "United Kingdom",
+ "Wales": "United Kingdom",
+ "Northern Ireland": "United Kingdom"
+ };
+
+ /**
+ * Extract country name from artist data
+ * @param {Object} artistData - Artist data from MusicBrainz API
+ * @returns {Object} Object with countryName and areaName, or null if not found
+ */
+ function extractCountryName(artistData) {
+ var countryName = null;
+ var areaName = null;
+
+ // Check area field first
+ if (artistData.area) {
+ if (artistData.area.type === "Country" && artistData.area.name) {
+ countryName = artistData.area.name;
+ areaName = artistData.area.name;
+ } else if (artistData.area.type === "Subdivision" && artistData.area.name) {
+ countryName = subdivisionToCountry[artistData.area.name];
+ areaName = artistData.area.name;
+ }
+ }
+
+ // Check begin-area if area didn't work
+ if (!countryName && artistData["begin-area"]) {
+ if (artistData["begin-area"].type === "Country" && artistData["begin-area"].name) {
+ countryName = artistData["begin-area"].name;
+ areaName = artistData["begin-area"].name;
+ } else if (artistData["begin-area"].type === "Subdivision" && artistData["begin-area"].name) {
+ countryName = subdivisionToCountry[artistData["begin-area"].name];
+ areaName = artistData["begin-area"].name;
+ }
+ }
+
+ return countryName ? { countryName: countryName, areaName: areaName } : null;
+ }
+
+ /**
+ * Get country for an artist from MusicBrainz API
+ * @param {String} artist - Artist name
+ * @param {Function} callback - Callback function with result object
+ */
+ function getCountry(artist, callback) {
+ var url = "https://musicbrainz.org/ws/2/artist/?query=artist:" + encodeURIComponent(artist) + "&fmt=json&limit=1";
+
+ // Use XMLHttpRequest for consistency with rest of codebase and better abort support
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ // Check for CORS error (status 0 typically indicates CORS failure)
+ if (xhr.status === 0) {
+ callback({
+ artist: artist,
+ error: "cors_error"
+ });
+ return;
+ }
+
+ // Check for rate limit
+ if (xhr.status === 503) {
+ callback({
+ artist: artist,
+ error: "rate_limit"
+ });
+ return;
+ }
+
+ // Check for other HTTP errors
+ if (xhr.status < 200 || xhr.status >= 300) {
+ callback({
+ artist: artist,
+ error: "api_error"
+ });
+ return;
+ }
+
+ // Parse JSON response
+ var data;
+ try {
+ data = JSON.parse(xhr.responseText);
+ } catch (e) {
+ callback({
+ artist: artist,
+ error: "parse_error"
+ });
+ return;
+ }
+
+ // Check if we got valid artist data
+ if (!data || !data.artists || !data.artists.length) {
+ callback({
+ artist: artist,
+ error: "not_found"
+ });
+ return;
+ }
+
+ // Get first artist result
+ var artistData = data.artists[0];
+
+ // Extract country name from artist data
+ var countryInfo = extractCountryName(artistData);
+
+ if (countryInfo) {
+ callback({
+ artist: artist,
+ countryName: countryInfo.countryName,
+ area: countryInfo.areaName
+ });
+ } else {
+ callback({
+ artist: artist,
+ error: "no_country"
+ });
+ }
+ }
+ };
+
+ xhr.onerror = function() {
+ // Network error or CORS error (only fires if status is still 0)
+ // onreadystatechange will handle status 0, so this is a fallback
+ if (xhr.readyState === 4 && xhr.status === 0) {
+ callback({
+ artist: artist,
+ error: "cors_error"
+ });
+ }
+ };
+
+ xhr.ontimeout = function() {
+ callback({
+ artist: artist,
+ error: "api_error"
+ });
+ };
+
+ try {
+ xhr.open("GET", url, true);
+ xhr.setRequestHeader("Accept", "application/json");
+ xhr.timeout = 20000; // 20 second timeout
+ xhr.send();
+ } catch (e) {
+ callback({
+ artist: artist,
+ error: "api_error"
+ });
+ }
+
+ // Return abort function for compatibility
+ return {
+ abort: function() {
+ if (xhr.readyState !== 4 && xhr.readyState !== 0) {
+ xhr.abort();
+ }
+ }
+ };
+ }
+
+ /**
+ * Queue a request with rate limiting
+ * @param {String} artist - Artist name
+ * @param {Function} callback - Callback function
+ */
+ function queueRequest(artist, callback) {
+ requestQueue.push({
+ artist: artist,
+ callback: callback
+ });
+
+ processQueue();
+ }
+
+ /**
+ * Process the request queue with rate limiting
+ */
+ function processQueue() {
+ if (isProcessing) {
+ return;
+ }
+
+ if (requestQueue.length === 0) {
+ return;
+ }
+
+ isProcessing = true;
+
+ var processNext = function() {
+ if (requestQueue.length === 0) {
+ isProcessing = false;
+ return;
+ }
+
+ var now = Date.now();
+ var timeSinceLastRequest = now - lastRequestTime;
+ var delay = Math.max(0, MIN_REQUEST_INTERVAL - timeSinceLastRequest);
+
+ setTimeout(function() {
+ var request = requestQueue.shift();
+ lastRequestTime = Date.now();
+
+ getCountry(request.artist, function(result) {
+ request.callback(result);
+
+ // Process next request
+ processNext();
+ });
+ }, delay);
+ };
+
+ processNext();
+ }
+
+ /**
+ * Clear the request queue
+ */
+ function clearQueue() {
+ requestQueue = [];
+ isProcessing = false;
+ }
+
+ return {
+ getCountry: getCountry,
+ queueRequest: queueRequest,
+ clearQueue: clearQueue
+ };
+})();
+
diff --git a/src/assets/js/no-countries.js b/src/assets/js/no-countries.js
index 2322256..0badb1f 100644
--- a/src/assets/js/no-countries.js
+++ b/src/assets/js/no-countries.js
@@ -1,6 +1,7 @@
const noCountries = noCountries || {};
var listOfArtistsWithNoCountry = [];
+var updateNoCountriesListInterval = null;
var saveToStorage = function (key, object, cb) {
localforage.setItem(key, object, cb || function () {});
@@ -13,61 +14,91 @@ function sortArtists(data, method) {
return data.sort((a, b) => a.artist.localeCompare(b.artist));
}
-var addArtistsWithNoCountry = function (data) {
- listOfArtistsWithNoCountry = listOfArtistsWithNoCountry.concat(data);
- saveToStorage("no_countries", listOfArtistsWithNoCountry);
+// Define updateNoCountriesList outside so it can be called globally
+function updateNoCountriesList() {
+ let artistsState = JSON.parse(localStorage.getItem('noCountryArtistsProgress')) || {};
+ const sortedData = sortArtists(listOfArtistsWithNoCountry, noCountryArtistSortMethod);
+ var noCountriesListEl = d3.select(".no-countries__content ul");
+ noCountriesListEl.html("");
+ sortedData.forEach(function (_art) {
+ let artistState = artistsState[_art.artist] || { artistName: _art.artist, checked: false };
+ let isInQueue = typeof api !== 'undefined' && api.isArtistInMusicBrainzQueue && api.isArtistInMusicBrainzQueue(_art.artist);
+ let listItem = noCountriesListEl.append("li");
+ listItem.append("input")
+ .attr("type", "checkbox")
+ .property("checked", artistState.checked)
+ .attr("id", _art.artist)
+ .on("change", handleCheckboxChange);
+
+ // Build label HTML with optional MusicBrainz indicator
+ let labelHtml = '' + _art.artist + '';
+ if (isInQueue) {
+ labelHtml += '...';
+ }
+ labelHtml += '' + _art.playcount + ' scrobbles';
+
+ listItem.append("label")
+ .attr("for", _art.artist)
+ .html(labelHtml);
+ if (document.querySelector("#hide-checked")?.checked && artistState.checked) {
+ listItem.style("display", "none");
+ }
+ })
+ d3.select(".no-countries__info").html(listOfArtistsWithNoCountry.length + " artists without a country:");
+}
- function handleCheckboxChange() {
- let artistName = this.id;
- let checked = this.checked;
- let artistsState = JSON.parse(localStorage.getItem('noCountryArtistsProgress')) || {};
- artistsState[artistName] = { artistName, checked };
- localStorage.setItem('noCountryArtistsProgress', JSON.stringify(artistsState));
- // If you just checked and the filter is on, remove the artist from the DOM
- if (checked && document.querySelector("#hide-checked")?.checked) {
- this.parentNode.style.display = 'none';
- let nextCheckbox = this.parentNode.nextElementSibling.querySelector('input');
- if (nextCheckbox) {
- nextCheckbox.focus();
- }
+function handleCheckboxChange() {
+ let artistName = this.id;
+ let checked = this.checked;
+ let artistsState = JSON.parse(localStorage.getItem('noCountryArtistsProgress')) || {};
+ artistsState[artistName] = { artistName, checked };
+ localStorage.setItem('noCountryArtistsProgress', JSON.stringify(artistsState));
+ // If you just checked and the filter is on, remove the artist from the DOM
+ if (checked && document.querySelector("#hide-checked")?.checked) {
+ this.parentNode.style.display = 'none';
+ let nextCheckbox = this.parentNode.nextElementSibling.querySelector('input');
+ if (nextCheckbox) {
+ nextCheckbox.focus();
}
- // get the label element for the filter checked checkbox
- let filterCheckedLabel = document.querySelector("label[for='hide-checked']");
- // Update the label to include the number of checked artists
- filterCheckedLabel.innerHTML = `Hide checked artists (${document.querySelectorAll("dialog[open] ul li input[type='checkbox']:checked").length})`;
- ga('send', {
- hitType: 'event',
- eventCategory: 'No countries',
- eventAction: 'Check artist as done',
- eventLabel: 'test'
- });
}
+ // get the label element for the filter checked checkbox
+ let filterCheckedLabel = document.querySelector("label[for='hide-checked']");
+ // Update the label to include the number of checked artists
+ filterCheckedLabel.innerHTML = `Hide checked artists (${document.querySelectorAll("dialog[open] ul li input[type='checkbox']:checked").length})`;
+ ga('send', {
+ hitType: 'event',
+ eventCategory: 'No countries',
+ eventAction: 'Check artist as done',
+ eventLabel: 'test'
+ });
+}
+var addArtistsWithNoCountry = function (data) {
+ listOfArtistsWithNoCountry = listOfArtistsWithNoCountry.concat(data);
+ saveToStorage("no_countries", listOfArtistsWithNoCountry);
-
- function updateNoCountriesList() {
- let artistsState = JSON.parse(localStorage.getItem('noCountryArtistsProgress')) || {};
- const sortedData = sortArtists(listOfArtistsWithNoCountry, noCountryArtistSortMethod);
- var noCountriesListEl = d3.select(".no-countries__content ul");
- noCountriesListEl.html("");
- sortedData.forEach(function (_art) {
- let artistState = artistsState[_art.artist] || { artistName: _art.artist, checked: false };
- let listItem = noCountriesListEl.append("li");
- listItem.append("input")
- .attr("type", "checkbox")
- .property("checked", artistState.checked)
- .attr("id", _art.artist)
- .on("change", handleCheckboxChange);
- listItem.append("label")
- .attr("for", _art.artist)
- .html('' + _art.artist + '' + _art.playcount + ' scrobbles');
- if (document.querySelector("#hide-checked")?.checked && artistState.checked) {
- listItem.style("display", "none");
+ // Queue artists for MusicBrainz fallback if they haven't been queued yet
+ if (typeof api !== 'undefined' && typeof api.queueArtistsForMusicBrainz === 'function') {
+ // Filter out artists that are already in the queue or already have a country
+ var artistsToQueue = data.filter(function(art) {
+ // Check if artist already has a country in STORED_ARTISTS
+ if (typeof STORED_ARTISTS !== 'undefined' && STORED_ARTISTS[art.artist] && STORED_ARTISTS[art.artist].country && STORED_ARTISTS[art.artist].country.id) {
+ return false; // Already has a country, don't queue
+ }
+ // Check if already in queue
+ if (typeof api !== 'undefined' && api.isArtistInMusicBrainzQueue && api.isArtistInMusicBrainzQueue(art.artist)) {
+ return false; // Already in queue
}
- })
- d3.select(".no-countries__info").html(listOfArtistsWithNoCountry.length + " artists without a country:");
+ return true; // Should be queued
+ });
+
+ if (artistsToQueue.length > 0) {
+ console.log("[NoCountries] Queueing", artistsToQueue.length, "artists for MusicBrainz fallback");
+ api.queueArtistsForMusicBrainz(artistsToQueue);
+ }
}
+
// Check if the checkbox and label already exist
if (!d3.select("#hide-checked").node() && !d3.select("label[for='hide-checked']").node()) {
// Add the checkbox next to the filter radios
@@ -106,6 +137,18 @@ var addArtistsWithNoCountry = function (data) {
updateNoCountriesList("scrobbles");
+ // Periodically update the list to show/hide MusicBrainz fetching indicators
+ if (updateNoCountriesListInterval) {
+ clearInterval(updateNoCountriesListInterval);
+ }
+ updateNoCountriesListInterval = setInterval(function() {
+ // Only update if dialog is open
+ var dialog = document.querySelector(".no-countries__content");
+ if (dialog && dialog.hasAttribute('open')) {
+ updateNoCountriesList();
+ }
+ }, 1000); // Update every second
+
document.querySelector(".no-countries__title").addEventListener("click", function () {
const dialog = document.querySelector(".no-countries__content");
dialog.showModal();
@@ -135,6 +178,8 @@ var addArtistsWithNoCountry = function (data) {
const dialog = document.querySelector(".no-countries__content");
dialog.close();
document.querySelector(".no-countries__title").focus();
+ // Update list when dialog closes to reflect any changes
+ updateNoCountriesList();
});
const dialog = document.querySelector(".no-countries__content");
dialog.addEventListener("click", function (event) {
@@ -150,4 +195,33 @@ var addArtistsWithNoCountry = function (data) {
}
}
-noCountries.addArtistsWithNoCountry = addArtistsWithNoCountry;
\ No newline at end of file
+var removeArtistWithNoCountry = function(artistName) {
+ // Remove artist from the list
+ var index = listOfArtistsWithNoCountry.findIndex(function(art) {
+ return art.artist === artistName;
+ });
+
+ if (index !== -1) {
+ listOfArtistsWithNoCountry.splice(index, 1);
+ saveToStorage("no_countries", listOfArtistsWithNoCountry);
+ console.log("[NoCountries] Removed artist from no-countries list:", artistName);
+
+ // Update the UI if dialog is open
+ var dialog = document.querySelector(".no-countries__content");
+ if (dialog && dialog.hasAttribute('open')) {
+ updateNoCountriesList();
+ }
+
+ // Hide the no-countries section if list is now empty
+ if (listOfArtistsWithNoCountry.length === 0) {
+ document.querySelector(".no-countries").classList.add("hidden");
+ }
+
+ return true;
+ }
+ return false;
+};
+
+noCountries.addArtistsWithNoCountry = addArtistsWithNoCountry;
+noCountries.updateList = updateNoCountriesList;
+noCountries.removeArtist = removeArtistWithNoCountry;
\ No newline at end of file
diff --git a/src/assets/js/script.js b/src/assets/js/script.js
index 78d90e2..cc786fc 100644
--- a/src/assets/js/script.js
+++ b/src/assets/js/script.js
@@ -293,19 +293,37 @@ var countryCountObj = {};
// Fade in loader
d3.select(".loader").transition().duration(2000).style("opacity", 1);
- d3.select("#loading-text").html("Getting library...");
+ var loadingTextEl = d3.select("#loading-text");
+ if (!loadingTextEl.empty()) {
+ loadingTextEl.html("Getting library...");
+ } else {
+ console.warn("[Script] #loading-text element not found when trying to set loading message");
+ }
// Screen reader status update every 30 seconds
setTimeout(function () {
- announcer.announce(document.getElementById("loading-text")?.innerText);
+ var loadingText = document.getElementById("loading-text");
+ if (loadingText) {
+ announcer.announce(loadingText.innerText);
+ }
}, 6000);
setTimeout(function () {
- if (d3.select("#loading-text")?.html() === "Getting library...") {
- d3.select("#loading-text").html("Last.fm is taking
a long time to
respond...");
+ var loadingText = d3.select("#loading-text");
+ if (loadingText.empty()) {
+ console.warn("[Script] #loading-text element not found, skipping timeout message");
+ return;
+ }
+ if (loadingText.html() === "Getting library...") {
+ loadingText.html("Last.fm is taking
a long time to
respond...");
setTimeout(function () {
- if (d3.select("#loading-text").html() === "Last.fm is taking
a long time to
respond...") {
- d3.select("#loading-text").html("Maybe last.fm has
gone offline...")
+ var loadingText2 = d3.select("#loading-text");
+ if (loadingText2.empty()) {
+ console.warn("[Script] #loading-text element not found, skipping timeout message");
+ return;
+ }
+ if (loadingText2.html() === "Last.fm is taking
a long time to
respond...") {
+ loadingText2.html("Maybe last.fm has
gone offline...")
.style("pointer-events", "all");
}
}, 8000);
@@ -429,6 +447,15 @@ var countryCountObj = {};
CACHED_USERS[user] = new Date().getTime();
window.localStorage.cached_users = JSON.stringify(CACHED_USERS);
window.localStorage.countryCountObj = JSON.stringify(countryCountObj);
+
+ // MusicBrainz processing should already be running in parallel if there were artists without countries
+ // If queue still has items, ensure processing continues
+ var fallbackQueue = api.getMusicBrainzFallbackQueue();
+ if (fallbackQueue.length > 0) {
+ console.log("Final check: " + fallbackQueue.length + " artists still in MusicBrainz queue");
+ // Processing should already be active, but ensure it continues
+ api.processMusicBrainzFallbacks();
+ }
}
// // Set theme
diff --git a/src/assets/scss/pages/_map.scss b/src/assets/scss/pages/_map.scss
index b4a3e27..8286618 100644
--- a/src/assets/scss/pages/_map.scss
+++ b/src/assets/scss/pages/_map.scss
@@ -286,6 +286,19 @@ div.colorChange {
&__secondary {
opacity: 0.54;
}
+
+ &__fetching {
+ display: inline-block;
+ margin-left: 0.3em;
+ color: var(--textPrimary);
+ animation: blink 1.4s infinite;
+ font-weight: bold;
+
+ @keyframes blink {
+ 0%, 50% { opacity: 1; }
+ 51%, 100% { opacity: 0.3; }
+ }
+ }
}
dialog {
diff --git a/src/index.html b/src/index.html
index e5440bc..84a522a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -407,9 +407,34 @@