diff --git a/package-lock.json b/package-lock.json index 81bb14b..0ce5fcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,9 @@ "version": "1.14.1", "license": "MIT", "devDependencies": { - "@discoveryjs/discovery": "1.0.0-beta.83", - "@discoveryjs/json-ext": "^0.5.7", + "@discoveryjs/discovery": "1.0.0-beta.87", "css-tree": "^2.3.1", - "esbuild": "^0.20.1", + "esbuild": "^0.24.0", "eslint": "^8.50.0", "jszip": "^3.10.1", "mime": "^3.0.0" @@ -28,15 +27,16 @@ } }, "node_modules/@discoveryjs/discovery": { - "version": "1.0.0-beta.83", - "resolved": "https://registry.npmjs.org/@discoveryjs/discovery/-/discovery-1.0.0-beta.83.tgz", - "integrity": "sha512-dLJ0wvIpj/6Cnn3WezTEhbSsGumM65O00+6UVZ0Dg3IUBDIPyDdCaT0cnhSo1y/rWuPKO/oq9TCdTVwxbrK16Q==", + "version": "1.0.0-beta.87", + "resolved": "https://registry.npmjs.org/@discoveryjs/discovery/-/discovery-1.0.0-beta.87.tgz", + "integrity": "sha512-h4KZLyjICXSOgaP4m8hpCaTVhmVOPe4K8xpKQz3RzVczRXhpsBxoVK+c5JdLQkdr9W/nvnhIs3tncUQhsiE56w==", "dev": true, + "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "^0.5.7", + "@discoveryjs/json-ext": "^0.6.1", "codemirror": "^5.65.2", "hitext": "^1.0.0-beta.1", - "jora": "1.0.0-beta.10", + "jora": "1.0.0-beta.13", "marked": "^4.3.0" }, "engines": { @@ -44,12 +44,13 @@ } }, "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz", + "integrity": "sha512-boghen8F0Q8D+0/Q1/1r6DUEieUJ8w2a1gIknExMSHBsJFOr2+0KUfHiVYBvucPwl3+RU5PFBK833FjFCh3BhA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=14.17.0" } }, "node_modules/@discoveryjs/natural-compare": { @@ -57,376 +58,417 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/natural-compare/-/natural-compare-1.1.0.tgz", "integrity": "sha512-yuctPJs5lRXoI8LkpVZGAV6n+DKOuEsfpfcIDQ8ZjWHwazqk1QjBc4jMlof0UlZHyUqv4dwsOTooMiAmtzvwXA==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", - "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", - "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", - "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", - "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", - "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", - "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", - "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", - "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", - "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", - "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", - "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", - "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", - "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", - "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", - "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", - "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", - "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", - "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", - "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", - "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", - "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", - "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", - "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -760,41 +802,43 @@ } }, "node_modules/esbuild": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", - "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.1", - "@esbuild/android-arm": "0.20.1", - "@esbuild/android-arm64": "0.20.1", - "@esbuild/android-x64": "0.20.1", - "@esbuild/darwin-arm64": "0.20.1", - "@esbuild/darwin-x64": "0.20.1", - "@esbuild/freebsd-arm64": "0.20.1", - "@esbuild/freebsd-x64": "0.20.1", - "@esbuild/linux-arm": "0.20.1", - "@esbuild/linux-arm64": "0.20.1", - "@esbuild/linux-ia32": "0.20.1", - "@esbuild/linux-loong64": "0.20.1", - "@esbuild/linux-mips64el": "0.20.1", - "@esbuild/linux-ppc64": "0.20.1", - "@esbuild/linux-riscv64": "0.20.1", - "@esbuild/linux-s390x": "0.20.1", - "@esbuild/linux-x64": "0.20.1", - "@esbuild/netbsd-x64": "0.20.1", - "@esbuild/openbsd-x64": "0.20.1", - "@esbuild/sunos-x64": "0.20.1", - "@esbuild/win32-arm64": "0.20.1", - "@esbuild/win32-ia32": "0.20.1", - "@esbuild/win32-x64": "0.20.1" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/escape-string-regexp": { @@ -1230,12 +1274,13 @@ "dev": true }, "node_modules/jora": { - "version": "1.0.0-beta.10", - "resolved": "https://registry.npmjs.org/jora/-/jora-1.0.0-beta.10.tgz", - "integrity": "sha512-4uksWcMtbXItSF9P7LLdvDnF0woVmnGrpQ63Fi5Asj3QbE0y4TsIPVTL0gXNGPU5sA66b12ltERJQ/l5PtbnuA==", + "version": "1.0.0-beta.13", + "resolved": "https://registry.npmjs.org/jora/-/jora-1.0.0-beta.13.tgz", + "integrity": "sha512-MzIUKA+t5IUwMsCzhkHCcL4M2xWxNN+3nntFm8q1LEF7jdWWGAL3lAHpnymFmsbxlctrdK8z5B1mx5z5SPDlkQ==", "dev": true, + "license": "MIT", "dependencies": { - "@discoveryjs/natural-compare": "^1.0.0" + "@discoveryjs/natural-compare": "^1.1.0" }, "engines": { "node": "^10.12.0 || ^12.20.0 || ^14.13.0 || >=15.0.0" @@ -1765,22 +1810,22 @@ "dev": true }, "@discoveryjs/discovery": { - "version": "1.0.0-beta.83", - "resolved": "https://registry.npmjs.org/@discoveryjs/discovery/-/discovery-1.0.0-beta.83.tgz", - "integrity": "sha512-dLJ0wvIpj/6Cnn3WezTEhbSsGumM65O00+6UVZ0Dg3IUBDIPyDdCaT0cnhSo1y/rWuPKO/oq9TCdTVwxbrK16Q==", + "version": "1.0.0-beta.87", + "resolved": "https://registry.npmjs.org/@discoveryjs/discovery/-/discovery-1.0.0-beta.87.tgz", + "integrity": "sha512-h4KZLyjICXSOgaP4m8hpCaTVhmVOPe4K8xpKQz3RzVczRXhpsBxoVK+c5JdLQkdr9W/nvnhIs3tncUQhsiE56w==", "dev": true, "requires": { - "@discoveryjs/json-ext": "^0.5.7", + "@discoveryjs/json-ext": "^0.6.1", "codemirror": "^5.65.2", "hitext": "^1.0.0-beta.1", - "jora": "1.0.0-beta.10", + "jora": "1.0.0-beta.13", "marked": "^4.3.0" } }, "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz", + "integrity": "sha512-boghen8F0Q8D+0/Q1/1r6DUEieUJ8w2a1gIknExMSHBsJFOr2+0KUfHiVYBvucPwl3+RU5PFBK833FjFCh3BhA==", "dev": true }, "@discoveryjs/natural-compare": { @@ -1790,163 +1835,170 @@ "dev": true }, "@esbuild/aix-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", - "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "dev": true, "optional": true }, "@esbuild/android-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", - "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", - "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", - "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", - "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", - "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", - "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", - "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", - "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", - "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", - "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", - "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", - "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", - "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", - "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", - "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", - "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", - "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", - "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", - "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", - "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", - "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", - "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "dev": true, "optional": true }, @@ -2194,34 +2246,35 @@ } }, "esbuild": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", - "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "requires": { - "@esbuild/aix-ppc64": "0.20.1", - "@esbuild/android-arm": "0.20.1", - "@esbuild/android-arm64": "0.20.1", - "@esbuild/android-x64": "0.20.1", - "@esbuild/darwin-arm64": "0.20.1", - "@esbuild/darwin-x64": "0.20.1", - "@esbuild/freebsd-arm64": "0.20.1", - "@esbuild/freebsd-x64": "0.20.1", - "@esbuild/linux-arm": "0.20.1", - "@esbuild/linux-arm64": "0.20.1", - "@esbuild/linux-ia32": "0.20.1", - "@esbuild/linux-loong64": "0.20.1", - "@esbuild/linux-mips64el": "0.20.1", - "@esbuild/linux-ppc64": "0.20.1", - "@esbuild/linux-riscv64": "0.20.1", - "@esbuild/linux-s390x": "0.20.1", - "@esbuild/linux-x64": "0.20.1", - "@esbuild/netbsd-x64": "0.20.1", - "@esbuild/openbsd-x64": "0.20.1", - "@esbuild/sunos-x64": "0.20.1", - "@esbuild/win32-arm64": "0.20.1", - "@esbuild/win32-ia32": "0.20.1", - "@esbuild/win32-x64": "0.20.1" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "escape-string-regexp": { @@ -2557,12 +2610,12 @@ "dev": true }, "jora": { - "version": "1.0.0-beta.10", - "resolved": "https://registry.npmjs.org/jora/-/jora-1.0.0-beta.10.tgz", - "integrity": "sha512-4uksWcMtbXItSF9P7LLdvDnF0woVmnGrpQ63Fi5Asj3QbE0y4TsIPVTL0gXNGPU5sA66b12ltERJQ/l5PtbnuA==", + "version": "1.0.0-beta.13", + "resolved": "https://registry.npmjs.org/jora/-/jora-1.0.0-beta.13.tgz", + "integrity": "sha512-MzIUKA+t5IUwMsCzhkHCcL4M2xWxNN+3nntFm8q1LEF7jdWWGAL3lAHpnymFmsbxlctrdK8z5B1mx5z5SPDlkQ==", "dev": true, "requires": { - "@discoveryjs/natural-compare": "^1.0.0" + "@discoveryjs/natural-compare": "^1.1.0" } }, "js-yaml": { diff --git a/package.json b/package.json index 53931f0..cc1c61f 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,9 @@ "build": "NODE_ENV=production node ./scripts/build.js && node ./scripts/zip.js" }, "devDependencies": { - "@discoveryjs/discovery": "1.0.0-beta.83", - "@discoveryjs/json-ext": "^0.5.7", + "@discoveryjs/discovery": "1.0.0-beta.87", "css-tree": "^2.3.1", - "esbuild": "^0.20.1", + "esbuild": "^0.24.0", "eslint": "^8.50.0", "jszip": "^3.10.1", "mime": "^3.0.0" diff --git a/scripts/build.js b/scripts/build.js index c437f5a..f39706b 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -49,24 +49,20 @@ async function build(browser) { fs.rmSync(outdir, { recursive: true, force: true }); // rm -rf fs.mkdirSync(outdir, { recursive: true }); - fs.writeFileSync(outdir + '/manifest.json', manifest(browser)); + fs.writeFileSync(path.join(outdir, 'manifest.json'), manifest(browser)); + copyFile(path.join(indir, 'sandbox.html'), outdir); copyFiles(path.join(indir, 'icons'), outdir); // build bundle - const result = await esbuild.build({ + await esbuild.build({ entryPoints: [ - path.join(indir, 'background.js'), - path.join(indir, 'content/discovery.css'), - path.join(indir, 'content/preloader.css'), - path.join(indir, 'content/discovery.js'), - path.join(indir, 'content/discovery-esm.js'), - path.join(indir, 'content/init.js') + { in: path.join(indir, 'content/init.js'), out: 'init' }, + path.join(indir, 'sandbox.js') ], format: 'esm', bundle: true, minify: true, - write: false, outdir, define: { global: 'window' @@ -77,16 +73,6 @@ async function build(browser) { '.md': 'text' } }); - - for (const file of result.outputFiles) { - const content = path.extname(file.path) === '.css' - ? processCss(file.text, outdir, 'assets') - : file.contents; - - const filePath = path.join(outdir, path.basename(file.path)); - - fs.writeFileSync(filePath, content); - } } const buildAll = async function() { @@ -131,6 +117,10 @@ const buildAll = async function() { } })(); +function copyFile(filepath, dest) { + fs.copyFileSync(filepath, path.join(dest, path.basename(filepath))); +} + function copyFiles(src, dest) { fs.mkdirSync(dest, { recursive: true }); @@ -139,6 +129,6 @@ function copyFiles(src, dest) { copyFiles(path.join(src, p), path.join(dest, path.basename(src))) ); } else { - fs.copyFileSync(src, path.join(dest, path.basename(src))); + copyFile(src, dest); } } diff --git a/src/content/discovery-esm.js b/src/content/discovery-esm.js deleted file mode 100644 index 1203a99..0000000 --- a/src/content/discovery-esm.js +++ /dev/null @@ -1 +0,0 @@ -export { initDiscovery } from '../discovery'; diff --git a/src/content/discovery.css b/src/content/discovery.css deleted file mode 100644 index f609168..0000000 --- a/src/content/discovery.css +++ /dev/null @@ -1 +0,0 @@ -@import '../discovery/discovery.css'; diff --git a/src/content/discovery.js b/src/content/discovery.js deleted file mode 100644 index c2e1a55..0000000 --- a/src/content/discovery.js +++ /dev/null @@ -1,7 +0,0 @@ -import { initDiscovery } from '../discovery'; - -initDiscovery(...window.__discoveryOptions) // eslint-disable-line no-underscore-dangle - .then(() => { - window.__discoveryPreloader.el.remove(); // eslint-disable-line no-underscore-dangle - }); - diff --git a/src/content/init.js b/src/content/init.js index 2737267..5e206cd 100644 --- a/src/content/init.js +++ b/src/content/init.js @@ -1,70 +1,23 @@ -import { rollbackContainerStyles } from '@discoveryjs/discovery/src/core/utils/container-styles'; -import { preloader as createPreloader } from '@discoveryjs/discovery/src/preloader.js'; -import parseChunked from '@discoveryjs/json-ext/src/parse-chunked'; +import { applyContainerStyles, rollbackContainerStyles } from '@discoveryjs/discovery/src/core/utils/container-styles.js'; +import { connectToEmbedApp } from '@discoveryjs/discovery/src/extensions/embed-host.js'; +import copyText from '@discoveryjs/discovery/lib/core/utils/copy-text.js'; +import { downloadAsFile } from '../discovery/download-as-file'; -let loaded = document.readyState === 'complete'; +let documentFullyLoaded = document.readyState === 'complete'; let loadedTimer; let disabledElements = []; let pre = null; +let iframe = null; let preCursor; let prevCursorValue = ''; -let preloader = null; -let pushChunk = () => {}; +let dataStreamController = null; +let stylesApplied = false; let totalSize = 0; let firstSlice = ''; const firstSliceMaxSize = 100 * 1000; -const chunkBuffer = []; -const getChunk = () => { - if (chunkBuffer.length) { - return chunkBuffer.shift(); - } - - return new Promise(resolve => { - pushChunk = chunk => { - resolve(chunk); - pushChunk = chunk => chunkBuffer.push(chunk); - }; - }); -}; -const data = parseChunked(async function*() { - const loadStartTime = Date.now(); - const getState = done => ({ - stage: 'receive', - progress: { - done, - elapsed: Date.now() - loadStartTime, - units: 'bytes', - completed: totalSize - } - }); - - while (true) { - const chunk = await getChunk(); - - if (!chunk) { - break; - } - - yield chunk; - totalSize += chunk.length; - - if (firstSlice.length < firstSliceMaxSize) { - const left = firstSliceMaxSize - firstSlice.length; - firstSlice += left > chunk.length ? chunk : chunk.slice(0, left); - } - - if (preloader !== null) { - await preloader.progressbar.setState(getState(false)); - } - } - - if (preloader !== null) { - preloader.progressbar.setState(getState(true)); - } -}); -function raiseBailout() { - return Object.assign(new Error('Rollback'), { rollback: true }); +function raiseBailout(reason) { + return Object.assign(new Error('Rollback'), { bailout: reason }); } const flushData = (settings) => { @@ -84,9 +37,9 @@ const flushData = (settings) => { : preCursor.nextSibling; if (!chunkNode) { - if (isFirstChunk && (loaded || pre.nextSibling)) { + if (isFirstChunk && (documentFullyLoaded || pre.nextSibling)) { // bailout: first
is empty - throw raiseBailout(); + throw raiseBailout('Empty input'); } break; @@ -96,29 +49,36 @@ const flushData = (settings) => { if (isFirstChunk) { if (/^\s*[{[]/.test(chunkNode.nodeValue)) { // probably JSON, accept an object or an array only to reduce false positive - preloader = createPreloader({ - container: document.body, - styles: [{ type: 'link', href: chrome.runtime.getURL('preloader.css') }], - darkmode: settings.darkmode - }); - preloader.el.classList.add('discovery'); - preloader.progressbar.setState({ stage: 'request' }); + if (dataStreamController === null) { + if (iframe === null) { + pre.before(getIframe(settings)); + } + + return; + } } else { // bailout: not a JSON or a non-object / non-array value - throw raiseBailout(); + throw raiseBailout('Not a JSON or a non-object / non-array value'); } } - pushChunk( - chunkNode === preCursor - // slice a new content from a chunk node in case a content - // was appended to an existing text node - ? chunkNode.nodeValue.slice(prevCursorValue.length) - : chunkNode.nodeValue - ); + const chunk = chunkNode === preCursor + // slice a new content from a chunk node in case a content + // was appended to an existing text node + ? chunkNode.nodeValue.slice(prevCursorValue.length) + : chunkNode.nodeValue; + + totalSize += chunk.length; + + if (firstSlice.length < firstSliceMaxSize) { + const left = firstSliceMaxSize - firstSlice.length; + firstSlice += left > chunk.length ? chunk : chunk.slice(0, left); + } + + dataStreamController.enqueue(chunk); } else { // bailout: not a text node -> a complex markup is not a JSON - throw raiseBailout(); + throw raiseBailout('Input not a text'); } preCursor = chunkNode; @@ -127,13 +87,15 @@ const flushData = (settings) => { }; function rollbackPageChanges(error) { - chunkBuffer.length = 0; // clean up buffer cancelAnimationFrame(loadedTimer); rollbackContainerStyles(document.body); - if (preloader !== null) { - preloader.el.remove(); - preloader = null; + dataStreamController?.close(); + dataStreamController = null; + + if (iframe !== null) { + iframe.remove(); + iframe = null; } // it might to take a lot of time to render large text, @@ -147,8 +109,8 @@ function rollbackPageChanges(error) { } }); - if (!error.rollback) { - console.error('[JsonDiscovery] Failed to parse JSON', error); // eslint-disable-line no-console + if (error.bailout) { + console.warn('[JsonDiscovery] Bailout reason:', error.bailout); // eslint-disable-line no-console } } @@ -189,8 +151,122 @@ function disableElement(element, remove = false) { element.hidden = true; } +function getIframe(settings) { + if (iframe !== null) { + return iframe; + } + + iframe = document.createElement('iframe'); + iframe.className = 'discovery'; + iframe.setAttribute('sandbox', 'allow-scripts'); + iframe.src = chrome.runtime.getURL('sandbox.html'); + iframe.style.cssText = 'position: fixed; inset: 0; border: 0; width: 100%; height: 100%; visibility: hidden'; + + // Check if scripts in the sandbox iframe work, otherwise rollback since we can't display anything. + // The first script in the sandbox iframe sends message, it should be delivered before onload event fires + { + let scriptsWorks = false; + + window.addEventListener('message', e => { + if (e.data === 'json-discovery-sandbox-scripts-work') { + scriptsWorks = true; + } + }, { once: true }); + + iframe.onload = () => { + if (!scriptsWorks) { + rollbackPageChanges(raiseBailout('Scripts or postMessage() doesn\'t work in sandbox')); + } else { + // enable visibility on iframe load to avoid flash of white background when in dark mode + iframe.style.visibility = 'visible'; + } + }; + } + + connectToEmbedApp(iframe, (app) => { + // settings + let darkmode = 'auto'; + + switch (settings.darkmode) { + case true: + darkmode = 'dark'; + break; + case false: + darkmode = 'light'; + break; + } + + app.setDarkmode(darkmode); + app.defineAction('getSettings', () => settings); + app.defineAction('setSettings', settings => { + chrome.storage.sync.set(settings); + }); + + app.defineAction('copyToClipboard', () => copyText(pre.textContent)); + app.defineAction('downloadAsFile', () => { + // FIXME: bad for large files + downloadAsFile(pre.textContent); + }); + + app.defineAction('permalink', () => window.location.toString()); + + app.defineAction('getRaw', () => ({ + firstSliceText: firstSlice, + firstSliceSize: firstSlice.length, + fullSize: totalSize + })); + app.defineAction('getRawFull', () => ({ + json: pre.textContent + })); + + app.on('darkmodeChanged', async event => { + const settings = await getSettings(); + let darkmode = 'auto'; + + switch (event.value) { + case 'light': + darkmode = false; + break; + case 'dark': + darkmode = true; + break; + } + + chrome.storage.sync.set({ ...settings, darkmode }); + }); + + // upload data + app.uploadData(new ReadableStream({ + start(controller_) { + dataStreamController = controller_; + }, + cancel() { + dataStreamController = null; + } + })); + + // sync location + // Note: should be last since lead to renders + app.setRouterPreventLocationUpdate(true); + app.setPageHash(location.hash); + addEventListener('hashchange', () => app.setPageHash(location.hash), false); + app.on('pageHashChanged', (newPageHash, replace) => { + if (replace) { + location.replace(newPageHash); + } else { + location.hash = newPageHash; + } + }); + + // check load and appearance + getSettings().then(checkLoaded); + }); + + return iframe; +} + async function checkLoaded(settings) { - if (pre === null) { + if (pre === null && !stylesApplied) { const firstElement = document.body?.firstElementChild; pre = isPre(firstElement) || isPre(firstElement?.nextElementSibling); @@ -212,11 +288,16 @@ async function checkLoaded(settings) { } } - if (!settings) { + if (!settings || pre === null) { return; } - if (!loaded) { + if (!stylesApplied) { + stylesApplied = true; + applyContainerStyles(document.body, settings); + } + + if (!documentFullyLoaded) { flushData(settings); loadedTimer = requestAnimationFrame(() => checkLoaded(settings).catch(rollbackPageChanges) @@ -226,55 +307,16 @@ async function checkLoaded(settings) { if (pre !== null) { flushData(settings); - pushChunk(null); // end of input - - const [{ initDiscovery }, json] = await Promise.all([ - import(chrome.runtime.getURL('discovery-esm.js')), - data - ]); - - const discoveryOptions = [ - { - node: document.body, - raw: Object.defineProperties({}, { - firstSlice: { - value: totalSize < firstSliceMaxSize * 2 ? null : firstSlice - }, - size: { - value: totalSize - }, - json: totalSize <= firstSliceMaxSize ? { value: firstSlice } : { - configurable: true, - get() { - return Object.defineProperty(this, 'json', { - value: pre.textContent - }).json; - } - } - }), - settings, - version: chrome.runtime.getManifest().version, - styles: [chrome.runtime.getURL('index.css')], - progressbar: preloader.progressbar - }, json - ]; - - // In case of sandboxed CSP pages await import will fail - // so here we send message to bg which executes discovery initiation via chrome API - if (typeof initDiscovery !== 'function') { - window.__discoveryPreloader = preloader; // eslint-disable-line no-underscore-dangle - window.__discoveryOptions = discoveryOptions; // eslint-disable-line no-underscore-dangle - - await chrome.runtime.sendMessage({ type: 'initDiscovery' }); - } else { - await initDiscovery(...discoveryOptions); - preloader.el.remove(); - } + dataStreamController?.close(); + dataStreamController = null; } } -window.addEventListener('DOMContentLoaded', () => loaded = true, false); +window.addEventListener('DOMContentLoaded', () => { + documentFullyLoaded = true; + checkLoaded(); +}, { once: true }); checkLoaded(); getSettings() .then(checkLoaded) @@ -285,13 +327,9 @@ getSettings() * @returns {Promise} */ function getSettings() { - return new Promise(resolve => { - chrome.storage.sync.get({ - expandLevel: 3, - darkmode: 'auto', - whatsnew: {} - }, settings => { - resolve(settings); - }); + return chrome.storage.sync.get({ + expandLevel: 3, + darkmode: 'auto', + whatsnew: {} }); } diff --git a/src/content/preloader.css b/src/content/preloader.css deleted file mode 100644 index 06742de..0000000 --- a/src/content/preloader.css +++ /dev/null @@ -1,6 +0,0 @@ -@import '@discoveryjs/discovery/src/preloader.css'; -:host { - top: 0; - left: 0; - z-index: 1; -} diff --git a/src/discovery/copy-to-clipboard.js b/src/discovery/copy-to-clipboard.js index 5f9ec8c..5bc0a50 100644 --- a/src/discovery/copy-to-clipboard.js +++ b/src/discovery/copy-to-clipboard.js @@ -1,12 +1,8 @@ -import { flashMessage } from './flash-messages'; -import copyText from '@discoveryjs/discovery/src/core/utils/copy-text'; - export const copyToClipboardButton = { view: 'button', content: 'text:"Copy to clipboard"', - onClick(_, { json }) { - copyText(json).then(() => { - flashMessage('JSON copied to clipboard', 'success'); - }); + async onClick(_, __, host) { + await host.actions.copyToClipboard(); + host.actions.flashMessage('JSON copied to clipboard', 'success'); } }; diff --git a/src/discovery/discovery.css b/src/discovery/discovery.css index ff8d40a..ae74930 100644 --- a/src/discovery/discovery.css +++ b/src/discovery/discovery.css @@ -1,4 +1,4 @@ -@import '@discoveryjs/discovery/src/lib.css'; +@import '@discoveryjs/discovery/lib/lib.css'; @import './pages/raw.css'; @import './pages/settings.css'; @import './pages/whatsnew.css'; @@ -8,6 +8,7 @@ position: fixed; inset: 0; z-index: 1000; + transition: none; } .discovery-root { --discovery-page-padding-right: 12px; @@ -40,8 +41,21 @@ border-top-left-radius: 0; border-bottom-left-radius: 0; } -.view-page-header .view-button svg { +.view-page-header .view-button.collapse-all:empty::before, +.view-page-header .view-button.expand-all:empty::before { + content: ''; + width: 16px; + height: 16px; margin: -4px 0; + display: inline-block; + mask: url('./img/collapse-all.svg'); + mask-size: 16px; + background-color: currentColor; + visibility: visible; +} + +.view-page-header .view-button.expand-all::before { + mask-image: url('./img/expand-all.svg'); } /* Safari quirk mode fix */ diff --git a/src/discovery/download-as-file.js b/src/discovery/download-as-file.js index 5410958..665ada8 100644 --- a/src/discovery/download-as-file.js +++ b/src/discovery/download-as-file.js @@ -14,7 +14,7 @@ export function downloadAsFile(text) { export const downloadAsFileButton = { view: 'button', content: 'text:"Download as file"', - onClick(_, { json }) { - downloadAsFile(json); + onClick(_, __, host) { + host.actions.downloadAsFile(); } }; diff --git a/src/discovery/flash-messages.js b/src/discovery/flash-messages.js index dc305be..890b591 100644 --- a/src/discovery/flash-messages.js +++ b/src/discovery/flash-messages.js @@ -1,27 +1,20 @@ import { utils } from '@discoveryjs/discovery'; -const flashMessagesContainer = utils.createElement('div', 'flash-messages-container'); -let renderEl; - export default function(host) { + const flashMessagesContainer = utils.createElement('div', 'flash-messages-container'); + host.dom.container.append(flashMessagesContainer); - renderEl = (config, data, context) => { + + host.action.define('flashMessage', async(text, type) => { const fragment = document.createDocumentFragment(); - return host.view.render(fragment, config, data, context) - .then(() => fragment.firstChild); - }; -} + await host.view.render(fragment, { + view: `alert-${type}`, + content: 'text' + }, text); -export function flashMessage(text, type) { - if (typeof renderEl !== 'function') { - return; - } + const el = fragment.firstChild; - renderEl({ - view: `alert-${type}`, - content: 'text' - }, text).then((el) => { flashMessagesContainer.append(el); setTimeout(() => el.classList.add('ready-to-remove'), 1250); setTimeout(() => el.remove(), 1500); diff --git a/src/discovery/img/collapse-all.svg b/src/discovery/img/collapse-all.svg new file mode 100644 index 0000000..0232cdb --- /dev/null +++ b/src/discovery/img/collapse-all.svg @@ -0,0 +1,3 @@ + diff --git a/src/discovery/img/expand-all.svg b/src/discovery/img/expand-all.svg new file mode 100644 index 0000000..3928a16 --- /dev/null +++ b/src/discovery/img/expand-all.svg @@ -0,0 +1,3 @@ + diff --git a/src/discovery/index.js b/src/discovery/index.js index 09419f0..a49eede 100644 --- a/src/discovery/index.js +++ b/src/discovery/index.js @@ -1,55 +1,30 @@ -import { Widget, router } from '@discoveryjs/discovery'; +import './discovery.css'; +import { version } from '../../package.json'; +import { App } from '@discoveryjs/discovery'; +import joraHelpers from './jora-helpers'; import flashMessages from './flash-messages'; import navbar from './navbar'; import * as pages from './pages'; /** * Discovery initialization - * @param {Object} options - * @param {Object} data - * @returns {Discovery} */ -export function initDiscovery(options, data) { - const { settings, version, progressbar, raw } = options; - const { darkmode = 'auto' } = settings; - const discovery = new Widget({ - defaultPage: null, - container: options.node, +export function initDiscovery() { + const discovery = new App({ + styles: [{ type: 'link', href: 'sandbox.css' }], + embed: true, inspector: true, - darkmode, - darkmodePersistent: false, - styles: [{ type: 'link', href: chrome.runtime.getURL('discovery.css') }] + darkmodePersistent: true, + extensions: [ + flashMessages, + navbar, + pages + ], + setup: ({ addQueryHelpers }) => { + addQueryHelpers(joraHelpers); + } }); - discovery.raw = raw; // TODO: move to context? - discovery.apply(router); - discovery.apply(flashMessages); - discovery.apply(navbar); - discovery.apply(pages); - - discovery.setPrepare((_, { addQueryHelpers }) => { - addQueryHelpers({ - weight(current, prec = 1) { - const unit = ['bytes', 'kB', 'MB', 'GB']; - - while (current > 1000) { - current = current / 1000; - unit.shift(); - } - - return current.toFixed(prec).replace(/\.0+$/, '') + unit[0]; - } - }); - }); - - return discovery.setDataProgress( - data, - { - name: options.title, - settings, - version, - createdAt: new Date().toISOString() // TODO fix in discovery - }, - progressbar - ); + discovery.nav.remove('index-page'); + discovery.version = version; } diff --git a/src/discovery/jora-helpers.js b/src/discovery/jora-helpers.js new file mode 100644 index 0000000..fe36f0a --- /dev/null +++ b/src/discovery/jora-helpers.js @@ -0,0 +1,12 @@ +export default { + weight(current, prec = 1) { + const unit = ['bytes', 'kB', 'MB', 'GB']; + + while (current > 1000) { + current = current / 1000; + unit.shift(); + } + + return current.toFixed(prec).replace(/\.0+$/, '') + unit[0]; + } +}; diff --git a/src/discovery/navbar.js b/src/discovery/navbar.js index 4750bc9..750800e 100644 --- a/src/discovery/navbar.js +++ b/src/discovery/navbar.js @@ -1,12 +1,9 @@ -import { navButtons } from '@discoveryjs/discovery'; -import copyText from '@discoveryjs/discovery/src/core/utils/copy-text'; -import { downloadAsFile } from './download-as-file'; -import { flashMessage } from './flash-messages'; +import copyText from '@discoveryjs/discovery/lib/core/utils/copy-text.js'; import { showWhatsNew, setWhatsnewViewed } from './pages/whatsnew'; export default host => { host.nav.append({ - when: () => showWhatsNew(host.context) && host.pageId !== 'whatsnew', + when: () => showWhatsNew(host.version) && host.pageId !== 'whatsnew', content: 'text:"What\'s new"', onClick: () => { host.setPage('whatsnew'); @@ -15,23 +12,19 @@ export default host => { }); host.nav.append({ content: 'text:"Copy URL"', - onClick: () => - copyText(window.location.toString()) & - flashMessage('URL copied to clipboard', 'success') + async onClick() { + copyText(await host.action.call('permalink')); + host.action.call('flashMessage', 'URL copied to clipboard', 'success'); + } }); host.nav.append({ when: () => host.pageId !== 'default', content: 'text:"Default view"', - onClick: () => { + onClick() { host.setPage('default'); - history.replaceState(null, null, ' '); + history.replaceState(null, null, ' '); // ???? } }); - host.nav.append({ - when: () => host.pageId !== 'discovery', - content: 'text:"Discover"', - onClick: () => host.setPage('discovery') - }); host.nav.append({ when: () => host.pageId !== 'raw', content: 'text:"JSON"', @@ -40,23 +33,34 @@ export default host => { el.title = 'Show JSON as is'; } }); - host.apply(navButtons.inspect); host.nav.menu.append({ content: 'text:"Download JSON as file"', - onClick: (_, { hide }) => hide() & downloadAsFile(host.raw.json) + onClick(_, { hide }) { + hide(); + host.action.call('downloadAsFile'); + } }); host.nav.menu.append({ content: 'text:"Copy JSON to clipboard"', - onClick: (_, { hide }) => hide() & - copyText(host.raw.json) & - flashMessage('JSON copied to clipboard', 'success') + async onClick(_, { hide }) { + hide(); + await host.action.call('copyToClipboard'); + host.action.call('flashMessage', 'JSON copied to clipboard', 'success'); + } }); host.nav.menu.append({ content: 'text:"Settings"', - onClick: (_, { hide }) => hide() & host.setPage('settings') + onClick(_, { hide }) { + hide(); + host.setPage('settings'); + } }); host.nav.menu.append({ content: 'text:"What\'s new"', - onClick: (_, { hide }) => hide() & host.setPage('whatsnew') & setWhatsnewViewed(host.context) + onClick(_, { hide }) { + hide(); + host.setPage('whatsnew'); + setWhatsnewViewed(host.context); + } }); }; diff --git a/src/discovery/pages/default.js b/src/discovery/pages/default.js index 2676499..3b94123 100644 --- a/src/discovery/pages/default.js +++ b/src/discovery/pages/default.js @@ -12,35 +12,31 @@ export default host => { downloadAsFileButton, { view: 'block', + data: '"getSettings".callAction()', content: [ + function(el, config, data, context) { + context.expandLevel = data.expandLevel; + }, { view: 'button', className: 'collapse-all', - content: 'text:"-"', + tooltip: 'text:"Collapse all"', onClick(el, data, { onChange }) { onChange(1, 'expandLevel'); }, postRender(el, config, data, context) { context.onChange = config.onChange; - el.title = 'Collapse all'; - el.innerHTML = ''; } }, { view: 'button', className: 'expand-all', - content: 'text:"+"', + tooltip: 'text:"Expand all"', onClick(el, data, { onChange }) { onChange(100, 'expandLevel'); }, postRender(el, config, data, context) { context.onChange = config.onChange; - el.title = 'Expand all'; - el.innerHTML = ''; } } ] @@ -49,7 +45,8 @@ export default host => { }, content: { view: 'struct', - expanded: '=+(#.expandLevel or #.settings.expandLevel)' + expanded: '=+(#.expandLevel or "getSettings".callAction().expandLevel)', + data: '#.data' } }); }; diff --git a/src/discovery/pages/raw.js b/src/discovery/pages/raw.js index f25101e..5c70282 100644 --- a/src/discovery/pages/raw.js +++ b/src/discovery/pages/raw.js @@ -2,34 +2,46 @@ import { copyToClipboardButton } from '../copy-to-clipboard'; import { downloadAsFileButton } from '../download-as-file'; export default host => { - host.view.define('raw', (el, _, raw) => { + host.view.define('raw', async function(el) { const contentEl = el.appendChild(document.createElement('pre')); contentEl.className = 'content'; - if (raw.firstSlice) { - contentEl.append(raw.firstSlice); - host.view.render(el, { + const { + firstSliceText, + firstSliceSize, + fullSize + } = await host.action.call('getRaw'); + + contentEl.append(firstSliceText); + + if (firstSliceSize < fullSize) { + this.render(el, { view: 'alert-warning', className: 'too-big-json', content: [ - 'text:`JSON is too big (${size.weight()} bytes), only first ${firstSlice.size().weight()} is shown. Output the entire JSON may cause to browser\'s tab freezing for a while. `', + 'text:`JSON is too big (${fullSize.weight()} bytes), only first ${firstSliceSize.weight()} is shown. Output the entire JSON may cause to browser\'s tab freezing for a while. `', { view: 'button', content: 'text:"Show all"', onClick(el) { const alertEl = el.parentNode; + alertEl.textContent = 'Output entire JSON...'; - setTimeout(() => { - contentEl.append(raw.json.slice(raw.firstSlice.length)); + + setTimeout(async() => { + const { json } = await host.action.call('getRawFull'); + + contentEl.textContent = json; alertEl.remove(); }, 50); } } ] - }, raw); - } else { - contentEl.append(raw.json); + }, { + firstSliceSize, + fullSize + }); } }); diff --git a/src/discovery/pages/settings.js b/src/discovery/pages/settings.js index 43bbe64..24df0a1 100644 --- a/src/discovery/pages/settings.js +++ b/src/discovery/pages/settings.js @@ -74,8 +74,12 @@ export default host => { } ].map(content => ({ view: 'fieldset', content })); - host.page.define('settings', function(el, data, context) { - const { settings } = context; + host.page.define('settings', async function(el, data) { + if (!data) { + return; + } + + const settings = await host.query('"getSettings".callAction()', data); host.view.render(el, [ 'h1:"JsonDiscovery settings"', @@ -103,16 +107,11 @@ export default host => { const { valid, errors } = validate(settings); if (valid) { - if (typeof chrome !== 'undefined') { - chrome.storage.sync.set(settings); - } else if (typeof safari !== 'undefined') { - safari.extension.dispatchMessage('setSettings', settings); - } + host.query(`"setSettings".callAction(${JSON.stringify(settings)})`, host.data); - host.context.settings = settings; - host.flashMessage('Options saved.', 'success'); + host.action.call('flashMessage', 'Options saved.', 'success'); } else { - host.flashMessage(errors.join(' '), 'danger'); + host.action.call('flashMessage', errors.join(' '), 'danger'); } } diff --git a/src/discovery/pages/whatsnew.js b/src/discovery/pages/whatsnew.js index d3197e2..1fe153b 100644 --- a/src/discovery/pages/whatsnew.js +++ b/src/discovery/pages/whatsnew.js @@ -8,12 +8,9 @@ export const setWhatsnewViewed = ({ version }) => { } }; export const showWhatsNew = context => { - const { version } = context; + const { version } = context || {}; return !version ? false : !( - context && - context.settings && - context.settings.whatsnew && - context.settings.whatsnew[version] + context?.settings?.whatsnew?.[version] ); }; diff --git a/src/manifest.js b/src/manifest.js index d41359e..f633279 100644 --- a/src/manifest.js +++ b/src/manifest.js @@ -8,7 +8,7 @@ module.exports = function(browser = 'chrome') { manifest.version = packageJson.version; if (browser === 'firefox') { - manifest.applications = { + manifest.browser_specific_settings = { // eslint-disable-line camelcase gecko: { id: 'jsondiscovery@exdis.me', strict_min_version: '57.0' // eslint-disable-line camelcase diff --git a/src/manifest.json b/src/manifest.json index 562a4dc..3e4171d 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -4,31 +4,40 @@ "short_name": "JsonDiscovery", "description": "Browser extension that changes the way you're viewing JSON", "author": "exdis", - "manifest_version": 2, + "manifest_version": 3, "icons": { "16": "icons/16.png", "48": "icons/48.png", "128": "icons/128.png" }, "permissions": [ - "", "storage" ], + "host_permissions": [ + "*://*/*" + ], "content_scripts": [{ "js": ["init.js"], "run_at": "document_start", "matches": [" "] }], - "background": { - "scripts": ["background.js"] + "sandbox": { + "pages": [ + "sandbox.html" + ] }, "web_accessible_resources": [ - "discovery.css", - "discovery.js", - "discovery-esm.js", - "preloader.css", - "icons/*", - "assets/*" + { + "resources": [ + "sandbox.html", + "sandbox.js", + "icons/*", + "assets/*" + ], + "matches": [ + " " + ] + } ], "offline_enabled": true } diff --git a/src/sandbox.html b/src/sandbox.html new file mode 100644 index 0000000..4495db1 --- /dev/null +++ b/src/sandbox.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/src/sandbox.js b/src/sandbox.js new file mode 100644 index 0000000..8cbacd4 --- /dev/null +++ b/src/sandbox.js @@ -0,0 +1,3 @@ +import { initDiscovery } from './discovery'; + +initDiscovery();