diff --git a/CHANGELOG.md b/CHANGELOG.md index da50dda27..6b5e43f2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ By far most changes relate to `atomic-server`, so if not specified, assume the c **Changes to JS assets (including the front-end and JS libraries) are not shown here**, but in [`/browser/CHANGELOG`](/browser/CHANGELOG.md). See [STATUS.md](server/STATUS.md) to learn more about which features will remain stable. +## Unreleased + +- The download endpoint can now optimize images on the fly. This is controlled via query parameters. #257 + ## [v0.38.0] - 2024-06-08 - Remove `process-management` feature #324 #334 diff --git a/Cargo.lock b/Cargo.lock index c6ce0bb80..215557cba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,6 +373,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "alloc-no-stdlib" version = "2.0.3" @@ -409,12 +415,41 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "arc-swap" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "askama_escape" version = "0.10.3" @@ -483,11 +518,13 @@ dependencies = [ "directories", "dotenv", "futures", + "image", "instant-acme", "opentelemetry", "opentelemetry-jaeger", "percent-encoding", "rand 0.8.5", + "ravif", "rcgen", "regex", "rio_api", @@ -511,6 +548,7 @@ dependencies = [ "ureq", "urlencoding", "walkdir", + "webp", ] [[package]] @@ -560,6 +598,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] + [[package]] name = "base64" version = "0.13.0" @@ -581,6 +642,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -602,6 +669,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "bitstream-io" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499" + [[package]] name = "block-buffer" version = "0.10.3" @@ -643,18 +716,36 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + [[package]] name = "bumpalo" version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.2.1" @@ -698,6 +789,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -760,7 +861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" dependencies = [ "ciborium-io", - "half", + "half 1.8.2", ] [[package]] @@ -784,7 +885,7 @@ version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro-error", "proc-macro2", "quote", @@ -811,6 +912,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colored" version = "2.0.0" @@ -1300,6 +1407,22 @@ dependencies = [ "str-buf", ] +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half 2.4.1", + "lebe", + "miniz_oxide 0.7.4", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fastdivide" version = "0.4.0" @@ -1323,6 +1446,15 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "firestorm" version = "0.5.1" @@ -1336,7 +1468,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.5.4", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin 0.9.8", ] [[package]] @@ -1527,6 +1668,16 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "glob" version = "0.3.1" @@ -1558,6 +1709,16 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1589,6 +1750,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1759,6 +1926,45 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d" +dependencies = [ + "byteorder-lite", + "thiserror", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "impl-more" version = "0.1.6" @@ -1820,6 +2026,17 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "io-lifetimes" version = "0.7.3" @@ -1855,6 +2072,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -1896,6 +2122,12 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.67" @@ -1946,6 +2178,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "levenshtein_automata" version = "0.2.1" @@ -1958,6 +2196,27 @@ version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + +[[package]] +name = "libwebp-sys" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829b6b604f31ed6d2bccbac841fe0788de93dbd87e4eb1ba2c4adfe8c012a838" +dependencies = [ + "cc", + "glob", +] + [[package]] name = "linux-raw-sys" version = "0.0.46" @@ -2041,6 +2300,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "lru" version = "0.11.1" @@ -2103,6 +2371,16 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "measure_time" version = "0.8.2" @@ -2168,6 +2446,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "mio" version = "0.8.4" @@ -2192,6 +2480,15 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e" +[[package]] +name = "nasm-rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4d98d0065f4b1daf164b3eafb11974c94662e5e2396cf03f32d0bb5c17da51" +dependencies = [ + "rayon", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -2236,6 +2533,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "ntest" version = "0.9.0" @@ -2279,6 +2582,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -2289,6 +2614,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -2704,6 +3041,19 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.7.4", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -2793,6 +3143,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.38", +] + [[package]] name = "promptly" version = "0.3.1" @@ -2802,6 +3171,21 @@ dependencies = [ "rustyline", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.33" @@ -2902,11 +3286,63 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cc", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "nasm-rs", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ba61c28ba24c0cf8406e025cb29a742637e3f70776e61c27a8a8b72a042d12" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + [[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3007,6 +3443,15 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "rgb" +version = "0.8.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade4539f42266ded9e755c605bdddf546242b2c961b03b06a7375260788a0523" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.16.20" @@ -3453,6 +3898,21 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "simple-server-timing-header" version = "0.1.1" @@ -3536,6 +3996,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "stable_deref_trait" @@ -3614,6 +4077,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.8", + "version-compare", +] + [[package]] name = "tantivy" version = "0.21.1" @@ -3754,6 +4230,12 @@ dependencies = [ "serde", ] +[[package]] +name = "target-lexicon" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" + [[package]] name = "tempfile" version = "3.8.1" @@ -3860,6 +4342,17 @@ dependencies = [ "threadpool", ] +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.1.44" @@ -4250,12 +4743,29 @@ dependencies = [ "serde", ] +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.4" @@ -4384,6 +4894,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f53152f51fb5af0c08484c33d16cca96175881d1f3dec068c23b31a158c2d99" +dependencies = [ + "image", + "libwebp-sys", +] + [[package]] name = "webpki" version = "0.22.2" @@ -4403,6 +4923,12 @@ dependencies = [ "webpki", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "which" version = "4.3.0" @@ -4830,3 +5356,27 @@ dependencies = [ "cc", "pkg-config", ] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +dependencies = [ + "zune-core", +] diff --git a/browser/CHANGELOG.md b/browser/CHANGELOG.md index d8f99656a..115d58560 100644 --- a/browser/CHANGELOG.md +++ b/browser/CHANGELOG.md @@ -32,6 +32,11 @@ This changelog covers all five packages, as they are (for now) updated as a whol - BREAKING CHANGE: Removed the `useLocalStorage` hook. - When using any `useValue` type hook, values will now update when local changes are made to the resource from elsewhere in the app. +- [#257](https://github.com/atomicdata-dev/atomic-server/issues/257) Added `` component that automatically optimizes images for the web. + +### @tomic/svelte + +- [#257](https://github.com/atomicdata-dev/atomic-server/issues/257) Added `` component that automatically optimizes images for the web. ## v0.38.0 diff --git a/browser/data-browser/src/components/Thumbnail.tsx b/browser/data-browser/src/components/Thumbnail.tsx index ddc82e8b9..40f5e37f9 100644 --- a/browser/data-browser/src/components/Thumbnail.tsx +++ b/browser/data-browser/src/components/Thumbnail.tsx @@ -1,32 +1,32 @@ import { styled } from 'styled-components'; +import { Image } from '@tomic/react'; import { InnerWrapper } from '../views/FolderPage/GridItem/components'; interface ThumbnailProps { - src: string | undefined; + subject: string; style?: React.CSSProperties | undefined; } -export function Thumbnail({ src, style }: ThumbnailProps): JSX.Element { - if (src === undefined) { - return No preview available; - } - +export function Thumbnail({ subject, style }: ThumbnailProps): JSX.Element { return ( - + ); } -const Image = styled.img` +const StyledImage = styled(Image)` width: 100%; height: 100%; object-fit: cover; object-position: center; `; - -const TextWrapper = styled(InnerWrapper)` - display: grid; - place-items: center; - color: ${p => p.theme.colors.textLight}; -`; diff --git a/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx b/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx index 299ba775a..1fc957153 100644 --- a/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx +++ b/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx @@ -2,7 +2,13 @@ import { useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { FaEdit } from 'react-icons/fa'; import { styled } from 'styled-components'; -import { useProperty, useValue, Datatype, Resource } from '@tomic/react'; +import { + useProperty, + useValue, + Datatype, + Resource, + useCanWrite, +} from '@tomic/react'; import ValueComp from '../../ValueComp'; import { useSettings } from '../../../helpers/AppSettings'; import { ValueFormEdit } from './ValueFormEdit'; @@ -27,6 +33,7 @@ export function ValueForm({ resource, propertyURL, datatype }: ValueFormProps) { const property = useProperty(propertyURL); const [value] = useValue(resource, propertyURL); const { agent } = useSettings(); + const [canWrite] = useCanWrite(resource); useHotkeys( 'esc', @@ -40,6 +47,8 @@ export function ValueForm({ resource, propertyURL, datatype }: ValueFormProps) { const hasAgent = agent !== undefined; + const shouldShowEditButton = hasAgent && canWrite && !property.isDynamic; + if (value === undefined) { return null; } @@ -52,7 +61,7 @@ export function ValueForm({ resource, propertyURL, datatype }: ValueFormProps) { return ( - {hasAgent && ( + {shouldShowEditButton && ( setEditMode(!editMode)} /> diff --git a/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx b/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx index ba1d73fbe..460f77276 100644 --- a/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx +++ b/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx @@ -39,14 +39,14 @@ function FilePreviewThumbnailInner({ }: FilePreviewThumbnailProps): JSX.Element { const { downloadUrl, mimeType, bytes } = useFileInfo(resource); const previewSizeLimit = useFilePreviewSizeLimit(); - const transitionStyles = useFileImageTransitionStyles(resource.getSubject()); + const transitionStyles = useFileImageTransitionStyles(resource.subject); if (bytes >= previewSizeLimit) { return To large for preview; } if (isImageFile(mimeType)) { - return ; + return ; } if (isTextFile(mimeType)) { diff --git a/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx index 51d5bfa77..bd56486f4 100644 --- a/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx +++ b/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx @@ -1,4 +1,4 @@ -import { Server, useResource, useSubject } from '@tomic/react'; +import { unknownSubject, useSubject } from '@tomic/react'; import { atomicArgu } from '../../../ontologies/atomic-argu'; import { GridItemViewProps } from './GridItemViewProps'; @@ -10,7 +10,5 @@ export function ArticleGridItem({ resource }: GridItemViewProps): JSX.Element { atomicArgu.properties.coverImage, ); - const coverImg = useResource(coverImgSubject); - - return ; + return ; } diff --git a/browser/data-browser/src/views/ResourceInline/FileInline.tsx b/browser/data-browser/src/views/ResourceInline/FileInline.tsx index 4b7b3322b..165ff25f7 100644 --- a/browser/data-browser/src/views/ResourceInline/FileInline.tsx +++ b/browser/data-browser/src/views/ResourceInline/FileInline.tsx @@ -1,15 +1,15 @@ -import { useString, properties, useResource } from '@tomic/react'; +import { useString, useResource, server, Image } from '@tomic/react'; import { imageMimeTypes, getFileIcon } from '../../helpers/filetypes'; import { ResourceInlineInstanceProps } from './ResourceInline'; import { styled } from 'styled-components'; +const THUMB_SIZE = '2rem'; export function FileInline({ subject, }: ResourceInlineInstanceProps): JSX.Element { const resource = useResource(subject); - const [filename] = useString(resource, properties.file.filename); - const [mimeType] = useString(resource, properties.file.mimetype); - const [downloadUrl] = useString(resource, properties.file.downloadUrl); + const [filename] = useString(resource, server.properties.filename); + const [mimeType] = useString(resource, server.properties.mimetype); const isImage = imageMimeTypes.has(mimeType ?? ''); const Icon = getFileIcon(mimeType ?? ''); @@ -17,7 +17,12 @@ export function FileInline({ return ( {isImage ? ( - {resource.title} + {resource.title} ) : ( )} @@ -29,16 +34,16 @@ export function FileInline({ const Wrapper = styled.span` display: inline-flex; align-items: center; - height: 2rem; + height: ${THUMB_SIZE}; gap: 0.7ch; & svg { font-size: 1rem; } `; -const Img = styled.img` - aspect-ratio: 1/1; +const Img = styled(Image)` object-fit: cover; border-radius: 5px; - height: 100%; + height: ${THUMB_SIZE}; + width: ${THUMB_SIZE}; `; diff --git a/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/FileCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/FileCell.tsx index 075afd7a2..b9324d2ea 100644 --- a/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/FileCell.tsx +++ b/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/FileCell.tsx @@ -1,4 +1,4 @@ -import { properties, useResource, useString, useTitle } from '@tomic/react'; +import { useResource, useString, useTitle, Image, server } from '@tomic/react'; import { styled } from 'styled-components'; import { getFileIcon, imageMimeTypes } from '../../../../helpers/filetypes'; @@ -8,8 +8,7 @@ import { SimpleResourceLink } from './SimpleResourceLink'; export function FileCell({ subject }: ResourceCellProps) { const resource = useResource(subject); const [title] = useTitle(resource); - const [mimeType] = useString(resource, properties.file.mimetype); - const [downloadUrl] = useString(resource, properties.file.downloadUrl); + const [mimeType] = useString(resource, server.properties.mimetype); const isImage = imageMimeTypes.has(mimeType ?? ''); const Icon = getFileIcon(mimeType ?? ''); @@ -18,7 +17,12 @@ export function FileCell({ subject }: ResourceCellProps) { {isImage ? ( - {title} + {title} ) : ( @@ -28,11 +32,13 @@ export function FileCell({ subject }: ResourceCellProps) { ); } -const Img = styled.img` +const Img = styled(Image)` width: calc(var(--table-row-height) - 6px); + height: calc(var(--table-row-height) - 6px); aspect-ratio: 1/1; object-fit: cover; border-radius: 5px; + vertical-align: middle; `; const Wrapper = styled.div` @@ -45,4 +51,5 @@ const Wrapper = styled.div` const StyledLink = styled(SimpleResourceLink)` display: flex; height: fit-content; + align-items: center; `; diff --git a/browser/lib/src/ontologies/server.ts b/browser/lib/src/ontologies/server.ts index c12319fd6..8ebf253dd 100644 --- a/browser/lib/src/ontologies/server.ts +++ b/browser/lib/src/ontologies/server.ts @@ -43,6 +43,8 @@ export const server = { 'https://atomicdata.dev/ontology/server/property/response-message', defaultOntology: 'https://atomicdata.dev/ontology/server/property/default-ontology', + imageWidth: 'https://atomicdata.dev/properties/imageWidth', + imageHeight: 'https://atomicdata.dev/properties/imageHeight', }, } as const; @@ -92,7 +94,9 @@ declare module '../index.js' { | typeof server.properties.filename | typeof server.properties.checksum | typeof server.properties.mimetype - | typeof server.properties.internalId; + | typeof server.properties.internalId + | typeof server.properties.imageWidth + | typeof server.properties.imageHeight; }; [server.classes.invite]: { requires: BaseProps | typeof server.properties.target; @@ -136,6 +140,8 @@ declare module '../index.js' { [server.properties.status]: number; [server.properties.responseMessage]: string; [server.properties.defaultOntology]: string; + [server.properties.imageWidth]: number; + [server.properties.imageHeight]: number; } interface PropSubjectToNameMapping { @@ -163,5 +169,7 @@ declare module '../index.js' { [server.properties.status]: 'status'; [server.properties.responseMessage]: 'responseMessage'; [server.properties.defaultOntology]: 'defaultOntology'; + [server.properties.imageWidth]: 'imageWidth'; + [server.properties.imageHeight]: 'imageHeight'; } } diff --git a/browser/pnpm-lock.yaml b/browser/pnpm-lock.yaml index 6c62362f9..797274e65 100644 --- a/browser/pnpm-lock.yaml +++ b/browser/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: version: 6.7.1(eslint@8.57.0) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) + version: 5.1.3(@types/eslint@9.6.0)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) eslint-plugin-react: specifier: ^7.28.0 version: 7.33.1(eslint@8.57.0) @@ -375,28 +375,61 @@ importers: '@tomic/lib': specifier: workspace:* version: link:../lib - svelte: - specifier: ^3.55.0 - version: 3.59.2 devDependencies: - '@rollup/plugin-typescript': - specifier: ^10.0.1 - version: 10.0.1(rollup@2.79.1)(tslib@2.6.1)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^5.47.0 - version: 5.62.0(eslint@8.57.0)(typescript@5.4.5) - rollup-plugin-typescript-paths: - specifier: ^1.4.0 - version: 1.4.0(typescript@5.4.5) - tslib: - specifier: ^2.4.1 - version: 2.6.1 + '@sveltejs/adapter-auto': + specifier: ^3.0.0 + version: 3.2.2(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0))) + '@sveltejs/kit': + specifier: ^2.0.0 + version: 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + '@sveltejs/package': + specifier: ^2.0.0 + version: 2.3.2(svelte@4.2.18)(typescript@5.4.5) + '@sveltejs/vite-plugin-svelte': + specifier: ^3.0.0 + version: 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + '@types/eslint': + specifier: ^9.6.0 + version: 9.6.0 + eslint: + specifier: ^9.0.0 + version: 9.8.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@9.8.0) + eslint-plugin-svelte: + specifier: ^2.36.0 + version: 2.43.0(eslint@9.8.0)(svelte@4.2.18)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)) + globals: + specifier: ^15.0.0 + version: 15.9.0 + prettier: + specifier: ^3.1.1 + version: 3.2.5 + prettier-plugin-svelte: + specifier: ^3.1.2 + version: 3.2.6(prettier@3.2.5)(svelte@4.2.18) + publint: + specifier: ^0.1.9 + version: 0.1.16 + svelte: + specifier: ^4.2.7 + version: 4.2.18 + svelte-check: + specifier: ^3.6.0 + version: 3.8.5(@babel/core@7.24.5)(postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)))(postcss@8.4.40)(svelte@4.2.18) typescript: specifier: ^5.4.5 version: 5.4.5 + typescript-eslint: + specifier: ^8.0.0 + version: 8.0.0(eslint@9.8.0)(typescript@5.4.5) + vite: + specifier: ^5.0.11 + version: 5.3.5(@types/node@20.11.5)(terser@5.31.0) vitest: - specifier: ^0.34.6 - version: 0.34.6(playwright@1.43.1)(terser@5.31.0) + specifier: ^2.0.0 + version: 2.0.5(@types/node@20.11.5)(terser@5.31.0) packages: @@ -1632,6 +1665,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.19.2': resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} engines: {node: '>=12'} @@ -1650,6 +1689,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.19.2': resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} engines: {node: '>=12'} @@ -1668,6 +1713,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.19.2': resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} engines: {node: '>=12'} @@ -1686,6 +1737,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.19.2': resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} engines: {node: '>=12'} @@ -1704,6 +1761,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.19.2': resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} engines: {node: '>=12'} @@ -1722,6 +1785,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.19.2': resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} engines: {node: '>=12'} @@ -1740,6 +1809,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.19.2': resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} engines: {node: '>=12'} @@ -1758,6 +1833,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.19.2': resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} engines: {node: '>=12'} @@ -1776,6 +1857,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.19.2': resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} engines: {node: '>=12'} @@ -1794,6 +1881,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.19.2': resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} engines: {node: '>=12'} @@ -1812,6 +1905,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.19.2': resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} engines: {node: '>=12'} @@ -1830,6 +1929,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.19.2': resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} engines: {node: '>=12'} @@ -1848,6 +1953,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.19.2': resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} engines: {node: '>=12'} @@ -1866,6 +1977,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.19.2': resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} engines: {node: '>=12'} @@ -1884,6 +2001,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.19.2': resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} engines: {node: '>=12'} @@ -1902,6 +2025,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.19.2': resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} engines: {node: '>=12'} @@ -1920,6 +2049,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.19.2': resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} engines: {node: '>=12'} @@ -1938,6 +2073,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-x64@0.19.2': resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} engines: {node: '>=12'} @@ -1956,6 +2097,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.19.2': resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} engines: {node: '>=12'} @@ -1974,6 +2121,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.19.2': resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} engines: {node: '>=12'} @@ -1992,6 +2145,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.19.2': resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==} engines: {node: '>=12'} @@ -2010,6 +2169,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.19.2': resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} engines: {node: '>=12'} @@ -2028,6 +2193,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2038,18 +2209,38 @@ packages: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.6.2': resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.17.1': + resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@8.57.0': resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/js@9.8.0': + resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@esm-bundle/chai@4.3.4': resolution: {integrity: sha512-6Tx35wWiNw7X0nLY9RMx8v3EL8SacCFW+eEZOE9Hc+XxmU5HFE2AFEg+GehUZpiyDGwVvPH75ckGlqC7coIPnA==} @@ -2118,6 +2309,10 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + '@import-maps/resolve@1.0.1': resolution: {integrity: sha512-tWZNBIS1CoekcwlMuyG2mr0a1Wo5lb5lEHwwWvZo+5GLgr3e9LLDTtmgtCWEwBpXMkxn9D+2W9j2FY6eZQq0tA==} @@ -2679,6 +2874,9 @@ packages: resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} engines: {node: '>=12'} + '@polka/url@1.0.0-next.25': + resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -3160,19 +3358,6 @@ packages: rollup: optional: true - '@rollup/plugin-typescript@10.0.1': - resolution: {integrity: sha512-wBykxRLlX7EzL8BmUqMqk5zpx2onnmRMSw/l9M1sVfkJvdwfxogZQVNUM9gVMJbjRLDR5H6U0OMOrlDGmIV45A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.14.0||^3.0.0 - tslib: '*' - typescript: '>=3.7.0' - peerDependenciesMeta: - rollup: - optional: true - tslib: - optional: true - '@rollup/pluginutils@3.1.0': resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} @@ -3183,15 +3368,6 @@ packages: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} - '@rollup/pluginutils@5.0.2': - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/pluginutils@5.1.0': resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} engines: {node: '>=14.0.0'} @@ -3403,6 +3579,42 @@ packages: '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + '@sveltejs/adapter-auto@3.2.2': + resolution: {integrity: sha512-Mso5xPCA8zgcKrv+QioVlqMZkyUQ5MjDJiEPuG/Z7cV/5tmwV7LmcVWk5tZ+H0NCOV1x12AsoSpt/CwFwuVXMA==} + peerDependencies: + '@sveltejs/kit': ^2.0.0 + + '@sveltejs/kit@2.5.20': + resolution: {integrity: sha512-47rJ5BoYwURE/Rp7FNMLp3NzdbWC9DQ/PmKd0mebxT2D/PrPxZxcLImcD3zsWdX2iS6oJk8ITJbO/N2lWnnUqA==} + engines: {node: '>=18.13'} + hasBin: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 + + '@sveltejs/package@2.3.2': + resolution: {integrity: sha512-6M8/Te7iXRG7SiH92wugqfyoJpuepjn78L433LnXicUeMso9M/N4vdL9DPK3MfTkVVY4klhNRptVqme3p4oZWA==} + engines: {node: ^16.14 || >=18} + hasBin: true + peerDependencies: + svelte: ^3.44.0 || ^4.0.0 || ^5.0.0-next.1 + + '@sveltejs/vite-plugin-svelte-inspector@2.1.0': + resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + + '@sveltejs/vite-plugin-svelte@3.1.1': + resolution: {integrity: sha512-rimpFEAboBBHIlzISibg94iP09k/KYdHgVhJlcsTfn7KMBhc70jFX/GRWkRdFCc2fdnk+4+Bdfej23cMDnJS6A==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + '@swc/core-darwin-arm64@1.3.104': resolution: {integrity: sha512-rCnVj8x3kn6s914Adddu+zROHUn6mUEMkNKUckofs3W9OthNlZXJA3C5bS2MMTRFXCWamJ0Zmh6INFpz+f4Tfg==} engines: {node: '>=10'} @@ -3679,6 +3891,9 @@ packages: '@types/chai@4.3.5': resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/d3-array@3.0.7': resolution: {integrity: sha512-4/Q0FckQ8TBjsB0VdGFemJOG8BLXUB2KKlL0VmZ+eOYeOnTb/wDRQqYWpBmQ6IlvWkXwkYiot+n9Px2aTJ7zGQ==} @@ -3775,12 +3990,12 @@ packages: '@types/debug@4.1.8': resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} + '@types/eslint@9.6.0': + resolution: {integrity: sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==} + '@types/estree@0.0.39': resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} - '@types/estree@1.0.1': - resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} - '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -3866,6 +4081,9 @@ packages: '@types/prop-types@15.7.5': resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + '@types/pug@2.0.10': + resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} + '@types/react-dom@18.2.14': resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} @@ -3943,11 +4161,12 @@ packages: typescript: optional: true - '@typescript-eslint/parser@5.62.0': - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/eslint-plugin@8.0.0': + resolution: {integrity: sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: @@ -3963,14 +4182,24 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@5.62.0': - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/parser@8.0.0': + resolution: {integrity: sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true '@typescript-eslint/scope-manager@7.8.0': resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.0.0': + resolution: {integrity: sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@7.8.0': resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3981,6 +4210,15 @@ packages: typescript: optional: true + '@typescript-eslint/type-utils@8.0.0': + resolution: {integrity: sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/types@5.62.0': resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3989,6 +4227,10 @@ packages: resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@8.0.0': + resolution: {integrity: sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4007,12 +4249,27 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.0.0': + resolution: {integrity: sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@7.8.0': resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 + '@typescript-eslint/utils@8.0.0': + resolution: {integrity: sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4021,6 +4278,10 @@ packages: resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@8.0.0': + resolution: {integrity: sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -4037,18 +4298,36 @@ packages: '@vitest/expect@0.34.6': resolution: {integrity: sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==} + '@vitest/expect@2.0.5': + resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + + '@vitest/pretty-format@2.0.5': + resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} + '@vitest/runner@0.34.6': resolution: {integrity: sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==} + '@vitest/runner@2.0.5': + resolution: {integrity: sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==} + '@vitest/snapshot@0.34.6': resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==} + '@vitest/snapshot@2.0.5': + resolution: {integrity: sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==} + '@vitest/spy@0.34.6': resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==} + '@vitest/spy@2.0.5': + resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + '@vitest/utils@0.34.6': resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==} + '@vitest/utils@2.0.5': + resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} + '@volar/language-core@1.11.1': resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} @@ -4136,6 +4415,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -4384,6 +4668,10 @@ packages: assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + assign-symbols@1.0.0: resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} engines: {node: '>=0.10.0'} @@ -4445,6 +4733,10 @@ packages: axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + b4a@1.6.4: resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} @@ -4607,6 +4899,10 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -4708,6 +5004,10 @@ packages: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} + chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} @@ -4745,6 +5045,10 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -4856,6 +5160,9 @@ packages: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} engines: {node: '>=0.10.0'} + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} @@ -5004,6 +5311,10 @@ packages: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + copy-descriptor@0.1.1: resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} engines: {node: '>=0.10.0'} @@ -5078,6 +5389,15 @@ packages: css-to-react-native@3.2.0: resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} @@ -5167,6 +5487,15 @@ packages: supports-color: optional: true + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decache@4.6.2: resolution: {integrity: sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw==} @@ -5197,6 +5526,9 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} + dedent-js@1.0.1: + resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} + dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} @@ -5212,6 +5544,10 @@ packages: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -5279,6 +5615,10 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + detect-libc@2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} @@ -5323,6 +5663,9 @@ packages: resolution: {integrity: sha512-Mq8egjnW2NSCkzEb/Az15/JnBI/Ryyl6Po0Y+0mABTFvOS6DAyUGRZqz1nyhu4QJmWWe0zaGs/ITIBeWkvCkGw==} engines: {node: ^14.14.0 || >=16.0.0} + devalue@5.0.0: + resolution: {integrity: sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -5478,6 +5821,9 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + es6-promisify@6.1.1: resolution: {integrity: sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==} @@ -5496,6 +5842,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -5536,6 +5887,12 @@ packages: engines: {node: '>=6.0'} hasBin: true + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + eslint-config-prettier@9.1.0: resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true @@ -5608,19 +5965,49 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + eslint-plugin-svelte@2.43.0: + resolution: {integrity: sha512-REkxQWvg2pp7QVLxQNa+dJ97xUqRe7Y2JJbSWkHSuszu0VcblZtXkPBPckkivk99y5CdLw4slqfPylL2d/X4jQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.191 + peerDependenciesMeta: + svelte: + optional: true + eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true + eslint@9.8.0: + resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + + esm-env@1.0.0: + resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5648,6 +6035,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -5679,6 +6069,10 @@ packages: resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -5837,6 +6231,10 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + file-selector@0.4.0: resolution: {integrity: sha512-iACCiXeMYOvZqlF1kTiYINzgepRBymz1wwjiuup9u9nayhb6g4fSwiyJ/6adli+EPwrWtpgQAh2PoS7HukEGEg==} engines: {node: '>= 10'} @@ -5915,9 +6313,16 @@ packages: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + flatted@3.2.7: resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + flush-write-stream@2.0.0: resolution: {integrity: sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==} @@ -6075,6 +6480,10 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -6137,10 +6546,21 @@ packages: resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.9.0: + resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} + engines: {node: '>=18'} + globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} + globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -6153,6 +6573,9 @@ packages: resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} engines: {node: '>=0.10.0'} + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + gonzales-pe@4.3.0: resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} engines: {node: '>=0.6.0'} @@ -6341,6 +6764,10 @@ packages: resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} engines: {node: '>=12.20.0'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + husky@8.0.3: resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} engines: {node: '>=14'} @@ -6356,6 +6783,10 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore-walk@5.0.1: + resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -6381,6 +6812,9 @@ packages: engines: {node: '>=8'} hasBin: true + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -6649,6 +7083,9 @@ packages: is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -7042,6 +7479,9 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + known-css-properties@0.34.0: + resolution: {integrity: sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==} + kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} @@ -7085,6 +7525,10 @@ packages: light-my-request@5.11.0: resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==} + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -7129,6 +7573,9 @@ packages: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -7239,6 +7686,12 @@ packages: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 + loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lowercase-keys@1.0.1: resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} engines: {node: '>=0.10.0'} @@ -7393,6 +7846,9 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} @@ -7719,6 +8175,10 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -7783,6 +8243,9 @@ packages: resolution: {integrity: sha512-ByFz8S08HWVKd9r/lkTahZX7xSq4IRyPCUvuaduI4GHyQaSWEdVNK1krC05vlhL9W0SzDn8Yjowh0Ru4PKrOYw==} engines: {node: ^14.16.0 || >=16.0.0} + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -7860,6 +8323,19 @@ packages: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} engines: {node: '>=14.16'} + npm-bundled@2.0.1: + resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-normalize-package-bin@2.0.0: + resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-packlist@5.1.3: + resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -8116,6 +8592,9 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + pascalcase@0.1.1: resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} engines: {node: '>=0.10.0'} @@ -8164,9 +8643,16 @@ packages: pathe@1.1.1: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + pdfjs-dist@2.16.105: resolution: {integrity: sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==} peerDependencies: @@ -8186,9 +8672,15 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -8255,6 +8747,34 @@ packages: resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} engines: {node: '>=0.10.0'} + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-safe-parser@6.0.0: + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-parser@6.1.1: + resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} + engines: {node: '>=4'} + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -8272,6 +8792,10 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.40: + resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} + engines: {node: ^10 || ^12 || >=14} + precinct@11.0.5: resolution: {integrity: sha512-oHSWLC8cL/0znFhvln26D14KfCQFFn4KOLSw6hmLhd+LQ2SKt9Ljm89but76Pc7flM9Ty1TnXyrA2u16MfRV3w==} engines: {node: ^14.14.0 || >=16.0.0} @@ -8299,6 +8823,12 @@ packages: peerDependencies: prettier: ^3.0.0 + prettier-plugin-svelte@3.2.6: + resolution: {integrity: sha512-Y1XWLw7vXUQQZmgv1JAEiLcErqUniAF2wO7QJsw8BVMvpLET2dI5WpEIEJx1r11iHVdSMzQxivyfrH9On9t2IQ==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + prettier@3.0.3: resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} @@ -8437,6 +8967,11 @@ packages: resolution: {integrity: sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + publint@0.1.16: + resolution: {integrity: sha512-wJgk7HnXDT5Ap0DjFYbGz78kPkN44iQvDiaq8P63IEEyNU9mYXvaMd2cAyIM6OgqXM/IA3CK6XWIsRq+wjNpgw==} + engines: {node: '>=16'} + hasBin: true + pump@1.0.3: resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==} @@ -8882,6 +9417,11 @@ packages: rfdc@1.3.0: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -8892,11 +9432,6 @@ packages: peerDependencies: rollup: ^2.0.0 - rollup-plugin-typescript-paths@1.4.0: - resolution: {integrity: sha512-6EgeLRjTVmymftEyCuYu91XzY5XMB5lR0YrJkeT0D7OG2RGSdbNL+C/hfPIdc/sjMa9Sl5NLsxIr6C/+/5EUpA==} - peerDependencies: - typescript: '>=3.4' - rollup@2.79.1: resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} engines: {node: '>=10.0.0'} @@ -8962,6 +9497,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sander@0.5.1: + resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} + scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} @@ -9001,6 +9539,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} @@ -9067,6 +9610,10 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -9116,6 +9663,10 @@ packages: sonic-boom@3.7.0: resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} + sorcery@0.11.1: + resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} + hasBin: true + sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} engines: {node: '>=0.10.0'} @@ -9226,6 +9777,9 @@ packages: std-env@3.4.3: resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==} + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + stdin-discarder@0.1.0: resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -9405,9 +9959,73 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte@3.59.2: - resolution: {integrity: sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==} - engines: {node: '>= 8'} + svelte-check@3.8.5: + resolution: {integrity: sha512-3OGGgr9+bJ/+1nbPgsvulkLC48xBsqsgtc8Wam281H4G9F5v3mYGa2bHRsPuwHC5brKl4AxJH95QF73kmfihGQ==} + hasBin: true + peerDependencies: + svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + + svelte-eslint-parser@0.41.0: + resolution: {integrity: sha512-L6f4hOL+AbgfBIB52Z310pg1d2QjRqm7wy3kI1W6hhdhX5bvu7+f0R6w4ykp5HoDdzq+vGhIJmsisaiJDGmVfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.191 + peerDependenciesMeta: + svelte: + optional: true + + svelte-hmr@0.16.0: + resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + + svelte-preprocess@5.1.4: + resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==} + engines: {node: '>= 16.0.0'} + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + + svelte2tsx@0.7.15: + resolution: {integrity: sha512-91RbLJI448FR1UEZqXSS3ucVMERuWo8ACOhxfkBPK1CL2ocGMOC5bwc8tzFvb/Ji8NqZ7wmSGfvRebcUsiauKA==} + peerDependencies: + svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 + typescript: ^4.9.4 || ^5.0.0 + + svelte@4.2.18: + resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} + engines: {node: '>=16'} symbol-observable@1.2.0: resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} @@ -9495,6 +10113,9 @@ packages: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} engines: {node: '>=4'} + tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + tiny-invariant@1.3.1: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} @@ -9505,14 +10126,29 @@ packages: tinybench@2.5.1: resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinypool@0.7.0: resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} engines: {node: '>=14.0.0'} + tinypool@1.0.0: + resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + tinyspy@2.2.0: resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} engines: {node: '>=14.0.0'} + tinyspy@3.0.0: + resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} + engines: {node: '>=14.0.0'} + tippy.js@6.3.7: resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} @@ -9577,6 +10213,10 @@ packages: tomlify-j0.4@3.0.0: resolution: {integrity: sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ==} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -9745,6 +10385,15 @@ packages: types-wm@1.1.0: resolution: {integrity: sha512-kGecZLoCh4ge8rcRsoMtLs4nuSyi8wl687EfAH9Iss602rFDU/Heih86Awv/6958GwxxDm8gLztkLkrUEsxXug==} + typescript-eslint@8.0.0: + resolution: {integrity: sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + typescript@5.4.2: resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} engines: {node: '>=14.17'} @@ -9985,6 +10634,11 @@ packages: engines: {node: '>=v14.18.0'} hasBin: true + vite-node@2.0.5: + resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + vite-plugin-dts@3.9.0: resolution: {integrity: sha512-pwFIEYQ3LZvMafkEGvNnileb6af5JuyZsBfYQrTDYxdeGEy0OS4B4hCsLPo5YGnhK5k9EzyO6BXVO6y+Lt5T2A==} engines: {node: ^14.18.0 || >=16.0.0} @@ -10068,6 +10722,42 @@ packages: terser: optional: true + vite@5.3.5: + resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitefu@0.2.5: + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@0.34.6: resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} @@ -10099,6 +10789,31 @@ packages: webdriverio: optional: true + vitest@2.0.5: + resolution: {integrity: sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.0.5 + '@vitest/ui': 2.0.5 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} @@ -10168,6 +10883,11 @@ packages: engines: {node: '>=8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -10427,7 +11147,7 @@ snapshots: '@ampproject/remapping@2.2.1': dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/trace-mapping': 0.3.25 '@ampproject/remapping@2.3.0': dependencies: @@ -10469,7 +11189,7 @@ snapshots: '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/compat-data@7.22.9': {} @@ -10612,7 +11332,7 @@ snapshots: '@babel/helper-plugin-utils': 7.22.5 debug: 4.3.4(supports-color@9.4.0) lodash.debounce: 4.0.8 - resolve: 1.22.3 + resolve: 1.22.8 transitivePeerDependencies: - supports-color @@ -10621,7 +11341,7 @@ snapshots: '@babel/core': 7.24.5 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.5 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.6 lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -10784,7 +11504,7 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/parser@7.22.7': dependencies: @@ -12023,7 +12743,7 @@ snapshots: '@dnd-kit/accessibility@3.1.0(react@18.2.0)': dependencies: react: 18.2.0 - tslib: 2.6.1 + tslib: 2.6.2 '@dnd-kit/core@6.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: @@ -12061,6 +12781,9 @@ snapshots: '@esbuild/aix-ppc64@0.20.2': optional: true + '@esbuild/aix-ppc64@0.21.5': + optional: true + '@esbuild/android-arm64@0.19.2': optional: true @@ -12070,6 +12793,9 @@ snapshots: '@esbuild/android-arm64@0.20.2': optional: true + '@esbuild/android-arm64@0.21.5': + optional: true + '@esbuild/android-arm@0.19.2': optional: true @@ -12079,6 +12805,9 @@ snapshots: '@esbuild/android-arm@0.20.2': optional: true + '@esbuild/android-arm@0.21.5': + optional: true + '@esbuild/android-x64@0.19.2': optional: true @@ -12088,6 +12817,9 @@ snapshots: '@esbuild/android-x64@0.20.2': optional: true + '@esbuild/android-x64@0.21.5': + optional: true + '@esbuild/darwin-arm64@0.19.2': optional: true @@ -12097,6 +12829,9 @@ snapshots: '@esbuild/darwin-arm64@0.20.2': optional: true + '@esbuild/darwin-arm64@0.21.5': + optional: true + '@esbuild/darwin-x64@0.19.2': optional: true @@ -12106,6 +12841,9 @@ snapshots: '@esbuild/darwin-x64@0.20.2': optional: true + '@esbuild/darwin-x64@0.21.5': + optional: true + '@esbuild/freebsd-arm64@0.19.2': optional: true @@ -12115,6 +12853,9 @@ snapshots: '@esbuild/freebsd-arm64@0.20.2': optional: true + '@esbuild/freebsd-arm64@0.21.5': + optional: true + '@esbuild/freebsd-x64@0.19.2': optional: true @@ -12124,6 +12865,9 @@ snapshots: '@esbuild/freebsd-x64@0.20.2': optional: true + '@esbuild/freebsd-x64@0.21.5': + optional: true + '@esbuild/linux-arm64@0.19.2': optional: true @@ -12133,6 +12877,9 @@ snapshots: '@esbuild/linux-arm64@0.20.2': optional: true + '@esbuild/linux-arm64@0.21.5': + optional: true + '@esbuild/linux-arm@0.19.2': optional: true @@ -12142,6 +12889,9 @@ snapshots: '@esbuild/linux-arm@0.20.2': optional: true + '@esbuild/linux-arm@0.21.5': + optional: true + '@esbuild/linux-ia32@0.19.2': optional: true @@ -12151,6 +12901,9 @@ snapshots: '@esbuild/linux-ia32@0.20.2': optional: true + '@esbuild/linux-ia32@0.21.5': + optional: true + '@esbuild/linux-loong64@0.19.2': optional: true @@ -12160,6 +12913,9 @@ snapshots: '@esbuild/linux-loong64@0.20.2': optional: true + '@esbuild/linux-loong64@0.21.5': + optional: true + '@esbuild/linux-mips64el@0.19.2': optional: true @@ -12169,6 +12925,9 @@ snapshots: '@esbuild/linux-mips64el@0.20.2': optional: true + '@esbuild/linux-mips64el@0.21.5': + optional: true + '@esbuild/linux-ppc64@0.19.2': optional: true @@ -12178,6 +12937,9 @@ snapshots: '@esbuild/linux-ppc64@0.20.2': optional: true + '@esbuild/linux-ppc64@0.21.5': + optional: true + '@esbuild/linux-riscv64@0.19.2': optional: true @@ -12187,6 +12949,9 @@ snapshots: '@esbuild/linux-riscv64@0.20.2': optional: true + '@esbuild/linux-riscv64@0.21.5': + optional: true + '@esbuild/linux-s390x@0.19.2': optional: true @@ -12196,6 +12961,9 @@ snapshots: '@esbuild/linux-s390x@0.20.2': optional: true + '@esbuild/linux-s390x@0.21.5': + optional: true + '@esbuild/linux-x64@0.19.2': optional: true @@ -12205,6 +12973,9 @@ snapshots: '@esbuild/linux-x64@0.20.2': optional: true + '@esbuild/linux-x64@0.21.5': + optional: true + '@esbuild/netbsd-x64@0.19.2': optional: true @@ -12214,6 +12985,9 @@ snapshots: '@esbuild/netbsd-x64@0.20.2': optional: true + '@esbuild/netbsd-x64@0.21.5': + optional: true + '@esbuild/openbsd-x64@0.19.2': optional: true @@ -12223,6 +12997,9 @@ snapshots: '@esbuild/openbsd-x64@0.20.2': optional: true + '@esbuild/openbsd-x64@0.21.5': + optional: true + '@esbuild/sunos-x64@0.19.2': optional: true @@ -12232,6 +13009,9 @@ snapshots: '@esbuild/sunos-x64@0.20.2': optional: true + '@esbuild/sunos-x64@0.21.5': + optional: true + '@esbuild/win32-arm64@0.19.2': optional: true @@ -12241,6 +13021,9 @@ snapshots: '@esbuild/win32-arm64@0.20.2': optional: true + '@esbuild/win32-arm64@0.21.5': + optional: true + '@esbuild/win32-ia32@0.19.2': optional: true @@ -12250,6 +13033,9 @@ snapshots: '@esbuild/win32-ia32@0.20.2': optional: true + '@esbuild/win32-ia32@0.21.5': + optional: true + '@esbuild/win32-x64@0.19.2': optional: true @@ -12259,15 +13045,33 @@ snapshots: '@esbuild/win32-x64@0.20.2': optional: true + '@esbuild/win32-x64@0.21.5': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.4.0(eslint@9.8.0)': + dependencies: + eslint: 9.8.0 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.11.0': {} + '@eslint-community/regexpp@4.6.2': {} + '@eslint/config-array@0.17.1': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.4(supports-color@9.4.0) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -12282,8 +13086,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.1.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@9.4.0) + espree: 10.1.0 + globals: 14.0.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@8.57.0': {} + '@eslint/js@9.8.0': {} + + '@eslint/object-schema@2.1.4': {} + '@esm-bundle/chai@4.3.4': dependencies: '@types/chai': 4.3.5 @@ -12292,8 +13114,8 @@ snapshots: '@fastify/ajv-compiler@3.5.0': dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) + ajv: 8.13.0 + ajv-formats: 2.1.1(ajv@8.13.0) fast-uri: 2.3.0 '@fastify/deepmerge@1.3.0': {} @@ -12382,6 +13204,8 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.3.0': {} + '@import-maps/resolve@1.0.1': {} '@istanbuljs/load-nyc-config@1.1.0': @@ -12649,7 +13473,7 @@ snapshots: '@rushstack/ts-command-line': 4.19.1(@types/node@20.11.5) lodash: 4.17.21 minimatch: 3.0.8 - resolve: 1.22.3 + resolve: 1.22.8 semver: 7.5.4 source-map: 0.6.1 typescript: 5.4.2 @@ -12808,7 +13632,7 @@ snapshots: '@netlify/framework-info@9.8.10': dependencies: - ajv: 8.12.0 + ajv: 8.13.0 filter-obj: 5.1.0 find-up: 6.3.0 is-plain-obj: 4.1.0 @@ -12966,7 +13790,7 @@ snapshots: junk: 4.0.1 locate-path: 7.2.0 merge-options: 3.0.4 - minimatch: 9.0.3 + minimatch: 9.0.4 normalize-path: 3.0.0 p-map: 5.5.0 path-exists: 5.0.0 @@ -13312,6 +14136,8 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 + '@polka/url@1.0.0-next.25': {} + '@popperjs/core@2.11.8': {} '@protobufjs/aspromise@1.1.2': {} @@ -13777,7 +14603,7 @@ snapshots: builtin-modules: 3.3.0 deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.3 + resolve: 1.22.8 rollup: 2.79.1 '@rollup/plugin-node-resolve@15.2.3(rollup@2.79.1)': @@ -13805,15 +14631,6 @@ snapshots: optionalDependencies: rollup: 2.79.1 - '@rollup/plugin-typescript@10.0.1(rollup@2.79.1)(tslib@2.6.1)(typescript@5.4.5)': - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@2.79.1) - resolve: 1.22.3 - typescript: 5.4.5 - optionalDependencies: - rollup: 2.79.1 - tslib: 2.6.1 - '@rollup/pluginutils@3.1.0(rollup@2.79.1)': dependencies: '@types/estree': 0.0.39 @@ -13826,25 +14643,17 @@ snapshots: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/pluginutils@5.0.2(rollup@2.79.1)': + '@rollup/pluginutils@5.1.0(rollup@2.79.1)': dependencies: - '@types/estree': 1.0.1 + '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: rollup: 2.79.1 - '@rollup/pluginutils@5.1.0(rollup@2.79.1)': + '@rollup/pluginutils@5.1.0(rollup@4.17.2)': dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - optionalDependencies: - rollup: 2.79.1 - - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': - dependencies: - '@types/estree': 1.0.1 + '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: @@ -13939,7 +14748,7 @@ snapshots: fs-extra: 7.0.1 import-lazy: 4.0.0 jju: 1.4.0 - resolve: 1.22.3 + resolve: 1.22.8 semver: 7.5.4 z-schema: 5.0.5 optionalDependencies: @@ -13947,7 +14756,7 @@ snapshots: '@rushstack/rig-package@0.5.2': dependencies: - resolve: 1.22.3 + resolve: 1.22.8 strip-json-comments: 3.1.1 '@rushstack/terminal@0.10.0(@types/node@20.11.5)': @@ -14004,6 +14813,63 @@ snapshots: magic-string: 0.25.9 string.prototype.matchall: 4.0.8 + '@sveltejs/adapter-auto@3.2.2(@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))': + dependencies: + '@sveltejs/kit': 2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + import-meta-resolve: 4.1.0 + + '@sveltejs/kit@2.5.20(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0))': + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + '@types/cookie': 0.6.0 + cookie: 0.6.0 + devalue: 5.0.0 + esm-env: 1.0.0 + import-meta-resolve: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.10 + mrmime: 2.0.0 + sade: 1.8.1 + set-cookie-parser: 2.6.0 + sirv: 2.0.4 + svelte: 4.2.18 + tiny-glob: 0.2.9 + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + + '@sveltejs/package@2.3.2(svelte@4.2.18)(typescript@5.4.5)': + dependencies: + chokidar: 3.6.0 + kleur: 4.1.5 + sade: 1.8.1 + semver: 7.6.0 + svelte: 4.2.18 + svelte2tsx: 0.7.15(svelte@4.2.18)(typescript@5.4.5) + transitivePeerDependencies: + - typescript + + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0))': + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + debug: 4.3.4(supports-color@9.4.0) + svelte: 4.2.18 + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + debug: 4.3.4(supports-color@9.4.0) + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.10 + svelte: 4.2.18 + svelte-hmr: 0.16.0(svelte@4.2.18) + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + vitefu: 0.2.5(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)) + transitivePeerDependencies: + - supports-color + '@swc/core-darwin-arm64@1.3.104': optional: true @@ -14274,6 +15140,8 @@ snapshots: '@types/chai@4.3.5': {} + '@types/cookie@0.6.0': {} + '@types/d3-array@3.0.7': {} '@types/d3-axis@3.0.3': @@ -14395,9 +15263,12 @@ snapshots: dependencies: '@types/ms': 0.7.31 - '@types/estree@0.0.39': {} + '@types/eslint@9.6.0': + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 - '@types/estree@1.0.1': {} + '@types/estree@0.0.39': {} '@types/estree@1.0.5': {} @@ -14481,6 +15352,8 @@ snapshots: '@types/prop-types@15.7.5': {} + '@types/pug@2.0.10': {} + '@types/react-dom@18.2.14': dependencies: '@types/react': 18.3.1 @@ -14575,13 +15448,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.4.5))(eslint@9.8.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(supports-color@9.4.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@9.4.0) - eslint: 8.57.0 + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/type-utils': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0 + eslint: 9.8.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: @@ -14600,16 +15479,29 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@5.62.0': + '@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0 + debug: 4.3.4(supports-color@9.4.0) + eslint: 9.8.0 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color '@typescript-eslint/scope-manager@7.8.0': dependencies: '@typescript-eslint/types': 7.8.0 '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/scope-manager@8.0.0': + dependencies: + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/visitor-keys': 8.0.0 + '@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) @@ -14622,10 +15514,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.0.0(eslint@9.8.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + debug: 4.3.4(supports-color@9.4.0) + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - eslint + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@7.8.0': {} + '@typescript-eslint/types@8.0.0': {} + '@typescript-eslint/typescript-estree@5.62.0(supports-color@9.4.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -14633,7 +15539,7 @@ snapshots: debug: 4.3.4(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.4 + semver: 7.6.0 tsutils: 3.21.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 @@ -14655,6 +15561,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.0.0(typescript@5.4.5)': + dependencies: + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/visitor-keys': 8.0.0 + debug: 4.3.4(supports-color@9.4.0) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) @@ -14669,6 +15590,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.0.0(eslint@9.8.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + eslint: 9.8.0 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -14679,13 +15611,18 @@ snapshots: '@typescript-eslint/types': 7.8.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.0.0': + dependencies: + '@typescript-eslint/types': 8.0.0 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} '@vercel/nft@0.23.1(supports-color@9.4.0)': dependencies: '@mapbox/node-pre-gyp': 1.0.11(supports-color@9.4.0) '@rollup/pluginutils': 4.2.1 - acorn: 8.10.0 + acorn: 8.11.3 async-sema: 3.1.1 bindings: 1.5.0 estree-walker: 2.0.2 @@ -14711,28 +15648,61 @@ snapshots: '@vitest/utils': 0.34.6 chai: 4.3.10 + '@vitest/expect@2.0.5': + dependencies: + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 + chai: 5.1.1 + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.0.5': + dependencies: + tinyrainbow: 1.2.0 + '@vitest/runner@0.34.6': dependencies: '@vitest/utils': 0.34.6 p-limit: 4.0.0 pathe: 1.1.1 + '@vitest/runner@2.0.5': + dependencies: + '@vitest/utils': 2.0.5 + pathe: 1.1.2 + '@vitest/snapshot@0.34.6': dependencies: - magic-string: 0.30.5 + magic-string: 0.30.10 pathe: 1.1.1 pretty-format: 29.6.2 + '@vitest/snapshot@2.0.5': + dependencies: + '@vitest/pretty-format': 2.0.5 + magic-string: 0.30.10 + pathe: 1.1.2 + '@vitest/spy@0.34.6': dependencies: tinyspy: 2.2.0 + '@vitest/spy@2.0.5': + dependencies: + tinyspy: 3.0.0 + '@vitest/utils@0.34.6': dependencies: diff-sequences: 29.4.3 loupe: 2.3.6 pretty-format: 29.6.2 + '@vitest/utils@2.0.5': + dependencies: + '@vitest/pretty-format': 2.0.5 + estree-walker: 3.0.3 + loupe: 3.1.1 + tinyrainbow: 1.2.0 + '@volar/language-core@1.11.1': dependencies: '@volar/source-map': 1.11.1 @@ -14845,12 +15815,18 @@ snapshots: dependencies: acorn: 8.10.0 + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + acorn-walk@8.3.0: {} acorn@8.10.0: {} acorn@8.11.3: {} + acorn@8.12.1: {} + agent-base@6.0.2(supports-color@9.4.0): dependencies: debug: 4.3.4(supports-color@9.4.0) @@ -14871,9 +15847,9 @@ snapshots: dependencies: ajv: 8.12.0 - ajv-formats@2.1.1(ajv@8.12.0): + ajv-formats@2.1.1(ajv@8.13.0): optionalDependencies: - ajv: 8.12.0 + ajv: 8.13.0 ajv@6.12.6: dependencies: @@ -15128,6 +16104,8 @@ snapshots: assertion-error@1.1.0: {} + assertion-error@2.0.1: {} + assign-symbols@1.0.0: {} ast-module-types@5.0.0: {} @@ -15176,6 +16154,8 @@ snapshots: dependencies: dequal: 2.0.3 + axobject-query@4.1.0: {} + b4a@1.6.4: {} babel-jest@29.6.2(@babel/core@7.24.5): @@ -15432,6 +16412,8 @@ snapshots: buffer-crc32@0.2.13: {} + buffer-crc32@1.0.0: {} + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} @@ -15550,6 +16532,14 @@ snapshots: pathval: 1.1.1 type-detect: 4.0.8 + chai@5.1.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.1 + pathval: 2.0.0 + chalk@1.1.3: dependencies: ansi-styles: 2.2.1 @@ -15588,6 +16578,8 @@ snapshots: dependencies: get-func-name: 2.0.2 + check-error@2.1.1: {} + chokidar@3.5.3: dependencies: anymatch: 3.1.3 @@ -15611,7 +16603,6 @@ snapshots: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - optional: true chownr@2.0.0: {} @@ -15700,6 +16691,14 @@ snapshots: code-point-at@1.1.0: {} + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.3 + estree-walker: 3.0.3 + periscopic: 3.1.0 + collect-v8-coverage@1.0.2: {} collection-visit@1.0.0: @@ -15853,6 +16852,8 @@ snapshots: cookie@0.5.0: {} + cookie@0.6.0: {} + copy-descriptor@0.1.1: {} copy-template-dir@1.4.0: @@ -15951,6 +16952,13 @@ snapshots: css-color-keywords: 1.0.0 postcss-value-parser: 4.2.0 + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.0 + + cssesc@3.0.0: {} + csstype@3.1.2: {} csstype@3.1.3: {} @@ -16019,6 +17027,10 @@ snapshots: optionalDependencies: supports-color: 9.4.0 + debug@4.3.6: + dependencies: + ms: 2.1.2 + decache@4.6.2: dependencies: callsite: 1.0.0 @@ -16049,6 +17061,8 @@ snapshots: dependencies: mimic-response: 3.1.0 + dedent-js@1.0.1: {} + dedent@0.7.0: {} dedent@1.5.1: {} @@ -16057,6 +17071,8 @@ snapshots: dependencies: type-detect: 4.0.8 + deep-eql@5.0.2: {} + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -16105,6 +17121,8 @@ snapshots: destroy@1.2.0: {} + detect-indent@6.1.0: {} + detect-libc@2.0.2: {} detect-newline@3.1.0: {} @@ -16130,8 +17148,8 @@ snapshots: detective-postcss@6.1.3: dependencies: is-url: 1.2.4 - postcss: 8.4.33 - postcss-values-parser: 6.0.2(postcss@8.4.33) + postcss: 8.4.40 + postcss-values-parser: 6.0.2(postcss@8.4.40) detective-sass@5.0.3: dependencies: @@ -16154,6 +17172,8 @@ snapshots: transitivePeerDependencies: - supports-color + devalue@5.0.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -16320,6 +17340,8 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + es6-promise@3.3.1: {} + es6-promisify@6.1.1: {} esbuild@0.19.2: @@ -16398,6 +17420,32 @@ snapshots: '@esbuild/win32-ia32': 0.20.2 '@esbuild/win32-x64': 0.20.2 + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + escalade@3.1.1: {} escalade@3.1.2: {} @@ -16424,15 +17472,24 @@ snapshots: optionalDependencies: source-map: 0.6.1 + eslint-compat-utils@0.5.1(eslint@9.8.0): + dependencies: + eslint: 9.8.0 + semver: 7.6.3 + eslint-config-prettier@9.1.0(eslint@8.57.0): dependencies: eslint: 8.57.0 + eslint-config-prettier@9.1.0(eslint@9.8.0): + dependencies: + eslint: 9.8.0 + eslint-import-resolver-node@0.3.7: dependencies: debug: 3.2.7 is-core-module: 2.12.1 - resolve: 1.22.3 + resolve: 1.22.8 transitivePeerDependencies: - supports-color @@ -16494,13 +17551,14 @@ snapshots: object.fromentries: 2.0.6 semver: 6.3.1 - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): + eslint-plugin-prettier@5.1.3(@types/eslint@9.6.0)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): dependencies: eslint: 8.57.0 prettier: 3.2.5 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 optionalDependencies: + '@types/eslint': 9.6.0 eslint-config-prettier: 9.1.0(eslint@8.57.0) eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): @@ -16526,13 +17584,39 @@ snapshots: semver: 6.3.1 string.prototype.matchall: 4.0.8 + eslint-plugin-svelte@2.43.0(eslint@9.8.0)(svelte@4.2.18)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@jridgewell/sourcemap-codec': 1.4.15 + eslint: 9.8.0 + eslint-compat-utils: 0.5.1(eslint@9.8.0) + esutils: 2.0.3 + known-css-properties: 0.34.0 + postcss: 8.4.40 + postcss-load-config: 3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)) + postcss-safe-parser: 6.0.0(postcss@8.4.40) + postcss-selector-parser: 6.1.1 + semver: 7.6.3 + svelte-eslint-parser: 0.41.0(svelte@4.2.18) + optionalDependencies: + svelte: 4.2.18 + transitivePeerDependencies: + - ts-node + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.0.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.0.0: {} + eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) @@ -16576,6 +17660,53 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.8.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.17.1 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.8.0 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@9.4.0) + escape-string-regexp: 4.0.0 + eslint-scope: 8.0.2 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + esm-env@1.0.0: {} + + espree@10.1.0: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 4.0.0 + espree@9.6.1: dependencies: acorn: 8.10.0 @@ -16598,6 +17729,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + esutils@2.0.3: {} etag@1.8.1: {} @@ -16644,6 +17779,18 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 3.0.0 + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + exit@0.1.2: {} expand-brackets@2.1.4: @@ -16781,8 +17928,8 @@ snapshots: fast-json-stringify@5.9.1: dependencies: '@fastify/deepmerge': 1.3.0 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) + ajv: 8.13.0 + ajv-formats: 2.1.1(ajv@8.13.0) fast-deep-equal: 3.1.3 fast-uri: 2.3.0 json-schema-ref-resolver: 1.0.1 @@ -16881,9 +18028,13 @@ snapshots: dependencies: flat-cache: 3.0.4 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + file-selector@0.4.0: dependencies: - tslib: 2.6.1 + tslib: 2.6.2 file-type@18.7.0: dependencies: @@ -16974,8 +18125,15 @@ snapshots: flatted: 3.2.7 rimraf: 3.0.2 + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + flatted@3.2.7: {} + flatted@3.3.1: {} + flush-write-stream@2.0.0: dependencies: inherits: 2.0.4 @@ -17124,6 +18282,8 @@ snapshots: get-stream@6.0.1: {} + get-stream@8.0.1: {} + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.2 @@ -17201,10 +18361,16 @@ snapshots: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + + globals@15.9.0: {} + globalthis@1.0.3: dependencies: define-properties: 1.2.0 + globalyzer@0.1.0: {} + globby@11.1.0: dependencies: array-union: 2.1.0 @@ -17218,7 +18384,7 @@ snapshots: dependencies: dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.2.4 + ignore: 5.3.1 merge2: 1.4.1 slash: 4.0.0 @@ -17230,6 +18396,8 @@ snapshots: pify: 2.3.0 pinkie-promise: 2.0.1 + globrex@0.1.2: {} + gonzales-pe@4.3.0: dependencies: minimist: 1.2.8 @@ -17429,6 +18597,8 @@ snapshots: human-signals@3.0.1: {} + human-signals@5.0.0: {} + husky@8.0.3: {} iconv-lite@0.4.24: @@ -17439,6 +18609,10 @@ snapshots: ieee754@1.2.1: {} + ignore-walk@5.0.1: + dependencies: + minimatch: 5.1.6 + ignore@5.2.4: {} ignore@5.3.1: {} @@ -17457,6 +18631,8 @@ snapshots: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 + import-meta-resolve@4.1.0: {} + imurmurhash@0.1.4: {} indent-string@3.2.0: {} @@ -17696,6 +18872,10 @@ snapshots: is-promise@2.2.2: {} + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + is-regex@1.1.4: dependencies: call-bind: 1.0.2 @@ -18004,7 +19184,7 @@ snapshots: jest-pnp-resolver: 1.2.3(jest-resolve@29.6.2) jest-util: 29.6.2 jest-validate: 29.6.2 - resolve: 1.22.3 + resolve: 1.22.8 resolve.exports: 2.0.2 slash: 3.0.0 @@ -18082,7 +19262,7 @@ snapshots: jest-util: 29.6.2 natural-compare: 1.4.0 pretty-format: 29.6.2 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - supports-color @@ -18261,6 +19441,8 @@ snapshots: kleur@4.1.5: {} + known-css-properties@0.34.0: {} + kolorist@1.8.0: {} kuler@2.0.0: {} @@ -18304,6 +19486,8 @@ snapshots: process-warning: 2.3.1 set-cookie-parser: 2.6.0 + lilconfig@2.1.0: {} + lines-and-columns@1.2.4: {} linkify-it@5.0.0: @@ -18383,6 +19567,8 @@ snapshots: local-pkg@0.4.3: {} + locate-character@3.0.0: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -18495,6 +19681,14 @@ snapshots: dependencies: get-func-name: 2.0.2 + loupe@3.1.1: + dependencies: + get-func-name: 2.0.2 + + lower-case@2.0.2: + dependencies: + tslib: 2.6.2 + lowercase-keys@1.0.1: {} lowercase-keys@2.0.0: {} @@ -18716,6 +19910,8 @@ snapshots: dependencies: '@types/mdast': 4.0.3 + mdn-data@2.0.30: {} + mdurl@2.0.0: {} media-typer@0.3.0: {} @@ -19184,7 +20380,7 @@ snapshots: mlly@1.4.2: dependencies: - acorn: 8.10.0 + acorn: 8.11.3 pathe: 1.1.1 pkg-types: 1.0.3 ufo: 1.3.1 @@ -19207,6 +20403,8 @@ snapshots: mri@1.2.0: {} + mrmime@2.0.0: {} + ms@2.0.0: {} ms@2.1.2: {} @@ -19401,6 +20599,11 @@ snapshots: p-wait-for: 4.1.0 qs: 6.11.2 + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.6.2 + node-domexception@1.0.0: {} node-fetch@2.6.12: @@ -19451,14 +20654,14 @@ snapshots: normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.3 + resolve: 1.22.8 semver: 5.7.2 validate-npm-package-license: 3.0.4 normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.12.1 + is-core-module: 2.13.1 semver: 7.6.0 validate-npm-package-license: 3.0.4 @@ -19472,6 +20675,19 @@ snapshots: normalize-url@8.0.0: {} + npm-bundled@2.0.1: + dependencies: + npm-normalize-package-bin: 2.0.0 + + npm-normalize-package-bin@2.0.0: {} + + npm-packlist@5.1.3: + dependencies: + glob: 8.1.0 + ignore-walk: 5.0.1 + npm-bundled: 2.0.1 + npm-normalize-package-bin: 2.0.0 + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -19746,6 +20962,11 @@ snapshots: parseurl@1.3.3: {} + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + pascalcase@0.1.1: {} path-browserify@1.0.1: {} @@ -19773,8 +20994,12 @@ snapshots: pathe@1.1.1: {} + pathe@1.1.2: {} + pathval@1.1.1: {} + pathval@2.0.0: {} + pdfjs-dist@2.16.105: dependencies: dommatrix: 1.0.3 @@ -19792,8 +21017,16 @@ snapshots: pend@1.2.0: {} + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + picocolors@1.0.0: {} + picocolors@1.0.1: {} + picomatch@2.3.1: {} pify@2.3.0: {} @@ -19861,13 +21094,34 @@ snapshots: posix-character-classes@0.1.1: {} + postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.4.40 + ts-node: 10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5) + + postcss-safe-parser@6.0.0(postcss@8.4.40): + dependencies: + postcss: 8.4.40 + + postcss-scss@4.0.9(postcss@8.4.40): + dependencies: + postcss: 8.4.40 + + postcss-selector-parser@6.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss-value-parser@4.2.0: {} - postcss-values-parser@6.0.2(postcss@8.4.33): + postcss-values-parser@6.0.2(postcss@8.4.40): dependencies: color-name: 1.1.4 is-url-superb: 4.0.0 - postcss: 8.4.33 + postcss: 8.4.40 quote-unquote: 1.0.0 postcss@8.4.33: @@ -19882,6 +21136,12 @@ snapshots: picocolors: 1.0.0 source-map-js: 1.2.0 + postcss@8.4.40: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + precinct@11.0.5(supports-color@9.4.0): dependencies: '@dependents/detective-less': 4.1.0 @@ -19918,6 +21178,11 @@ snapshots: transitivePeerDependencies: - supports-color + prettier-plugin-svelte@3.2.6(prettier@3.2.5)(svelte@4.2.18): + dependencies: + prettier: 3.2.5 + svelte: 4.2.18 + prettier@3.0.3: {} prettier@3.2.5: {} @@ -20098,6 +21363,12 @@ snapshots: ps-list@8.1.1: {} + publint@0.1.16: + dependencies: + npm-packlist: 5.1.3 + picocolors: 1.0.1 + sade: 1.8.1 + pump@1.0.3: dependencies: end-of-stream: 1.4.4 @@ -20523,7 +21794,7 @@ snapshots: dependencies: debug: 4.3.4(supports-color@9.4.0) module-details-from-path: 1.0.3 - resolve: 1.22.3 + resolve: 1.22.8 transitivePeerDependencies: - supports-color @@ -20549,7 +21820,7 @@ snapshots: resolve@1.19.0: dependencies: - is-core-module: 2.12.1 + is-core-module: 2.13.1 path-parse: 1.0.7 resolve@1.22.3: @@ -20603,6 +21874,10 @@ snapshots: rfdc@1.3.0: {} + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -20615,10 +21890,6 @@ snapshots: serialize-javascript: 4.0.0 terser: 5.19.2 - rollup-plugin-typescript-paths@1.4.0(typescript@5.4.5): - dependencies: - typescript: 5.4.5 - rollup@2.79.1: optionalDependencies: fsevents: 2.3.3 @@ -20675,7 +21946,7 @@ snapshots: rxjs@7.8.1: dependencies: - tslib: 2.6.1 + tslib: 2.6.2 sade@1.8.1: dependencies: @@ -20712,6 +21983,13 @@ snapshots: safer-buffer@2.1.2: {} + sander@0.5.1: + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.11 + mkdirp: 0.5.6 + rimraf: 2.7.1 + scheduler@0.23.0: dependencies: loose-envify: 1.4.0 @@ -20744,6 +22022,8 @@ snapshots: dependencies: lru-cache: 6.0.0 + semver@7.6.3: {} + send@0.18.0: dependencies: debug: 2.6.9 @@ -20835,6 +22115,12 @@ snapshots: dependencies: is-arrayish: 0.3.2 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + sisteransi@1.0.5: {} slash@2.0.0: {} @@ -20891,6 +22177,13 @@ snapshots: dependencies: atomic-sleep: 1.0.0 + sorcery@0.11.1: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + buffer-crc32: 1.0.0 + minimist: 1.2.8 + sander: 0.5.1 + sort-keys-length@1.0.1: dependencies: sort-keys: 1.1.2 @@ -20988,6 +22281,8 @@ snapshots: std-env@3.4.3: {} + std-env@3.7.0: {} + stdin-discarder@0.1.0: dependencies: bl: 5.1.0 @@ -21189,7 +22484,77 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte@3.59.2: {} + svelte-check@3.8.5(@babel/core@7.24.5)(postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)))(postcss@8.4.40)(svelte@4.2.18): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + chokidar: 3.6.0 + picocolors: 1.0.1 + sade: 1.8.1 + svelte: 4.2.18 + svelte-preprocess: 5.1.4(@babel/core@7.24.5)(postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)))(postcss@8.4.40)(svelte@4.2.18)(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + + svelte-eslint-parser@0.41.0(svelte@4.2.18): + dependencies: + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + postcss: 8.4.40 + postcss-scss: 4.0.9(postcss@8.4.40) + optionalDependencies: + svelte: 4.2.18 + + svelte-hmr@0.16.0(svelte@4.2.18): + dependencies: + svelte: 4.2.18 + + svelte-preprocess@5.1.4(@babel/core@7.24.5)(postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)))(postcss@8.4.40)(svelte@4.2.18)(typescript@5.4.5): + dependencies: + '@types/pug': 2.0.10 + detect-indent: 6.1.0 + magic-string: 0.30.10 + sorcery: 0.11.1 + strip-indent: 3.0.0 + svelte: 4.2.18 + optionalDependencies: + '@babel/core': 7.24.5 + postcss: 8.4.40 + postcss-load-config: 3.1.4(postcss@8.4.40)(ts-node@10.9.1(@swc/core@1.3.104)(@types/node@20.11.5)(typescript@5.4.5)) + typescript: 5.4.5 + + svelte2tsx@0.7.15(svelte@4.2.18)(typescript@5.4.5): + dependencies: + dedent-js: 1.0.1 + pascal-case: 3.1.2 + svelte: 4.2.18 + typescript: 5.4.5 + + svelte@4.2.18: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + '@types/estree': 1.0.5 + acorn: 8.11.3 + aria-query: 5.3.0 + axobject-query: 4.1.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.10 + periscopic: 3.1.0 symbol-observable@1.2.0: {} @@ -21258,14 +22623,14 @@ snapshots: terser@5.19.2: dependencies: '@jridgewell/source-map': 0.3.5 - acorn: 8.10.0 + acorn: 8.11.3 commander: 2.20.3 source-map-support: 0.5.21 terser@5.31.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 + acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 @@ -21308,16 +22673,29 @@ snapshots: time-zone@1.0.0: {} + tiny-glob@0.2.9: + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + tiny-invariant@1.3.1: {} tiny-lru@11.2.5: {} tinybench@2.5.1: {} + tinybench@2.9.0: {} + tinypool@0.7.0: {} + tinypool@1.0.0: {} + + tinyrainbow@1.2.0: {} + tinyspy@2.2.0: {} + tinyspy@3.0.0: {} + tippy.js@6.3.7: dependencies: '@popperjs/core': 2.11.8 @@ -21381,6 +22759,8 @@ snapshots: tomlify-j0.4@3.0.0: {} + totalist@3.0.1: {} + tr46@0.0.3: {} tr46@1.0.1: @@ -21432,7 +22812,7 @@ snapshots: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.11.5 - acorn: 8.10.0 + acorn: 8.11.3 acorn-walk: 8.3.0 arg: 4.1.3 create-require: 1.1.1 @@ -21536,6 +22916,17 @@ snapshots: types-wm@1.1.0: {} + typescript-eslint@8.0.0(eslint@9.8.0)(typescript@5.4.5): + dependencies: + '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.4.5))(eslint@9.8.0)(typescript@5.4.5) + '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - eslint + - supports-color + typescript@5.4.2: {} typescript@5.4.5: {} @@ -21664,13 +23055,13 @@ snapshots: dependencies: browserslist: 4.21.10 escalade: 3.1.1 - picocolors: 1.0.0 + picocolors: 1.0.1 update-browserslist-db@1.0.14(browserslist@4.23.0): dependencies: browserslist: 4.23.0 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 update-notifier@4.1.3: dependencies: @@ -21793,7 +23184,24 @@ snapshots: mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 5.2.11(@types/node@20.11.5)(terser@5.31.0) + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + vite-node@2.0.5(@types/node@20.11.5)(terser@5.31.0): + dependencies: + cac: 6.7.14 + debug: 4.3.6 + pathe: 1.1.2 + tinyrainbow: 1.2.0 + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) transitivePeerDependencies: - '@types/node' - less @@ -21870,6 +23278,20 @@ snapshots: fsevents: 2.3.3 terser: 5.31.0 + vite@5.3.5(@types/node@20.11.5)(terser@5.31.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.40 + rollup: 4.17.2 + optionalDependencies: + '@types/node': 20.11.5 + fsevents: 2.3.3 + terser: 5.31.0 + + vitefu@0.2.5(vite@5.3.5(@types/node@20.11.5)(terser@5.31.0)): + optionalDependencies: + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + vitest@0.34.6(playwright@1.43.1)(terser@5.31.0): dependencies: '@types/chai': 4.3.5 @@ -21907,6 +23329,38 @@ snapshots: - supports-color - terser + vitest@2.0.5(@types/node@20.11.5)(terser@5.31.0): + dependencies: + '@ampproject/remapping': 2.3.0 + '@vitest/expect': 2.0.5 + '@vitest/pretty-format': 2.0.5 + '@vitest/runner': 2.0.5 + '@vitest/snapshot': 2.0.5 + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 + chai: 5.1.1 + debug: 4.3.6 + execa: 8.0.1 + magic-string: 0.30.10 + pathe: 1.1.2 + std-env: 3.7.0 + tinybench: 2.9.0 + tinypool: 1.0.0 + tinyrainbow: 1.2.0 + vite: 5.3.5(@types/node@20.11.5)(terser@5.31.0) + vite-node: 2.0.5(@types/node@20.11.5)(terser@5.31.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.11.5 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + vscode-oniguruma@1.7.0: {} vscode-textmate@8.0.0: {} @@ -21920,7 +23374,7 @@ snapshots: dependencies: '@volar/typescript': 1.11.1 '@vue/language-core': 1.8.27(typescript@5.4.5) - semver: 7.5.4 + semver: 7.6.0 typescript: 5.4.5 w3c-keyname@2.2.8: {} @@ -21989,6 +23443,11 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wide-align@1.1.5: dependencies: string-width: 4.2.3 diff --git a/browser/react/src/components/Image.tsx b/browser/react/src/components/Image.tsx new file mode 100644 index 000000000..08b8449ab --- /dev/null +++ b/browser/react/src/components/Image.tsx @@ -0,0 +1,227 @@ +import type { Resource, Server } from '@tomic/lib'; +import React from 'react'; +import { server, useResource, useString } from '../index.js'; + +const imageFormatsWithBasicSupport = new Set([ + 'image/svg+xml', + 'image/vnd.adobe.photoshop', + 'image/heif', + 'image/heif-sequence', + 'image/heic-sequence', + 'image/avif-sequence', + 'image/gif', + 'image/heic', + 'image/heif', +]); + +const imageFormatsWithFullSupport = new Set([ + 'image/png', + 'image/jpeg', + 'image/vnd.microsoft.icon', + 'image/webp', + 'image/bmp', + 'image/tiff', + 'image/avif', +]); + +const DEFAULT_SIZES = [100, 300, 500, 800, 1200, 1600, 2000]; + +type SizeIndicationKey = `${number}px`; +type Unit = number | `${number}${'px' | 'vw' | 'em' | 'rem' | 'ch'}`; + +export type SizeIndication = + | { + [key: SizeIndicationKey]: Unit; + default: Unit; + } + | Unit; + +interface ImageInnerProps + extends Omit< + React.ImgHTMLAttributes, + 'resource' | 'src' + > { + resource: Resource; + /** + * SizeIndication is used to help the browser choose the right image size to fetch. + * By default, the browser looks at the entire viewport width and chooses the smallest version that still covers this width. + * This is often too big so we should help by giving it an approximation of the size of the image relative to the viewport. + * + * When the unit given is a number it is interpreted as a percentage of the viewport width. If your image is displayed in a static size you can also pass a string like '4rem'. + * Note that percentages don't work as the browser doesn't know the size of the parent element yet. + * + * ```jsx + * a person standing in front of a mountain + * ``` + * When the image size changes based on media queries we can give the browser a more detailed indication. + * ```jsx + * a person standing in front of a mountain + * ``` + */ + sizeIndication?: SizeIndication; + /** Alt text for the image, if you can't add alt text it's best practice to pass an empty string */ + alt: string; + /** Quality setting used by the image encoders, defaults to 60 (more than enough in most cases). Should be between 0 - 100 */ + quality?: number; +} + +export interface ImageProps extends Omit { + /** Subject of the file resource */ + subject: string; +} + +/** + * Takes the subject of a file resource and renders it as an image. + * Uses AtomicServer to automatically generate avif and webp versions of the image and scale them to different sizes. + * To help the browser choose the best size to load use the `sizeIndication` prop. + * + * Throws when the file is not an image. + * @example + * ```jsx + * a person standing in front of a mountain + * ``` + */ +export const Image: React.FC = ({ subject, ...props }) => { + const resource = useResource(subject); + const [mimeType] = useString(resource, server.properties.mimetype); + + if (resource.loading) { + return null; + } + + if (!resource.hasClasses(server.classes.file)) { + throw new Error('Incompatible resource class, resource is not a file'); + } + + // If the resource does have a file class but mimetype is still undefined, it's still loading so we return null until the value is available + if (mimeType === undefined) { + return null; + } + + if (imageFormatsWithBasicSupport.has(mimeType)) { + return ; + } + + if (!imageFormatsWithFullSupport.has(mimeType)) { + throw new Error('Incompatible or missing mime-type: ' + mimeType); + } + + return ; +}; + +const ImageInner: React.FC = ({ + resource, + sizeIndication, + quality = 60, + ...props +}) => { + const [downloadUrl] = useString(resource, server.properties.downloadUrl); + const toSrcSet = buildSrcSet(downloadUrl ?? ''); + + return ( + + + + {/* eslint-disable-next-line jsx-a11y/alt-text */} + + + ); +}; + +const BasicImage: React.FC = ({ + resource, + sizeIndication: _sizeIndication, + quality: _quality, + ...props // html image atrributes only +}) => { + const [downloadUrl] = useString(resource, server.properties.downloadUrl); + + // eslint-disable-next-line jsx-a11y/alt-text + return ; +}; + +const indicationToSizes = (indication: SizeIndication | undefined): string => { + if (indication === undefined) { + return '100vw'; + } + + if (typeof indication === 'number' || typeof indication === 'string') { + return parseUnit(indication); + } + + return Object.entries(indication) + .map(([key, value]) => + key === 'default' + ? parseUnit(value) + : `(max-width: ${key}) ${parseUnit(value)}`, + ) + .join(', '); +}; + +const parseUnit = (unit: Unit): string => + typeof unit === 'number' ? `${unit}vw` : unit; + +const toUrl = ( + base: string, + format?: string, + quality?: number, + width?: number, +) => { + const url = new URL(base); + const queryParams = new URLSearchParams(); + format && queryParams.set('f', format); + width && queryParams.set('w', width.toString()); + quality && queryParams.set('q', quality.toString()); + url.search = queryParams.toString(); + + return url.toString(); +}; + +const buildSrcSet = + (base: string) => + (format: string, quality: number, sizes: number[]): string => { + return sizes + .map(size => { + return `${toUrl(base, format, quality, size)} ${size}w`; + }) + .join(', '); + }; diff --git a/browser/react/src/index.ts b/browser/react/src/index.ts index 7933f31ee..5b2a6069f 100644 --- a/browser/react/src/index.ts +++ b/browser/react/src/index.ts @@ -32,4 +32,5 @@ export * from './useServerSearch.js'; export * from './useCollection.js'; export * from './useMemberFromCollection.js'; export * from './useCollectionPage.js'; +export * from './components/Image.js'; export * from '@tomic/lib'; diff --git a/browser/svelte/.eslintrc.cjs b/browser/svelte/.eslintrc.cjs deleted file mode 100644 index 966216546..000000000 --- a/browser/svelte/.eslintrc.cjs +++ /dev/null @@ -1,93 +0,0 @@ -module.exports = { - root: true, - extends: [ - 'eslint:recommended', - 'plugin:prettier/recommended', - 'plugin:@typescript-eslint/eslint-recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'prettier', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - ], - parser: '@typescript-eslint/parser', // Specifies the ESLint parser - env: { - browser: true, - es6: true, - jest: true, - node: true, - }, - parserOptions: { - ecmaVersion: 'latest', // Allows for the parsing of modern ECMAScript features - ecmaFeatures: { - jsx: true, // Allows for the parsing of JSX - }, - // Next two lines enable deeper TS type checking - // https://typescript-eslint.io/docs/linting/typed-linting/ - tsconfigRootDir: __dirname, - }, - plugins: ['@typescript-eslint', 'prettier'], - settings: { - 'import/resolver': { - node: { - extensions: ['.js', '.svelte', '.ts', '.tsx'], - paths: ['./src'], - }, - }, - }, - rules: { - // Existing rules - 'comma-dangle': 'off', // https://eslint.org/docs/rules/comma-dangle - 'function-paren-newline': 'off', // https://eslint.org/docs/rules/function-paren-newline - 'global-require': 'off', // https://eslint.org/docs/rules/global-require - 'import/no-dynamic-require': 'off', // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md - 'class-methods-use-this': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, - ], - 'import/prefer-default-export': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - 'no-console': ['error', { allow: ['error', 'warn'] }], - 'padding-line-between-statements': [ - 'error', - { - blankLine: 'always', - next: 'return', - prev: '*', - }, - { - blankLine: 'always', - next: 'export', - prev: '*', - }, - { - blankLine: 'always', - next: 'multiline-block-like', - prev: '*', - }, - { - blankLine: 'always', - next: '*', - prev: 'multiline-block-like', - }, - { - blankLine: 'any', - next: 'export', - prev: 'export', - }, - ], - '@typescript-eslint/explicit-member-accessibility': 'error', - eqeqeq: 'error', - 'no-unused-expressions': [ - 'error', - { allowShortCircuit: true, allowTaggedTemplates: true }, - ], - // This has a bug, so we use typescripts version - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': ['error'], - '@typescript-eslint/no-non-null-assertion': 'off', - 'no-eval': 'error', - 'no-implied-eval': 'error', - '@typescript-eslint/member-ordering': 'error', - }, -}; diff --git a/browser/svelte/.gitignore b/browser/svelte/.gitignore index 0f4cb3a26..715b548f7 100644 --- a/browser/svelte/.gitignore +++ b/browser/svelte/.gitignore @@ -1,25 +1,22 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - node_modules -dist -dist-ssr -dist/* -*.local -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea +# Output +.output +.vercel +/.svelte-kit +/build +/dist + +# OS .DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/browser/svelte/.npmrc b/browser/svelte/.npmrc new file mode 100644 index 000000000..b6f27f135 --- /dev/null +++ b/browser/svelte/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/browser/svelte/.prettierignore b/browser/svelte/.prettierignore new file mode 100644 index 000000000..ab78a95dd --- /dev/null +++ b/browser/svelte/.prettierignore @@ -0,0 +1,4 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/browser/svelte/.prettierrc.json b/browser/svelte/.prettierrc.json index 3177c3a8e..32a10af85 100644 --- a/browser/svelte/.prettierrc.json +++ b/browser/svelte/.prettierrc.json @@ -8,5 +8,13 @@ "arrowParens": "avoid", "jsxSingleQuote": true, "trailingComma": "all", - "jsdocParser": true + "plugins": ["prettier-plugin-svelte"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ] } diff --git a/browser/svelte/LICENSE b/browser/svelte/LICENSE deleted file mode 100644 index e81ae5371..000000000 --- a/browser/svelte/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Ontola (Argu B.V.) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/browser/svelte/eslint.config.js b/browser/svelte/eslint.config.js new file mode 100644 index 000000000..e0ff2f538 --- /dev/null +++ b/browser/svelte/eslint.config.js @@ -0,0 +1,33 @@ +import js from '@eslint/js'; +import ts from 'typescript-eslint'; +import svelte from 'eslint-plugin-svelte'; +import prettier from 'eslint-config-prettier'; +import globals from 'globals'; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs['flat/recommended'], + prettier, + ...svelte.configs['flat/prettier'], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, + { + files: ['**/*.svelte'], + languageOptions: { + parserOptions: { + parser: ts.parser, + }, + }, + }, + { + ignores: ['build/', '.svelte-kit/', 'dist/'], + }, +]; diff --git a/browser/svelte/package.json b/browser/svelte/package.json index b71e2a5a7..a53103838 100644 --- a/browser/svelte/package.json +++ b/browser/svelte/package.json @@ -1,49 +1,64 @@ { "author": "Ontola, Polle Pas", - "dependencies": { - "@tomic/lib": "workspace:*", - "svelte": "^3.55.0" + "name": "@tomic/svelte", + "version": "0.38.0", + "license": "MIT", + "private": false, + "publishConfig": { + "access": "public" }, "description": "Atomic Data Svelte library", - "devDependencies": { - "@rollup/plugin-typescript": "^10.0.1", - "@typescript-eslint/parser": "^5.47.0", - "rollup-plugin-typescript-paths": "^1.4.0", - "tslib": "^2.4.1", - "vitest": "^0.34.6", - "typescript": "^5.4.5" + "scripts": { + "dev": "vite dev", + "build": "vite build && npm run package", + "preview": "vite preview", + "package": "svelte-kit sync && svelte-package && publint", + "prepublishOnly": "npm run package", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "test": "vitest", + "lint": "prettier --check . && eslint .", + "format": "prettier --write ." }, "exports": { ".": { - "import": "./dist/index.js", - "require": "./dist/index.cjs.js" + "types": "./dist/index.d.ts", + "svelte": "./dist/index.js" } }, - "files": ["dist"], - "license": "MIT", - "main": "./dist/index.cjs.js", - "module": "./dist/index.js", - "main-dev": "src/index.ts", - "name": "@tomic/svelte", - "peerDependencies": { + "files": [ + "dist", + "!dist/**/*.test.*", + "!dist/**/*.spec.*" + ], + "dependencies": { "@tomic/lib": "workspace:*" }, - "private": false, - "publishConfig": { - "access": "public" + "peerDependencies": { + "svelte": "^4.0.0", + "@tomic/lib": "workspace:*" }, - "scripts": { - "build": "tsc && vite build", - "build:watch": "tsc && vite build --watch", - "coverage": "vitest run --coverage", - "dev": "vite", - "lint": "eslint ./src --ext .js,.svelte,.ts,.tsx", - "lint-fix": "eslint ./src --ext .js,.svelte,.ts,.tsx --fix", - "test": "vitest run" + "devDependencies": { + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/package": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@types/eslint": "^9.6.0", + "eslint": "^9.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-svelte": "^2.36.0", + "globals": "^15.0.0", + "prettier": "^3.1.1", + "prettier-plugin-svelte": "^3.1.2", + "publint": "^0.1.9", + "svelte": "^4.2.7", + "svelte-check": "^3.6.0", + "typescript": "^5.4.5", + "typescript-eslint": "^8.0.0", + "vite": "^5.0.11", + "vitest": "^2.0.0" }, - "source": "src/index.ts", - "type": "module", - "types": "dist/index.d.ts", - "typings": "./dist/index.d.ts", - "version": "0.38.0" + "svelte": "./dist/index.js", + "types": "./dist/index.d.ts", + "type": "module" } diff --git a/browser/svelte/src/app.d.ts b/browser/svelte/src/app.d.ts new file mode 100644 index 000000000..ede601ab9 --- /dev/null +++ b/browser/svelte/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/browser/svelte/src/app.html b/browser/svelte/src/app.html new file mode 100644 index 000000000..b37687a19 --- /dev/null +++ b/browser/svelte/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/browser/svelte/src/index.ts b/browser/svelte/src/index.ts deleted file mode 100644 index 78a4dc7e9..000000000 --- a/browser/svelte/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Store } from '@tomic/lib'; -import { __store_internal } from './stores/store'; - -export const initStore = (store: Store) => { - __store_internal.set(store); -}; - -export { store } from './stores/store'; -export { getResource } from './stores/getResource'; -export { getValue } from './stores/getValue'; -export * from './loadResourceTree'; diff --git a/browser/svelte/src/lib/components/Image/Image.svelte b/browser/svelte/src/lib/components/Image/Image.svelte new file mode 100644 index 000000000..93afd2316 --- /dev/null +++ b/browser/svelte/src/lib/components/Image/Image.svelte @@ -0,0 +1,100 @@ + + +{#if $resource.error} +

