diff --git a/.vscode/settings.json b/.vscode/settings.json index d49e7fe1..8e17eb17 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,9 @@ "source.organizeImports": true, "source.fixAll.eslint": true } - } + }, + "typescript.format.semicolons": "remove", + "editor.insertSpaces": false, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true } diff --git a/package-lock.json b/package-lock.json index 28e4d006..a6512ae5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "deepslate": "^0.9.0-beta.13", "deepslate-1.18": "npm:deepslate@^0.9.0-beta.9", "deepslate-rs": "^0.1.6", + "highlight.js": "^11.5.1", "howler": "^2.2.3", "js-yaml": "^3.14.1", "lz-string": "^1.4.4", @@ -45,11 +46,12 @@ "@typescript-eslint/parser": "^4.25.0", "cypress": "^9.2.0", "eslint": "^7.27.0", + "fast-glob": "^3.2.11", "preact": "^10.5.13", "preact-router": "^3.2.1", - "rollup-plugin-copy": "^3.4.0", "typescript": "^4.1.3", - "vite": "^2.3.7" + "vite": "^2.3.7", + "vite-plugin-static-copy": "^0.5.0" } }, "@mcschema/java-1.18@0.3.0-beta": { @@ -584,25 +586,6 @@ "rollup": "^1.20.0||^2.0.0" } }, - "node_modules/@types/fs-extra": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", - "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "node_modules/@types/google.analytics": { "version": "0.0.40", "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz", @@ -639,17 +622,12 @@ "integrity": "sha512-ZigEmCWdNUU7IjZEuQ/iaimYdDHWHfTe3kg8ORfKjyGYd9RWumPoOJRQXB0bO+XLkNwzCthW3wUIQtANaEZ1ag==", "dev": true }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, "node_modules/@types/node": { "version": "16.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz", "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ==", - "dev": true + "dev": true, + "optional": true }, "node_modules/@types/seedrandom": { "version": "2.4.28", @@ -973,6 +951,19 @@ "node": ">=4" } }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -1121,6 +1112,15 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -1280,6 +1280,33 @@ "node": ">= 0.8.0" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -1831,13 +1858,358 @@ } }, "node_modules/esbuild": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.7.tgz", - "integrity": "sha512-vxENKWBo928ErLiT/uUv8Sl2EoC5cF3cZzCTc8hDEh9ZAZ75xblJCr72NeJo74lxWaGopIePZPIWq1qDpLUHQQ==", + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz", + "integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.38", + "esbuild-android-arm64": "0.14.38", + "esbuild-darwin-64": "0.14.38", + "esbuild-darwin-arm64": "0.14.38", + "esbuild-freebsd-64": "0.14.38", + "esbuild-freebsd-arm64": "0.14.38", + "esbuild-linux-32": "0.14.38", + "esbuild-linux-64": "0.14.38", + "esbuild-linux-arm": "0.14.38", + "esbuild-linux-arm64": "0.14.38", + "esbuild-linux-mips64le": "0.14.38", + "esbuild-linux-ppc64le": "0.14.38", + "esbuild-linux-riscv64": "0.14.38", + "esbuild-linux-s390x": "0.14.38", + "esbuild-netbsd-64": "0.14.38", + "esbuild-openbsd-64": "0.14.38", + "esbuild-sunos-64": "0.14.38", + "esbuild-windows-32": "0.14.38", + "esbuild-windows-64": "0.14.38", + "esbuild-windows-arm64": "0.14.38" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz", + "integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz", + "integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz", + "integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz", + "integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz", + "integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz", + "integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz", + "integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz", + "integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz", + "integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz", + "integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz", + "integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz", + "integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz", + "integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz", + "integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz", + "integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz", + "integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz", + "integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz", + "integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz", + "integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz", + "integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, "node_modules/escalade": { @@ -2283,9 +2655,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2295,7 +2667,7 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { @@ -2409,20 +2781,6 @@ "node": ">= 0.12" } }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2622,6 +2980,14 @@ "node": ">=8" } }, + "node_modules/highlight.js": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.5.1.tgz", + "integrity": "sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/howler": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.3.tgz", @@ -2737,6 +3103,18 @@ "node": ">=10" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -2755,9 +3133,9 @@ } }, "node_modules/is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -2830,15 +3208,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2955,15 +3324,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -3357,9 +3717,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -3380,6 +3740,15 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -3524,6 +3893,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -3546,21 +3921,27 @@ } }, "node_modules/postcss": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", - "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map-js": "^0.6.2" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" } }, "node_modules/preact": { @@ -3709,6 +4090,18 @@ "react": "17.0.2" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -3748,13 +4141,17 @@ } }, "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3813,9 +4210,9 @@ } }, "node_modules/rollup": { - "version": "2.51.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.1.tgz", - "integrity": "sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw==", + "version": "2.70.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.2.tgz", + "integrity": "sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -3824,51 +4221,7 @@ "node": ">=10.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/rollup-plugin-copy": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", - "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", - "dev": true, - "dependencies": { - "@types/fs-extra": "^8.0.1", - "colorette": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "10.0.1", - "is-plain-object": "^3.0.0" - }, - "engines": { - "node": ">=8.3" - } - }, - "node_modules/rollup-plugin-copy/node_modules/globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rollup-plugin-copy/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" + "fsevents": "~2.3.2" } }, "node_modules/run-parallel": { @@ -4036,9 +4389,9 @@ } }, "node_modules/source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4149,6 +4502,18 @@ "node": ">=4" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/table": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", @@ -4328,15 +4693,6 @@ "node": ">=4.2.0" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -4407,24 +4763,93 @@ "dev": true }, "node_modules/vite": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.3.7.tgz", - "integrity": "sha512-Y0xRz11MPYu/EAvzN94+FsOZHbSvO6FUvHv127CyG7mV6oDoay2bw+g5y9wW3Blf8OY3chaz3nc/DcRe1IQ3Nw==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.6.tgz", + "integrity": "sha512-3IffdrByHW95Yjv0a13TQOQfJs7L5dVlSPuTt432XLbRMriWbThqJN2k/IS6kXn5WY4xBLhK9XoaWay1B8VzUw==", "dev": true, "dependencies": { - "esbuild": "^0.12.5", - "postcss": "^8.3.0", - "resolve": "^1.19.0", - "rollup": "^2.38.5" + "esbuild": "^0.14.27", + "postcss": "^8.4.12", + "resolve": "^1.22.0", + "rollup": "^2.59.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": ">=12.0.0" + "node": ">=12.2.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vite-plugin-static-copy": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.5.0.tgz", + "integrity": "sha512-SqqG2MUfdMOLOiSL5iwQVq2aO8lAR/Xft6tODQFFrqijm3US0YPyshlTczP0KmzaUwwXgztw+iU3yVE3XCnXkQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "fast-glob": "^3.2.11", + "fs-extra": "^10.0.1", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=12.2" + }, + "peerDependencies": { + "vite": "^2.6.14" + } + }, + "node_modules/vite-plugin-static-copy/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-static-copy/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/vite-plugin-static-copy/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" } }, "node_modules/which": { @@ -4991,25 +5416,6 @@ "picomatch": "^2.2.2" } }, - "@types/fs-extra": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", - "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "@types/google.analytics": { "version": "0.0.40", "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz", @@ -5046,17 +5452,12 @@ "integrity": "sha512-ZigEmCWdNUU7IjZEuQ/iaimYdDHWHfTe3kg8ORfKjyGYd9RWumPoOJRQXB0bO+XLkNwzCthW3wUIQtANaEZ1ag==", "dev": true }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, "@types/node": { "version": "16.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz", "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ==", - "dev": true + "dev": true, + "optional": true }, "@types/seedrandom": { "version": "2.4.28", @@ -5264,6 +5665,16 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -5367,6 +5778,12 @@ "tweetnacl": "^0.14.3" } }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -5477,6 +5894,22 @@ "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", "dev": true }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, "ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -5918,10 +6351,172 @@ } }, "esbuild": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.7.tgz", - "integrity": "sha512-vxENKWBo928ErLiT/uUv8Sl2EoC5cF3cZzCTc8hDEh9ZAZ75xblJCr72NeJo74lxWaGopIePZPIWq1qDpLUHQQ==", - "dev": true + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz", + "integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.38", + "esbuild-android-arm64": "0.14.38", + "esbuild-darwin-64": "0.14.38", + "esbuild-darwin-arm64": "0.14.38", + "esbuild-freebsd-64": "0.14.38", + "esbuild-freebsd-arm64": "0.14.38", + "esbuild-linux-32": "0.14.38", + "esbuild-linux-64": "0.14.38", + "esbuild-linux-arm": "0.14.38", + "esbuild-linux-arm64": "0.14.38", + "esbuild-linux-mips64le": "0.14.38", + "esbuild-linux-ppc64le": "0.14.38", + "esbuild-linux-riscv64": "0.14.38", + "esbuild-linux-s390x": "0.14.38", + "esbuild-netbsd-64": "0.14.38", + "esbuild-openbsd-64": "0.14.38", + "esbuild-sunos-64": "0.14.38", + "esbuild-windows-32": "0.14.38", + "esbuild-windows-64": "0.14.38", + "esbuild-windows-arm64": "0.14.38" + } + }, + "esbuild-android-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz", + "integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz", + "integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz", + "integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz", + "integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz", + "integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz", + "integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz", + "integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz", + "integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz", + "integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz", + "integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz", + "integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz", + "integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz", + "integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz", + "integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz", + "integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz", + "integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz", + "integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz", + "integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz", + "integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.38", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz", + "integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==", + "dev": true, + "optional": true }, "escalade": { "version": "3.1.1", @@ -6247,9 +6842,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -6349,17 +6944,6 @@ "mime-types": "^2.1.12" } }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -6509,6 +7093,11 @@ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==" }, + "highlight.js": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.5.1.tgz", + "integrity": "sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==" + }, "howler": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.3.tgz", @@ -6586,6 +7175,15 @@ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -6601,9 +7199,9 @@ } }, "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "requires": { "has": "^1.0.3" @@ -6652,12 +7250,6 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6747,15 +7339,6 @@ "minimist": "^1.2.5" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -7057,9 +7640,9 @@ "dev": true }, "nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true }, "natural-compare": { @@ -7074,6 +7657,12 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -7185,6 +7774,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -7198,14 +7793,14 @@ "dev": true }, "postcss": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", - "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map-js": "^0.6.2" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, "preact": { @@ -7306,6 +7901,15 @@ "scheduler": "^0.20.2" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -7333,13 +7937,14 @@ "dev": true }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { @@ -7379,49 +7984,12 @@ } }, "rollup": { - "version": "2.51.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.1.tgz", - "integrity": "sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw==", + "version": "2.70.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.2.tgz", + "integrity": "sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg==", "dev": true, "requires": { - "fsevents": "~2.3.1" - } - }, - "rollup-plugin-copy": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", - "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", - "dev": true, - "requires": { - "@types/fs-extra": "^8.0.1", - "colorette": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "10.0.1", - "is-plain-object": "^3.0.0" - }, - "dependencies": { - "globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - } + "fsevents": "~2.3.2" } }, "run-parallel": { @@ -7549,9 +8117,9 @@ "dev": true }, "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "sourcemapped-stacktrace": { @@ -7632,6 +8200,12 @@ "has-flag": "^3.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, "table": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", @@ -7769,12 +8343,6 @@ "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", "dev": true }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -7840,16 +8408,57 @@ } }, "vite": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.3.7.tgz", - "integrity": "sha512-Y0xRz11MPYu/EAvzN94+FsOZHbSvO6FUvHv127CyG7mV6oDoay2bw+g5y9wW3Blf8OY3chaz3nc/DcRe1IQ3Nw==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.6.tgz", + "integrity": "sha512-3IffdrByHW95Yjv0a13TQOQfJs7L5dVlSPuTt432XLbRMriWbThqJN2k/IS6kXn5WY4xBLhK9XoaWay1B8VzUw==", "dev": true, "requires": { - "esbuild": "^0.12.5", - "fsevents": "~2.3.1", - "postcss": "^8.3.0", - "resolve": "^1.19.0", - "rollup": "^2.38.5" + "esbuild": "^0.14.27", + "fsevents": "~2.3.2", + "postcss": "^8.4.12", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + } + }, + "vite-plugin-static-copy": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.5.0.tgz", + "integrity": "sha512-SqqG2MUfdMOLOiSL5iwQVq2aO8lAR/Xft6tODQFFrqijm3US0YPyshlTczP0KmzaUwwXgztw+iU3yVE3XCnXkQ==", + "dev": true, + "requires": { + "chokidar": "^3.5.3", + "fast-glob": "^3.2.11", + "fs-extra": "^10.0.1", + "picocolors": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } } }, "which": { diff --git a/package.json b/package.json index 25e34c5e..e7090ba6 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "deepslate": "^0.9.0-beta.13", "deepslate-1.18": "npm:deepslate@^0.9.0-beta.9", "deepslate-rs": "^0.1.6", + "highlight.js": "^11.5.1", "howler": "^2.2.3", "js-yaml": "^3.14.1", "lz-string": "^1.4.4", @@ -51,10 +52,11 @@ "@typescript-eslint/parser": "^4.25.0", "cypress": "^9.2.0", "eslint": "^7.27.0", + "fast-glob": "^3.2.11", "preact": "^10.5.13", "preact-router": "^3.2.1", - "rollup-plugin-copy": "^3.4.0", "typescript": "^4.1.3", - "vite": "^2.3.7" + "vite": "^2.3.7", + "vite-plugin-static-copy": "^0.5.0" } } diff --git a/src/app/App.tsx b/src/app/App.tsx index dce6453d..e6c0017e 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -4,11 +4,12 @@ import '../styles/global.css' import '../styles/nodes.css' import { Analytics } from './Analytics' import { Header } from './components' -import { Category, Changelog, Generator, Home, Project, Sounds, Versions } from './pages' +import { Category, Changelog, Generator, Guide, Guides, Home, Project, Sounds, Versions } from './pages' import { cleanUrl } from './Utils' export function App() { const changeRoute = (e: RouterOnChangeArgs) => { + window.dispatchEvent(new CustomEvent('replacestate')) // Needs a timeout to ensure the title is set correctly setTimeout(() => Analytics.pageview(cleanUrl(e.url))) } @@ -23,6 +24,8 @@ export function App() { + + diff --git a/src/app/Utils.ts b/src/app/Utils.ts index c8329430..d7223ca9 100644 --- a/src/app/Utils.ts +++ b/src/app/Utils.ts @@ -1,6 +1,7 @@ import type { DataModel } from '@mcschema/core' import { Path } from '@mcschema/core' -import { getCurrentUrl, route } from 'preact-router' +import yaml from 'js-yaml' +import { route } from 'preact-router' import rfdc from 'rfdc' import config from '../config.json' @@ -8,7 +9,7 @@ export function isPromise(obj: any): obj is Promise { return typeof (obj as any)?.then === 'function' } -export function isObject(obj: any) { +export function isObject(obj: any): obj is Record { return typeof obj === 'object' && obj !== null } @@ -68,29 +69,79 @@ export function getGenerator(url: string) { return config.generators.find(g => g.url === trimmedUrl) } -export function getSearchParams(url: string) { - const searchIndex = url.indexOf('?') - if (searchIndex >= 0) { - url = url.slice(searchIndex + 1) - return new Map(url.split('&').map<[string, string]>(param => { - const index = param.indexOf('=') - if (index === -1) return [param, 'true'] - return [decodeURIComponent(param.slice(0, index)), decodeURIComponent(param.slice(index + 1))] - })) - } - return new Map() +export function changeUrl({ path, search, hash, replace }: { path?: string, search?: string, hash?: string, replace?: boolean }) { + const url = (path !== undefined ? cleanUrl(path) : location.pathname) + + (search !== undefined ? (search.startsWith('?') || search.length === 0 ? search : '?' + search) : location.search) + + (hash !== undefined ? (hash.startsWith('#') ? hash : '#' + hash) : location.hash) + route(url, replace) } -export function setSeachParams(modifications: Record, newPath?: string) { - const url = getCurrentUrl() - const searchParams = getSearchParams(url) - Object.entries(modifications).forEach(([key, value]) => { - if (value === undefined) searchParams.delete(key) - else searchParams.set(key, value) - }) - const search = Array.from(searchParams).map(([key, value]) => - `${encodeURIComponent(key)}=${encodeURIComponent(value).replaceAll('%2F', '/')}`) - route(`${newPath ? cleanUrl(newPath) : getPath(url)}${search.length === 0 ? '' : `?${search.join('&')}`}`, true) +export function parseFrontMatter(source: string): Record { + const data = yaml.load(source.substring(3, source.indexOf('---', 3))) + if (!isObject(data)) return {} + return data +} + +export function versionContent(content: string, version: string) { + let cursor = 0 + while (true) { + const start = content.indexOf('{#', cursor) + if (start < 0) { + break + } + const end = findMatchingClose(content, start + 2) + const vStart = content.indexOf('#[', start + 1) + let sub = '' + if (vStart >= 0 && vStart < end) { + const vEnd = content.indexOf(']', vStart + 2) + const v = content.substring(vStart + 2, vEnd) + if (v === version) { + sub = content.substring(vEnd + 1, end).trim() + } + } else { + const key = content.substring(start + 2, end) + const versionConfig = config.versions.find(v => v.id === version) + sub = ({ + version: versionConfig?.id, + pack_format: versionConfig?.pack_format.toString(), + } as Record)[key] ?? '' + } + content = content.substring(0, start) + sub + content.substring(end + 2) + cursor = start + + } + return content +} + +function findMatchingClose(source: string, index: number) { + let depth = 0 + let iteration = 0 + while (iteration++ < 1000) { + const close = source.indexOf('#}', index) + const open = source.indexOf('{#', index) + if (close < 0) { + console.warn('Missing closing bracket') + return source.length + } + if (open < 0) { + if (depth === 0) { + return close + } else { + depth -= 1 + index = close + 2 + } + } else if (open < close) { + depth += 1 + index = open + 2 + } else if (depth === 0) { + return close + } else { + depth -= 1 + index = close + 2 + } + } + console.warn('Exceeded max iterations while finding closing bracket') + return source.length } export function stringToColor(str: string): [number, number, number] { diff --git a/src/app/components/Giscus.tsx b/src/app/components/Giscus.tsx index 8d82f204..cfc758d7 100644 --- a/src/app/components/Giscus.tsx +++ b/src/app/components/Giscus.tsx @@ -9,7 +9,7 @@ export function Giscus({ term }: Props) { const themeSuffix = actualTheme === 'light' ? '-burn' : '' const themeUrl = (import.meta as any).env.DEV ? `http://localhost:3000/src/styles/giscus${themeSuffix}.css` - : `https://${location.host}/assets/giscus${themeSuffix}.css` + : `${location.protocol}//${location.host}/assets/giscus${themeSuffix}.css` return unknown, +} +export function GuideCard({ title, link, versions, tags, activeTags, toggleTag }: Props) { + const onToggleTag = (tag: string) => (e: MouseEvent) => { + if (toggleTag) toggleTag(tag) + e.preventDefault() + e.stopImmediatePropagation() + } + + return + {versions.join(' • ')} +

{title}

+
+ {tags.sort().map(tag => )} +
+
+} diff --git a/src/app/components/index.ts b/src/app/components/index.ts index 8470b05e..d858264a 100644 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -6,6 +6,7 @@ export * from './ErrorPanel' export * from './forms' export * from './generator' export * from './Giscus' +export * from './GuideCard' export * from './Header' export * from './Icons' export * from './Octicon' diff --git a/src/app/components/versions/ChangelogList.tsx b/src/app/components/versions/ChangelogList.tsx index 18410758..c4a94593 100644 --- a/src/app/components/versions/ChangelogList.tsx +++ b/src/app/components/versions/ChangelogList.tsx @@ -56,9 +56,9 @@ export function ChangelogList({ changes, defaultOrder }: Props) { }
{sortedChangelogs === undefined - ? {locale('loading')} + ? {locale('loading')} : sortedChangelogs.length === 0 - ? {locale('changelog.no_results')} + ? {locale('changelog.no_results')} : sortedChangelogs.map(change => )}
diff --git a/src/app/components/versions/ChangelogTag.tsx b/src/app/components/versions/ChangelogTag.tsx index 10e75159..88e39a33 100644 --- a/src/app/components/versions/ChangelogTag.tsx +++ b/src/app/components/versions/ChangelogTag.tsx @@ -4,7 +4,7 @@ import { hashString } from '../../Utils' type TagProps = { label: string, active?: boolean, - onClick?: () => unknown, + onClick?: (e: MouseEvent) => unknown, } export function ChangelogTag({ label, active, onClick }: TagProps) { const color = label === 'breaking' ? 5 : hashString(label) % 360 diff --git a/src/app/components/versions/VersionList.tsx b/src/app/components/versions/VersionList.tsx index 9617b83c..a23f7006 100644 --- a/src/app/components/versions/VersionList.tsx +++ b/src/app/components/versions/VersionList.tsx @@ -22,7 +22,7 @@ export function VersionList({ versions, link }: Props) { return <>
-
diff --git a/src/app/contexts/Title.tsx b/src/app/contexts/Title.tsx index 48758194..583f76c1 100644 --- a/src/app/contexts/Title.tsx +++ b/src/app/contexts/Title.tsx @@ -32,7 +32,7 @@ export function TitleProvider({ children }: { children: ComponentChildren }) { const changeTitle = useCallback((title: string, versions?: VersionId[]) => { versions ??= config.versions.map(v => v.id as VersionId) - const titleVersions = versions.slice(versions.length - VERSIONS_IN_TITLE) + const titleVersions = versions.slice(-VERSIONS_IN_TITLE) document.title = `${title} Minecraft ${titleVersions.join(', ')}` setTitle(title) }, []) diff --git a/src/app/contexts/Version.tsx b/src/app/contexts/Version.tsx index 2db2fcab..1f43183d 100644 --- a/src/app/contexts/Version.tsx +++ b/src/app/contexts/Version.tsx @@ -1,22 +1,23 @@ import type { ComponentChildren } from 'preact' import { createContext } from 'preact' -import { getCurrentUrl } from 'preact-router' import { useCallback, useContext, useEffect, useState } from 'preact/hooks' import { Analytics } from '../Analytics' +import { useSearchParam } from '../hooks' import type { VersionId } from '../services' import { VersionIds } from '../services' import { Store } from '../Store' -import { getSearchParams, setSeachParams } from '../Utils' const VERSION_PARAM = 'version' interface Version { version: VersionId, - changeVersion: (version: VersionId, store?: boolean) => unknown, + changeVersion: (version: VersionId, store?: boolean, updateSearch?: boolean) => unknown, + changeTargetVersion: (version: VersionId, replace?: boolean) => unknown, } const Version = createContext({ version: '1.18.2', changeVersion: () => {}, + changeTargetVersion: () => {}, }) export function useVersion() { @@ -26,28 +27,29 @@ export function useVersion() { export function VersionProvider({ children }: { children: ComponentChildren }) { const [version, setVersion] = useState(Store.getVersion()) - const searchParams = getSearchParams(getCurrentUrl()) - const targetVersion = searchParams.get(VERSION_PARAM) + const [targetVersion, changeTargetVersion] = useSearchParam(VERSION_PARAM) + useEffect(() => { if (VersionIds.includes(targetVersion as VersionId) && version !== targetVersion) { setVersion(targetVersion as VersionId) } }, [version, targetVersion]) - const changeVersion = useCallback((version: VersionId, store = true) => { - if (getSearchParams(getCurrentUrl()).has(VERSION_PARAM)) { - setSeachParams({ version }) + const changeVersion = useCallback((newVersion: VersionId, store = true, updateSearch = false) => { + if (updateSearch || targetVersion) { + changeTargetVersion(newVersion, true) } if (store) { - Analytics.setVersion(version) - Store.setVersion(version) + Analytics.setVersion(newVersion) + Store.setVersion(newVersion) } - setVersion(version) - }, []) + setVersion(newVersion) + }, [targetVersion]) const value: Version = { version, changeVersion, + changeTargetVersion, } return diff --git a/src/app/hooks/index.ts b/src/app/hooks/index.ts index 414d3054..f3596569 100644 --- a/src/app/hooks/index.ts +++ b/src/app/hooks/index.ts @@ -1,5 +1,7 @@ export * from './useActiveTimout' export * from './useCanvas' export * from './useFocus' +export * from './useHash' export * from './useMediaQuery' export * from './useModel' +export * from './useSearchParam' diff --git a/src/app/hooks/useHash.ts b/src/app/hooks/useHash.ts new file mode 100644 index 00000000..85d38fec --- /dev/null +++ b/src/app/hooks/useHash.ts @@ -0,0 +1,27 @@ +import { useCallback, useEffect, useState } from 'preact/hooks' +import { changeUrl } from '../Utils' + +export function useHash(): [string, (hash: string) => unknown] { + const [hash, setHash] = useState(window.location.hash) + + const onChange = useCallback(() => { + setHash(window.location.hash) + }, []) + + useEffect(() => { + window.addEventListener('hashchange', onChange) + window.addEventListener('replacestate', onChange) + return () => { + window.removeEventListener('hashchange', onChange) + window.removeEventListener('replacestate', onChange) + } + }, []) + + const changeHash = useCallback((newHash: string) => { + if (newHash !== hash) { + changeUrl({ hash: newHash }) + } + }, [hash]) + + return [hash, changeHash] +} diff --git a/src/app/hooks/useSearchParam.ts b/src/app/hooks/useSearchParam.ts new file mode 100644 index 00000000..fe7961c0 --- /dev/null +++ b/src/app/hooks/useSearchParam.ts @@ -0,0 +1,39 @@ +import { useCallback, useEffect, useState } from 'preact/hooks' +import { changeUrl } from '../Utils' + +const getValue = (search: string, param: string) => new URLSearchParams(search).get(param) ?? undefined + +export function useSearchParam(param: string): [string | undefined, (value: string | undefined, replace?: boolean) => unknown] { + const location = window.location + const [value, setValue] = useState(getValue(location.search, param)) + + useEffect(() => { + const onChange = () => { + setValue(getValue(location.search, param)) + } + + window.addEventListener('popstate', onChange) + window.addEventListener('pushstate', onChange) + window.addEventListener('replacestate', onChange) + + return () => { + window.removeEventListener('popstate', onChange) + window.removeEventListener('pushstate', onChange) + window.removeEventListener('replacestate', onChange) + } + }, []) + + const changeValue = useCallback((newValue: string | undefined, replace?: boolean) => { + if (newValue !== value) { + const params = new URLSearchParams(location.search) + if (newValue === undefined || newValue.length === 0) { + params.delete(param) + } else { + params.set(param, newValue) + } + changeUrl({ search: params.toString().replaceAll('%7C', '|'), replace }) + } + }, [value]) + + return [value, changeValue] +}; diff --git a/src/app/pages/Generator.tsx b/src/app/pages/Generator.tsx index 38c30b5a..9873af74 100644 --- a/src/app/pages/Generator.tsx +++ b/src/app/pages/Generator.tsx @@ -1,23 +1,23 @@ import { DataModel, Path } from '@mcschema/core' import { getCurrentUrl, route } from 'preact-router' -import { useEffect, useErrorBoundary, useMemo, useState } from 'preact/hooks' +import { useEffect, useErrorBoundary, useMemo, useRef, useState } from 'preact/hooks' import config from '../../config.json' import { Analytics } from '../Analytics' import { Ad, Btn, BtnMenu, ErrorPanel, HasPreview, Octicon, PreviewPanel, SearchList, SourcePanel, TextInput, Tree } from '../components' import { useLocale, useProject, useTitle, useVersion } from '../contexts' -import { useActiveTimeout, useModel } from '../hooks' +import { useActiveTimeout, useModel, useSearchParam } from '../hooks' import { getOutput } from '../schema/transformOutput' import type { BlockStateRegistry, VersionId } from '../services' import { checkVersion, fetchPreset, getBlockStates, getCollections, getModel, getSnippet, shareSnippet, SHARE_KEY } from '../services' import { Store } from '../Store' -import { cleanUrl, deepEqual, getGenerator, getSearchParams, message, setSeachParams } from '../Utils' +import { cleanUrl, deepEqual, getGenerator } from '../Utils' interface Props { default?: true, } export function Generator({}: Props) { const { locale } = useLocale() - const { version, changeVersion } = useVersion() + const { version, changeVersion, changeTargetVersion } = useVersion() const { project, file, updateFile, openFile, closeFile } = useProject() const [error, setError] = useState(null) const [errorBoundary, errorRetry] = useErrorBoundary() @@ -31,9 +31,12 @@ export function Generator({}: Props) { return
} - const allowedVersions = config.versions - .filter(v => checkVersion(v.id, gen.minVersion, gen.maxVersion)) - .map(v => v.id as VersionId) + const allowedVersions = useMemo(() => { + return config.versions + .filter(v => checkVersion(v.id, gen.minVersion, gen.maxVersion)) + .map(v => v.id as VersionId) + .reverse() + }, [gen.minVersion, gen.maxVersion]) useTitle(locale('title.generator', locale(gen.id)), allowedVersions) @@ -44,14 +47,15 @@ export function Generator({}: Props) { setError(`This generator is not available in versions above ${gen.maxVersion}`) } - const searchParams = getSearchParams(getCurrentUrl()) - const currentPreset = searchParams.get('preset') - const sharedSnippetId = searchParams.get(SHARE_KEY) + const [currentPreset, setCurrentPreset] = useSearchParam('preset') + const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY) + const ignoreChange = useRef(false) useEffect(() => { if (model && currentPreset) { loadPreset(currentPreset).then(preset => { + ignoreChange.current = true model.reset(DataModel.wrapLists(preset), false) - setSeachParams({ version, preset: currentPreset, [SHARE_KEY]: undefined }) + setSharedSnippetId(undefined) }) } else if (model && sharedSnippetId) { getSnippet(sharedSnippetId).then(s => loadSnippet(model, s)) @@ -107,11 +111,15 @@ export function Generator({}: Props) { const [dirty, setDirty] = useState(false) useModel(model, () => { - setSeachParams({ version: undefined, preset: undefined, [SHARE_KEY]: undefined }) + if (!ignoreChange.current) { + setCurrentPreset(undefined, true) + setSharedSnippetId(undefined, true) + } + ignoreChange.current = false Store.setBackup(gen.id, DataModel.unwrapLists(model?.data)) setError(null) setDirty(true) - }, [gen.id]) + }, [gen.id, setCurrentPreset, setSharedSnippetId]) const [fileRename, setFileRename] = useState('') const [fileSaved, doSave] = useActiveTimeout() @@ -211,7 +219,9 @@ export function Generator({}: Props) { const selectPreset = (id: string) => { Analytics.generatorEvent('load-preset', id) - setSeachParams({ version, preset: id, [SHARE_KEY]: undefined }) + setSharedSnippetId(undefined, true) + changeTargetVersion(version, true) + setCurrentPreset(id) } const loadPreset = async (id: string) => { @@ -226,12 +236,13 @@ export function Generator({}: Props) { } return preset } catch (e) { - setError(e instanceof Error ? e : message(e)) + setError(`Cannot load preset ${id} in ${version}`) + setCurrentPreset(undefined, true) } } const selectVersion = (version: VersionId) => { - setSeachParams({ [SHARE_KEY]: undefined }) + setSharedSnippetId(undefined, true) changeVersion(version) } @@ -244,13 +255,13 @@ export function Generator({}: Props) { return } if (currentPreset) { - setShareUrl(`${location.protocol}//${location.host}/${gen.url}/?version=${version}&preset=${currentPreset}`) + setShareUrl(`${location.origin}/${gen.url}/?version=${version}&preset=${currentPreset}`) setShareShown(true) copySharedId() } else if (model && blockStates) { const output = getOutput(model, blockStates) if (deepEqual(output, model.schema.default())) { - setShareUrl(`${location.protocol}//${location.host}/${gen.url}/?version=${version}`) + setShareUrl(`${location.origin}/${gen.url}/?version=${version}`) setShareShown(true) } else { shareSnippet(gen.id, version, output, previewShown) @@ -345,7 +356,7 @@ export function Generator({}: Props) { - {allowedVersions.reverse().map(v => + {allowedVersions.map(v => selectVersion(v)} /> )} diff --git a/src/app/pages/Guide.tsx b/src/app/pages/Guide.tsx new file mode 100644 index 00000000..a827d5f3 --- /dev/null +++ b/src/app/pages/Guide.tsx @@ -0,0 +1,147 @@ +import hljs from 'highlight.js' +import { marked } from 'marked' +import { route } from 'preact-router' +import { useCallback, useEffect, useMemo, useState } from 'preact/hooks' +import config from '../../config.json' +import { Ad, Btn, BtnMenu, ChangelogTag, Giscus, Octicon } from '../components' +import { useLocale, useTitle, useVersion } from '../contexts' +import { useActiveTimeout, useHash } from '../hooks' +import type { VersionId } from '../services' +import { parseFrontMatter, versionContent } from '../Utils' + +const HASH = '' + +marked.use({ + highlight: (code, lang) => { + if (lang === '') return undefined + return hljs.highlight(code, { language: lang }).value + }, +}) + +interface Props { + path?: string + id?: string +} +export function Guide({ id }: Props) { + const { locale } = useLocale() + const { version, changeVersion } = useVersion() + const { changeTitle } = useTitle() + + const [content, setContent] = useState(undefined) + + const frontMatter = useMemo(() => { + if (!content) return undefined + const data = parseFrontMatter(content) + changeTitle(data?.title, data?.versions) + return data + }, [content]) + + const allowedVersions = useMemo(() => { + const orderedVersions = config.versions.map(v => v.id) + return (frontMatter?.versions as string[]) + ?.sort((a, b) => orderedVersions.indexOf(b) - orderedVersions.indexOf(a)) + }, [frontMatter?.versions]) + + const guideVersion = useMemo(() => { + if (!allowedVersions) return version + if (allowedVersions.includes(version)) return version + return allowedVersions[0] + }, [version, frontMatter?.versions]) + + const versionedContent = useMemo(() => { + if (!content) return undefined + const guide = content.substring(content.indexOf('---', 3) + 3) + return versionContent(guide, guideVersion) + }, [guideVersion, content]) + + const html = useMemo(() => { + if (!versionedContent) return undefined + marked.use({ renderer: { + link(href, title, text) { + if (href === null) return text + const title2 = title ? ` title="${title}"` : '' + const target = href?.match(/^https?:\/\//) ? ' target="_blank"' : '' + return `${text}` + }, + heading(text, level, raw, slugger) { + const id = slugger.slug(raw) + const link = `${HASH}` + return `${link}${text}` + }, + }}) + return marked(versionedContent, { version: '1.19' } as any) + }, [versionedContent]) + + const [hash, setHash] = useHash() + + const scrollToHeading = useCallback(() => { + if (!html) return + const heading = document.querySelector(`[id=guide-${hash.slice(1)}]`) + if (heading) { + const top = heading.getBoundingClientRect().top + window.scrollY + window.scrollTo({ top: top - 68, behavior: 'smooth' }) + } + }, [html, hash]) + + useEffect(() => { + scrollToHeading() + }, [html === undefined, hash]) + + const clickGuideContent = useCallback((e: MouseEvent) => { + if (!(e.target instanceof HTMLSpanElement)) return + const targetHash = '#' + e.target.id.replace(/^guide-/, '') + changeVersion(version, false, true) + setHash(targetHash) + if (targetHash === hash) { + scrollToHeading() + } + }, [scrollToHeading, hash, version]) + + useEffect(() => { + (async () => { + const res = await fetch(`../../guides/${id}.md`) + const text = await res.text() + setContent(text) + })() + }, [id]) + + const [shareActive, shareSuccess] = useActiveTimeout() + + const onShare = useCallback(() => { + const url = `${location.origin}/guides/${id}/?version=${version}` + navigator.clipboard.writeText(url) + shareSuccess() + }, [id, version]) + + const onClickTag = (tag: string) => { + route(`/guides/?tags=${tag}`) + } + + const [largeWidth] = useState(window.innerWidth > 600) + + return
+
+ + {(frontMatter?.tags && frontMatter.tags.length > 0) &&
+ {frontMatter.tags.map((tag: string) => + onClickTag(tag)} /> + )} +
} + {html && <> + +
+ + } +
+
+} diff --git a/src/app/pages/Guides.tsx b/src/app/pages/Guides.tsx new file mode 100644 index 00000000..2560b426 --- /dev/null +++ b/src/app/pages/Guides.tsx @@ -0,0 +1,87 @@ +import { useMemo, useState } from 'preact/hooks' +import config from '../../config.json' +import { Btn, BtnMenu, ChangelogTag, GuideCard, TextInput } from '../components' +import { useLocale, useTitle, useVersion } from '../contexts' +import { useSearchParam } from '../hooks' +import type { VersionId } from '../services' + +interface Guide { + id: string, + title: string, + versions?: string[], + tags?: string[], +} + +declare var __GUIDES__: Guide[] + +const TAG_KEY = 'tags' +const TAG_SEP = '|' + +interface Props { + path?: string +} +export function Guides({}: Props) { + const { locale } = useLocale() + const { version, changeVersion } = useVersion() + useTitle(locale('title.guides')) + + const [search, setSearch] = useState('') + const [tags, setTags] = useSearchParam(TAG_KEY) + const activeTags = useMemo(() => tags?.split(TAG_SEP) ?? [], [tags]) + const toggleTag = (tag: string) => { + if (activeTags.includes(tag)) { + setTags(activeTags.filter(t => t !== tag).join(TAG_SEP)) + } else { + setTags([...activeTags, tag].sort().join(TAG_SEP)) + } + } + + const [versionFilter, setVersionFiler] = useState(false) + + const versionedGuides = useMemo(() => { + if (versionFilter === false) return __GUIDES__ + return __GUIDES__.filter(guide => { + return guide.versions?.includes(version) + }) + }, [version, versionFilter]) + + const filteredGuides = useMemo(() => { + const query = search.split(' ').map(q => q.trim().toLowerCase()).filter(q => q.length > 0) + return versionedGuides.filter(guide => { + if (!activeTags.every(tag => guide.tags?.includes(tag))) { + return false + } + const content = guide.tags?.join(' ') + ' ' + guide.title.toLowerCase() + return query.every(q => { + if (q.startsWith('!')) { + return q.length === 1 || !content.includes(q.slice(1)) + } + return content.includes(q) + }) + }) + }, [versionedGuides, search, tags]) + + return
+
+
+ + + setVersionFiler(!versionFilter)} /> + {config.versions.slice().reverse().map(v => + {changeVersion(v.id as VersionId); setVersionFiler(true)}} /> + )} + +
+ {activeTags.length > 0 &&
+ {activeTags.map(tag => toggleTag(tag)} />)} +
} + {versionedGuides.length === 0 ? <> + {locale('guides.no_results.version')} + : filteredGuides.length === 0 ? <> + {locale('guides.no_results.query')} + : filteredGuides.map(g => + + )} +
+
+} diff --git a/src/app/pages/Home.tsx b/src/app/pages/Home.tsx index 2b1d5446..8e7f0b13 100644 --- a/src/app/pages/Home.tsx +++ b/src/app/pages/Home.tsx @@ -33,6 +33,7 @@ export function Home({}: Props) { desc="Convert your data packs from 1.16 to 1.17 to 1.18" /> + diff --git a/src/app/pages/Sounds.tsx b/src/app/pages/Sounds.tsx index 4fea6491..513d049b 100644 --- a/src/app/pages/Sounds.tsx +++ b/src/app/pages/Sounds.tsx @@ -64,8 +64,8 @@ export function Sounds({}: Props) { {configs.length > 1 && }
- - {config.versions.reverse().map(v => + + {config.versions.slice().reverse().map(v => changeVersion(v.id as VersionId)} /> )} diff --git a/src/app/pages/Versions.tsx b/src/app/pages/Versions.tsx index 99b26674..5e38b6fd 100644 --- a/src/app/pages/Versions.tsx +++ b/src/app/pages/Versions.tsx @@ -1,10 +1,9 @@ -import { getCurrentUrl } from 'preact-router' import { useEffect, useState } from 'preact/hooks' import { Ad, ErrorPanel, Octicon, VersionDetail, VersionList } from '../components' import { useLocale, useTitle } from '../contexts' +import { useSearchParam } from '../hooks' import type { VersionMeta } from '../services' import { fetchVersions } from '../services' -import { getSearchParams } from '../Utils' interface Props { path?: string, @@ -21,7 +20,7 @@ export function Versions({}: Props) { .catch(e => { console.error(e); setError(e) }) }, []) - const selectedId = getSearchParams(getCurrentUrl()).get('id') + const [selectedId] = useSearchParam('id') const selected = versions.find(v => v.id === selectedId) useTitle(selected ? selected.name : 'Versions Explorer', selected ? [] : undefined) @@ -34,7 +33,7 @@ export function Versions({}: Props) { {error && setError(null)} />}
{selectedId ? <> -
+