From 9cfbac70d3c4621d38bee0e7e6747d6ba63e64bb Mon Sep 17 00:00:00 2001 From: arndom Date: Mon, 3 Oct 2022 09:43:26 +0100 Subject: [PATCH 01/16] add pie chart layout to language card --- package-lock.json | 1034 ++++++++++++++++++++++-------- package.json | 3 + readme.md | 194 +++--- src/cards/top-languages-card.js | 104 ++- tests/renderTopLanguages.test.js | 32 + 5 files changed, 1018 insertions(+), 349 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2235a4b45ac63..5e31d996580ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,12 @@ "license": "MIT", "dependencies": { "axios": "^0.24.0", + "d3": "^7.6.1", + "d3-shape": "^3.1.0", "dotenv": "^8.2.0", "emoji-name-map": "^1.2.8", "github-username-regex": "^1.0.0", + "jsdom": "^20.0.1", "upgrade": "^1.1.0", "word-wrap": "^1.2.3" }, @@ -1283,7 +1286,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, "engines": { "node": ">= 10" } @@ -1484,14 +1486,12 @@ "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1500,32 +1500,18 @@ } }, "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" } }, "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "engines": { "node": ">=0.4.0" } @@ -1534,7 +1520,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -1612,8 +1597,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { "version": "0.24.0", @@ -1761,12 +1745,6 @@ "node": ">=8" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "node_modules/browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", @@ -1936,7 +1914,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1944,6 +1921,14 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/compare-versions": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", @@ -2004,14 +1989,12 @@ "node_modules/cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" }, "node_modules/cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, "dependencies": { "cssom": "~0.3.6" }, @@ -2022,14 +2005,382 @@ "node_modules/cssstyle/node_modules/cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "node_modules/d3": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", + "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", + "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", + "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", + "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", + "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz", + "integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", + "integrity": "sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, "dependencies": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -2043,7 +2394,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2059,8 +2409,7 @@ "node_modules/decimal.js": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", - "dev": true + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" }, "node_modules/dedent": { "version": "0.7.0", @@ -2071,8 +2420,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deepmerge": { "version": "4.2.2", @@ -2083,11 +2431,18 @@ "node": ">=0.10.0" } }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -2126,7 +2481,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, "dependencies": { "webidl-conversions": "^7.0.0" }, @@ -2185,7 +2539,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -2224,7 +2577,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -2246,7 +2598,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2259,7 +2610,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -2268,7 +2618,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2336,8 +2685,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fb-watchman": { "version": "2.0.2", @@ -2411,7 +2759,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2560,7 +2907,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, "dependencies": { "whatwg-encoding": "^2.0.0" }, @@ -2578,7 +2924,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -2592,7 +2937,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -2644,7 +2988,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -2733,6 +3076,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2813,8 +3164,7 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, "node_modules/is-stream": { "version": "2.0.1", @@ -3814,18 +4164,17 @@ } }, "node_modules/jsdom": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", - "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==", - "dev": true, + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", "dependencies": { "abab": "^2.0.6", - "acorn": "^8.7.1", - "acorn-globals": "^6.0.0", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", "data-urls": "^3.0.2", - "decimal.js": "^10.3.1", + "decimal.js": "^10.4.1", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", @@ -3833,18 +4182,17 @@ "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "^7.0.0", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", + "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^3.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0", - "ws": "^8.8.0", + "ws": "^8.9.0", "xml-name-validator": "^4.0.0" }, "engines": { @@ -3911,7 +4259,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -4026,7 +4373,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4035,7 +4381,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4076,8 +4421,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -4163,8 +4507,7 @@ "node_modules/nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" }, "node_modules/once": { "version": "1.4.0", @@ -4203,7 +4546,6 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -4307,7 +4649,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", - "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -4455,7 +4796,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -4517,14 +4857,12 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, "engines": { "node": ">=6" } @@ -4532,8 +4870,7 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/react-is": { "version": "17.0.2", @@ -4572,8 +4909,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { "version": "1.22.1", @@ -4631,6 +4967,16 @@ "node": ">=10" } }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -4640,14 +4986,12 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -4728,7 +5072,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -4882,8 +5226,7 @@ "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/terminal-link": { "version": "2.1.1", @@ -4946,7 +5289,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", - "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -4961,7 +5303,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, "dependencies": { "punycode": "^2.1.1" }, @@ -4982,7 +5323,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, @@ -5021,7 +5361,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -5061,7 +5400,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -5090,20 +5428,10 @@ "node": ">=10.12.0" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, "node_modules/w3c-xmlserializer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, "dependencies": { "xml-name-validator": "^4.0.0" }, @@ -5124,7 +5452,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, "engines": { "node": ">=12" } @@ -5133,7 +5460,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -5145,7 +5471,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, "engines": { "node": ">=12" } @@ -5154,7 +5479,6 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -5235,7 +5559,6 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, "engines": { "node": ">=10.0.0" }, @@ -5256,7 +5579,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, "engines": { "node": ">=12" } @@ -5264,8 +5586,7 @@ "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, "node_modules/y18n": { "version": "5.0.8", @@ -6336,8 +6657,7 @@ "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, "@types/aria-query": { "version": "4.2.2", @@ -6528,44 +6848,31 @@ "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" }, "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" } }, "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "requires": { "debug": "4" } @@ -6619,8 +6926,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { "version": "0.24.0", @@ -6741,12 +7047,6 @@ "fill-range": "^7.0.1" } }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", @@ -6868,11 +7168,15 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, "compare-versions": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", @@ -6927,14 +7231,12 @@ "cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" }, "cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, "requires": { "cssom": "~0.3.6" }, @@ -6942,16 +7244,277 @@ "cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" } } }, + "d3": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", + "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", + "requires": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + } + }, + "d3-array": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", + "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==" + }, + "d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + } + }, + "d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "requires": { + "d3-path": "1 - 3" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-contour": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", + "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", + "requires": { + "d3-array": "^3.2.0" + } + }, + "d3-delaunay": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", + "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", + "requires": { + "delaunator": "5" + } + }, + "d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" + }, + "d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + } + }, + "d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "requires": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + } + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "requires": { + "d3-dsv": "1 - 3" + } + }, + "d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-geo": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", + "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "requires": { + "d3-array": "2.5.0 - 3" + } + }, + "d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==" + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz", + "integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==" + }, + "d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==" + }, + "d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" + }, + "d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "requires": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + } + }, + "d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" + }, + "d3-shape": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", + "integrity": "sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==", + "requires": { + "d3-path": "1 - 3" + } + }, + "d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "requires": { + "d3-time": "1 - 3" + } + }, + "d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" + }, + "d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "requires": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + } + }, "data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, "requires": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -6962,7 +7525,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -6970,8 +7532,7 @@ "decimal.js": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", - "dev": true + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" }, "dedent": { "version": "0.7.0", @@ -6982,8 +7543,7 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "deepmerge": { "version": "4.2.2", @@ -6991,11 +7551,18 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "requires": { + "robust-predicates": "^3.0.0" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "deprecation": { "version": "2.3.1", @@ -7025,7 +7592,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, "requires": { "webidl-conversions": "^7.0.0" } @@ -7071,8 +7637,7 @@ "entities": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" }, "error-ex": { "version": "1.3.2", @@ -7099,7 +7664,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, "requires": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -7111,20 +7675,17 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "execa": { "version": "5.1.1", @@ -7177,8 +7738,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "fb-watchman": { "version": "2.0.2", @@ -7226,7 +7786,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7332,7 +7891,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, "requires": { "whatwg-encoding": "^2.0.0" } @@ -7347,7 +7905,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, "requires": { "@tootallnate/once": "2", "agent-base": "6", @@ -7358,7 +7915,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -7392,7 +7948,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -7456,6 +8011,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -7504,8 +8064,7 @@ "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, "is-stream": { "version": "2.0.1", @@ -8280,18 +8839,17 @@ } }, "jsdom": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", - "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==", - "dev": true, + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", "requires": { "abab": "^2.0.6", - "acorn": "^8.7.1", - "acorn-globals": "^6.0.0", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", "data-urls": "^3.0.2", - "decimal.js": "^10.3.1", + "decimal.js": "^10.4.1", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", @@ -8299,18 +8857,17 @@ "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "^7.0.0", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", + "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^3.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0", - "ws": "^8.8.0", + "ws": "^8.9.0", "xml-name-validator": "^4.0.0" } }, @@ -8348,7 +8905,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -8441,14 +8997,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -8477,8 +9031,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "natural-compare": { "version": "1.4.0", @@ -8549,8 +9102,7 @@ "nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" }, "once": { "version": "1.4.0", @@ -8580,7 +9132,6 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -8656,7 +9207,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", - "dev": true, "requires": { "entities": "^4.4.0" } @@ -8760,8 +9310,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" }, "prettier": { "version": "2.7.1", @@ -8801,20 +9350,17 @@ "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "react-is": { "version": "17.0.2", @@ -8847,8 +9393,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "resolve": { "version": "1.22.1", @@ -8890,6 +9435,16 @@ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, + "robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8899,14 +9454,12 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, "requires": { "xmlchars": "^2.2.0" } @@ -8966,7 +9519,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "devOptional": true }, "source-map-support": { "version": "0.5.13", @@ -9078,8 +9631,7 @@ "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "terminal-link": { "version": "2.1.1", @@ -9127,7 +9679,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", - "dev": true, "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -9139,7 +9690,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, "requires": { "punycode": "^2.1.1" } @@ -9154,7 +9704,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -9180,8 +9729,7 @@ "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" }, "update-browserslist-db": { "version": "1.0.9", @@ -9202,7 +9750,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -9225,20 +9772,10 @@ "convert-source-map": "^1.6.0" } }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, "w3c-xmlserializer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, "requires": { "xml-name-validator": "^4.0.0" } @@ -9255,14 +9792,12 @@ "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" }, "whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, "requires": { "iconv-lite": "0.6.3" } @@ -9270,14 +9805,12 @@ "whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" }, "whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, "requires": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -9334,20 +9867,17 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, "requires": {} }, "xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" }, "xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index ffadefdeda100..e33a9340af32c 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,12 @@ }, "dependencies": { "axios": "^0.24.0", + "d3": "^7.6.1", + "d3-shape": "^3.1.0", "dotenv": "^8.2.0", "emoji-name-map": "^1.2.8", "github-username-regex": "^1.0.0", + "jsdom": "^20.0.1", "upgrade": "^1.1.0", "word-wrap": "^1.2.3" }, diff --git a/readme.md b/readme.md index ae8038855de03..0c63c6a161921 100644 --- a/readme.md +++ b/readme.md @@ -26,7 +26,7 @@

-

+

View Demo ยท Report Bug @@ -71,25 +71,25 @@ Are you considering supporting the project by donating? Please DON'T!! Instead, Help India fight the 2nd deadly wave of COVID-19. Thousands of people are dying in India because of a lack of Oxygen & also COVID-related infrastructure. -Visit and make a small donation to help us fight COVID and overcome this crisis. +Visit [https://indiafightscorona.giveindia.org](https://indiafightscorona.giveindia.org) and make a small donation to help us fight COVID and overcome this crisis. A small donation goes a long way. :heart:

# Features -- [GitHub Stats Card](#github-stats-card) -- [GitHub Extra Pins](#github-extra-pins) -- [Top Languages Card](#top-languages-card) -- [Wakatime Week Stats](#wakatime-week-stats) -- [Themes](#themes) -- [Customization](#customization) - - [Common Options](#common-options) - - [Stats Card Exclusive Options](#stats-card-exclusive-options) - - [Repo Card Exclusive Options](#repo-card-exclusive-options) - - [Language Card Exclusive Options](#language-card-exclusive-options) - - [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options) -- [Deploy Yourself](#deploy-on-your-own-vercel-instance) +- [GitHub Stats Card](#github-stats-card) +- [GitHub Extra Pins](#github-extra-pins) +- [Top Languages Card](#top-languages-card) +- [Wakatime Week Stats](#wakatime-week-stats) +- [Themes](#themes) +- [Customization](#customization) + - [Common Options](#common-options) + - [Stats Card Exclusive Options](#stats-card-exclusive-options) + - [Repo Card Exclusive Options](#repo-card-exclusive-options) + - [Language Card Exclusive Options](#language-card-exclusive-options) + - [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options) +- [Deploy Yourself](#deploy-on-your-own-vercel-instance) # GitHub Stats Card @@ -159,16 +159,16 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you #### Common Options: -- `title_color` - Card's title color _(hex color)_. Default: `2f80ed`. -- `text_color` - Body text color _(hex color)_. Default: `434d58`. -- `icon_color` - Icons color if available _(hex color)_. Default: `4c71f2`. -- `border_color` - Card's border color _(hex color)_. Default: `e4e2e2` (Does not apply when `hide_border` is enabled). -- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe` -- `hide_border` - Hides the card's border _(boolean)_. Default: `false` -- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme. -- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`. -- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`. -- `border_radius` - Corner rounding on the card. Default: `4.5`. +- `title_color` - Card's title color _(hex color)_. Default: `2f80ed`. +- `text_color` - Body text color _(hex color)_. Default: `434d58`. +- `icon_color` - Icons color if available _(hex color)_. Default: `4c71f2`. +- `border_color` - Card's border color _(hex color)_. Default: `e4e2e2` (Does not apply when `hide_border` is enabled). +- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe` +- `hide_border` - Hides the card's border _(boolean)_. Default: `false` +- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme. +- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`. +- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`. +- `border_radius` - Corner rounding on the card. Default: `4.5`. > Note: The minimum of cache_seconds is currently 4 hours as a temporary fix for PATs exhaustion. @@ -176,41 +176,40 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you You can provide multiple comma-separated values in the bg_color option to render a gradient, with the following format: - &bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 - +&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 > Note on cache: Repo cards have a default cache of 4 hours (14400 seconds) if the fork count & star count is less than 1k, otherwise, it's 2 hours (7200 seconds). Also, note that the cache is clamped to a minimum of 2 hours and a maximum of 24 hours. #### Stats Card Exclusive Options: -- `hide` - Hides the [specified items](#hiding-individual-stats) from stats _(Comma-separated values)_. Default: `[] (blank array)`. -- `hide_title` - _(boolean)_. Default: `false`. -- `card_width` - Set the card's width manually _(number)_. Default: `500px (approx.)`. -- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width. Default: `false`. -- `show_icons` - _(boolean)_. Default: `false`. -- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`. -- `count_private` - Count private commits _(boolean)_. Default: `false`. -- `line_height` - Sets the line-height between text _(number)_. Default: `25`. -- `exclude_repo` - Exclude stars from specified repositories _(Comma-separated values)_. Default: `[] (blank array)`. -- `custom_title` - Sets a custom title for the card. Default: ` Github Stats`. -- `text_bold` - Use bold text _(boolean)_. Default: `true`. -- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. +- `hide` - Hides the [specified items](#hiding-individual-stats) from stats _(Comma-separated values)_. Default: `[] (blank array)`. +- `hide_title` - _(boolean)_. Default: `false`. +- `card_width` - Set the card's width manually _(number)_. Default: `500px (approx.)`. +- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width. Default: `false`. +- `show_icons` - _(boolean)_. Default: `false`. +- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`. +- `count_private` - Count private commits _(boolean)_. Default: `false`. +- `line_height` - Sets the line-height between text _(number)_. Default: `25`. +- `exclude_repo` - Exclude stars from specified repositories _(Comma-separated values)_. Default: `[] (blank array)`. +- `custom_title` - Sets a custom title for the card. Default: ` Github Stats`. +- `text_bold` - Use bold text _(boolean)_. Default: `true`. +- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. > Note on `hide_rank`: > When hide_rank=`true`, the minimum card width is 270 px + the title length and padding. #### Repo Card Exclusive Options: -- `show_owner` - Show the repo's owner name _(boolean)_ +- `show_owner` - Show the repo's owner name _(boolean)_ #### Language Card Exclusive Options: -- `hide` - Hide the languages specified from the card _(Comma-separated values)_ -- `hide_title` - _(boolean)_ -- `layout` - Switch between two available layouts `default` & `compact` -- `card_width` - Set the card's width manually _(number)_ -- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_ -- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_ -- `custom_title` - Sets a custom title for the card +- `hide` - Hide the languages specified from the card _(Comma-separated values)_ +- `hide_title` - _(boolean)_ +- `layout` - Switch between two available layouts `default` & `compact` +- `card_width` - Set the card's width manually _(number)_ +- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_ +- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_ +- `custom_title` - Sets a custom title for the card > :warning: **Important:** > Language names should be uri-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) @@ -219,17 +218,17 @@ You can provide multiple comma-separated values in the bg_color option to render #### Wakatime Card Exclusive Options: -- `hide` - Hide the languages specified from the card _(Comma-separated values)_ -- `hide_title` - _(boolean)_ -- `line_height` - Sets the line-height between text _(number)_ -- `hide_progress` - Hides the progress bar and percentage _(boolean)_ -- `custom_title` - Sets a custom title for the card -- `layout` - Switch between two available layouts `default` & `compact` -- `langs_count` - Limit the number of languages on the card, defaults to all reported languages -- `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) -- `range` โ€“ Request a range different from your WakaTime default, e.g. `last_7_days`. See [WakaTime API docs](https://wakatime.com/developers#stats) for a list of available options. +- `hide` - Hide the languages specified from the card _(Comma-separated values)_ +- `hide_title` - _(boolean)_ +- `line_height` - Sets the line-height between text _(number)_ +- `hide_progress` - Hides the progress bar and percentage _(boolean)_ +- `custom_title` - Sets a custom title for the card +- `layout` - Switch between two available layouts `default` & `compact` +- `langs_count` - Limit the number of languages on the card, defaults to all reported languages +- `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) +- `range` โ€“ Request a range different from your WakaTime default, e.g. `last_7_days`. See [WakaTime API docs](https://wakatime.com/developers#stats) for a list of available options. -* * * +--- # GitHub Extra Pins @@ -246,7 +245,6 @@ Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats` ```md [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats)](https://github.com/anuraghazra/github-readme-stats) ``` - ### Demo [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats)](https://github.com/anuraghazra/github-readme-stats) @@ -270,7 +268,6 @@ Endpoint: `api/top-langs?username=anuraghazra` ```md [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats) ``` - ### Exclude individual repositories You can use `&exclude_repo=repo1,repo2` parameter to exclude individual repositories. @@ -278,7 +275,6 @@ You can use `&exclude_repo=repo1,repo2` parameter to exclude individual reposito ```md [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&exclude_repo=github-readme-stats,anuraghazra.github.io)](https://github.com/anuraghazra/github-readme-stats) ``` - ### Hide individual languages You can use `&hide=language1,language2` parameter to hide individual languages. @@ -286,7 +282,6 @@ You can use `&hide=language1,language2` parameter to hide individual languages. ```md [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide=javascript,html)](https://github.com/anuraghazra/github-readme-stats) ``` - ### Show more languages You can use the `&langs_count=` option to increase or decrease the number of languages shown on the card. Valid values are integers between 1 and 10 (inclusive), and the default is 5. @@ -294,7 +289,6 @@ You can use the `&langs_count=` option to increase or decrease the number of lan ```md [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&langs_count=8)](https://github.com/anuraghazra/github-readme-stats) ``` - ### Compact Language Card Layout You can use the `&layout=compact` option to change the card design. @@ -302,15 +296,25 @@ You can use the `&layout=compact` option to change the card design. ```md [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats) ``` +### Pie Chart Language Card Layout +You can use the `&layout=pie` option to change the card design. + +```md +[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats) +``` ### Demo [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats) -- Compact layout +- Compact layout [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats) +- Pie Chart layout + +[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats) + # Wakatime Week Stats Change the `?username=` value to your [Wakatime](https://wakatime.com) username. @@ -318,7 +322,6 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username. ```md [![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats) ``` - > Note: Please be aware that we currently only show data from Wakatime profiles that are public. ### Demo @@ -327,65 +330,65 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username. [![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats) -- Compact layout +- Compact layout [![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats) -* * * +--- ### All Demos -- Default +- Default ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra) -- Hiding specific stats +- Hiding specific stats ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=contribs,issues) -- Showing icons +- Showing icons ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=issues&show_icons=true) -- Customize Border Color +- Customize Border Color ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&border_color=2e4058) -- Include All Commits +- Include All Commits ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&include_all_commits=true) -- Themes +- Themes Choose from any of the [default themes](#themes) ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=radical) -- Gradient +- Gradient ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&bg_color=30,e96443,904e95&title_color=fff&text_color=fff) -- Customizing stats card +- Customizing stats card ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra&show_icons=true&title_color=fff&icon_color=79ff97&text_color=9f9f9f&bg_color=151515) -- Setting card locale +- Setting card locale ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra&locale=es) -- Customizing repo card +- Customizing repo card ![Customized Card](https://github-readme-stats.vercel.app/api/pin?username=anuraghazra&repo=github-readme-stats&title_color=fff&icon_color=f9f9f9&text_color=9f9f9f&bg_color=151515) -- Top languages +- Top languages [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats) -- Wakatime card +- Wakatime card [![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats) -* * * +--- ### Quick Tip (Align The Repo Cards) @@ -399,7 +402,6 @@ You usually won't be able to layout the images side by side. To do that you can ``` - ## Deploy on your own Vercel instance #### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107) @@ -413,19 +415,19 @@ NOTE: Since [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) we
Guide on setting up Vercel ๐Ÿ”จ -1. Go to [vercel.com](https://vercel.com/) -2. Click on `Log in` - ![](https://files.catbox.moe/tct1wg.png) -3. Sign in with GitHub by pressing `Continue with GitHub` - ![](https://files.catbox.moe/btd78j.jpeg) -4. Sign in to GitHub and allow access to all repositories, if prompted -5. Fork this repo -6. After forking the repo, open the [`vercel.json`](https://github.com/anuraghazra/github-readme-stats/blob/master/vercel.json#L5) file and change the `maxDuration` field to `10` -7. Go back to your [Vercel dashboard](https://vercel.com/dashboard) -8. Select `Import Project` - ![](https://files.catbox.moe/qckos0.png) -9. Select `Import Git Repository`. Select root and keep everything as is. - ![](https://files.catbox.moe/pqub9q.png) +1. Go to [vercel.com](https://vercel.com/) +2. Click on `Log in` + ![](https://files.catbox.moe/tct1wg.png) +3. Sign in with GitHub by pressing `Continue with GitHub` + ![](https://files.catbox.moe/btd78j.jpeg) +4. Sign in to GitHub and allow access to all repositories, if prompted +5. Fork this repo +6. After forking the repo, open the [`vercel.json`](https://github.com/anuraghazra/github-readme-stats/blob/master/vercel.json#L5) file and change the `maxDuration` field to `10` +7. Go back to your [Vercel dashboard](https://vercel.com/dashboard) +8. Select `Import Project` + ![](https://files.catbox.moe/qckos0.png) +9. Select `Import Git Repository`. Select root and keep everything as is. + ![](https://files.catbox.moe/pqub9q.png) 10. Create a personal access token (PAT) [here](https://github.com/settings/tokens/new) and enable the `repo` permissions (this allows access to see private repo stats) 11. Add the PAT as an environment variable named `PAT_1` (as shown). ![](https://files.catbox.moe/0ez4g7.png) @@ -440,13 +442,13 @@ this takes time. You can use this service for free. However, if you are using this project and are happy with it or just want to encourage me to continue creating stuff, there are a few ways you can do it:- -- Giving proper credit when you use github-readme-stats on your readme, linking back to it :D -- Starring and sharing the project :rocket: -- [![paypal.me/anuraghazra](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/anuraghazra) - You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea: +- Giving proper credit when you use github-readme-stats on your readme, linking back to it :D +- Starring and sharing the project :rocket: +- [![paypal.me/anuraghazra](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/anuraghazra) - You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea: Thanks! :heart: -* * * +--- [![https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss](./powered-by-vercel.svg)](https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index b181fc12adf61..99435c0c832cd 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -12,6 +12,9 @@ import { } from "../common/utils.js"; import { langCardLocales } from "../translations.js"; +import * as d3 from 'd3'; +import {JSDOM} from 'jsdom'; + const DEFAULT_CARD_WIDTH = 300; const MIN_CARD_WIDTH = 230; const DEFAULT_LANGS_COUNT = 5; @@ -60,7 +63,7 @@ const createProgressTextNode = ({ width, color, name, progress }) => { }; /** - * @param {{ lang: Lang, totalSize: number }} props + * @param {{ lang: Lang, totalSize: number, isDonut: boolean }} props */ const createCompactLangNode = ({ lang, totalSize }) => { const percentage = ((lang.size / totalSize) * 100).toFixed(2); @@ -108,6 +111,23 @@ const createLanguageTextNode = ({ langs, totalSize }) => { }).join(""); }; + +/** + * @param {{ langs: Lang[], totalLanguageSize: number }} props + */ +const createDonutTextNode = (langs, totalLanguageSize) => { + return flexLayout({ + items: langs.map((lang) => { + return createCompactLangNode({ + lang, + totalSize: totalLanguageSize, + }); + }), + gap: 32, + direction: "column", + }).join(""); +}; + /** * @param {Lang[]} langs * @param {number} width @@ -180,6 +200,84 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { `; }; +/** + * @param {Lang[]} langs + * @param {number} width + * @param {number} height + * @param {number} totalLanguageSize + * @returns {string} + */ +const renderDonutLayout = (langs, width, height, totalLanguageSize) => { + const pie = d3.pie().value(function (d) { + return d.size; + }); + + const pieData = pie(langs); + + const xPadding = 50; + const yPadding = 60; + + const widthOffset = 80; + const heightOffset = 25; + + const margin = 10; + const radius = ((width - widthOffset) - 2 * margin - yPadding) / 2; + + const arc = d3. + arc() + .outerRadius(radius - 30) + .innerRadius(radius / 2); + + const fakeDom = new JSDOM(''); + const body = d3.select(fakeDom.window.document).select('body'); + + const svg = body + .append('div') + .attr('class', 'container') + .append('svg') + .attr('xmlns', 'http://www.w3.org/2000/svg') + .attr('width', width) + .attr('height', height) + .attr('viewBox', `0 0 ${width} ${height}`); + + + const g = svg + .append('g') + .attr( + 'transform', + `translate( ${(width - xPadding - widthOffset)}, ${(height - yPadding + heightOffset) / 2} )` + ) + .selectAll('.arc') + .data(pieData) + .enter() + .append('g') + .attr('class', 'arc') + .attr('data-testid', 'lang-pie') + .attr('size', function (pieData) { + return ((pieData.data.size / totalLanguageSize) * 100).toFixed(2); + }); + + + g.append('path') + .attr('d', arc) + .style('fill', function (pieData) { + return pieData.data.color; + }) + .style('stroke-width', '2px'); + + const donut = body.select('.container').html(); + + return ` + + + ${createDonutTextNode(langs, totalLanguageSize)} + + + ${donut} + + `; +}; + /** * @param {number} totalLangs * @returns {number} @@ -275,6 +373,10 @@ const renderTopLanguages = (topLangs, options = {}) => { height = calculateCompactLayoutHeight(langs.length); finalLayout = renderCompactLayout(langs, width, totalLanguageSize); + } else if (layout === "pie") { + height = height - 25 // padding + width = width + 80; // padding + finalLayout = renderDonutLayout(langs, width, height, totalLanguageSize); } else { finalLayout = renderNormalLayout(langs, width, totalLanguageSize); } diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index 8c6bcbef49438..c444514c6f34e 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -236,6 +236,38 @@ describe("Test renderTopLanguages", () => { ); }); + it("should render with layout pie", () => { + document.body.innerHTML = renderTopLanguages(langs, { layout: "pie" }); + + expect(queryByTestId(document.body, "header")).toHaveTextContent( + "Most Used Languages", + ); + + expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( + "HTML 40.00%", + ); + expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute( + "size", + "40.00", + ); + + expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent( + "javascript 40.00%", + ); + expect(queryAllByTestId(document.body, "lang-pie")[1]).toHaveAttribute( + "size", + "40.00", + ); + + expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent( + "css 20.00%", + ); + expect(queryAllByTestId(document.body, "lang-pie")[2]).toHaveAttribute( + "size", + "20.00", + ); + }); + it("should render a translated title", () => { document.body.innerHTML = renderTopLanguages(langs, { locale: "cn" }); expect(document.getElementsByClassName("header")[0].textContent).toBe( From 04682a020902233ddd5c9d212f5105152235ebcc Mon Sep 17 00:00:00 2001 From: arndom Date: Wed, 5 Oct 2022 19:12:55 +0100 Subject: [PATCH 02/16] resolve failing top-lang card tests --- jest-ext.js | 4 ++++ jest.config.js | 1 + 2 files changed, 5 insertions(+) create mode 100644 jest-ext.js diff --git a/jest-ext.js b/jest-ext.js new file mode 100644 index 0000000000000..9955002934d0c --- /dev/null +++ b/jest-ext.js @@ -0,0 +1,4 @@ +import { TextDecoder, TextEncoder, } from 'util'; + +global.TextEncoder = TextEncoder; +global.TextDecoder = TextDecoder; diff --git a/jest.config.js b/jest.config.js index b4578cf5aaad5..2d657dbe86179 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,6 +5,7 @@ export default { coverageProvider: "v8", testPathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], modulePathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], + setupFiles: [`/jest-ext.js`], coveragePathIgnorePatterns: [ "/node_modules/", "/tests/E2E/", From b6356a85ec8d42e140f92e1d018a31f65a705a03 Mon Sep 17 00:00:00 2001 From: arndom Date: Sat, 8 Oct 2022 13:17:46 +0100 Subject: [PATCH 03/16] scale down pie chart --- src/cards/top-languages-card.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index e5e3b0d8a2b32..2c255217e8c40 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -234,11 +234,11 @@ const renderDonutLayout = (langs, width, height, totalLanguageSize) => { const pieData = pie(langs); - const xPadding = 50; - const yPadding = 60; + const xPadding = 80; + const yPadding = 90; - const widthOffset = 80; - const heightOffset = 25; + const widthOffset = 50; + const heightOffset = 60; const margin = 10; const radius = ((width - widthOffset) - 2 * margin - yPadding) / 2; @@ -288,12 +288,14 @@ const renderDonutLayout = (langs, width, height, totalLanguageSize) => { const donut = body.select('.container').html(); return ` - - + + ${createDonutTextNode(langs, totalLanguageSize)} - ${donut} + + ${donut} + `; }; @@ -401,8 +403,8 @@ const renderTopLanguages = (topLangs, options = {}) => { finalLayout = renderCompactLayout(langs, width, totalLanguageSize); } else if (layout === "pie") { - height = height - 25 // padding - width = width + 80; // padding + height = height - 60 // padding + width = width + 50; // padding finalLayout = renderDonutLayout(langs, width, height, totalLanguageSize); } else { finalLayout = renderNormalLayout(langs, width, totalLanguageSize); From a6e4fcc93695e44bc8bac8572959e5008b91094d Mon Sep 17 00:00:00 2001 From: Nabil Alamin Date: Sat, 8 Oct 2022 18:04:47 +0100 Subject: [PATCH 04/16] update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cbc10e9fbe7b4..ba073b1a701b4 100644 --- a/readme.md +++ b/readme.md @@ -179,7 +179,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you You can provide multiple comma-separated values in the bg_color option to render a gradient with the following format: -&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 +`&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10` #### Stats Card Exclusive Options From d23dec695f60101640c515be69e2638cf671ed75 Mon Sep 17 00:00:00 2001 From: Nabil Alamin Date: Sat, 8 Oct 2022 18:09:12 +0100 Subject: [PATCH 05/16] Update readme.md Co-authored-by: Rick Staa --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index ba073b1a701b4..7b5ed0d2870de 100644 --- a/readme.md +++ b/readme.md @@ -179,7 +179,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you You can provide multiple comma-separated values in the bg_color option to render a gradient with the following format: -`&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10` + ```&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10``` #### Stats Card Exclusive Options From 527300fad89e49e89bad1df2f29298061308e78c Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sat, 8 Oct 2022 19:13:38 +0200 Subject: [PATCH 06/16] style: format code --- jest-ext.js | 2 +- package-lock.json | 59 ++++++++++++++++++----------- readme.md | 4 +- src/cards/top-languages-card.js | 67 ++++++++++++++++----------------- 4 files changed, 74 insertions(+), 58 deletions(-) diff --git a/jest-ext.js b/jest-ext.js index 9955002934d0c..0cd1a8cbaac1b 100644 --- a/jest-ext.js +++ b/jest-ext.js @@ -1,4 +1,4 @@ -import { TextDecoder, TextEncoder, } from 'util'; +import { TextDecoder, TextEncoder } from "util"; global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; diff --git a/package-lock.json b/package-lock.json index 021413832c0b8..8f630a1424440 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2249,6 +2249,14 @@ "node": ">=12" } }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -5195,16 +5203,6 @@ "node": ">=10" } }, - "node_modules/robust-predicates": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", - "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" - }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -5224,6 +5222,16 @@ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/rxjs": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", @@ -7702,6 +7710,13 @@ "commander": "7", "iconv-lite": "0.6", "rw": "1" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } } }, "d3-ease": { @@ -9866,16 +9881,6 @@ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, - "robust-predicates": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", - "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9892,6 +9897,16 @@ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, + "robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "rxjs": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", @@ -9899,8 +9914,8 @@ "dev": true, "requires": { "tslib": "^2.1.0" - } - }, + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", diff --git a/readme.md b/readme.md index 7b5ed0d2870de..d905d819f71d0 100644 --- a/readme.md +++ b/readme.md @@ -179,7 +179,9 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you You can provide multiple comma-separated values in the bg_color option to render a gradient with the following format: - ```&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10``` +``` +&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 +``` #### Stats Card Exclusive Options diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 2c255217e8c40..fc51c10629b2f 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -12,8 +12,8 @@ import { } from "../common/utils.js"; import { langCardLocales } from "../translations.js"; -import * as d3 from 'd3'; -import {JSDOM} from 'jsdom'; +import * as d3 from "d3"; +import { JSDOM } from "jsdom"; const DEFAULT_CARD_WIDTH = 300; const MIN_CARD_WIDTH = 230; @@ -127,7 +127,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => { }).join(""); }; - /** * @param {{ langs: Lang[], totalLanguageSize: number }} props */ @@ -231,7 +230,7 @@ const renderDonutLayout = (langs, width, height, totalLanguageSize) => { const pie = d3.pie().value(function (d) { return d.size; }); - + const pieData = pie(langs); const xPadding = 80; @@ -239,53 +238,53 @@ const renderDonutLayout = (langs, width, height, totalLanguageSize) => { const widthOffset = 50; const heightOffset = 60; - + const margin = 10; - const radius = ((width - widthOffset) - 2 * margin - yPadding) / 2; + const radius = (width - widthOffset - 2 * margin - yPadding) / 2; - const arc = d3. - arc() + const arc = d3 + .arc() .outerRadius(radius - 30) .innerRadius(radius / 2); - const fakeDom = new JSDOM(''); - const body = d3.select(fakeDom.window.document).select('body'); + const fakeDom = new JSDOM(""); + const body = d3.select(fakeDom.window.document).select("body"); const svg = body - .append('div') - .attr('class', 'container') - .append('svg') - .attr('xmlns', 'http://www.w3.org/2000/svg') - .attr('width', width) - .attr('height', height) - .attr('viewBox', `0 0 ${width} ${height}`); - + .append("div") + .attr("class", "container") + .append("svg") + .attr("xmlns", "http://www.w3.org/2000/svg") + .attr("width", width) + .attr("height", height) + .attr("viewBox", `0 0 ${width} ${height}`); const g = svg - .append('g') + .append("g") .attr( - 'transform', - `translate( ${(width - xPadding - widthOffset)}, ${(height - yPadding + heightOffset) / 2} )` + "transform", + `translate( ${width - xPadding - widthOffset}, ${ + (height - yPadding + heightOffset) / 2 + } )`, ) - .selectAll('.arc') + .selectAll(".arc") .data(pieData) .enter() - .append('g') - .attr('class', 'arc') - .attr('data-testid', 'lang-pie') - .attr('size', function (pieData) { + .append("g") + .attr("class", "arc") + .attr("data-testid", "lang-pie") + .attr("size", function (pieData) { return ((pieData.data.size / totalLanguageSize) * 100).toFixed(2); }); - - g.append('path') - .attr('d', arc) - .style('fill', function (pieData) { - return pieData.data.color; + g.append("path") + .attr("d", arc) + .style("fill", function (pieData) { + return pieData.data.color; }) - .style('stroke-width', '2px'); + .style("stroke-width", "2px"); - const donut = body.select('.container').html(); + const donut = body.select(".container").html(); return ` @@ -403,7 +402,7 @@ const renderTopLanguages = (topLangs, options = {}) => { finalLayout = renderCompactLayout(langs, width, totalLanguageSize); } else if (layout === "pie") { - height = height - 60 // padding + height = height - 60; // padding width = width + 50; // padding finalLayout = renderDonutLayout(langs, width, height, totalLanguageSize); } else { From 3dc2fd76ad279c37a34da8d994f8210d689a17fd Mon Sep 17 00:00:00 2001 From: arndom Date: Sat, 15 Oct 2022 15:55:35 +0100 Subject: [PATCH 07/16] update donut layout to be created without dependencies --- jest-ext.js | 4 - jest.config.js | 1 - package-lock.json | 870 ++++++-------------------------- package.json | 2 - src/cards/top-languages-card.js | 171 ++++--- 5 files changed, 273 insertions(+), 775 deletions(-) delete mode 100644 jest-ext.js diff --git a/jest-ext.js b/jest-ext.js deleted file mode 100644 index 9955002934d0c..0000000000000 --- a/jest-ext.js +++ /dev/null @@ -1,4 +0,0 @@ -import { TextDecoder, TextEncoder, } from 'util'; - -global.TextEncoder = TextEncoder; -global.TextDecoder = TextDecoder; diff --git a/jest.config.js b/jest.config.js index 2d657dbe86179..b4578cf5aaad5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,7 +5,6 @@ export default { coverageProvider: "v8", testPathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], modulePathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], - setupFiles: [`/jest-ext.js`], coveragePathIgnorePatterns: [ "/node_modules/", "/tests/E2E/", diff --git a/package-lock.json b/package-lock.json index 021413832c0b8..dd98e87b74db2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,10 @@ "license": "MIT", "dependencies": { "axios": "^0.24.0", - "d3": "^7.6.1", "d3-shape": "^3.1.0", "dotenv": "^8.2.0", "emoji-name-map": "^1.2.8", "github-username-regex": "^1.0.0", - "jsdom": "^20.0.1", "upgrade": "^1.1.0", "word-wrap": "^1.2.3" }, @@ -1287,6 +1285,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, "engines": { "node": ">= 10" } @@ -1481,12 +1480,14 @@ "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1498,6 +1499,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, "dependencies": { "acorn": "^8.1.0", "acorn-walk": "^8.0.2" @@ -1507,6 +1509,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -1515,6 +1518,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -1614,7 +1618,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/axios": { "version": "0.24.0", @@ -2018,6 +2023,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2072,12 +2078,14 @@ "node_modules/cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true }, "node_modules/cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, "dependencies": { "cssom": "~0.3.6" }, @@ -2088,236 +2096,8 @@ "node_modules/cssstyle/node_modules/cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - }, - "node_modules/d3": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", - "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", - "dependencies": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-array": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", - "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-contour": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", - "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", - "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "dependencies": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json.js", - "csv2tsv": "bin/dsv2dsv.js", - "dsv2dsv": "bin/dsv2dsv.js", - "dsv2json": "bin/dsv2json.js", - "json2csv": "bin/json2dsv.js", - "json2dsv": "bin/json2dsv.js", - "json2tsv": "bin/json2dsv.js", - "tsv2csv": "bin/dsv2dsv.js", - "tsv2json": "bin/dsv2json.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", - "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true }, "node_modules/d3-path": { "version": "3.0.1", @@ -2327,65 +2107,6 @@ "node": ">=12" } }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/d3-shape": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", @@ -2397,73 +2118,11 @@ "node": ">=12" } }, - "node_modules/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, "dependencies": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -2477,6 +2136,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2492,7 +2152,8 @@ "node_modules/decimal.js": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", + "dev": true }, "node_modules/dedent": { "version": "0.7.0", @@ -2503,7 +2164,8 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "node_modules/deepmerge": { "version": "4.2.2", @@ -2514,18 +2176,11 @@ "node": ">=0.10.0" } }, - "node_modules/delaunator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", - "dependencies": { - "robust-predicates": "^3.0.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -2564,6 +2219,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, "dependencies": { "webidl-conversions": "^7.0.0" }, @@ -2628,6 +2284,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -2666,6 +2323,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -2687,6 +2345,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2699,6 +2358,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -2707,6 +2367,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2774,7 +2435,8 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "node_modules/fb-watchman": { "version": "2.0.2", @@ -2833,6 +2495,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2981,6 +2644,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, "dependencies": { "whatwg-encoding": "^2.0.0" }, @@ -2998,6 +2662,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -3011,6 +2676,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -3047,6 +2713,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -3119,14 +2786,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "engines": { - "node": ">=12" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3207,7 +2866,8 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "node_modules/is-stream": { "version": "2.0.1", @@ -4210,6 +3870,7 @@ "version": "20.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "dev": true, "dependencies": { "abab": "^2.0.6", "acorn": "^8.8.0", @@ -4302,6 +3963,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -4671,6 +4333,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -4679,6 +4342,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4719,7 +4383,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/natural-compare": { "version": "1.4.0", @@ -4805,7 +4470,8 @@ "node_modules/nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "dev": true }, "node_modules/object-inspect": { "version": "1.12.2", @@ -4844,6 +4510,7 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -4950,6 +4617,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -5033,6 +4701,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -5094,12 +4763,14 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } @@ -5107,7 +4778,8 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, "node_modules/react-is": { "version": "17.0.2", @@ -5146,7 +4818,8 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, "node_modules/resolve": { "version": "1.22.1", @@ -5195,16 +4868,6 @@ "node": ">=10" } }, - "node_modules/robust-predicates": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", - "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" - }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -5242,12 +4905,14 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -5350,7 +5015,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5513,7 +5178,8 @@ "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, "node_modules/terminal-link": { "version": "2.1.1", @@ -5582,6 +5248,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -5596,6 +5263,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, "dependencies": { "punycode": "^2.1.1" }, @@ -5622,6 +5290,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, @@ -5660,6 +5329,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -5699,6 +5369,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -5731,6 +5402,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, "dependencies": { "xml-name-validator": "^4.0.0" }, @@ -5751,6 +5423,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, "engines": { "node": ">=12" } @@ -5759,6 +5432,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -5770,6 +5444,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, "engines": { "node": ">=12" } @@ -5778,6 +5453,7 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -5849,6 +5525,7 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "dev": true, "engines": { "node": ">=10.0.0" }, @@ -5869,6 +5546,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, "engines": { "node": ">=12" } @@ -5876,7 +5554,8 @@ "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true }, "node_modules/y18n": { "version": "5.0.8", @@ -6947,7 +6626,8 @@ "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true }, "@types/aria-query": { "version": "4.2.2", @@ -7132,17 +6812,20 @@ "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true }, "acorn-globals": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, "requires": { "acorn": "^8.1.0", "acorn-walk": "^8.0.2" @@ -7151,12 +6834,14 @@ "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "requires": { "debug": "4" } @@ -7226,7 +6911,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "axios": { "version": "0.24.0", @@ -7527,6 +7213,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -7572,12 +7259,14 @@ "cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true }, "cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, "requires": { "cssom": "~0.3.6" }, @@ -7585,220 +7274,16 @@ "cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true } } }, - "d3": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", - "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", - "requires": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" - } - }, - "d3-array": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", - "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", - "requires": { - "internmap": "1 - 2" - } - }, - "d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==" - }, - "d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - } - }, - "d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "requires": { - "d3-path": "1 - 3" - } - }, - "d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" - }, - "d3-contour": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", - "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", - "requires": { - "d3-array": "^3.2.0" - } - }, - "d3-delaunay": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", - "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", - "requires": { - "delaunator": "5" - } - }, - "d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" - }, - "d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - } - }, - "d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "requires": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - } - }, - "d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" - }, - "d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "requires": { - "d3-dsv": "1 - 3" - } - }, - "d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - } - }, - "d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" - }, - "d3-geo": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", - "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", - "requires": { - "d3-array": "2.5.0 - 3" - } - }, - "d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==" - }, - "d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "requires": { - "d3-color": "1 - 3" - } - }, "d3-path": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz", "integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==" }, - "d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==" - }, - "d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" - }, - "d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==" - }, - "d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "requires": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - } - }, - "d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", - "requires": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - } - }, - "d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" - }, "d3-shape": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", @@ -7807,55 +7292,11 @@ "d3-path": "1 - 3" } }, - "d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", - "requires": { - "d3-array": "2 - 3" - } - }, - "d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "requires": { - "d3-time": "1 - 3" - } - }, - "d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" - }, - "d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "requires": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - } - }, - "d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - } - }, "data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, "requires": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -7866,6 +7307,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -7873,7 +7315,8 @@ "decimal.js": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", + "dev": true }, "dedent": { "version": "0.7.0", @@ -7884,7 +7327,8 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "deepmerge": { "version": "4.2.2", @@ -7892,18 +7336,11 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, - "delaunator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", - "requires": { - "robust-predicates": "^3.0.0" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true }, "deprecation": { "version": "2.3.1", @@ -7933,6 +7370,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, "requires": { "webidl-conversions": "^7.0.0" } @@ -7984,7 +7422,8 @@ "entities": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true }, "error-ex": { "version": "1.3.2", @@ -8011,6 +7450,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, "requires": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -8022,17 +7462,20 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "execa": { "version": "5.1.1", @@ -8085,7 +7528,8 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "fb-watchman": { "version": "2.0.2", @@ -8124,6 +7568,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -8229,6 +7674,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, "requires": { "whatwg-encoding": "^2.0.0" } @@ -8243,6 +7689,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, "requires": { "@tootallnate/once": "2", "agent-base": "6", @@ -8253,6 +7700,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -8274,6 +7722,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -8327,11 +7776,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8380,7 +7824,8 @@ "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "is-stream": { "version": "2.0.1", @@ -9158,6 +8603,7 @@ "version": "20.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "dev": true, "requires": { "abab": "^2.0.6", "acorn": "^8.8.0", @@ -9221,6 +8667,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -9482,12 +8929,14 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "requires": { "mime-db": "1.52.0" } @@ -9516,7 +8965,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "natural-compare": { "version": "1.4.0", @@ -9587,7 +9037,8 @@ "nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "dev": true }, "object-inspect": { "version": "1.12.2", @@ -9617,6 +9068,7 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -9692,6 +9144,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, "requires": { "entities": "^4.4.0" } @@ -9747,7 +9200,8 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true }, "prettier": { "version": "2.7.1", @@ -9787,17 +9241,20 @@ "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, "react-is": { "version": "17.0.2", @@ -9830,7 +9287,8 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, "resolve": { "version": "1.22.1", @@ -9866,16 +9324,6 @@ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, - "robust-predicates": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", - "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9899,8 +9347,8 @@ "dev": true, "requires": { "tslib": "^2.1.0" - } - }, + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -9910,12 +9358,14 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, "requires": { "xmlchars": "^2.2.0" } @@ -9987,7 +9437,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "devOptional": true + "dev": true }, "source-map-support": { "version": "0.5.13", @@ -10105,7 +9555,8 @@ "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, "terminal-link": { "version": "2.1.1", @@ -10159,6 +9610,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dev": true, "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -10170,6 +9622,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, "requires": { "punycode": "^2.1.1" } @@ -10190,6 +9643,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -10215,7 +9669,8 @@ "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true }, "update-browserslist-db": { "version": "1.0.9", @@ -10236,6 +9691,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -10262,6 +9718,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, "requires": { "xml-name-validator": "^4.0.0" } @@ -10278,12 +9735,14 @@ "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true }, "whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, "requires": { "iconv-lite": "0.6.3" } @@ -10291,12 +9750,14 @@ "whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true }, "whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, "requires": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -10347,17 +9808,20 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "dev": true, "requires": {} }, "xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true }, "xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index 568c57bd96f96..89e95ba033a59 100644 --- a/package.json +++ b/package.json @@ -39,12 +39,10 @@ }, "dependencies": { "axios": "^0.24.0", - "d3": "^7.6.1", "d3-shape": "^3.1.0", "dotenv": "^8.2.0", "emoji-name-map": "^1.2.8", "github-username-regex": "^1.0.0", - "jsdom": "^20.0.1", "upgrade": "^1.1.0", "word-wrap": "^1.2.3" }, diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 2c255217e8c40..4fcdf736796aa 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -12,9 +12,6 @@ import { } from "../common/utils.js"; import { langCardLocales } from "../translations.js"; -import * as d3 from 'd3'; -import {JSDOM} from 'jsdom'; - const DEFAULT_CARD_WIDTH = 300; const MIN_CARD_WIDTH = 230; const DEFAULT_LANGS_COUNT = 5; @@ -221,71 +218,115 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { }; /** - * @param {Lang[]} langs - * @param {number} width - * @param {number} height - * @param {number} totalLanguageSize - * @returns {string} + * Renders donut layout to display user's most frequently used programming languages. + * + * @param {number} cx Center position x-axis. + * @param {number} cy Center position y-axis. + * @param {number} radius Arc Radius. + * @param {{value: string}[]} data Array of donut section values. + * @returns {string[]} Array of svg path elements */ -const renderDonutLayout = (langs, width, height, totalLanguageSize) => { - const pie = d3.pie().value(function (d) { - return d.size; - }); - - const pieData = pie(langs); +const createDonutPaths = (cx, cy, radius, data) => { + + const arcradius = (cx, cy, radius, degrees) => { + const radians = ((degrees - 90) * Math.PI) / 180.0; + + return { + x: cx + radius * Math.cos(radians), + y: cy + radius * Math.sin(radians), + }; + } - const xPadding = 80; - const yPadding = 90; + const decimals = 4; + let total = 0; + const arr = []; + + let beginning = 0; + let end = 0; + let count = 0; + + for (let i = 0; i < data.length; i++) total += data[i].value; + + for (let i = 0; i < data.length; i++) { + const item = data[i]; + const tmp = {}; + + const p = Number((((item.value + 1) / total) * 100).toFixed(2)); + + count += p; + + if (i === data.length - 1 && count < 100) p = p + (100 - count); + + end = beginning + (360 / 100) * p; + tmp.value = item.value; + + const b = arcradius(cx, cy, radius, end); + const e = arcradius(cx, cy, radius, beginning); + const la = end - beginning <= 180 ? 0 : 1; + + tmp.d = [ + "M", + // Math.floor(b.x, decimals), + Number((b.x).toFixed(decimals)), + // Math.floor(b.y, decimals), + Number((b.y).toFixed(decimals)), + "A", + radius, + radius, + 0, + la, + 0, + // Math.floor(e.x, decimals), + Number((e.x).toFixed(decimals)), + // Math.floor(e.y, decimals), + Number((e.y).toFixed(decimals)), + ].join(" "); + + arr.push(tmp); + beginning = end; + } + + return arr; +} - const widthOffset = 50; - const heightOffset = 60; +/** + * Renders donut layout to display user's most frequently used programming languages. + * + * @param {Lang[]} langs Array of programming languages. + * @param {number} width Card width. + * @param {number} totalLanguageSize Total size of all languages. + * @returns {string} Donut layout card SVG object. + */ +const renderDonutLayout = (langs, width, totalLanguageSize) => { + const centerX = width / 3; + const centerY = width / 3; + const radius = centerX - 60 - const margin = 10; - const radius = ((width - widthOffset) - 2 * margin - yPadding) / 2; - - const arc = d3. - arc() - .outerRadius(radius - 30) - .innerRadius(radius / 2); - - const fakeDom = new JSDOM(''); - const body = d3.select(fakeDom.window.document).select('body'); - - const svg = body - .append('div') - .attr('class', 'container') - .append('svg') - .attr('xmlns', 'http://www.w3.org/2000/svg') - .attr('width', width) - .attr('height', height) - .attr('viewBox', `0 0 ${width} ${height}`); - - - const g = svg - .append('g') - .attr( - 'transform', - `translate( ${(width - xPadding - widthOffset)}, ${(height - yPadding + heightOffset) / 2} )` - ) - .selectAll('.arc') - .data(pieData) - .enter() - .append('g') - .attr('class', 'arc') - .attr('data-testid', 'lang-pie') - .attr('size', function (pieData) { - return ((pieData.data.size / totalLanguageSize) * 100).toFixed(2); - }); + const strokeWidth = 12; + + const colors = langs.map((lang) => lang.color); + const langSections = langs.map((lang) => ({ + value: Number(((lang.size / totalLanguageSize) * 100).toFixed(2)) + })); + + const langArray = createDonutPaths(centerX, centerY, radius, langSections); + + const paths = langArray.map((section, i) => { + const output = ` + + + + + `; - - g.append('path') - .attr('d', arc) - .style('fill', function (pieData) { - return pieData.data.color; - }) - .style('stroke-width', '2px'); + return output; + }).join(""); - const donut = body.select('.container').html(); + const donut = `${paths}`; return ` @@ -293,8 +334,8 @@ const renderDonutLayout = (langs, width, height, totalLanguageSize) => { ${createDonutTextNode(langs, totalLanguageSize)} - - ${donut} + + ${donut} `; @@ -405,7 +446,7 @@ const renderTopLanguages = (topLangs, options = {}) => { } else if (layout === "pie") { height = height - 60 // padding width = width + 50; // padding - finalLayout = renderDonutLayout(langs, width, height, totalLanguageSize); + finalLayout = renderDonutLayout(langs, width, totalLanguageSize); } else { finalLayout = renderNormalLayout(langs, width, totalLanguageSize); } From a36d91d6ad77aa89c773b86ecac04e6331437c85 Mon Sep 17 00:00:00 2001 From: arndom Date: Sat, 15 Oct 2022 16:09:47 +0100 Subject: [PATCH 08/16] minor update --- src/cards/top-languages-card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 30596ad647440..642dc5f66586f 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -250,7 +250,7 @@ const createDonutPaths = (cx, cy, radius, data) => { const item = data[i]; const tmp = {}; - const p = Number((((item.value + 1) / total) * 100).toFixed(2)); + let p = Number((((item.value + 1) / total) * 100).toFixed(2)); count += p; From 6c1baf1213732e5f20409dea6e7b3d8f48c75e5d Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sun, 16 Oct 2022 13:17:14 +0200 Subject: [PATCH 09/16] style: format readme --- readme.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/readme.md b/readme.md index d905d819f71d0..23320e2316db2 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,7 @@

-

+

View Demo ยท Report Bug @@ -167,28 +167,26 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you - `border_color` - Card's border color _(hex color)_. Default: `e4e2e2` (Does not apply when `hide_border` is enabled). - `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe` - `hide_border` - Hides the card's border _(boolean)_. Default: `false` -- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme. -- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`. -- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`. +- `theme` - Name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme. +- `cache_seconds` - Set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`. +- `locale` - Set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`. - `border_radius` - Corner rounding on the card. Default: `4.5`. > **Warning** -> We use caching to decrease the load on our servers (see https://github.com/anuraghazra/github-readme-stats/issues/1471#issuecomment-1271551425). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours. +> We use caching to decrease the load on our servers (see ). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours. ##### Gradient in bg_color You can provide multiple comma-separated values in the bg_color option to render a gradient with the following format: -``` -&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 -``` + &bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10 #### Stats Card Exclusive Options - `hide` - Hides the [specified items](#hiding-individual-stats) from stats _(Comma-separated values)_. Default: `[] (blank array)`. - `hide_title` - _(boolean)_. Default: `false`. - `card_width` - Set the card's width manually _(number)_. Default: `500px (approx.)`. -- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width. Default: `false`. +- `hide_rank` - _(boolean)_ Hides the rank and automatically resizes the card width. Default: `false`. - `show_icons` - _(boolean)_. Default: `false`. - `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`. - `count_private` - Count private commits _(boolean)_. Default: `false`. @@ -263,7 +261,7 @@ Use [show_owner](#customization) variable to include the repo's owner username The top languages card shows a GitHub user's most frequently used top language. > **Note** -> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats._ +> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.\_ ### Usage From 57bca94717901084d2837b1452ecbf1356870d8d Mon Sep 17 00:00:00 2001 From: arndom Date: Sun, 16 Oct 2022 14:37:21 +0100 Subject: [PATCH 10/16] resolve failing tests --- src/cards/top-languages-card.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 642dc5f66586f..7f64f1c344d10 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -223,7 +223,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { * @param {number} cy Center position y-axis. * @param {number} radius Arc Radius. * @param {{value: number}[]} data Array of donut section values. - * @returns {{d: string}[]} Array of svg path elements + * @returns {{d: string, value: number}[]} Array of svg path elements */ const createDonutPaths = (cx, cy, radius, data) => { @@ -262,6 +262,8 @@ const createDonutPaths = (cx, cy, radius, data) => { const e = arcradius(cx, cy, radius, beginning); const la = end - beginning <= 180 ? 0 : 1; + tmp.value = Number(item.value).toFixed(2); + tmp.d = [ "M", Number((b.x).toFixed(decimals)), @@ -309,6 +311,8 @@ const renderDonutLayout = (langs, width, totalLanguageSize) => { const output = ` Date: Mon, 24 Oct 2022 11:51:05 +0200 Subject: [PATCH 11/16] refactor: clean up code and add extra tests This commit cleans up the pie chart generation code and adds additional tests. --- src/cards/top-languages-card.js | 352 +++++++++++++++++-------------- src/cards/types.d.ts | 2 +- tests/renderTopLanguages.test.js | 220 ++++++++++++++++++- 3 files changed, 410 insertions(+), 164 deletions(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 7f64f1c344d10..7b53e4d367d8f 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -36,17 +36,119 @@ const getLongestLang = (arr) => ); /** - * Creates a node to display usage of a programming language in percentage - * using text and a horizontal progress bar. + * Convert degrees to radians. + * + * @param {number} angleInDegrees Angle in degrees. + * @returns Angle in radians. + */ +const degreesToRadians = (angleInDegrees) => angleInDegrees * (Math.PI / 180.0); + +/** + * Convert radians to degrees. + * + * @param {number} angleInRadians Angle in radians. + * @returns Angle in degrees. + */ +const radiansToDegrees = (angleInRadians) => angleInRadians / (Math.PI / 180.0); + +/** + * Convert polar coordinates to cartesian coordinates. + * + * @param {number} centerX Center x coordinate. + * @param {number} centerY Center y coordinate. + * @param {number} radius Radius of the circle. + * @param {number} angleInDegrees Angle in degrees. + * @returns {{x: number, y: number}} Cartesian coordinates. + */ +const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => { + const rads = degreesToRadians(angleInDegrees); + return { + x: centerX + radius * Math.cos(rads), + y: centerY + radius * Math.sin(rads), + }; +}; + +/** + * Convert cartesian coordinates to polar coordinates. + * + * @param {number} centerX Center x coordinate. + * @param {number} centerY Center y coordinate. + * @param {number} x Point x coordinate. + * @param {number} y Point y coordinate. + * @returns {{radius: number, angleInDegrees: number}} Polar coordinates. + */ +const cartesianToPolar = (centerX, centerY, x, y) => { + const radius = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2)); + let angleInDegrees = radiansToDegrees(Math.atan2(y - centerY, x - centerX)); + if (angleInDegrees < 0) angleInDegrees += 360; + return { radius, angleInDegrees }; +}; + +/** + * Calculates height for the compact layout. + * + * @param {number} totalLangs Total number of languages. + * @returns {number} Card height. + */ +const calculateCompactLayoutHeight = (totalLangs) => { + return 90 + Math.round(totalLangs / 2) * 25; +}; + +/** + * Calculates height for the normal layout. + * + * @param {number} totalLangs Total number of languages. + * @returns {number} Card height. + */ +const calculateNormalLayoutHeight = (totalLangs) => { + return 45 + (totalLangs + 1) * 40; +}; + +/** + * Trim top languages to lang_count while also hiding certain languages. + * + * @param {Record} topLangs Top languages. + * @param {string[]} hide Languages to hide. + * @param {string} langs_count Number of languages to show. + * @returns {{topLangs: Record, totalSize: number}} Trimmed top languages and total size. + */ +const trimTopLanguages = (topLangs, hide, langs_count) => { + let langs = Object.values(topLangs); + let langsToHide = {}; + let langsCount = clampValue(parseInt(langs_count), 1, 10); + + // populate langsToHide map for quick lookup + // while filtering out + if (hide) { + hide.forEach((langName) => { + langsToHide[lowercaseTrim(langName)] = true; + }); + } + + // filter out languages to be hidden + langs = langs + .sort((a, b) => b.size - a.size) + .filter((lang) => { + return !langsToHide[lowercaseTrim(lang.name)]; + }) + .slice(0, langsCount); + + const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0); + + return { langs, totalLanguageSize }; +}; + +/** + * Create progress bar text item for a programming language. * * @param {object[]} props Function properties. * @param {number} props.width The card width - * @param {string} props.name Name of the programming language. * @param {string} props.color Color of the programming language. + * @param {string} props.name Name of the programming language. * @param {string} props.progress Usage of the programming language in percentage. - * @returns {string} Programming language SVG node. + * @returns {string} Programming language progress bar SVG text node. */ -const createProgressTextNode = ({ width, color, name, progress }) => { +const createProgressBarLanguageNode = ({ width, color, name, progress }) => { const paddingRight = 95; const progressTextX = width - paddingRight + 10; const progressWidth = width - paddingRight; @@ -66,7 +168,7 @@ const createProgressTextNode = ({ width, color, name, progress }) => { }; /** - * Creates a text only node to display usage of a programming language in percentage. + * Creates compact text item for a programming language. * * @param {object[]} props Function properties. * @param {Lang} props.lang Programming language object. @@ -88,24 +190,22 @@ const createCompactLangNode = ({ lang, totalSize }) => { }; /** - * Creates compact layout of text only language nodes. + * Create compact languages text items for all programming languages. * * @param {object[]} props Function properties. * @param {Lang[]} props.langs Array of programming languages. * @param {number} props.totalSize Total size of all languages. * @returns {string} Programming languages SVG node. */ -const createLanguageTextNode = ({ langs, totalSize }) => { +const createCompactLanguagesNode = ({ langs, totalSize }) => { const longestLang = getLongestLang(langs); const chunked = chunkArray(langs, langs.length / 2); const layouts = chunked.map((array) => { // @ts-ignore - const items = array.map((lang, index) => + const items = array.map((lang) => createCompactLangNode({ lang, totalSize, - // @ts-ignore - index, }), ); return flexLayout({ @@ -125,14 +225,19 @@ const createLanguageTextNode = ({ langs, totalSize }) => { }; /** - * @param {{ langs: Lang[], totalLanguageSize: number }} props + * Create doughnut languages text items for all programming languages. + * + * @param {object[]} props Function properties. + * @param {Lang[]} props.langs Array of programming languages. + * @param {number} props.totalSize Total size of all languages. + * @returns {string} Doughnut layout programming language SVG node. */ -const createDonutTextNode = (langs, totalLanguageSize) => { +const createDoughnutLanguagesNode = ({ langs, totalSize }) => { return flexLayout({ items: langs.map((lang) => { return createCompactLangNode({ lang, - totalSize: totalLanguageSize, + totalSize: totalSize, }); }), gap: 32, @@ -141,7 +246,7 @@ const createDonutTextNode = (langs, totalLanguageSize) => { }; /** - * Renders layout to display user's most frequently used programming languages. + * Renders the default language card layout. * * @param {Lang[]} langs Array of programming languages. * @param {number} width Card width. @@ -151,8 +256,8 @@ const createDonutTextNode = (langs, totalLanguageSize) => { const renderNormalLayout = (langs, width, totalLanguageSize) => { return flexLayout({ items: langs.map((lang) => { - return createProgressTextNode({ - width: width, + return createProgressBarLanguageNode({ + width, name: lang.name, color: lang.color || DEFAULT_LANG_COLOR, progress: ((lang.size / totalLanguageSize) * 100).toFixed(2), @@ -164,7 +269,7 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => { }; /** - * Renders compact layout to display user's most frequently used programming languages. + * Renders the compact language card layout. * * @param {Lang[]} langs Array of programming languages. * @param {number} width Card width. @@ -208,7 +313,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { ${compactProgressBar} - ${createLanguageTextNode({ + ${createCompactLanguagesNode({ langs, totalSize: totalLanguageSize, })} @@ -217,102 +322,77 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { }; /** - * Renders donut layout to display user's most frequently used programming languages. - * - * @param {number} cx Center position x-axis. - * @param {number} cy Center position y-axis. - * @param {number} radius Arc Radius. - * @param {{value: number}[]} data Array of donut section values. - * @returns {{d: string, value: number}[]} Array of svg path elements + * Creates the SVG paths for the language doughnut chart. + * + * @param {number} cx Doughnut center x-position. + * @param {number} cy Doughnut center y-position. + * @param {number} radius Doughnut arc Radius. + * @param {number[]} percentages Array with doughnut section percentages. + * @returns {{d: string, percent: number}[]} Array of svg path elements */ -const createDonutPaths = (cx, cy, radius, data) => { - - const arcradius = (cx, cy, radius, degrees) => { - const radians = ((degrees - 90) * Math.PI) / 180.0; - - return { - x: cx + radius * Math.cos(radians), - y: cy + radius * Math.sin(radians), - }; - } - - const decimals = 4; - let total = 0; - const arr = []; - - let beginning = 0; - let end = 0; - let count = 0; - - for (let i = 0; i < data.length; i++) total += data[i].value; - - for (let i = 0; i < data.length; i++) { - const item = data[i]; - const tmp = {}; - - let p = Number((((item.value + 1) / total) * 100).toFixed(2)); - - count += p; - - if (i === data.length - 1 && count < 100) p = p + (100 - count); - - end = beginning + (360 / 100) * p; - - const b = arcradius(cx, cy, radius, end); - const e = arcradius(cx, cy, radius, beginning); - const la = end - beginning <= 180 ? 0 : 1; +const createDoughnutPaths = (cx, cy, radius, percentages) => { + const paths = []; + let startAngle = 0; + let endAngle = 0; + let doughnutPercent = 0; + + const totalPercent = percentages.reduce((acc, curr) => acc + curr, 0); + for (let i = 0; i < percentages.length; i++) { + const tmpPath = {}; + + let percent = parseFloat( + ((percentages[i] / totalPercent) * 100).toFixed(2), + ); + doughnutPercent += percent; - tmp.value = Number(item.value).toFixed(2); + endAngle = 3.6 * percent + startAngle; + const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate doughnut 90 degrees counter-clockwise. + const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate doughnut 90 degrees counter-clockwise. + const largeArc = endAngle - startAngle <= 180 ? 0 : 1; - tmp.d = [ - "M", - Number((b.x).toFixed(decimals)), - Number((b.y).toFixed(decimals)), - "A", - radius, - radius, - 0, - la, - 0, - Number((e.x).toFixed(decimals)), - Number((e.y).toFixed(decimals)), - ].join(" "); + tmpPath.percent = percent; + tmpPath.d = `M ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArc} 0 ${endPoint.x} ${endPoint.y}`; - arr.push(tmp); - beginning = end; + paths.push(tmpPath); + startAngle = endAngle; } - return arr; -} + return paths; +}; /** - * Renders donut layout to display user's most frequently used programming languages. - * + * Renders the doughnut language card layout. + * * @param {Lang[]} langs Array of programming languages. * @param {number} width Card width. * @param {number} totalLanguageSize Total size of all languages. * @returns {string} Donut layout card SVG object. */ -const renderDonutLayout = (langs, width, totalLanguageSize) => { +const renderDoughnutLayout = (langs, width, totalLanguageSize) => { const centerX = width / 3; const centerY = width / 3; - const radius = centerX - 60 - + const radius = centerX - 60; const strokeWidth = 12; const colors = langs.map((lang) => lang.color); - const langSections = langs.map((lang) => ({ - value: Number(((lang.size / totalLanguageSize) * 100).toFixed(2)) - })); + const langsPercents = langs.map((lang) => + parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)), + ); - const langArray = createDonutPaths(centerX, centerY, radius, langSections); + const langPaths = createDoughnutPaths( + centerX, + centerY, + radius, + langsPercents, + ); - const paths = langArray.map((section, i) => { - const output = ` + const doughnutPaths = langPaths + .map((section, i) => { + const output = ` { `; - return output; - }).join(""); + return output; + }) + .join(""); - const donut = `${paths}`; + const donut = `${doughnutPaths}`; return ` - ${createDonutTextNode(langs, totalLanguageSize)} + ${createDoughnutLanguagesNode({ langs, totalSize: totalLanguageSize })} @@ -340,60 +421,7 @@ const renderDonutLayout = (langs, width, totalLanguageSize) => { }; /** - * Calculates height for the compact layout. - * - * @param {number} totalLangs Total number of languages. - * @returns {number} Card height. - */ -const calculateCompactLayoutHeight = (totalLangs) => { - return 90 + Math.round(totalLangs / 2) * 25; -}; - -/** - * Calculates height for the normal layout. - * - * @param {number} totalLangs Total number of languages. - * @returns {number} Card height. - */ -const calculateNormalLayoutHeight = (totalLangs) => { - return 45 + (totalLangs + 1) * 40; -}; - -/** - * Hides languages and trims the list to show only the top N languages. - * - * @param {Record} topLangs Top languages. - * @param {string[]} hide Languages to hide. - * @param {string} langs_count Number of languages to show. - */ -const useLanguages = (topLangs, hide, langs_count) => { - let langs = Object.values(topLangs); - let langsToHide = {}; - let langsCount = clampValue(parseInt(langs_count), 1, 10); - - // populate langsToHide map for quick lookup - // while filtering out - if (hide) { - hide.forEach((langName) => { - langsToHide[lowercaseTrim(langName)] = true; - }); - } - - // filter out languages to be hidden - langs = langs - .sort((a, b) => b.size - a.size) - .filter((lang) => { - return !langsToHide[lowercaseTrim(lang.name)]; - }) - .slice(0, langsCount); - - const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0); - - return { langs, totalLanguageSize }; -}; - -/** - * Renders card to display user's most frequently used programming languages. + * Renders card that display user's most frequently used programming languages. * * @param {import('../fetchers/types').TopLangData} topLangs User's most frequently used programming languages. * @param {Partial} options Card options. @@ -422,7 +450,7 @@ const renderTopLanguages = (topLangs, options = {}) => { translations: langCardLocales, }); - const { langs, totalLanguageSize } = useLanguages( + const { langs, totalLanguageSize } = trimTopLanguages( topLangs, hide, String(langs_count), @@ -436,15 +464,14 @@ const renderTopLanguages = (topLangs, options = {}) => { let height = calculateNormalLayoutHeight(langs.length); let finalLayout = ""; - if (layout === "compact") { + if (layout?.toLowerCase() === "compact") { width = width + 50; // padding height = calculateCompactLayoutHeight(langs.length); - finalLayout = renderCompactLayout(langs, width, totalLanguageSize); - } else if (layout === "pie") { + } else if (layout?.toLowerCase() === "pie") { height = height - 60; // padding width = width + 50; // padding - finalLayout = renderDonutLayout(langs, width, totalLanguageSize); + finalLayout = renderDoughnutLayout(langs, width, totalLanguageSize); } else { finalLayout = renderNormalLayout(langs, width, totalLanguageSize); } @@ -481,4 +508,15 @@ const renderTopLanguages = (topLangs, options = {}) => { `); }; -export { renderTopLanguages, MIN_CARD_WIDTH }; +export { + getLongestLang, + degreesToRadians, + radiansToDegrees, + polarToCartesian, + cartesianToPolar, + calculateCompactLayoutHeight, + calculateNormalLayoutHeight, + trimTopLanguages, + renderTopLanguages, + MIN_CARD_WIDTH, +}; diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 502314c41fa92..6549b34147768 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -34,7 +34,7 @@ export type TopLangOptions = CommonOptions & { hide_border: boolean; card_width: number; hide: string[]; - layout: "compact" | "normal"; + layout: "compact" | "normal" | "pie"; custom_title: string; langs_count: number; }; diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index eb842381ad2ee..fd2f99ef6de8a 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -2,8 +2,19 @@ import { queryAllByTestId, queryByTestId } from "@testing-library/dom"; import { cssToObject } from "@uppercod/css-to-object"; import { MIN_CARD_WIDTH, + radiansToDegrees, renderTopLanguages, + calculateCompactLayoutHeight, + calculateNormalLayoutHeight, + trimTopLanguages, } from "../src/cards/top-languages-card.js"; +import { + getLongestLang, + degreesToRadians, + polarToCartesian, + cartesianToPolar, +} from "../src/cards/top-languages-card.js"; + // adds special assertions like toHaveTextContent import "@testing-library/jest-dom"; @@ -27,6 +38,177 @@ const langs = { }, }; +/** + * Retrieve the language percentage from the doughnut chart SVG. + * @param {string} d The SVG path element. + * @param {number} centerX The center X coordinate of the doughnut chart. + * @param {number} centerY The center Y coordinate of the doughnut chart. + * @returns {number} The percentage of the language. + */ +const langPercentFromSvg = (d, centerX, centerY) => { + const dTmp = d + .split(" ") + .filter((x) => !isNaN(x)) + .map((x) => parseFloat(x)); + const endAngle = + cartesianToPolar(centerX, centerY, dTmp[0], dTmp[1]).angleInDegrees + 90; + let startAngle = + cartesianToPolar(centerX, centerY, dTmp[7], dTmp[8]).angleInDegrees + 90; + if (startAngle > endAngle) startAngle -= 360; + return (endAngle - startAngle) / 3.6; +}; + +describe("Test renderTopLanguages helper functions", () => { + it("getLongestLang", () => { + const langArray = Object.values(langs); + expect(getLongestLang(langArray)).toBe(langs.javascript); + }); + + it("degreesToRadians", () => { + expect(degreesToRadians(0)).toBe(0); + expect(degreesToRadians(90)).toBe(Math.PI / 2); + expect(degreesToRadians(180)).toBe(Math.PI); + expect(degreesToRadians(270)).toBe((3 * Math.PI) / 2); + expect(degreesToRadians(360)).toBe(2 * Math.PI); + }); + + it("radiansToDegrees", () => { + expect(radiansToDegrees(0)).toBe(0); + expect(radiansToDegrees(Math.PI / 2)).toBe(90); + expect(radiansToDegrees(Math.PI)).toBe(180); + expect(radiansToDegrees((3 * Math.PI) / 2)).toBe(270); + expect(radiansToDegrees(2 * Math.PI)).toBe(360); + }); + + it("polarToCartesian", () => { + expect(polarToCartesian(100, 100, 60, 0)).toStrictEqual({ x: 160, y: 100 }); + expect(polarToCartesian(100, 100, 60, 45)).toStrictEqual({ + x: 142.42640687119285, + y: 142.42640687119285, + }); + expect(polarToCartesian(100, 100, 60, 90)).toStrictEqual({ + x: 100, + y: 160, + }); + expect(polarToCartesian(100, 100, 60, 135)).toStrictEqual({ + x: 57.573593128807154, + y: 142.42640687119285, + }); + expect(polarToCartesian(100, 100, 60, 180)).toStrictEqual({ + x: 40, + y: 100.00000000000001, + }); + expect(polarToCartesian(100, 100, 60, 225)).toStrictEqual({ + x: 57.57359312880714, + y: 57.573593128807154, + }); + expect(polarToCartesian(100, 100, 60, 270)).toStrictEqual({ + x: 99.99999999999999, + y: 40, + }); + expect(polarToCartesian(100, 100, 60, 315)).toStrictEqual({ + x: 142.42640687119285, + y: 57.57359312880714, + }); + expect(polarToCartesian(100, 100, 60, 360)).toStrictEqual({ + x: 160, + y: 99.99999999999999, + }); + }); + + it("cartesianToPolar", () => { + expect(cartesianToPolar(100, 100, 160, 100)).toStrictEqual({ + radius: 60, + angleInDegrees: 0, + }); + expect( + cartesianToPolar(100, 100, 142.42640687119285, 142.42640687119285), + ).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 45 }); + expect(cartesianToPolar(100, 100, 100, 160)).toStrictEqual({ + radius: 60, + angleInDegrees: 90, + }); + expect( + cartesianToPolar(100, 100, 57.573593128807154, 142.42640687119285), + ).toStrictEqual({ radius: 60, angleInDegrees: 135 }); + expect(cartesianToPolar(100, 100, 40, 100.00000000000001)).toStrictEqual({ + radius: 60, + angleInDegrees: 180, + }); + expect( + cartesianToPolar(100, 100, 57.57359312880714, 57.573593128807154), + ).toStrictEqual({ radius: 60, angleInDegrees: 225 }); + expect(cartesianToPolar(100, 100, 99.99999999999999, 40)).toStrictEqual({ + radius: 60, + angleInDegrees: 270, + }); + expect( + cartesianToPolar(100, 100, 142.42640687119285, 57.57359312880714), + ).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 315 }); + expect(cartesianToPolar(100, 100, 160, 99.99999999999999)).toStrictEqual({ + radius: 60, + angleInDegrees: 360, + }); + }); + + it("calculateCompactLayoutHeight", () => { + expect(calculateCompactLayoutHeight(0)).toBe(90); + expect(calculateCompactLayoutHeight(1)).toBe(115); + expect(calculateCompactLayoutHeight(2)).toBe(115); + expect(calculateCompactLayoutHeight(3)).toBe(140); + expect(calculateCompactLayoutHeight(4)).toBe(140); + expect(calculateCompactLayoutHeight(5)).toBe(165); + expect(calculateCompactLayoutHeight(6)).toBe(165); + expect(calculateCompactLayoutHeight(7)).toBe(190); + expect(calculateCompactLayoutHeight(8)).toBe(190); + expect(calculateCompactLayoutHeight(9)).toBe(215); + expect(calculateCompactLayoutHeight(10)).toBe(215); + }); + + it("calculateNormalLayoutHeight", () => { + expect(calculateNormalLayoutHeight(0)).toBe(85); + expect(calculateNormalLayoutHeight(1)).toBe(125); + expect(calculateNormalLayoutHeight(2)).toBe(165); + expect(calculateNormalLayoutHeight(3)).toBe(205); + expect(calculateNormalLayoutHeight(4)).toBe(245); + expect(calculateNormalLayoutHeight(5)).toBe(285); + expect(calculateNormalLayoutHeight(6)).toBe(325); + expect(calculateNormalLayoutHeight(7)).toBe(365); + expect(calculateNormalLayoutHeight(8)).toBe(405); + expect(calculateNormalLayoutHeight(9)).toBe(445); + expect(calculateNormalLayoutHeight(10)).toBe(485); + }); + + it("trimTopLanguages", () => { + expect(trimTopLanguages([])).toStrictEqual({ + langs: [], + totalLanguageSize: 0, + }); + expect(trimTopLanguages([langs.javascript])).toStrictEqual({ + langs: [langs.javascript], + totalLanguageSize: 200, + }); + expect( + trimTopLanguages([langs.javascript, langs.HTML], [], 5), + ).toStrictEqual({ + langs: [langs.javascript, langs.HTML], + totalLanguageSize: 400, + }); + expect(trimTopLanguages(langs, [], 5)).toStrictEqual({ + langs: Object.values(langs), + totalLanguageSize: 500, + }); + expect(trimTopLanguages(langs, [], 2)).toStrictEqual({ + langs: Object.values(langs).slice(0, 2), + totalLanguageSize: 400, + }); + expect(trimTopLanguages(langs, ["javascript"], 5)).toStrictEqual({ + langs: [langs.HTML, langs.css], + totalLanguageSize: 300, + }); + }); +}); + describe("Test renderTopLanguages", () => { it("should render correctly", () => { document.body.innerHTML = renderTopLanguages(langs); @@ -246,26 +428,52 @@ describe("Test renderTopLanguages", () => { expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( "HTML 40.00%", ); - expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-doughnut")[0]).toHaveAttribute( "size", - "40.00", + "40", + ); + const d = queryAllByTestId(document.body, "lang-doughnut")[0] + .getAttribute("d") + .split(" ") + .filter((x) => !isNaN(x)) + .map((x) => parseFloat(x)); + const center = { x: d[7], y: d[7] }; + const HTMLLangPercent = langPercentFromSvg( + queryAllByTestId(document.body, "lang-doughnut")[0].getAttribute("d"), + center.x, + center.y, ); + expect(HTMLLangPercent).toBeCloseTo(40); expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent( "javascript 40.00%", ); - expect(queryAllByTestId(document.body, "lang-pie")[1]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-doughnut")[1]).toHaveAttribute( "size", - "40.00", + "40", + ); + const javascriptLangPercent = langPercentFromSvg( + queryAllByTestId(document.body, "lang-doughnut")[1].getAttribute("d"), + center.x, + center.y, ); + expect(javascriptLangPercent).toBeCloseTo(40); expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent( "css 20.00%", ); - expect(queryAllByTestId(document.body, "lang-pie")[2]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-doughnut")[2]).toHaveAttribute( "size", - "20.00", + "20", ); + const cssLangPercent = langPercentFromSvg( + queryAllByTestId(document.body, "lang-doughnut")[2].getAttribute("d"), + center.x, + center.y, + ); + expect(cssLangPercent).toBeCloseTo(20); + + expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100); }); it("should render a translated title", () => { From f1c67a5edfcf1fc307c932dbcd8951d301f0efa0 Mon Sep 17 00:00:00 2001 From: rickstaa Date: Mon, 24 Oct 2022 13:49:11 +0200 Subject: [PATCH 12/16] feat: improve pie chart positioning --- src/cards/top-languages-card.js | 42 ++++++++++++++++------ tests/renderTopLanguages.test.js | 61 +++++++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 7b53e4d367d8f..207888b96e08b 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -104,6 +104,25 @@ const calculateNormalLayoutHeight = (totalLangs) => { return 45 + (totalLangs + 1) * 40; }; +/** + * Calculates height for the pie layout. + * + * @param {number} totalLangs Total number of languages. + * @returns {number} Card height. + */ +const calculatePieLayoutHeight = (totalLangs) => { + return 215 + Math.max(totalLangs - 5, 0) * 32; +}; + +/** + * Calculates the center translation needed to keep the doughnut chart centred. + * @param {number} totalLangs Total number of languages. + * @returns {number} Doughnut center translation. + */ +const doughnutCenterTranslation = (totalLangs) => { + return -45 + Math.max(totalLangs - 5, 0) * 16; +}; + /** * Trim top languages to lang_count while also hiding certain languages. * @@ -334,7 +353,6 @@ const createDoughnutPaths = (cx, cy, radius, percentages) => { const paths = []; let startAngle = 0; let endAngle = 0; - let doughnutPercent = 0; const totalPercent = percentages.reduce((acc, curr) => acc + curr, 0); for (let i = 0; i < percentages.length; i++) { @@ -343,7 +361,6 @@ const createDoughnutPaths = (cx, cy, radius, percentages) => { let percent = parseFloat( ((percentages[i] / totalPercent) * 100).toFixed(2), ); - doughnutPercent += percent; endAngle = 3.6 * percent + startAngle; const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate doughnut 90 degrees counter-clockwise. @@ -386,9 +403,12 @@ const renderDoughnutLayout = (langs, width, totalLanguageSize) => { langsPercents, ); - const doughnutPaths = langPaths - .map((section, i) => { - const output = ` + const doughnutPaths = + langs.length === 1 + ? `` + : langPaths + .map((section, i) => { + const output = ` { `; - return output; - }) - .join(""); + return output; + }) + .join(""); const donut = `${doughnutPaths}`; @@ -413,7 +433,7 @@ const renderDoughnutLayout = (langs, width, totalLanguageSize) => { ${createDoughnutLanguagesNode({ langs, totalSize: totalLanguageSize })} - + ${donut} @@ -469,7 +489,7 @@ const renderTopLanguages = (topLangs, options = {}) => { height = calculateCompactLayoutHeight(langs.length); finalLayout = renderCompactLayout(langs, width, totalLanguageSize); } else if (layout?.toLowerCase() === "pie") { - height = height - 60; // padding + height = calculatePieLayoutHeight(langs.length); width = width + 50; // padding finalLayout = renderDoughnutLayout(langs, width, totalLanguageSize); } else { @@ -516,6 +536,8 @@ export { cartesianToPolar, calculateCompactLayoutHeight, calculateNormalLayoutHeight, + calculatePieLayoutHeight, + doughnutCenterTranslation, trimTopLanguages, renderTopLanguages, MIN_CARD_WIDTH, diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index fd2f99ef6de8a..ad60933d9e4b7 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -1,18 +1,18 @@ import { queryAllByTestId, queryByTestId } from "@testing-library/dom"; import { cssToObject } from "@uppercod/css-to-object"; -import { - MIN_CARD_WIDTH, - radiansToDegrees, - renderTopLanguages, - calculateCompactLayoutHeight, - calculateNormalLayoutHeight, - trimTopLanguages, -} from "../src/cards/top-languages-card.js"; import { getLongestLang, degreesToRadians, + radiansToDegrees, polarToCartesian, cartesianToPolar, + calculateCompactLayoutHeight, + calculateNormalLayoutHeight, + calculatePieLayoutHeight, + doughnutCenterTranslation, + trimTopLanguages, + renderTopLanguages, + MIN_CARD_WIDTH, } from "../src/cards/top-languages-card.js"; // adds special assertions like toHaveTextContent @@ -179,6 +179,34 @@ describe("Test renderTopLanguages helper functions", () => { expect(calculateNormalLayoutHeight(10)).toBe(485); }); + it("calculatePieLayoutHeight", () => { + expect(calculatePieLayoutHeight(0)).toBe(215); + expect(calculatePieLayoutHeight(1)).toBe(215); + expect(calculatePieLayoutHeight(2)).toBe(215); + expect(calculatePieLayoutHeight(3)).toBe(215); + expect(calculatePieLayoutHeight(4)).toBe(215); + expect(calculatePieLayoutHeight(5)).toBe(215); + expect(calculatePieLayoutHeight(6)).toBe(247); + expect(calculatePieLayoutHeight(7)).toBe(279); + expect(calculatePieLayoutHeight(8)).toBe(311); + expect(calculatePieLayoutHeight(9)).toBe(343); + expect(calculatePieLayoutHeight(10)).toBe(375); + }); + + it("doughnutCenterTranslation", () => { + expect(doughnutCenterTranslation(0)).toBe(-45); + expect(doughnutCenterTranslation(1)).toBe(-45); + expect(doughnutCenterTranslation(2)).toBe(-45); + expect(doughnutCenterTranslation(3)).toBe(-45); + expect(doughnutCenterTranslation(4)).toBe(-45); + expect(doughnutCenterTranslation(5)).toBe(-45); + expect(doughnutCenterTranslation(6)).toBe(-29); + expect(doughnutCenterTranslation(7)).toBe(-13); + expect(doughnutCenterTranslation(8)).toBe(3); + expect(doughnutCenterTranslation(9)).toBe(19); + expect(doughnutCenterTranslation(10)).toBe(35); + }); + it("trimTopLanguages", () => { expect(trimTopLanguages([])).toStrictEqual({ langs: [], @@ -474,6 +502,23 @@ describe("Test renderTopLanguages", () => { expect(cssLangPercent).toBeCloseTo(20); expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100); + + // Should render full doughnut (circle) if one language is 100%. + document.body.innerHTML = renderTopLanguages( + { HTML: langs.HTML }, + { layout: "pie" }, + ); + expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( + "HTML 100.00%", + ); + expect(queryAllByTestId(document.body, "lang-doughnut")[0]).toHaveAttribute( + "size", + "100", + ); + expect(queryAllByTestId(document.body, "lang-doughnut")).toHaveLength(1); + expect(queryAllByTestId(document.body, "lang-doughnut")[0].tagName).toBe( + "circle", + ); }); it("should render a translated title", () => { From 928394206a95ccea6a62af9cadac3ec7f2ed515f Mon Sep 17 00:00:00 2001 From: arndom Date: Tue, 9 May 2023 18:00:38 +0100 Subject: [PATCH 13/16] rename layout pie to donut --- readme.md | 6 +++--- src/cards/top-languages-card.js | 4 ++-- src/cards/types.d.ts | 2 +- tests/renderTopLanguages.test.js | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 06811becec1ca..76dd1a35a8a07 100644 --- a/readme.md +++ b/readme.md @@ -425,10 +425,10 @@ You can use the `&layout=compact` option to change the card design. ### Pie Chart Language Card Layout -You can use the `&layout=pie` option to change the card design. +You can use the `&layout=donut` option to change the card design. ```md -[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats) +[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats) ``` ### Hide Progress Bars @@ -449,7 +449,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro - Pie Chart layout -[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats) +[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats) - Hidden progress bars diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index cf19daf1e4b94..03764d6bdb6e3 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -105,7 +105,7 @@ const calculateNormalLayoutHeight = (totalLangs) => { }; /** - * Calculates height for the pie layout. + * Calculates height for the donut layout. * * @param {number} totalLangs Total number of languages. * @returns {number} Card height. @@ -515,7 +515,7 @@ const renderTopLanguages = (topLangs, options = {}) => { totalLanguageSize, hide_progress, ); - } else if (layout?.toLowerCase() === "pie") { + } else if (layout?.toLowerCase() === "donut") { height = calculatePieLayoutHeight(langs.length); width = width + 50; // padding finalLayout = renderDoughnutLayout(langs, width, totalLanguageSize); diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 3a4ab5e5d31cc..fea5aa954222c 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -39,7 +39,7 @@ export type TopLangOptions = CommonOptions & { hide_border: boolean; card_width: number; hide: string[]; - layout: "compact" | "normal" | "pie"; + layout: "compact" | "normal" | "donut"; custom_title: string; langs_count: number; disable_animations: boolean; diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index d925138b2081c..404a2ad64a8dd 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -446,8 +446,8 @@ describe("Test renderTopLanguages", () => { ); }); - it("should render with layout pie", () => { - document.body.innerHTML = renderTopLanguages(langs, { layout: "pie" }); + it("should render with layout donut", () => { + document.body.innerHTML = renderTopLanguages(langs, { layout: "donut" }); expect(queryByTestId(document.body, "header")).toHaveTextContent( "Most Used Languages", @@ -506,7 +506,7 @@ describe("Test renderTopLanguages", () => { // Should render full doughnut (circle) if one language is 100%. document.body.innerHTML = renderTopLanguages( { HTML: langs.HTML }, - { layout: "pie" }, + { layout: "donut" }, ); expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( "HTML 100.00%", From cee4ad1cac80d9000919c64acc3784064f8fb9a2 Mon Sep 17 00:00:00 2001 From: arndom Date: Tue, 9 May 2023 19:33:47 +0100 Subject: [PATCH 14/16] add animation to donut layout --- src/cards/top-languages-card.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 03764d6bdb6e3..1c642519e29a9 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -264,10 +264,11 @@ const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => { */ const createDoughnutLanguagesNode = ({ langs, totalSize }) => { return flexLayout({ - items: langs.map((lang) => { + items: langs.map((lang, index) => { return createCompactLangNode({ lang, - totalSize: totalSize, + totalSize, + index, }); }), gap: 32, @@ -426,14 +427,17 @@ const renderDoughnutLayout = (langs, width, totalLanguageSize) => { langs.length === 1 ? `` : langPaths - .map((section, i) => { + .map((section, index) => { + const staggerDelay = (index + 3) * 150; + const delay = staggerDelay + 300; + const output = ` - + From 4360826ed5d6cddeeb21a79d42bd0c6949cb55a2 Mon Sep 17 00:00:00 2001 From: rickstaa Date: Tue, 9 May 2023 20:45:47 +0200 Subject: [PATCH 15/16] refactor: rename pie and doughnut to donut --- readme.md | 4 +- src/cards/top-languages-card.js | 56 +++++++++++----------- tests/renderTopLanguages.test.js | 80 ++++++++++++++++---------------- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/readme.md b/readme.md index 76dd1a35a8a07..5f3c125476343 100644 --- a/readme.md +++ b/readme.md @@ -423,7 +423,7 @@ You can use the `&layout=compact` option to change the card design. [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats) ``` -### Pie Chart Language Card Layout +### Donut Chart Language Card Layout You can use the `&layout=donut` option to change the card design. @@ -447,7 +447,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats) -- Pie Chart layout +- Donut Chart layout [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 1c642519e29a9..824e03220e772 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -110,16 +110,16 @@ const calculateNormalLayoutHeight = (totalLangs) => { * @param {number} totalLangs Total number of languages. * @returns {number} Card height. */ -const calculatePieLayoutHeight = (totalLangs) => { +const calculateDonutLayoutHeight = (totalLangs) => { return 215 + Math.max(totalLangs - 5, 0) * 32; }; /** - * Calculates the center translation needed to keep the doughnut chart centred. + * Calculates the center translation needed to keep the donut chart centred. * @param {number} totalLangs Total number of languages. - * @returns {number} Doughnut center translation. + * @returns {number} Donut center translation. */ -const doughnutCenterTranslation = (totalLangs) => { +const donutCenterTranslation = (totalLangs) => { return -45 + Math.max(totalLangs - 5, 0) * 16; }; @@ -255,14 +255,14 @@ const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => { }; /** - * Create doughnut languages text items for all programming languages. + * Create donut languages text items for all programming languages. * * @param {object[]} props Function properties. * @param {Lang[]} props.langs Array of programming languages. * @param {number} props.totalSize Total size of all languages. - * @returns {string} Doughnut layout programming language SVG node. + * @returns {string} Donut layout programming language SVG node. */ -const createDoughnutLanguagesNode = ({ langs, totalSize }) => { +const createDonutLanguagesNode = ({ langs, totalSize }) => { return flexLayout({ items: langs.map((lang, index) => { return createCompactLangNode({ @@ -361,15 +361,15 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => { }; /** - * Creates the SVG paths for the language doughnut chart. + * Creates the SVG paths for the language donut chart. * - * @param {number} cx Doughnut center x-position. - * @param {number} cy Doughnut center y-position. - * @param {number} radius Doughnut arc Radius. - * @param {number[]} percentages Array with doughnut section percentages. + * @param {number} cx Donut center x-position. + * @param {number} cy Donut center y-position. + * @param {number} radius Donut arc Radius. + * @param {number[]} percentages Array with donut section percentages. * @returns {{d: string, percent: number}[]} Array of svg path elements */ -const createDoughnutPaths = (cx, cy, radius, percentages) => { +const createDonutPaths = (cx, cy, radius, percentages) => { const paths = []; let startAngle = 0; let endAngle = 0; @@ -383,8 +383,8 @@ const createDoughnutPaths = (cx, cy, radius, percentages) => { ); endAngle = 3.6 * percent + startAngle; - const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate doughnut 90 degrees counter-clockwise. - const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate doughnut 90 degrees counter-clockwise. + const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate donut 90 degrees counter-clockwise. + const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate donut 90 degrees counter-clockwise. const largeArc = endAngle - startAngle <= 180 ? 0 : 1; tmpPath.percent = percent; @@ -398,14 +398,14 @@ const createDoughnutPaths = (cx, cy, radius, percentages) => { }; /** - * Renders the doughnut language card layout. + * Renders the donut language card layout. * * @param {Lang[]} langs Array of programming languages. * @param {number} width Card width. * @param {number} totalLanguageSize Total size of all languages. * @returns {string} Donut layout card SVG object. */ -const renderDoughnutLayout = (langs, width, totalLanguageSize) => { +const renderDonutLayout = (langs, width, totalLanguageSize) => { const centerX = width / 3; const centerY = width / 3; const radius = centerX - 60; @@ -416,16 +416,16 @@ const renderDoughnutLayout = (langs, width, totalLanguageSize) => { parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)), ); - const langPaths = createDoughnutPaths( + const langPaths = createDonutPaths( centerX, centerY, radius, langsPercents, ); - const doughnutPaths = + const donutPaths = langs.length === 1 - ? `` + ? `` : langPaths .map((section, index) => { const staggerDelay = (index + 3) * 150; @@ -434,7 +434,7 @@ const renderDoughnutLayout = (langs, width, totalLanguageSize) => { const output = ` { }) .join(""); - const donut = `${doughnutPaths}`; + const donut = `${donutPaths}`; return ` - ${createDoughnutLanguagesNode({ langs, totalSize: totalLanguageSize })} + ${createDonutLanguagesNode({ langs, totalSize: totalLanguageSize })} - + ${donut} @@ -520,9 +520,9 @@ const renderTopLanguages = (topLangs, options = {}) => { hide_progress, ); } else if (layout?.toLowerCase() === "donut") { - height = calculatePieLayoutHeight(langs.length); + height = calculateDonutLayoutHeight(langs.length); width = width + 50; // padding - finalLayout = renderDoughnutLayout(langs, width, totalLanguageSize); + finalLayout = renderDonutLayout(langs, width, totalLanguageSize); } else { finalLayout = renderNormalLayout(langs, width, totalLanguageSize); } @@ -599,8 +599,8 @@ export { cartesianToPolar, calculateCompactLayoutHeight, calculateNormalLayoutHeight, - calculatePieLayoutHeight, - doughnutCenterTranslation, + calculateDonutLayoutHeight, + donutCenterTranslation, trimTopLanguages, renderTopLanguages, MIN_CARD_WIDTH, diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index 404a2ad64a8dd..e4f47c396b80b 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -8,8 +8,8 @@ import { cartesianToPolar, calculateCompactLayoutHeight, calculateNormalLayoutHeight, - calculatePieLayoutHeight, - doughnutCenterTranslation, + calculateDonutLayoutHeight, + donutCenterTranslation, trimTopLanguages, renderTopLanguages, MIN_CARD_WIDTH, @@ -39,10 +39,10 @@ const langs = { }; /** - * Retrieve the language percentage from the doughnut chart SVG. + * Retrieve the language percentage from the donut chart SVG. * @param {string} d The SVG path element. - * @param {number} centerX The center X coordinate of the doughnut chart. - * @param {number} centerY The center Y coordinate of the doughnut chart. + * @param {number} centerX The center X coordinate of the donut chart. + * @param {number} centerY The center Y coordinate of the donut chart. * @returns {number} The percentage of the language. */ const langPercentFromSvg = (d, centerX, centerY) => { @@ -179,32 +179,32 @@ describe("Test renderTopLanguages helper functions", () => { expect(calculateNormalLayoutHeight(10)).toBe(485); }); - it("calculatePieLayoutHeight", () => { - expect(calculatePieLayoutHeight(0)).toBe(215); - expect(calculatePieLayoutHeight(1)).toBe(215); - expect(calculatePieLayoutHeight(2)).toBe(215); - expect(calculatePieLayoutHeight(3)).toBe(215); - expect(calculatePieLayoutHeight(4)).toBe(215); - expect(calculatePieLayoutHeight(5)).toBe(215); - expect(calculatePieLayoutHeight(6)).toBe(247); - expect(calculatePieLayoutHeight(7)).toBe(279); - expect(calculatePieLayoutHeight(8)).toBe(311); - expect(calculatePieLayoutHeight(9)).toBe(343); - expect(calculatePieLayoutHeight(10)).toBe(375); + it("calculateDonutLayoutHeight", () => { + expect(calculateDonutLayoutHeight(0)).toBe(215); + expect(calculateDonutLayoutHeight(1)).toBe(215); + expect(calculateDonutLayoutHeight(2)).toBe(215); + expect(calculateDonutLayoutHeight(3)).toBe(215); + expect(calculateDonutLayoutHeight(4)).toBe(215); + expect(calculateDonutLayoutHeight(5)).toBe(215); + expect(calculateDonutLayoutHeight(6)).toBe(247); + expect(calculateDonutLayoutHeight(7)).toBe(279); + expect(calculateDonutLayoutHeight(8)).toBe(311); + expect(calculateDonutLayoutHeight(9)).toBe(343); + expect(calculateDonutLayoutHeight(10)).toBe(375); }); - it("doughnutCenterTranslation", () => { - expect(doughnutCenterTranslation(0)).toBe(-45); - expect(doughnutCenterTranslation(1)).toBe(-45); - expect(doughnutCenterTranslation(2)).toBe(-45); - expect(doughnutCenterTranslation(3)).toBe(-45); - expect(doughnutCenterTranslation(4)).toBe(-45); - expect(doughnutCenterTranslation(5)).toBe(-45); - expect(doughnutCenterTranslation(6)).toBe(-29); - expect(doughnutCenterTranslation(7)).toBe(-13); - expect(doughnutCenterTranslation(8)).toBe(3); - expect(doughnutCenterTranslation(9)).toBe(19); - expect(doughnutCenterTranslation(10)).toBe(35); + it("donutCenterTranslation", () => { + expect(donutCenterTranslation(0)).toBe(-45); + expect(donutCenterTranslation(1)).toBe(-45); + expect(donutCenterTranslation(2)).toBe(-45); + expect(donutCenterTranslation(3)).toBe(-45); + expect(donutCenterTranslation(4)).toBe(-45); + expect(donutCenterTranslation(5)).toBe(-45); + expect(donutCenterTranslation(6)).toBe(-29); + expect(donutCenterTranslation(7)).toBe(-13); + expect(donutCenterTranslation(8)).toBe(3); + expect(donutCenterTranslation(9)).toBe(19); + expect(donutCenterTranslation(10)).toBe(35); }); it("trimTopLanguages", () => { @@ -456,18 +456,18 @@ describe("Test renderTopLanguages", () => { expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( "HTML 40.00%", ); - expect(queryAllByTestId(document.body, "lang-doughnut")[0]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute( "size", "40", ); - const d = queryAllByTestId(document.body, "lang-doughnut")[0] + const d = queryAllByTestId(document.body, "lang-donut")[0] .getAttribute("d") .split(" ") .filter((x) => !isNaN(x)) .map((x) => parseFloat(x)); const center = { x: d[7], y: d[7] }; const HTMLLangPercent = langPercentFromSvg( - queryAllByTestId(document.body, "lang-doughnut")[0].getAttribute("d"), + queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"), center.x, center.y, ); @@ -476,12 +476,12 @@ describe("Test renderTopLanguages", () => { expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent( "javascript 40.00%", ); - expect(queryAllByTestId(document.body, "lang-doughnut")[1]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-donut")[1]).toHaveAttribute( "size", "40", ); const javascriptLangPercent = langPercentFromSvg( - queryAllByTestId(document.body, "lang-doughnut")[1].getAttribute("d"), + queryAllByTestId(document.body, "lang-donut")[1].getAttribute("d"), center.x, center.y, ); @@ -490,12 +490,12 @@ describe("Test renderTopLanguages", () => { expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent( "css 20.00%", ); - expect(queryAllByTestId(document.body, "lang-doughnut")[2]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-donut")[2]).toHaveAttribute( "size", "20", ); const cssLangPercent = langPercentFromSvg( - queryAllByTestId(document.body, "lang-doughnut")[2].getAttribute("d"), + queryAllByTestId(document.body, "lang-donut")[2].getAttribute("d"), center.x, center.y, ); @@ -503,7 +503,7 @@ describe("Test renderTopLanguages", () => { expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100); - // Should render full doughnut (circle) if one language is 100%. + // Should render full donut (circle) if one language is 100%. document.body.innerHTML = renderTopLanguages( { HTML: langs.HTML }, { layout: "donut" }, @@ -511,12 +511,12 @@ describe("Test renderTopLanguages", () => { expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent( "HTML 100.00%", ); - expect(queryAllByTestId(document.body, "lang-doughnut")[0]).toHaveAttribute( + expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute( "size", "100", ); - expect(queryAllByTestId(document.body, "lang-doughnut")).toHaveLength(1); - expect(queryAllByTestId(document.body, "lang-doughnut")[0].tagName).toBe( + expect(queryAllByTestId(document.body, "lang-donut")).toHaveLength(1); + expect(queryAllByTestId(document.body, "lang-donut")[0].tagName).toBe( "circle", ); }); From e11894393795a6c6bce62a09eea9577f6966b837 Mon Sep 17 00:00:00 2001 From: rickstaa Date: Tue, 9 May 2023 20:52:14 +0200 Subject: [PATCH 16/16] feat: decrease donus animation delay --- src/cards/top-languages-card.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 824e03220e772..262ae972a4002 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -416,19 +416,14 @@ const renderDonutLayout = (langs, width, totalLanguageSize) => { parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)), ); - const langPaths = createDonutPaths( - centerX, - centerY, - radius, - langsPercents, - ); + const langPaths = createDonutPaths(centerX, centerY, radius, langsPercents); const donutPaths = langs.length === 1 ? `` : langPaths .map((section, index) => { - const staggerDelay = (index + 3) * 150; + const staggerDelay = (index + 3) * 100; const delay = staggerDelay + 300; const output = `