{$resource.error.message}

+{:else if $resource.loading} +

Loading...

+{:else if supported === Support.None} +

Image format not supported

+{:else if supported === Support.Basic} + +{:else if supported === Support.Full} + + + + + +{/if} + + diff --git a/browser/svelte/src/lib/components/Image/imageHelpers.ts b/browser/svelte/src/lib/components/Image/imageHelpers.ts new file mode 100644 index 000000000..a0422ce52 --- /dev/null +++ b/browser/svelte/src/lib/components/Image/imageHelpers.ts @@ -0,0 +1,82 @@ +type SizeIndicationKey = `${number}px`; +export type Unit = number | `${number}${'px' | 'vw' | 'em' | 'rem' | 'ch'}`; + +export type SizeIndication = + | { + [key: SizeIndicationKey]: Unit; + default: Unit; + } + | Unit; + +export const imageFormatsWithBasicSupport = new Set([ + 'image/svg+xml', + 'image/vnd.adobe.photoshop', + 'image/heif', + 'image/heif-sequence', + 'image/heic-sequence', + 'image/avif-sequence', + 'image/gif', + 'image/heic', + 'image/heif', +]); + +export const imageFormatsWithFullSupport = new Set([ + 'image/png', + 'image/jpeg', + 'image/vnd.microsoft.icon', + 'image/webp', + 'image/bmp', + 'image/tiff', + 'image/avif', +]); + +export const DEFAULT_SIZES = [100, 300, 500, 800, 1200, 1600, 2000]; + +export const indicationToSizes = ( + indication: SizeIndication | undefined, +): string => { + if (indication === undefined) { + return '100vw'; + } + + if (typeof indication === 'number' || typeof indication === 'string') { + return parseUnit(indication); + } + + return Object.entries(indication) + .map(([key, value]) => + key === 'default' + ? parseUnit(value) + : `(max-width: ${key}) ${parseUnit(value)}`, + ) + .join(', '); +}; + +const parseUnit = (unit: Unit): string => + typeof unit === 'number' ? `${unit}vw` : unit; + +const toUrl = ( + base: string, + format?: string, + quality?: number, + width?: number, +) => { + const url = new URL(base); + const queryParams = new URLSearchParams(); + if (format) queryParams.set('f', format); + if (width !== undefined) queryParams.set('w', width.toString()); + if (quality !== undefined) queryParams.set('q', quality.toString()); + url.search = queryParams.toString(); + + return url.toString(); +}; + +export const buildSrcSet = + (base: string) => + (format: string, quality: number, sizes: number[]): string => { + return sizes + .map(size => { + return `${toUrl(base, format, quality, size)} ${size}w`; + }) + .join(', '); + }; diff --git a/browser/svelte/src/lib/components/Image/index.ts b/browser/svelte/src/lib/components/Image/index.ts new file mode 100644 index 000000000..c8bb56336 --- /dev/null +++ b/browser/svelte/src/lib/components/Image/index.ts @@ -0,0 +1,2 @@ +export { default as Image } from './Image.svelte'; +export { type SizeIndication } from './imageHelpers.js'; diff --git a/browser/svelte/src/lib/example-helpers/getStore.ts b/browser/svelte/src/lib/example-helpers/getStore.ts new file mode 100644 index 000000000..70a4a9d53 --- /dev/null +++ b/browser/svelte/src/lib/example-helpers/getStore.ts @@ -0,0 +1,23 @@ +import { initStore } from '$lib/index.js'; +import { store as atomicStore } from '$lib/stores/store.js'; +import { Store } from '@tomic/lib'; +import { get } from 'svelte/store'; + +const init = () => { + const atomicStore = new Store({ + // Drive with example data + serverUrl: 'https://atomicdata.dev/drive/WnY9YDmm', + }); + initStore(atomicStore); +}; + +export const getStore = () => { + let store = get(atomicStore); + + if (store === undefined) { + init(); + store = get(atomicStore); + } + + return store; +}; diff --git a/browser/svelte/src/lib/index.ts b/browser/svelte/src/lib/index.ts new file mode 100644 index 000000000..817633e0f --- /dev/null +++ b/browser/svelte/src/lib/index.ts @@ -0,0 +1,14 @@ +// Reexport your entry components here + +import type { Store } from '@tomic/lib'; +import { __store_internal } from './stores/store.js'; + +export const initStore = (store: Store) => { + __store_internal.set(store); +}; + +export * from './components/Image/index.js'; +export { store } from './stores/store.js'; +export { getResource } from './stores/getResource.js'; +export { getValue } from './stores/getValue.js'; +export * from './loadResourceTree.js'; diff --git a/browser/svelte/src/loadResourceTree.ts b/browser/svelte/src/lib/loadResourceTree.ts similarity index 83% rename from browser/svelte/src/loadResourceTree.ts rename to browser/svelte/src/lib/loadResourceTree.ts index 4b68a780c..d0bef327c 100644 --- a/browser/svelte/src/loadResourceTree.ts +++ b/browser/svelte/src/lib/loadResourceTree.ts @@ -1,6 +1,6 @@ -import { JSONValue, Resource } from '@tomic/lib'; +import { type JSONValue, Resource } from '@tomic/lib'; import { get } from 'svelte/store'; -import { store as storeStore } from './stores/store'; +import { store as storeStore } from './stores/store.js'; export interface ResourceTreeTemplate { [property: string]: true | ResourceTreeTemplate; @@ -20,7 +20,7 @@ const normalize = (value: JSONValue): string[] => { /** * Make sure the given tree of resources are available in the store. - * This is only useful for SSR and SSG as the getResource functions don't wait for the resource to be fully available + * This is only useful for SSR and SSG as the getResource functions does not wait for the resource to be fully available * causing SvelteKit to render incomplete pages. * * When using **SvelteKit**, make sure you inject the custom fetch function into the store before calling this function. @@ -49,10 +49,10 @@ export const loadResourceTree = async ( const promises: Promise[] = []; for (const [property, branch] of Object.entries(tree)) { - await store.getResourceAsync(property); + await store.getResource(property); const values = normalize(resource.get(property)); const resources = await Promise.all( - values.map(value => store.getResourceAsync(value)), + values.map(value => store.getResource(value)), ); if (typeof branch === 'boolean') { @@ -67,7 +67,7 @@ export const loadResourceTree = async ( return Promise.allSettled(promises.flat()); }; - const resource = await store.getResourceAsync(subject); + const resource = await store.getResource(subject); await loadResourceTreeInner(resource, treeTemplate); }; diff --git a/browser/svelte/src/stores/getResource.test.ts b/browser/svelte/src/lib/stores/getResource.test.ts similarity index 96% rename from browser/svelte/src/stores/getResource.test.ts rename to browser/svelte/src/lib/stores/getResource.test.ts index c88a1c7d2..1761ff989 100644 --- a/browser/svelte/src/stores/getResource.test.ts +++ b/browser/svelte/src/lib/stores/getResource.test.ts @@ -1,6 +1,6 @@ import { Store, urls } from '@tomic/lib'; import { describe, it, expect, beforeEach } from 'vitest'; -import { getResource, initStore, store } from '~/index'; +import { getResource, initStore, store } from '../index.js'; import { get, writable } from 'svelte/store'; const resource1Subject = 'https://resource1'; diff --git a/browser/svelte/src/stores/getResource.ts b/browser/svelte/src/lib/stores/getResource.ts similarity index 88% rename from browser/svelte/src/stores/getResource.ts rename to browser/svelte/src/lib/stores/getResource.ts index cd1181229..6ccc76c3a 100644 --- a/browser/svelte/src/stores/getResource.ts +++ b/browser/svelte/src/lib/stores/getResource.ts @@ -1,7 +1,12 @@ -import { FetchOpts, OptionalClass, Resource, Store } from '@tomic/lib'; +import { + type FetchOpts, + type OptionalClass, + Resource, + Store, +} from '@tomic/lib'; -import { Readable, get, readable, Subscriber } from 'svelte/store'; -import { store } from './store'; +import { type Readable, get, readable, type Subscriber } from 'svelte/store'; +import { store } from './store.js'; const subscribeToADStore = ( adStore: Store, diff --git a/browser/svelte/src/stores/getValue.test.ts b/browser/svelte/src/lib/stores/getValue.test.ts similarity index 94% rename from browser/svelte/src/stores/getValue.test.ts rename to browser/svelte/src/lib/stores/getValue.test.ts index 7127187d3..3d647d9a3 100644 --- a/browser/svelte/src/stores/getValue.test.ts +++ b/browser/svelte/src/lib/stores/getValue.test.ts @@ -2,7 +2,7 @@ import { Store } from '@tomic/lib'; import { get } from 'svelte/store'; import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { getResource, getValue, initStore, store } from '~/index'; +import { getResource, getValue, initStore, store } from '../index.js'; const resourceSubject = 'https://resource1'; const property = 'https://property'; diff --git a/browser/svelte/src/stores/getValue.ts b/browser/svelte/src/lib/stores/getValue.ts similarity index 92% rename from browser/svelte/src/stores/getValue.ts rename to browser/svelte/src/lib/stores/getValue.ts index f8f67a367..f7ab344f4 100644 --- a/browser/svelte/src/stores/getValue.ts +++ b/browser/svelte/src/lib/stores/getValue.ts @@ -1,7 +1,11 @@ -import { Resource, InferTypeOfValueInTriple, OptionalClass } from '@tomic/lib'; -import { Readable, Writable, get } from 'svelte/store'; - -import { store } from './store'; +import { + Resource, + type InferTypeOfValueInTriple, + type OptionalClass, +} from '@tomic/lib'; +import { type Readable, type Writable, get } from 'svelte/store'; + +import { store } from './store.js'; export type ValueSubscriber< Prop extends string, diff --git a/browser/svelte/src/stores/store.ts b/browser/svelte/src/lib/stores/store.ts similarity index 100% rename from browser/svelte/src/stores/store.ts rename to browser/svelte/src/lib/stores/store.ts diff --git a/browser/svelte/src/routes/+layout.svelte b/browser/svelte/src/routes/+layout.svelte new file mode 100644 index 000000000..5de173cb6 --- /dev/null +++ b/browser/svelte/src/routes/+layout.svelte @@ -0,0 +1,22 @@ + + +
+ +
+ + diff --git a/browser/svelte/src/routes/+page.svelte b/browser/svelte/src/routes/+page.svelte new file mode 100644 index 000000000..0b2b7b69c --- /dev/null +++ b/browser/svelte/src/routes/+page.svelte @@ -0,0 +1,8 @@ +

@tomic/svelte exaples

+ +

Components

+ diff --git a/browser/svelte/src/routes/examples/image/+page.svelte b/browser/svelte/src/routes/examples/image/+page.svelte new file mode 100644 index 000000000..cb058f347 --- /dev/null +++ b/browser/svelte/src/routes/examples/image/+page.svelte @@ -0,0 +1,66 @@ + + + + Image Example + + +

Image example

+ +

+ The {'<'}Image /{'>'} component renders a file resource as an image and optimizes + it based on the screen size and supported image formats. +

+ +
+ A bonzai tree that lost half its leaves +
+ +
+
+ Quality: 60 (default) + A bonzai tree that lost half its leaves +
+
+ Quality: 20 + A bonzai tree that lost half its leaves +
+
+ + diff --git a/browser/svelte/src/vite-env.d.ts b/browser/svelte/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/browser/svelte/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/browser/svelte/static/favicon.png b/browser/svelte/static/favicon.png new file mode 100644 index 000000000..825b9e65a Binary files /dev/null and b/browser/svelte/static/favicon.png differ diff --git a/browser/svelte/svelte.config.js b/browser/svelte/svelte.config.js new file mode 100644 index 000000000..8a8cae634 --- /dev/null +++ b/browser/svelte/svelte.config.js @@ -0,0 +1,18 @@ +import adapter from '@sveltejs/adapter-auto'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), + + kit: { + // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. + // If your environment is not supported, or you settled on a specific environment, switch out the adapter. + // See https://kit.svelte.dev/docs/adapters for more information about adapters. + adapter: adapter(), + }, +}; + +export default config; diff --git a/browser/svelte/tsconfig.json b/browser/svelte/tsconfig.json index 8572b9ac6..8ed3dd7f2 100644 --- a/browser/svelte/tsconfig.json +++ b/browser/svelte/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "./.svelte-kit/tsconfig.json", "compilerOptions": { - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "types": ["vite/client", "node"], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "Node", "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "baseUrl": "./", - "paths": { - "~/*": ["src/*"] - } - }, - "include": ["./src"], - "exclude": ["node_modules"] + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "module": "NodeNext", + "moduleResolution": "NodeNext" + } } diff --git a/browser/svelte/vite.config.ts b/browser/svelte/vite.config.ts index ad2a33b6f..552220b89 100644 --- a/browser/svelte/vite.config.ts +++ b/browser/svelte/vite.config.ts @@ -1,43 +1,12 @@ -import { defineConfig } from 'vite'; - -import typescript from '@rollup/plugin-typescript'; -import path from 'path'; -import { typescriptPaths } from 'rollup-plugin-typescript-paths'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vitest/config'; export default defineConfig({ - plugins: [], - resolve: { - alias: [ - { - find: '~', - replacement: path.resolve(__dirname, './src'), - }, - ], + plugins: [sveltekit()], + test: { + include: ['src/**/*.{test,spec}.{js,ts}'], }, server: { port: 5175, }, - build: { - manifest: true, - minify: true, - reportCompressedSize: true, - lib: { - entry: path.resolve(__dirname, 'src/index.ts'), - fileName: 'index', - formats: ['es', 'cjs'], - }, - rollupOptions: { - external: [], - plugins: [ - typescriptPaths({ - preserveExtensions: true, - }), - typescript({ - sourceMap: false, - declaration: true, - outDir: 'dist', - }), - ], - }, - }, }); diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 06e71ece1..d124ce593 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -10,9 +10,8 @@ # AtomicServer - [AtomicServer](atomic-server.md) - - [When (not) to use it](atomicserver/when-to-use.md))] + - [When (not) to use it](atomicserver/when-to-use.md) - [Installation](atomicserver/installation.md) - - [FAQ & troubleshooting](atomicserver/faq.md) - [Getting started with the GUI](atomicserver/gui.md) - [API](atomicserver/API.md) - [Creating a JSON-AD file](create-json-ad.md) @@ -32,8 +31,10 @@ - [useServerSearch](react/useServerSearch.md) - [useCurrentAgent](react/useCurrentAgent.md) - [useCanWrite](react/useCanWrite.md) + - [Image](react/Image.md) - [Examples](react/examples.md) - [@tomic/svelte](svelte.md) + - [Image](svelte/image.md) - [JS CLI](js-cli.md) - [Rust](rust-lib.md) - [Rust lib](rust-lib.md) diff --git a/docs/src/atomicserver/API.md b/docs/src/atomicserver/API.md index f952821c4..36d2bd41d 100644 --- a/docs/src/atomicserver/API.md +++ b/docs/src/atomicserver/API.md @@ -2,7 +2,7 @@ The API of AtomicServer uses _Atomic Data_. -All Atomic Data resources have a unique URL, which van be fetched using HTTP. +All Atomic Data resources have a unique URL, which can be fetched using HTTP. Every single Class, Property or Endpoint also is a resource, which means you can visit these in the browser! This effectively makes most of the API **browsable** and **self-documenting**. @@ -27,7 +27,6 @@ The various [Endpoints](../endpoints.md) in AtomicServer can be seen at `/endpoi These include functionality to create changes using `/commits`, query data using `/query`, get `/versions`, or do full-text search queries using `/search`. Typically, you pass query parameters to these endpoints to specify what you want to do. - ## Libraries or API? diff --git a/docs/src/files.md b/docs/src/files.md index 42cf2b367..8da071a77 100644 --- a/docs/src/files.md +++ b/docs/src/files.md @@ -13,6 +13,7 @@ _url: [https://atomicdata.dev/classes/File](https://atomicdata.dev/classes/File) Files always have a downloadURL. They often also have a filename, a filesize, a checksum, a mimetype, and an internal ID (more on that later). They also often have a [`parent`](https://atomicdata.dev/properties/parent), which can be used to set permissions / rights. +If the file is an image they will also get an `imageWidth` and `imageHeight` property. ## Uploading a file @@ -28,6 +29,21 @@ In `atomic-server`, a `/upload` endpoint exists for uploading a file. Simply send an HTTP GET request to the File's [`download-url`](https://atomicdata.dev/properties/downloadURL) (make sure to authenticate this request). +### Image compression + +AtomicServer can automatically generate compressed versions of images in modern image formats (WebP, AVIF). +To do this add one or more of the following query parameters to the download URL: + +| Query parameter | Description | +| --- | --- | +| f | The format of the image. Can be `webp` or `avif`. | +| q | The quality used to encode the image. Can be a number between 0 and 100. (Only works when `f` is set to `webp` or `avif`). Default is 75| +| w | The width of the image. Height will be scaled based on the width to keep the right aspect-ratio | + +Example: `https://atomicdata.dev/download/files/1668879942069-funny-meme.jpg?f=avif&q=60&w=500` + +## Discussion + - [Discussion on specification](https://github.com/ontola/atomic-data-docs/issues/57) - [Discussion on Rust server implementation](https://github.com/atomicdata-dev/atomic-server/issues/72) - [Discussion on Typescript client implementation](https://github.com/atomicdata-dev/atomic-data-browser/issues/121) diff --git a/docs/src/react/Image.md b/docs/src/react/Image.md new file mode 100644 index 000000000..d935e3bb3 --- /dev/null +++ b/docs/src/react/Image.md @@ -0,0 +1,90 @@ +# The Image component + +AtomicServer can generate optimized versions of images in modern image formats **(WebP, AVIF)** on demand by adding query parameters to the download URL of an image. +More info [here](../files.md). + +Serving the correct size and format of an image can greatly improve the performance of your website. This is especially important on mobile devices, where bandwidth is limited. +But it's not always the easiest thing to do. You need to generate multiple versions of the same image and serve the correct one based on the device's capabilities. + +We added a component to `@tomic/react` that makes this easy: the `Image` component. + +In its most basic form, it looks like this: +```jsx +import { Image } from "@tomic/react"; + +const MyComponent = () => { + return ( + A funny looking cat + ); +}; +``` + +You give it the subject of a file resource that has an image MIME type and it will render a [picture](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture) element with sources for avif, webp and the original format. +It also creates a couple of sizes the browser can choose from, based on the device's screen size. + +## Making sure the browser chooses the right image + +By default, the browser looks at the entire viewport width and chooses the smallest version that still covers this width. +This is often too big so we should help by giving it an approximation of the size of the image relative to the viewport. +This is done via the `sizeIndication` prop. + +When the unit given is a number it is interpreted as a percentage of the viewport width. If your image is displayed in a static size you can also pass a string like '4rem'. +Note that percentages don't work as the browser doesn't know the size of the parent element yet. + +```jsx + a person standing in front of a mountain + ``` + +```jsx + a person standing in front of a mountain + ``` + +When the image's size changes based on media queries we can give the browser a more detailed indication. + +```jsx +a person standing in front of a mountain +``` + +## Specifying the encoding quality + +You can specify the quality of the image by passing a number between 0 and 100 to the `quality` prop. +This is only used for the webp and avif formats. + +```jsx +a person standing in front of a mountain +``` + +## Styling the image + +The `Image` component passes all standard HTML img attributes to the underlying img element so you can style it like any other element. +Keep in mind that there is also a picture element wrapped around it that can interfere with how you're targeting the image. + +## Accessibility + +The `alt` prop is required on the image component. +Screen readers use these to describe the image to visually impaired users. +If you don't have a good description of the image, you can use an empty string. +Using an empty string is still better than no alt text at all. diff --git a/docs/src/react/examples.md b/docs/src/react/examples.md index 0a7b7e4bd..fe7ca3f15 100644 --- a/docs/src/react/examples.md +++ b/docs/src/react/examples.md @@ -7,8 +7,14 @@ If you were to make this in vanilla react without any kind of persistence it wou The main difference is the use of the `useArray` and `useBoolean` hooks instead of `useState`. ```jsx -import { useArray, useBoolean, useResource } from '@tomic/react'; import { useState } from 'react'; +import { + useStore, + useArray, + useBoolean, + useResource + } from '@tomic/react'; +import { type Checklist, todoApp } from './ontologies/todoApp'; export const TodoList = () => { const store = useStore(); diff --git a/docs/src/svelte.md b/docs/src/svelte.md index 379433a4d..04fac31f7 100644 --- a/docs/src/svelte.md +++ b/docs/src/svelte.md @@ -33,7 +33,7 @@ This library is still at an early stage and the API is subject to change. const name = getValue(resource, core.properties.name); // Writable - + ``` ## Getting started @@ -73,7 +73,7 @@ Initialise the store You can now access this store from any component in your app with the store store. -```svelte +```html // Some random component.svelte + +A funny looking cat +``` + +You give it the subject of a file resource that has an image MIME type and it will render a [picture](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture) element with sources for avif, webp and the original format. +It also creates a couple of sizes the browser can choose from, based on the device's screen size. + +## Making sure the browser chooses the right image + +By default, the browser looks at the entire viewport width and chooses the smallest version that still covers this width. +This is often too big so we should help by giving it an approximation of the size of the image relative to the viewport. +This is done via the `sizeIndication` prop. + +When the unit given is a number it is interpreted as a percentage of the viewport width. If your image is displayed in a static size you can also pass a string like '4rem'. +Note that percentages don't work as the browser doesn't know the size of the parent element yet. + +```html + a person standing in front of a mountain + ``` + +```html + a person standing in front of a mountain + ``` + +When the image's size changes based on media queries we can give the browser a more detailed indication. + +```html +a person standing in front of a mountain +``` + +## Specifying the encoding quality + +You can specify the quality of the image by passing a number between 0 and 100 to the `quality` prop. +This is only used for the webp and avif formats. + +```html +a person standing in front of a mountain +``` + +## Styling the image + +By default the Image component has a max-width of `100%` and a height of `auto`. +If you don't want this, pass the `noBaseStyles` prop. +To style the image you can target it you can wrap it in a parent element and then target the image from there. + +```html + + +
+ A funny looking cat +
+ + +``` + +You can also pass a `class` prop and then use `:global()` selector to target that class. + + +## HTML Attributes +All standard HTML img attributes are passed to the underlying img element. +This makes it possible to for example add an `id` or set `loading="lazy"` + +## Accessibility + +The `alt` prop is required on the image component. +Screen readers use these to describe the image to visually impaired users. +If you don't have a good description of the image, you can use an empty string. +Using an empty string is still better than no alt text at all. diff --git a/lib/src/endpoints.rs b/lib/src/endpoints.rs index 1ce1c0811..bd56bb48d 100644 --- a/lib/src/endpoints.rs +++ b/lib/src/endpoints.rs @@ -81,6 +81,7 @@ pub fn default_endpoints() -> Vec { plugins::path::path_endpoint(), plugins::search::search_endpoint(), plugins::files::upload_endpoint(), + plugins::files::download_endpoint(), #[cfg(feature = "html")] plugins::bookmark::bookmark_endpoint(), plugins::importer::import_endpoint(), diff --git a/lib/src/plugins/files.rs b/lib/src/plugins/files.rs index a33d2f5e1..d43e32f99 100644 --- a/lib/src/plugins/files.rs +++ b/lib/src/plugins/files.rs @@ -4,10 +4,32 @@ pub fn upload_endpoint() -> Endpoint { Endpoint { path: "/upload".to_string(), params: vec![urls::PARENT.into()], - description: "In `atomic-server`, a `/upload` endpoint exists for uploading a file.\n\n- Decide where you want to add the file in the [hierarchy](hierarchy.md) of your server. You can add a file to any resource - your file will refer to this resource as its [`parent`](https://atomicdata.dev/properties/parent). Make sure you have `write` rights on this parent.\n- Use that parent to add a query parameter to the server's `/upload` endpoint, e.g. `/upload?parent=https%3A%2F%2Fatomicdata.dev%2Ffiles`.\n- Send an HTTP `POST` request to the server's `/upload` endpoint containing [`multi-part-form-data`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects). You can upload multiple files in one request. Add [authentication](https://docs.atomicdata.dev/authentication.html) headers, and sign the HTTP request.\n- The server will check your authentication headers, your permissions, and will persist your uploaded file(s). It will now create File resources.\n- The server will reply with an array of created Atomic Data Files\n".to_string(), + description: r#"In `atomic-server`, a `/upload` endpoint exists for uploading a file. + +- Decide where you want to add the file in the [hierarchy](hierarchy.md) of your server. You can add a file to any resource - your file will refer to this resource as its [`parent`](https://atomicdata.dev/properties/parent). Make sure you have `write` rights on this parent. +Use that parent to add a query parameter to the server's `/upload` endpoint, e.g. `/upload?parent=https%3A%2F%2Fatomicdata.dev%2Ffiles`. +- Send an HTTP `POST` request to the server's `/upload` endpoint containing [`multi-part-form-data`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects). You can upload multiple files in one request. Add [authentication](https://docs.atomicdata.dev/authentication.html) headers, and sign the HTTP request. +- The server will check your authentication headers, your permissions, and will persist your uploaded file(s). It will now create File resources. +- The server will reply with an array of created Atomic Data Files"#.to_string(), shortname: "upload".to_string(), handle: None, - // TODO: handle it here, instead of in Actix! + handle_post: None, + } +} + +pub fn download_endpoint() -> Endpoint { + Endpoint { + path: "/download".to_string(), + params: vec![], + description: r#"Downloads a file referenced by a file resource. +Usualy you will interact with this endpoint by following the `download-url` property on a file resource. +If the file is an image you can set a few query paremeters to make the server compress and scale the image for you. +The following query parameters are available: +- **f**: Format of the file, can be `webp` or `avif`. +- **w**: The width the image should be scaled to. +- **q**: Quality setting used during encoding. Must be a number between 0 - 100."#.to_string(), + shortname: "download".to_string(), + handle: None, handle_post: None, } } diff --git a/lib/src/urls.rs b/lib/src/urls.rs index 335150d09..03588c291 100644 --- a/lib/src/urls.rs +++ b/lib/src/urls.rs @@ -111,6 +111,8 @@ pub const MIMETYPE: &str = "https://atomicdata.dev/properties/mimetype"; pub const INTERNAL_ID: &str = "https://atomicdata.dev/properties/internalId"; pub const DOWNLOAD_URL: &str = "https://atomicdata.dev/properties/downloadURL"; pub const ATTACHMENTS: &str = "https://atomicdata.dev/properties/attachments"; +pub const IMAGE_WIDTH: &str = "https://atomicdata.dev/properties/imageWidth"; +pub const IMAGE_HEIGHT: &str = "https://atomicdata.dev/properties/imageHeight"; // ... for ChatRooms and Messages pub const MESSAGES: &str = "https://atomicdata.dev/properties/messages"; pub const NEXT_PAGE: &str = "https://atomicdata.dev/properties/nextPage"; diff --git a/server/Cargo.toml b/server/Cargo.toml index 1c86c8436..fb2bf1fa5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -49,6 +49,9 @@ tracing-chrome = "0.7" tracing-log = "0.2" ureq = "2" urlencoding = "2" +image = "0.25.2" +webp = "0.3" +ravif = "0.11.8" [dependencies.instant-acme] optional = true diff --git a/server/src/handlers/download.rs b/server/src/handlers/download.rs index 810a1e237..272444b90 100644 --- a/server/src/handlers/download.rs +++ b/server/src/handlers/download.rs @@ -1,20 +1,36 @@ +use crate::{appstate::AppState, errors::AtomicServerResult, helpers::get_client_agent}; use actix_files::NamedFile; use actix_web::{web, HttpRequest, HttpResponse}; use atomic_lib::{urls, Resource, Storelike}; +use image::GenericImageView; +use image::{codecs::avif::AvifEncoder, ImageReader}; +use serde::Deserialize; +use std::{collections::HashSet, io::Write, path::PathBuf}; -use crate::{appstate::AppState, errors::AtomicServerResult, helpers::get_client_agent}; +#[serde_with::serde_as] +#[serde_with::skip_serializing_none] +#[derive(Deserialize, Debug)] +pub struct DownloadParams { + pub q: Option, + pub w: Option, + pub f: Option, +} /// Downloads the File of the Resource that matches the same URL minus the `/download` path. #[tracing::instrument(skip(appstate, req))] pub async fn handle_download( path: Option>, appstate: web::Data, + params: web::Query, req: actix_web::HttpRequest, ) -> AtomicServerResult { let headers = req.headers(); let server_url = &appstate.config.server_url; let store = &appstate.store; + if let Some(quality) = ¶ms.q { + println!("Quality: {}", quality); + } // We replace `/download` with `/` to get the subject of the Resource. let subject = if let Some(pth) = path { let subject = format!("{}/{}", server_url, pth); @@ -27,19 +43,142 @@ pub async fn handle_download( let for_agent = get_client_agent(headers, &appstate, subject.clone())?; tracing::info!("handle_download: {}", subject); let resource = store.get_resource_extended(&subject, false, &for_agent)?; - download_file_handler_partial(&resource, &req, &appstate) + download_file_handler_partial(&resource, &req, ¶ms, &appstate) } pub fn download_file_handler_partial( resource: &Resource, req: &HttpRequest, + params: &web::Query, appstate: &AppState, ) -> AtomicServerResult { - let file_name = resource + let filename = resource .get(urls::INTERNAL_ID) - .map_err(|e| format!("Internal ID of file could not be resolved. {}", e))?; + .map_err(|e| format!("Internal ID of file could not be resolved. {}", e))? + .to_string(); let mut file_path = appstate.config.uploads_path.clone(); - file_path.push(file_name.to_string()); - let file = NamedFile::open(file_path)?; + file_path.push(&filename); + + // No params were given, so we just return the file. + if params.q.is_none() && params.w.is_none() && params.f.is_none() { + let file = NamedFile::open(file_path)?; + return Ok(file.into_response(req)); + } + + create_processed_folder_if_not_exists(&appstate.config.uploads_path)?; + let processed_file_path = + build_prossesed_file_path(&filename, params, appstate.config.uploads_path.clone())?; + + if processed_file_path.exists() { + let file = NamedFile::open(processed_file_path)?; + return Ok(file.into_response(req)); + } + + if !is_image(&file_path) { + return Err("Quality or with parameter are not supported for non image files".into()); + } + + process_image(&file_path, &processed_file_path, params)?; + + let file = NamedFile::open(processed_file_path)?; Ok(file.into_response(req)) } + +pub fn build_prossesed_file_path( + filename: &str, + params: &DownloadParams, + base_path: PathBuf, +) -> AtomicServerResult { + let format = get_format(params)?; + + let Some((timestamp, rest)) = filename.split_once('-') else { + return Err("Filename does not contain a timestamp.".into()); + }; + + let mut new_filename = String::new(); + + new_filename.push_str(timestamp); + + if let Some(quality) = ¶ms.q { + new_filename.push_str(&format!("-q{}", quality)); + } + if let Some(width) = ¶ms.w { + new_filename.push_str(&format!("-w{}", width)); + } + + new_filename.push_str(&format!("-{}", rest)); + let mut processed_file_path = base_path.join("processed").join(new_filename); + processed_file_path.set_extension(format); + + Ok(processed_file_path) +} + +fn is_image(file_path: &PathBuf) -> bool { + if let Ok(img) = image::open(file_path) { + return img.dimensions() > (0, 0); + } + false +} + +fn process_image( + file_path: &PathBuf, + new_path: &PathBuf, + params: &DownloadParams, +) -> AtomicServerResult<()> { + let format = get_format(params)?; + let quality = params.q.unwrap_or(100.0).clamp(0.0, 100.0); + + let mut img = ImageReader::open(file_path)? + .with_guessed_format()? + .decode() + .map_err(|e| format!("Failed to decode image: {}", e))?; + + if let Some(width) = ¶ms.w { + if *width < img.dimensions().0 { + img = img.resize(*width, 10000, image::imageops::FilterType::Lanczos3); + } + } + + if format == "webp" { + let encoder = webp::Encoder::from_image(&img)?; + let webp_image = match params.q { + Some(quality) => encoder.encode(quality), + None => encoder.encode(75.0), + }; + + let mut file = std::fs::File::create(new_path)?; + file.write_all(&webp_image)?; + + return Ok(()); + } + + if format == "avif" { + let mut file = std::fs::File::create(new_path)?; + let encoder = AvifEncoder::new_with_speed_quality(&mut file, 8, quality as u8); + img.write_with_encoder(encoder) + .map_err(|e| format!("Failed to encode image: {}", e))?; + + return Ok(()); + } + + Err(format!("Unsupported format: {}", format).into()) +} + +fn create_processed_folder_if_not_exists(base_path: &PathBuf) -> AtomicServerResult<()> { + let mut processed_folder = base_path.clone(); + processed_folder.push("processed"); + std::fs::create_dir_all(processed_folder)?; + Ok(()) +} + +fn get_format(params: &DownloadParams) -> AtomicServerResult { + let supported_compression_formats: HashSet = + HashSet::from_iter(vec!["webp".to_string(), "avif".to_string()]); + + let format = params.f.clone().unwrap_or("webp".to_string()); + if !supported_compression_formats.contains(&format) { + return Err("Unsupported format".into()); + } + + Ok(format) +} diff --git a/server/src/handlers/upload.rs b/server/src/handlers/upload.rs index e91915624..65d1d1456 100644 --- a/server/src/handlers/upload.rs +++ b/server/src/handlers/upload.rs @@ -1,11 +1,12 @@ use std::{ffi::OsStr, io::Write, path::Path}; -use actix_multipart::Multipart; +use actix_multipart::{Field, Multipart}; use actix_web::{web, HttpResponse}; use atomic_lib::{ commit::CommitResponse, hierarchy::check_write, urls, utils::now, Resource, Storelike, Value, }; -use futures::{StreamExt, TryStreamExt}; +use futures::{io::Cursor, StreamExt, TryStreamExt}; +use image::GenericImageView; use serde::Deserialize; use crate::{appstate::AppState, errors::AtomicServerResult, helpers::get_client_agent}; @@ -44,54 +45,8 @@ pub async fn upload_handler( let mut created_resources: Vec = Vec::new(); let mut commit_responses: Vec = Vec::new(); - while let Ok(Some(mut field)) = body.try_next().await { - let content_type = field.content_disposition().clone(); - let filename = content_type.get_filename().ok_or("Filename is missing")?; - - std::fs::create_dir_all(&appstate.config.uploads_path)?; - - let file_id = format!( - "{}-{}", - now(), - sanitize_filename::sanitize(filename) - // Spacebars lead to very annoying bugs in browsers - .replace(' ', "-") - ); - - let mut file_path = appstate.config.uploads_path.clone(); - file_path.push(&file_id); - let mut file = std::fs::File::create(file_path)?; - - // Field in turn is stream of *Bytes* object - while let Some(chunk) = field.next().await { - let data = chunk.map_err(|e| format!("Error while reading multipart data. {}", e))?; - // TODO: Update a SHA256 hash here for checksum - file.write_all(&data)?; - } - - let byte_count: i64 = file - .metadata()? - .len() - .try_into() - .map_err(|_e| "Too large")?; - - let subject_path = format!("files/{}", urlencoding::encode(&file_id)); - let new_subject = format!("{}/{}", store.get_server_url(), subject_path); - let download_url = format!("{}/download/{}", store.get_server_url(), subject_path); - - let mut resource = atomic_lib::Resource::new_instance(urls::FILE, store)?; - resource - .set_subject(new_subject) - .set_string(urls::PARENT.into(), &query.parent, store)? - .set_string(urls::INTERNAL_ID.into(), &file_id, store)? - .set(urls::FILESIZE.into(), Value::Integer(byte_count), store)? - .set_string( - urls::MIMETYPE.into(), - &guess_mime_for_filename(filename), - store, - )? - .set_string(urls::FILENAME.into(), filename, store)? - .set_string(urls::DOWNLOAD_URL.into(), &download_url, store)?; + while let Ok(Some(field)) = body.try_next().await { + let mut resource = save_file_and_create_resource(field, &appstate, &query.parent).await?; commit_responses.push(resource.save(store)?); created_resources.push(resource); } @@ -116,6 +71,78 @@ pub async fn upload_handler( )?)) } +async fn save_file_and_create_resource( + mut field: Field, + appstate: &web::Data, + parent: &str, +) -> AtomicServerResult { + let store = &appstate.store; + let content_type = field.content_disposition().clone(); + let filename = content_type.get_filename().ok_or("Filename is missing")?; + + std::fs::create_dir_all(&appstate.config.uploads_path)?; + + let file_id = format!( + "{}-{}", + now(), + sanitize_filename::sanitize(filename) + // Spacebars lead to very annoying bugs in browsers + .replace(' ', "-") + ); + + let mut file_path = appstate.config.uploads_path.clone(); + file_path.push(&file_id); + + let mut file = std::fs::File::create(&file_path)?; + + // Field in turn is stream of *Bytes* object + while let Some(chunk) = field.next().await { + let data = chunk.map_err(|e| format!("Error while reading multipart data. {}", e))?; + // TODO: Update a SHA256 hash here for checksum + file.write_all(&data)?; + } + + let byte_count: i64 = file + .metadata()? + .len() + .try_into() + .map_err(|_e| "Too large")?; + + let mimetype = guess_mime_for_filename(filename); + let subject_path = format!("files/{}", urlencoding::encode(&file_id)); + let new_subject = format!("{}/{}", store.get_server_url(), subject_path); + let download_url = format!("{}/download/{}", store.get_server_url(), subject_path); + + let mut resource = atomic_lib::Resource::new_instance(urls::FILE, store)?; + resource + .set_subject(new_subject) + .set_string(urls::PARENT.into(), parent, store)? + .set_string(urls::INTERNAL_ID.into(), &file_id, store)? + .set(urls::FILESIZE.into(), Value::Integer(byte_count), store)? + .set_string(urls::MIMETYPE.into(), &mimetype, store)? + .set_string(urls::FILENAME.into(), filename, store)? + .set_string(urls::DOWNLOAD_URL.into(), &download_url, store)?; + + if mimetype.starts_with("image/") { + if let Ok(img) = image::ImageReader::open(&file_path)?.decode() { + let (width, height) = img.dimensions(); + resource + .set( + urls::IMAGE_WIDTH.into(), + Value::Integer(width as i64), + store, + )? + .set( + urls::IMAGE_HEIGHT.into(), + Value::Integer(height as i64), + store, + )?; + } + } + + Ok(resource) +} + fn guess_mime_for_filename(filename: &str) -> String { if let Some(ext) = get_extension_from_filename(filename) { actix_files::file_extension_to_mime(ext).to_string()