From ebe8b567fdb9d011f574fc9053ad3f981b63930f Mon Sep 17 00:00:00 2001 From: Zak Nesler Date: Sun, 26 May 2024 18:21:35 -0400 Subject: [PATCH] feed refactor and processing (#37) * begin feed refactor * ui updates * keep icon url * debounce feed invalidation * sanitize fields * rm id [skip ci] * add more fields * add line [skip ci] * fetch column * fix favicon url * save favicon and render * more required fields * rename module * add saved to stats * count saved in total * 404 styles * improve styles and rm local entry store * debounce stats invalidation * rename classes * render html and display title * rename query state hook * scrape wip * add scraped_at field * libxml * sudo * initial readability port * add scraping job * check content_html * fix check * trim and retry urls * ui tweaks * scrape favicons * use b64 * readme [skip ci] --- Cargo.lock | 1104 +++++++++++- Cargo.toml | 1 + README.md | 2 +- .../migrations/20240422000000_feeds.sql | 5 +- .../migrations/20240430000000_entries.sql | 5 +- .../migrations/20240504000000_feeds_stats.sql | 15 - crates/blend-db/src/model/entry.rs | 5 +- crates/blend-db/src/model/feed.rs | 8 +- crates/blend-db/src/repo/entry.rs | 41 +- crates/blend-db/src/repo/feed.rs | 51 +- crates/blend-feed/Cargo.toml | 7 + crates/blend-feed/src/error.rs | 6 + crates/blend-feed/src/extract/html.rs | 25 + crates/blend-feed/src/extract/mod.rs | 10 + crates/blend-feed/src/extract/stylistic.rs | 69 + crates/blend-feed/src/extract/text.rs | 46 + crates/blend-feed/src/lib.rs | 43 +- crates/blend-feed/src/model.rs | 42 +- crates/blend-feed/src/parse/entry.rs | 46 + crates/blend-feed/src/parse/feed.rs | 31 + crates/blend-feed/src/parse/mod.rs | 31 + crates/blend-feed/src/parse/url.rs | 29 + crates/blend-feed/src/readability/dom.rs | 116 ++ crates/blend-feed/src/readability/extract.rs | 55 + crates/blend-feed/src/readability/mod.rs | 7 + crates/blend-feed/src/readability/score.rs | 293 ++++ crates/blend-feed/src/scrape.rs | 14 + crates/blend-web/src/context.rs | 4 +- crates/blend-web/src/router/feed.rs | 25 +- crates/blend-web/src/router/ws.rs | 6 +- crates/blend-worker/Cargo.toml | 3 + crates/blend-worker/src/error.rs | 6 + crates/blend-worker/src/handler.rs | 95 +- crates/blend-worker/src/job.rs | 6 +- crates/blend-worker/src/notification.rs | 28 +- crates/blend-worker/src/worker.rs | 22 +- package.json | 4 +- pnpm-lock.yaml | 1485 ++++++++--------- src/main.rs | 19 +- tailwind.config.ts | 16 +- ui/src/components/entry/entry-item.tsx | 73 +- ui/src/components/entry/entry-list.tsx | 17 +- ui/src/components/entry/entry-panel.tsx | 16 +- ui/src/components/entry/entry-view.tsx | 17 +- ui/src/components/feed/feed-header.tsx | 6 +- ui/src/components/feed/feed-info.tsx | 4 +- ui/src/components/feed/feed-item.tsx | 46 +- ui/src/components/feed/feed-list.tsx | 6 +- ui/src/components/menus/menu.tsx | 2 +- ui/src/components/modals/create-feed.tsx | 9 +- ui/src/components/nav/nav-row.tsx | 6 +- ui/src/components/nav/nav-view-switcher.tsx | 8 +- ui/src/components/ui/tooltip.tsx | 2 +- ui/src/hooks/queries/use-feeds-stats.ts | 3 +- ui/src/hooks/queries/use-infinite-entries.ts | 43 +- ui/src/hooks/queries/use-invalidate-feed.ts | 26 + ui/src/hooks/queries/use-invalidate-stats.ts | 20 + ui/src/hooks/use-list-nav.ts | 8 +- ui/src/hooks/use-notifications.ts | 20 +- ...se-filter-params.ts => use-query-state.ts} | 12 +- ui/src/layouts/base.tsx | 2 +- ui/src/routes/404.tsx | 20 +- ui/src/routes/feed.tsx | 28 +- ui/src/types/bindings.ts | 22 +- ui/src/utils/entries.ts | 2 +- 65 files changed, 3044 insertions(+), 1200 deletions(-) delete mode 100644 crates/blend-db/migrations/20240504000000_feeds_stats.sql create mode 100644 crates/blend-feed/src/extract/html.rs create mode 100644 crates/blend-feed/src/extract/mod.rs create mode 100644 crates/blend-feed/src/extract/stylistic.rs create mode 100644 crates/blend-feed/src/extract/text.rs create mode 100644 crates/blend-feed/src/parse/entry.rs create mode 100644 crates/blend-feed/src/parse/feed.rs create mode 100644 crates/blend-feed/src/parse/mod.rs create mode 100644 crates/blend-feed/src/parse/url.rs create mode 100644 crates/blend-feed/src/readability/dom.rs create mode 100644 crates/blend-feed/src/readability/extract.rs create mode 100644 crates/blend-feed/src/readability/mod.rs create mode 100644 crates/blend-feed/src/readability/score.rs create mode 100644 crates/blend-feed/src/scrape.rs create mode 100644 ui/src/hooks/queries/use-invalidate-feed.ts create mode 100644 ui/src/hooks/queries/use-invalidate-stats.ts rename ui/src/hooks/{use-filter-params.ts => use-query-state.ts} (81%) diff --git a/Cargo.lock b/Cargo.lock index 8752bf3e..b072ff2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,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.4" @@ -60,6 +66,19 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "ammonia" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" +dependencies = [ + "html5ever 0.27.0", + "maplit", + "once_cell", + "tendril", + "url", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -124,6 +143,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[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 = "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.66", +] + [[package]] name = "argon2" version = "0.5.3" @@ -136,6 +178,12 @@ dependencies = [ "password-hash", ] +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-compression" version = "0.4.10" @@ -157,7 +205,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -178,12 +226,41 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[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 = "axum" version = "0.7.5" @@ -295,6 +372,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[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" @@ -310,6 +393,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitstream-io" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c12d1856e42f0d817a835fe55853957c85c8c8a470114029143d3f12671446e" + [[package]] name = "blake2" version = "0.10.6" @@ -382,12 +471,19 @@ dependencies = [ name = "blend-feed" version = "0.0.0" dependencies = [ + "ammonia", "chrono", "feed-rs", + "futures", + "html5ever 0.27.0", + "lazy_static", + "markup5ever_rcdom", + "regex", "reqwest", "serde", "serde_json", "thiserror", + "url", ] [[package]] @@ -421,9 +517,11 @@ dependencies = [ name = "blend-worker" version = "0.0.0" dependencies = [ + "base64 0.22.1", "blend-config", "blend-db", "blend-feed", + "favilib", "futures", "reqwest", "serde", @@ -433,6 +531,7 @@ dependencies = [ "tokio", "tracing", "typeshare", + "url", "uuid", ] @@ -466,6 +565,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "built" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6a6c0b39c38fd754ac338b00a88066436389c0f029da5d37d1e01091d9b7c17" + [[package]] name = "bumpalo" version = "3.16.0" @@ -484,6 +589,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[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.6.0" @@ -492,9 +603,24 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + +[[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" @@ -548,7 +674,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -557,6 +683,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.1" @@ -620,6 +752,34 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -631,9 +791,15 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" @@ -645,6 +811,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.66", +] + [[package]] name = "darling" version = "0.20.9" @@ -666,7 +855,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -677,7 +866,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -706,6 +895,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.10.7" @@ -754,6 +954,27 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" + [[package]] name = "either" version = "1.12.0" @@ -805,12 +1026,52 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fastrand" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "favilib" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7556cbc1d9d8a63a1b0c5956e3a1f27e9c4a22862899fadbb56f0c41ef4d952" +dependencies = [ + "anyhow", + "clap", + "image", + "reqwest", + "scraper", + "thiserror", + "url", +] + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "feed-rs" version = "1.5.2" @@ -823,16 +1084,16 @@ dependencies = [ "regex", "serde", "serde_json", - "siphasher", + "siphasher 1.0.1", "url", "uuid", ] [[package]] name = "figment" -version = "0.10.18" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ "atomic", "pear", @@ -843,10 +1104,14 @@ dependencies = [ ] [[package]] -name = "finl_unicode" -version = "1.2.0" +name = "flate2" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] [[package]] name = "flume" @@ -889,6 +1154,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -956,7 +1231,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -989,6 +1264,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -999,17 +1283,36 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", "wasi", ] +[[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 = "gimli" version = "0.28.1" @@ -1018,15 +1321,15 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap", "slab", @@ -1035,6 +1338,16 @@ dependencies = [ "tracing", ] +[[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.14.5" @@ -1108,6 +1421,34 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever 0.11.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "http" version = "1.1.0" @@ -1199,9 +1540,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" dependencies = [ "bytes", "futures-channel", @@ -1256,6 +1597,45 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +dependencies = [ + "bytemuck", + "byteorder", + "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 = "indexmap" version = "2.2.6" @@ -1272,6 +1652,17 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[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.66", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1299,6 +1690,21 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +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.69" @@ -1332,11 +1738,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[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 = "libm" @@ -1367,9 +1790,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -1387,12 +1810,83 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever_rcdom" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edaa21ab3701bfee5099ade5f7e1f84553fd19228cf332f13cd6e964bf59be18" +dependencies = [ + "html5ever 0.27.0", + "markup5ever 0.12.1", + "tendril", + "xml5ever", +] + [[package]] name = "matchit" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[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 = "md-5" version = "0.10.6" @@ -1433,11 +1927,12 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -1469,6 +1964,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" @@ -1479,6 +1980,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 = "nu-ansi-term" version = "0.46.0" @@ -1489,6 +1996,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -1512,6 +2029,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[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.66", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -1522,12 +2050,23 @@ dependencies = [ ] [[package]] -name = "num-iter" -version = "0.1.45" +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", + "num-bigint", "num-integer", "num-traits", ] @@ -1590,7 +2129,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1601,9 +2140,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.2.3+3.2.1" +version = "300.3.0+3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" +checksum = "eba8804a1c5765b18c4b3f907e6897ebabeedebc9830e1a0046c4a4cf44663e1" dependencies = [ "cc", ] @@ -1635,9 +2174,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1693,7 +2232,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1711,6 +2250,96 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher 0.3.11", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -1728,7 +2357,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1770,6 +2399,19 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[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", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1782,6 +2424,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1808,9 +2456,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -1823,11 +2471,45 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "version_check", "yansi", ] +[[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.66", +] + +[[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 = "quick-xml" version = "0.31.0" @@ -1877,6 +2559,76 @@ dependencies = [ "getrandom", ] +[[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", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc13288f5ab39e6d7c9d501759712e6969fcc9734220846fc9ed26cae2cc4234" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1944,6 +2696,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", @@ -1977,6 +2730,15 @@ dependencies = [ "winreg", ] +[[package]] +name = "rgb" +version = "0.8.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +dependencies = [ + "bytemuck", +] + [[package]] name = "rsa" version = "0.9.6" @@ -2018,7 +2780,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.64", + "syn 2.0.66", "walkdir", ] @@ -2103,6 +2865,22 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b80b33679ff7a0ea53d37f3b39de77ea0c75b12c5805ac43ec0c33b3051af1b" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever 0.26.0", + "once_cell", + "selectors", + "tendril", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -2126,24 +2904,43 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags 2.5.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2188,6 +2985,15 @@ dependencies = [ "serde", ] +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2238,6 +3044,27 @@ dependencies = [ "rand_core", ] +[[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 = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "siphasher" version = "1.0.1" @@ -2507,15 +3334,47 @@ dependencies = [ "uuid", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -2543,9 +3402,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.64" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -2585,6 +3444,25 @@ dependencies = [ "libc", ] +[[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", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + [[package]] name = "tempfile" version = "3.10.1" @@ -2597,24 +3475,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2627,6 +3516,17 @@ dependencies = [ "once_cell", ] +[[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.3.36" @@ -2698,7 +3598,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2873,7 +3773,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2962,7 +3862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a615d6c2764852a2e88a4f16e9ce1ea49bb776b5872956309e170d63a042a34f" dependencies = [ "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -3004,12 +3904,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -3056,6 +3968,17 @@ 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 = "validator" version = "0.18.1" @@ -3083,7 +4006,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -3098,6 +4021,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[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" @@ -3156,7 +4085,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -3190,7 +4119,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3211,6 +4140,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "whoami" version = "1.5.1" @@ -3419,6 +4354,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "xml5ever" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c376f76ed09df711203e20c3ef5ce556f0166fa03d39590016c0fd625437fad" +dependencies = [ + "log", + "mac", + "markup5ever 0.12.1", +] + [[package]] name = "yansi" version = "1.0.1" @@ -3442,11 +4388,35 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[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 = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index df6afd94..565aee46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ thiserror = "1.0" tokio = { version = "1.37", features = ["macros", "rt-multi-thread"] } tracing = "0.1" typeshare = "1.0" +url = "2.5" uuid = { version = "1.8", features = ["v4", "fast-rng", "serde"] } [package] diff --git a/README.md b/README.md index 63247309..5d4772a2 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Demo is available at [blend.zak.fm](https://blend.zak.fm). - [x] Fetch metadata and feed entries in background - [x] Notifications via websocket - [x] Automatic + manual refreshing -- [ ] Scrape HTML if entries do not contain article content +- [x] Scrape HTML if entries do not contain article content - [ ] Organize feeds into folders - [ ] UI options for theme, font, etc. - [ ] Keyboard shortcuts diff --git a/crates/blend-db/migrations/20240422000000_feeds.sql b/crates/blend-db/migrations/20240422000000_feeds.sql index 3273f6d2..5a40ebb8 100644 --- a/crates/blend-db/migrations/20240422000000_feeds.sql +++ b/crates/blend-db/migrations/20240422000000_feeds.sql @@ -2,9 +2,10 @@ CREATE TABLE IF NOT EXISTS feeds ( uuid TEXT PRIMARY KEY NOT NULL, id TEXT NOT NULL, url_feed TEXT NOT NULL, - url_site TEXT, - title TEXT, + url_site TEXT NOT NULL, + title TEXT NOT NULL, title_display TEXT, + favicon_url TEXT, favicon_b64 BLOB, published_at DATETIME, updated_at DATETIME, diff --git a/crates/blend-db/migrations/20240430000000_entries.sql b/crates/blend-db/migrations/20240430000000_entries.sql index 770a116f..a62eab72 100644 --- a/crates/blend-db/migrations/20240430000000_entries.sql +++ b/crates/blend-db/migrations/20240430000000_entries.sql @@ -4,12 +4,15 @@ CREATE TABLE IF NOT EXISTS entries ( id TEXT NOT NULL, url TEXT, title TEXT, - summary TEXT, + summary_html TEXT, content_html TEXT, content_scraped_html TEXT, + media_url TEXT, published_at DATETIME, updated_at DATETIME, read_at DATETIME, + saved_at DATETIME, + scraped_at DATETIME, UNIQUE(feed_uuid, id), CONSTRAINT fk_feed FOREIGN KEY (feed_uuid) REFERENCES feeds(uuid) ON DELETE CASCADE ); diff --git a/crates/blend-db/migrations/20240504000000_feeds_stats.sql b/crates/blend-db/migrations/20240504000000_feeds_stats.sql deleted file mode 100644 index fb49de20..00000000 --- a/crates/blend-db/migrations/20240504000000_feeds_stats.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE VIEW IF NOT EXISTS feeds_stats AS -SELECT - feeds.uuid, - COUNT(entries.uuid) as count_total, - COUNT( - CASE - WHEN entries.read_at IS NULL THEN 1 - ELSE NULL - END - ) as count_unread -FROM - feeds - INNER JOIN entries ON feeds.uuid = entries.feed_uuid -GROUP BY - feeds.uuid diff --git a/crates/blend-db/src/model/entry.rs b/crates/blend-db/src/model/entry.rs index 4833a174..7a9bbc1b 100644 --- a/crates/blend-db/src/model/entry.rs +++ b/crates/blend-db/src/model/entry.rs @@ -12,12 +12,15 @@ pub struct Entry { pub id: String, pub url: String, pub title: Option, - pub summary: Option, + pub summary_html: Option, #[sqlx(default)] pub content_html: Option, #[sqlx(default)] pub content_scraped_html: Option, + pub media_url: Option, pub published_at: Option>, pub updated_at: Option>, pub read_at: Option>, + pub saved_at: Option>, + pub scraped_at: Option>, } diff --git a/crates/blend-db/src/model/feed.rs b/crates/blend-db/src/model/feed.rs index 29949d9e..c443c793 100644 --- a/crates/blend-db/src/model/feed.rs +++ b/crates/blend-db/src/model/feed.rs @@ -10,10 +10,11 @@ pub struct Feed { pub uuid: Uuid, pub id: String, pub url_feed: String, - pub url_site: Option, - pub title: Option, + pub url_site: String, + pub title: String, pub title_display: Option, - pub favicon_b64: Option>, + pub favicon_b64: Option, + pub favicon_url: Option, pub published_at: Option>, pub updated_at: Option>, } @@ -24,4 +25,5 @@ pub struct FeedStats { pub uuid: Uuid, pub count_total: u32, pub count_unread: u32, + pub count_saved: u32, } diff --git a/crates/blend-db/src/repo/entry.rs b/crates/blend-db/src/repo/entry.rs index 12e61e2d..8502eb08 100644 --- a/crates/blend-db/src/repo/entry.rs +++ b/crates/blend-db/src/repo/entry.rs @@ -14,8 +14,9 @@ pub struct CreateEntryParams { pub id: String, pub url: Option, pub title: Option, - pub summary: Option, + pub summary_html: Option, pub content_html: Option, + pub media_url: Option, pub published_at: Option>, pub updated_at: Option>, } @@ -86,7 +87,7 @@ impl EntryRepo { let el = filter.sort.query_elements(); let el_inv = filter.sort.query_elements_inverse(); - let mut query = QueryBuilder::::new("SELECT uuid, feed_uuid, id, url, title, summary, published_at, updated_at, read_at FROM entries WHERE 1=1"); + let mut query = QueryBuilder::::new("SELECT uuid, feed_uuid, id, url, title, summary_html, media_url, published_at, updated_at, read_at, saved_at, scraped_at FROM entries WHERE 1=1"); match filter.view { View::All => query.push(""), @@ -146,6 +147,17 @@ impl EntryRepo { .map_err(|err| err.into()) } + pub async fn get_entries_to_scrape( + &self, + feed_uuid: &uuid::Uuid, + ) -> DbResult> { + sqlx::query_as::<_, model::Entry>("SELECT * FROM entries WHERE feed_uuid = ?1 AND content_html IS NULL AND content_scraped_html IS NULL AND scraped_at IS NULL") + .bind(feed_uuid) + .fetch_all(&self.db) + .await + .map_err(|err| err.into()) + } + pub async fn update_entry_as_read(&self, entry_uuid: &uuid::Uuid) -> DbResult { let rows_affected = sqlx::query("UPDATE entries SET read_at = ?1 WHERE uuid = ?2") .bind(Utc::now()) @@ -176,15 +188,16 @@ impl EntryRepo { return Ok(vec![]); } - let mut query = QueryBuilder::::new("INSERT INTO entries (feed_uuid, uuid, id, url, title, summary, content_html, published_at, updated_at) "); + let mut query = QueryBuilder::::new("INSERT INTO entries (feed_uuid, uuid, id, url, title, summary_html, content_html, media_url, published_at, updated_at) "); query.push_values(entries.iter(), |mut b, entry| { b.push_bind(feed_uuid) .push_bind(uuid::Uuid::new_v4()) .push_bind(entry.id.clone()) .push_bind(entry.url.clone()) .push_bind(entry.title.clone()) - .push_bind(entry.summary.clone()) + .push_bind(entry.summary_html.clone()) .push_bind(entry.content_html.clone()) + .push_bind(entry.media_url.clone()) .push_bind(entry.published_at) .push_bind(entry.updated_at); }); @@ -194,7 +207,7 @@ impl EntryRepo { DO UPDATE SET url = excluded.url, title = excluded.title, - summary = excluded.summary, + summary_html = excluded.summary_html, content_html = excluded.content_html, updated_at = excluded.updated_at RETURNING uuid @@ -209,4 +222,22 @@ impl EntryRepo { .map(|row| row.try_get("uuid").map_err(|err| err.into())) .collect::>>() } + + pub async fn update_scraped_entry( + &self, + entry_uuid: &uuid::Uuid, + content_scraped_html: Option, + ) -> DbResult { + let rows_affected = sqlx::query( + "UPDATE entries SET content_scraped_html = ?1, scraped_at = ?2 WHERE uuid = ?3", + ) + .bind(content_scraped_html) + .bind(Utc::now()) + .bind(entry_uuid) + .execute(&self.db) + .await? + .rows_affected(); + + Ok(rows_affected > 0) + } } diff --git a/crates/blend-db/src/repo/feed.rs b/crates/blend-db/src/repo/feed.rs index ff5e29de..4ab32fca 100644 --- a/crates/blend-db/src/repo/feed.rs +++ b/crates/blend-db/src/repo/feed.rs @@ -7,8 +7,10 @@ pub struct FeedRepo { pub struct CreateFeedParams { pub id: String, - pub title: Option, - pub url_feed: Option, + pub title: String, + pub url_feed: String, + pub url_site: String, + pub favicon_url: Option, pub published_at: Option>, pub updated_at: Option>, } @@ -26,10 +28,21 @@ impl FeedRepo { } pub async fn get_stats(&self) -> DbResult> { - sqlx::query_as::<_, model::FeedStats>("SELECT * from feeds_stats") - .fetch_all(&self.db) - .await - .map_err(|err| err.into()) + sqlx::query_as::<_, model::FeedStats>( + r#" + SELECT + feeds.uuid, + COUNT(entries.uuid) as count_total, + COUNT(CASE WHEN entries.read_at IS NULL THEN 1 ELSE NULL END) as count_unread, + COUNT(CASE WHEN entries.saved_at IS NOT NULL THEN 1 ELSE NULL END) as count_saved + FROM feeds + INNER JOIN entries ON feeds.uuid = entries.feed_uuid + GROUP BY feeds.uuid + "#, + ) + .fetch_all(&self.db) + .await + .map_err(|err| err.into()) } pub async fn get_feed(&self, feed_uuid: uuid::Uuid) -> DbResult> { @@ -43,12 +56,14 @@ impl FeedRepo { pub async fn create_feed(&self, data: CreateFeedParams) -> DbResult { let feed = sqlx::query_as::<_, model::Feed>( r#" - INSERT INTO feeds (uuid, id, url_feed, title, published_at, updated_at) - VALUES (?1, ?2, ?3, ?4, ?5, ?6) + INSERT INTO feeds (uuid, id, url_feed, url_site, title, favicon_url, published_at, updated_at) + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8) ON CONFLICT (id) DO UPDATE SET url_feed = excluded.url_feed, + url_site = excluded.url_site, title = excluded.title, + favicon_url = excluded.favicon_url, updated_at = excluded.updated_at RETURNING * "#, @@ -56,7 +71,9 @@ impl FeedRepo { .bind(uuid::Uuid::new_v4()) .bind(data.id) .bind(data.url_feed) + .bind(data.url_site) .bind(data.title) + .bind(data.favicon_url) .bind(data.published_at) .bind(data.updated_at) .fetch_one(&self.db) @@ -64,4 +81,22 @@ impl FeedRepo { Ok(feed) } + + pub async fn update_favicon( + &self, + feed_uuid: &uuid::Uuid, + favicon_url: String, + favicon_base64: Option, + ) -> DbResult { + let rows_affected = + sqlx::query("UPDATE feeds SET favicon_url = ?1, favicon_b64 = ?2 WHERE uuid = ?3") + .bind(favicon_url) + .bind(favicon_base64) + .bind(feed_uuid) + .execute(&self.db) + .await? + .rows_affected(); + + Ok(rows_affected > 0) + } } diff --git a/crates/blend-feed/Cargo.toml b/crates/blend-feed/Cargo.toml index ead1f890..ff55f92c 100644 --- a/crates/blend-feed/Cargo.toml +++ b/crates/blend-feed/Cargo.toml @@ -7,9 +7,16 @@ repository.workspace = true license.workspace = true [dependencies] +ammonia = "4.0" chrono = { workspace = true, features = ["serde"] } feed-rs = { workspace = true } +futures = { workspace = true } +html5ever = "0.27" +lazy_static = "1.4" +markup5ever_rcdom = "0.3" +regex = "1.9" reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } +url = { workspace = true } diff --git a/crates/blend-feed/src/error.rs b/crates/blend-feed/src/error.rs index 84af6663..86c504fc 100644 --- a/crates/blend-feed/src/error.rs +++ b/crates/blend-feed/src/error.rs @@ -2,12 +2,18 @@ pub(crate) type FeedResult = Result; #[derive(thiserror::Error, Debug)] pub enum FeedError { + #[error("invalid url: {0}")] + InvalidUrl(String), + #[error(transparent)] Io(#[from] std::io::Error), #[error(transparent)] RequestError(#[from] reqwest::Error), + #[error(transparent)] + UrlParseError(#[from] url::ParseError), + #[error(transparent)] ParseFeedError(#[from] feed_rs::parser::ParseFeedError), } diff --git a/crates/blend-feed/src/extract/html.rs b/crates/blend-feed/src/extract/html.rs new file mode 100644 index 00000000..5bfc8ee3 --- /dev/null +++ b/crates/blend-feed/src/extract/html.rs @@ -0,0 +1,25 @@ +use ammonia::Builder; +use std::collections::HashSet; + +const REMOVE_TAGS: [&str; 1] = ["article"]; + +// Sanitize HTML input, allowing only safe elements +pub fn extract_html(src: &str) -> String { + Builder::default().rm_tags(HashSet::from(REMOVE_TAGS)).clean(src).to_string() +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn it_keeps_only_safe_elements() { + let src = r#"

Some body text that we want to keep.

[Read More]

"#; + + let parsed = extract_html(src); + assert_eq!( + parsed, + r#"

Some body text that we want to keep.

[Read More]

"# + ); + } +} diff --git a/crates/blend-feed/src/extract/mod.rs b/crates/blend-feed/src/extract/mod.rs new file mode 100644 index 00000000..28bc7d8f --- /dev/null +++ b/crates/blend-feed/src/extract/mod.rs @@ -0,0 +1,10 @@ +mod stylistic; +pub use stylistic::extract_stylistic_html; + +mod text; +pub use text::extract_text; + +mod html; +pub use html::extract_html; + +// TODO: use `.url_relative(UrlRelative::RewriteWithBase(...))` with ammonia and pass in site URL to rewrite relative URLs diff --git a/crates/blend-feed/src/extract/stylistic.rs b/crates/blend-feed/src/extract/stylistic.rs new file mode 100644 index 00000000..1c11175d --- /dev/null +++ b/crates/blend-feed/src/extract/stylistic.rs @@ -0,0 +1,69 @@ +use ammonia::Builder; +use std::collections::HashSet; + +const ALLOWED_TAGS: [&str; 12] = [ + "a", "abbr", "b", "code", "em", "i", "kbd", "small", "strike", "strong", "sub", "sup", +]; + +// Sanitize HTML input, allowing only inline/stylistic HTML elements +pub fn extract_stylistic_html(src: &str) -> String { + Builder::default().tags(HashSet::from(ALLOWED_TAGS)).clean(src).to_string() +} + +#[cfg(test)] +mod test { + use super::*; + + // TODO: add an extra step (or a more efficient way) to strip out empty tags left over from stripping out its child nodes. + // #[test] + // fn it_extracts_only_stylistic_elements() { + // let src = r#"

Some image

Some body text that we want to keep.

[Read More]

"#; + + // let parsed = extract_stylistic_html(src); + // assert_eq!( + // parsed, + // r#"Some body text that we want to keep. [Read More]"# + // ); + // } + + #[test] + fn it_extracts_only_stylistic_elements() { + let src = r#"

Some body text that we want to keep.

[Read More]

"#; + + let parsed = extract_stylistic_html(src); + assert_eq!( + parsed, + r#"Some body text that we want to keep. [Read More]"# + ); + } + + #[test] + fn it_allows_strong_and_b_tags() { + let src = r#"

Text with strong and bold tags.

"#; + + let parsed = extract_stylistic_html(src); + assert_eq!( + parsed, + r#"Text with strong and bold tags."# + ); + } + + #[test] + fn it_flattens_span_and_div() { + let src = r#"

Text with

div
and
span
tags.

"#; + + let parsed = extract_stylistic_html(src); + assert_eq!(parsed, r#"Text with div and span tags."#); + } + + #[test] + fn it_allows_a_tags() { + let src = r#"

Text with link inside.

"#; + + let parsed = extract_stylistic_html(src); + assert_eq!( + parsed, + r#"Text with link inside."# + ); + } +} diff --git a/crates/blend-feed/src/extract/text.rs b/crates/blend-feed/src/extract/text.rs new file mode 100644 index 00000000..3db7ec47 --- /dev/null +++ b/crates/blend-feed/src/extract/text.rs @@ -0,0 +1,46 @@ +use ammonia::Builder; + +/// Sanitize HTML input, allowing only plain text +pub fn extract_text(src: &str) -> String { + Builder::empty().clean(src).to_string() +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn it_extracts_only_stylistic_elements() { + let src = r#"

Some image

Some body text that we want to keep.

[Read More]

"#; + + let parsed = extract_text(src); + assert_eq!( + parsed, + r#"Some body text that we want to keep. [Read More]"# + ); + } + + #[test] + fn it_allows_strong_and_b_tags() { + let src = r#"

Text with strong and bold tags.

"#; + + let parsed = extract_text(src); + assert_eq!(parsed, r#"Text with strong and bold tags."#); + } + + #[test] + fn it_flattens_span_and_div() { + let src = r#"

Text with

div
and
span
tags.

"#; + + let parsed = extract_text(src); + assert_eq!(parsed, r#"Text with div and span tags."#); + } + + #[test] + fn it_removes_a_tags() { + let src = r#"

Text with link inside.

"#; + + let parsed = extract_text(src); + assert_eq!(parsed, r#"Text with link inside."#); + } +} diff --git a/crates/blend-feed/src/lib.rs b/crates/blend-feed/src/lib.rs index 6db02c62..3244ffd9 100644 --- a/crates/blend-feed/src/lib.rs +++ b/crates/blend-feed/src/lib.rs @@ -1,40 +1,17 @@ -use error::FeedResult; +#[macro_use] +extern crate lazy_static; mod error; -pub mod model; - pub use error::FeedError as Error; -pub async fn parse_feed(url: &str) -> FeedResult { - let data = reqwest::get(url).await?.text().await?; - let mut feed: model::ParsedFeed = feed_rs::parser::parse(data.as_bytes()) - .or_else(|err| match err { - feed_rs::parser::ParseFeedError::ParseError(_) => todo!(), // fallback to URL and look for feed URL in - _ => Err(err), - })? - .into(); - - // TODO: need a nicer way of doing this - if feed.url.is_none() { - feed.url = Some(url.to_owned()); - } - - Ok(feed) -} +pub mod model; +mod readability; -pub async fn parse_entries(url: &str) -> FeedResult> { - let data = reqwest::get(url).await?.text().await?; - let feed = feed_rs::parser::parse(data.as_bytes()).or_else(|err| match err { - feed_rs::parser::ParseFeedError::ParseError(_) => todo!(), - _ => Err(err), - })?; +mod scrape; +pub use scrape::scrape_entry; - let entries = feed - .entries - .iter() - .cloned() - .map(|entry| entry.into()) - .collect::>(); +mod parse; +pub use parse::{entry::*, feed::*, url::*}; - Ok(entries) -} +mod extract; +pub use extract::{extract_html, extract_stylistic_html, extract_text}; diff --git a/crates/blend-feed/src/model.rs b/crates/blend-feed/src/model.rs index bb9e542e..0340905d 100644 --- a/crates/blend-feed/src/model.rs +++ b/crates/blend-feed/src/model.rs @@ -1,54 +1,26 @@ use chrono::{DateTime, Utc}; +/// Intermediate model for mapping/tweaking feeds from feed-rs. #[derive(Debug, Clone)] pub struct ParsedFeed { pub id: String, + pub url_feed: String, + pub url_site: String, pub title: Option, - pub url: Option, - pub favicon: Option, + pub favicon_url: Option, pub published_at: Option>, pub updated_at: Option>, } -impl From for ParsedFeed { - fn from(value: feed_rs::model::Feed) -> Self { - Self { - id: value.id, - url: None, // TODO: normalize a way of getting this URL, should fallback sanitized user-submitted URL - title: value.title.map(|title| title.content), - favicon: None, - published_at: value.published, - updated_at: value.updated, - } - } -} - +/// Intermediate model for mapping/tweaking entries from feed-rs. #[derive(Debug, Clone)] pub struct ParsedEntry { pub id: String, pub url: Option, pub title: Option, - pub summary: Option, + pub summary_html: Option, pub content_html: Option, + pub media_url: Option, pub published_at: Option>, pub updated_at: Option>, } - -impl From for ParsedEntry { - fn from(value: feed_rs::model::Entry) -> Self { - let link = value - .links - .iter() - .find(|link| link.rel.as_ref().is_some_and(|rel| rel == "self")); - - Self { - id: value.id, - url: link.map(|link| link.href.clone()), // TODO: normalize this url - title: value.title.map(|title| title.content), - summary: value.summary.map(|summary| summary.content), - content_html: value.content.and_then(|content| content.body), // TODO: normalize and sanitize this - published_at: value.published, - updated_at: value.updated, - } - } -} diff --git a/crates/blend-feed/src/parse/entry.rs b/crates/blend-feed/src/parse/entry.rs new file mode 100644 index 00000000..7d7979d4 --- /dev/null +++ b/crates/blend-feed/src/parse/entry.rs @@ -0,0 +1,46 @@ +use super::get_feed; +use crate::{ + error::{FeedError, FeedResult}, + extract::*, + model::{self, ParsedEntry}, + parse_url, +}; + +/// Fetch feed and process each entry as needed +pub async fn parse_entries(url: &str) -> FeedResult> { + let url = parse_url(url).ok_or_else(|| FeedError::InvalidUrl(url.to_string()))?; + + // Parse feed + let (feed, _) = get_feed(url).await?; + + let entries = feed + .entries + .iter() + .cloned() + .map(|entry| { + // TODO: Find the best link somehow? Maybe not always the first? + let url = entry.links.first().map(|link| link.href.clone()); + + let media_url = entry + .media + .first() + .and_then(|media| media.content.first().and_then(|content| content.url.clone())) + .map(|url| url.to_string()); + + ParsedEntry { + id: entry.id, + url, + title: entry.title.map(|text| extract_text(&text.content)), + summary_html: entry.summary.map(|text| extract_stylistic_html(&text.content)), + content_html: entry + .content + .and_then(|content| content.body.map(|content| extract_html(&content))), + media_url, + published_at: entry.published, + updated_at: entry.updated, + } + }) + .collect::>(); + + Ok(entries) +} diff --git a/crates/blend-feed/src/parse/feed.rs b/crates/blend-feed/src/parse/feed.rs new file mode 100644 index 00000000..e549398a --- /dev/null +++ b/crates/blend-feed/src/parse/feed.rs @@ -0,0 +1,31 @@ +use super::get_feed; +use crate::{ + error::{FeedError, FeedResult}, + extract::*, + model::ParsedFeed, + parse_url, +}; + +// Fetch feed and process the basic feed data +pub async fn parse_feed(url: &str) -> FeedResult { + let url = parse_url(url).ok_or_else(|| FeedError::InvalidUrl(url.to_string()))?; + let url_feed = url.base.clone(); + + // Parse feed and get URL that we used to scrape the content + let (feed, url) = get_feed(url.clone()).await?; + + // Parse favicon URL to use until we can convert the remote image into binary data stored in the db + let favicon_url = feed.icon.or_else(|| feed.logo).map(|image| image.uri); + + let parsed = ParsedFeed { + id: feed.id, + url_feed: url, + url_site: url_feed, + title: feed.title.map(|text| extract_text(&text.content)), + favicon_url, + published_at: feed.published, + updated_at: feed.updated, + }; + + Ok(parsed) +} diff --git a/crates/blend-feed/src/parse/mod.rs b/crates/blend-feed/src/parse/mod.rs new file mode 100644 index 00000000..1d14a563 --- /dev/null +++ b/crates/blend-feed/src/parse/mod.rs @@ -0,0 +1,31 @@ +use self::url::ParsedUrl; +use crate::error::{FeedError, FeedResult}; + +pub(crate) mod entry; +pub(crate) mod feed; +pub(crate) mod url; + +/// Fetch and parse feed content with the trimmed URL, falling back to the result of the untrimmed URL +async fn get_feed(url: ParsedUrl) -> FeedResult<(feed_rs::model::Feed, String)> { + // Try parsing the feed using the trimmed URL (we want to keep the saved URLs as clean as possible) + match parse_feed_from_url(&url.trimmed, &url.base).await { + Ok(feed) => Ok((feed, url.trimmed)), + Err( + ref _outer @ FeedError::ParseFeedError( + ref _inner @ feed_rs::parser::ParseFeedError::ParseError(ref _err), + ), + ) => { + // If we encountered a feed parse error specifically, retry the parsing once more + let feed = parse_feed_from_url(&url.url, &url.base).await?; + Ok((feed, url.url)) + } + Err(err) => Err(err), + } +} + +async fn parse_feed_from_url(url: &str, base_url: &str) -> FeedResult { + let data = reqwest::get(url).await?.text().await?; + let feed = feed_rs::parser::parse_with_uri(data.as_bytes(), Some(base_url))?; + + Ok(feed) +} diff --git a/crates/blend-feed/src/parse/url.rs b/crates/blend-feed/src/parse/url.rs new file mode 100644 index 00000000..509b7951 --- /dev/null +++ b/crates/blend-feed/src/parse/url.rs @@ -0,0 +1,29 @@ +use url::Url; + +#[derive(Debug, Clone)] +pub struct ParsedUrl { + pub url: String, + pub trimmed: String, + pub base: String, +} + +pub fn parse_url(raw_url: &str) -> Option { + Url::parse(raw_url).ok().and_then(|url| { + url.host_str().map(|domain| domain.to_string()).map(|domain| { + // Trim trailing slashes + let trimmed = url.to_string().trim_end_matches('/').to_string(); + + // Construct the base URL from the scheme and domain + let mut base = format!("{}://{}", url.scheme(), domain); + + // We'll need to manually add the port to the base URL + if let Some(port) = url.port() { + base.push_str(format!(":{}", port).as_ref()); + } + + let url = url.to_string(); + + ParsedUrl { url, trimmed, base } + }) + }) +} diff --git a/crates/blend-feed/src/readability/dom.rs b/crates/blend-feed/src/readability/dom.rs new file mode 100644 index 00000000..68b46450 --- /dev/null +++ b/crates/blend-feed/src/readability/dom.rs @@ -0,0 +1,116 @@ +#![allow(dead_code)] + +use html5ever::tendril::StrTendril; +use html5ever::Attribute; +use markup5ever_rcdom::NodeData::{Element, Text}; +use markup5ever_rcdom::{Handle, Node}; +use std::rc::Rc; +use std::str::FromStr; + +pub fn get_tag_name(handle: Handle) -> Option { + match handle.data { + Element { ref name, .. } => Some(name.local.as_ref().to_lowercase().to_string()), + _ => None, + } +} + +pub fn get_attr(name: &str, handle: Handle) -> Option { + match handle.data { + Element { + name: _, ref attrs, .. + } => attr(name, &attrs.borrow()), + _ => None, + } +} + +pub fn attr(attr_name: &str, attrs: &[Attribute]) -> Option { + for attr in attrs.iter() { + if attr.name.local.as_ref() == attr_name { + return Some(attr.value.to_string()); + } + } + None +} + +pub fn set_attr(attr_name: &str, value: &str, handle: Handle) { + if let Element { + name: _, ref attrs, .. + } = handle.data + { + let attrs = &mut attrs.borrow_mut(); + if let Some(index) = attrs.iter().position(|attr| { + let name = attr.name.local.as_ref(); + name == attr_name + }) { + if let Ok(value) = StrTendril::from_str(value) { + attrs[index] = Attribute { + name: attrs[index].name.clone(), + value, + } + } + } + } +} + +pub fn extract_text(handle: Handle, text: &mut String, deep: bool) { + for child in handle.children.borrow().iter() { + let c = child.clone(); + match c.data { + Text { ref contents } => { + text.push_str(contents.borrow().as_ref()); + } + Element { .. } => { + if deep { + extract_text(child.clone(), text, deep); + } + } + _ => (), + } + } +} + +pub fn text_len(handle: Handle) -> usize { + let mut len = 0; + for child in handle.children.borrow().iter() { + let c = child.clone(); + match c.data { + Text { ref contents } => { + len += contents.borrow().trim().chars().count(); + } + Element { .. } => { + len += text_len(child.clone()); + } + _ => (), + } + } + len +} + +pub fn find_node(handle: Handle, tag_name: &str, nodes: &mut Vec>) { + for child in handle.children.borrow().iter() { + let c = child.clone(); + if let Element { ref name, .. } = c.data { + let t = name.local.as_ref(); + if t.to_lowercase() == tag_name { + nodes.push(child.clone()); + }; + find_node(child.clone(), tag_name, nodes) + } + } +} + +pub fn has_nodes(handle: Handle, tag_names: &Vec<&'static str>) -> bool { + for child in handle.children.borrow().iter() { + let tag_name: &str = &get_tag_name(child.clone()).unwrap_or_default(); + if tag_names.iter().any(|&n| n == tag_name) { + return true; + } + if match child.clone().data { + Element { .. } => has_nodes(child.clone(), tag_names), + _ => false, + } { + return true; + } + } + false +} diff --git a/crates/blend-feed/src/readability/extract.rs b/crates/blend-feed/src/readability/extract.rs new file mode 100644 index 00000000..a79c355d --- /dev/null +++ b/crates/blend-feed/src/readability/extract.rs @@ -0,0 +1,55 @@ +use super::score::{self, Candidate}; +use crate::error::FeedResult; +use html5ever::{parse_document, tendril::TendrilSink}; +use markup5ever_rcdom::{RcDom, SerializableHandle}; +use std::{cell::Cell, collections::BTreeMap, io::Cursor, path::Path}; + +#[derive(Debug)] +pub struct Result { + pub title: String, + pub content: String, +} + +pub fn extract(input: &str) -> FeedResult> { + let mut data = Cursor::new(input.as_bytes()); + + let mut dom = parse_document(RcDom::default(), Default::default()) + .from_utf8() + .read_from(&mut data)?; + + let mut title = String::new(); + let mut candidates = BTreeMap::new(); + let mut nodes = BTreeMap::new(); + let handle = dom.document.clone(); + + score::preprocess(&mut dom, handle.clone(), &mut title); + score::find_candidates(Path::new("/"), handle.clone(), &mut candidates, &mut nodes); + + let mut top_candidate = &Candidate { + node: handle.clone(), + score: Cell::new(0.0), + }; + + for (_, c) in candidates.iter() { + let score = c.score.get() * (1.0 - score::get_link_density(c.node.clone())); + c.score.set(score); + if score <= top_candidate.score.get() { + continue; + } + top_candidate = c; + } + + let mut bytes = vec![]; + let node = top_candidate.node.clone(); + + html5ever::serialize( + &mut bytes, + &SerializableHandle::from(node.clone()), + Default::default(), + ) + .ok(); + + let result = String::from_utf8(bytes).ok().map(|content| Result { title, content }); + + Ok(result) +} diff --git a/crates/blend-feed/src/readability/mod.rs b/crates/blend-feed/src/readability/mod.rs new file mode 100644 index 00000000..1ff2515b --- /dev/null +++ b/crates/blend-feed/src/readability/mod.rs @@ -0,0 +1,7 @@ +// Readbility module based on https://github.com/kumabook/readability + +mod dom; +mod score; + +mod extract; +pub use extract::extract; diff --git a/crates/blend-feed/src/readability/score.rs b/crates/blend-feed/src/readability/score.rs new file mode 100644 index 00000000..faf24f8c --- /dev/null +++ b/crates/blend-feed/src/readability/score.rs @@ -0,0 +1,293 @@ +use super::dom; +use html5ever::namespace_url; +use html5ever::tree_builder::TreeSink; +use html5ever::tree_builder::{ElementFlags, NodeOrText}; +use html5ever::{ns, LocalName, QualName}; +use markup5ever_rcdom::Handle; +use markup5ever_rcdom::Node; +use markup5ever_rcdom::NodeData::{Element, Text}; +use markup5ever_rcdom::RcDom; +use regex::Regex; +use std::cell::Cell; +use std::collections::BTreeMap; +use std::path::Path; +use std::rc::Rc; + +pub static PUNCTUATIONS_REGEX: &str = r"([、。,.!?]|\.[^A-Za-z0-9]|,[^0-9]|!|\?)"; +pub static UNLIKELY_CANDIDATES: &str = "combx|comment|community|disqus|extra|foot|header|menu|remark|rss|shoutbox|sidebar|sponsor|ad-break|agegate|pagination|pager|popup|tweet|twitter|ssba"; +pub static LIKELY_CANDIDATES: &str = "and|article|body|column|main|shadow|content"; +pub static POSITIVE_CANDIDATES: &str = + "article|body|content|entry|main|page|pagination|post|text|blog|story"; +pub static NEGATIVE_CANDIDATES: &str = "combx|comment|com|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget|form|textfield|uiScale|hidden"; +static BLOCK_CHILD_TAGS: [&str; 10] = [ + "a", + "blockquote", + "dl", + "div", + "img", + "ol", + "p", + "pre", + "table", + "ul", +]; + +lazy_static! { + static ref PUNCTUATIONS: Regex = Regex::new(PUNCTUATIONS_REGEX).unwrap(); + static ref LIKELY: Regex = Regex::new(LIKELY_CANDIDATES).unwrap(); + static ref UNLIKELY: Regex = Regex::new(UNLIKELY_CANDIDATES).unwrap(); + static ref POSITIVE: Regex = Regex::new(POSITIVE_CANDIDATES).unwrap(); + static ref NEGATIVE: Regex = Regex::new(NEGATIVE_CANDIDATES).unwrap(); +} + +pub struct Candidate { + pub node: Rc, + pub score: Cell, +} + +pub fn get_link_density(handle: Handle) -> f32 { + let text_length = dom::text_len(handle.clone()) as f32; + if text_length == 0.0 { + return 0.0; + } + + let mut link_length = 0.0; + let mut links: Vec> = vec![]; + + dom::find_node(handle.clone(), "a", &mut links); + + for link in links.iter() { + link_length += dom::text_len(link.clone()) as f32; + } + + link_length / text_length +} + +pub fn is_candidate(handle: Handle) -> bool { + let text_len = dom::text_len(handle.clone()); + if text_len < 20 { + return false; + } + + let n = dom::get_tag_name(handle.clone()).unwrap_or_default(); + + match n.as_str() { + "p" => true, + "div" | "article" | "center" | "section" => { + !dom::has_nodes(handle.clone(), &BLOCK_CHILD_TAGS.to_vec()) + } + _ => false, + } +} + +pub fn init_content_score(handle: Handle) -> f32 { + let tag_name = dom::get_tag_name(handle.clone()).unwrap_or_default(); + let score = match tag_name.as_ref() { + "article" => 10.0, + "div" => 5.0, + "blockquote" => 3.0, + "form" => -3.0, + "th" => 5.0, + _ => 0.0, + }; + + score + get_class_weight(handle.clone()) +} + +pub fn calc_content_score(handle: Handle) -> f32 { + let mut score: f32 = 1.0; + let mut text = String::new(); + + dom::extract_text(handle.clone(), &mut text, true); + + let mat = PUNCTUATIONS.find_iter(&text); + + score += mat.count() as f32; + score += f32::min(f32::floor(text.chars().count() as f32 / 100.0), 3.0); + score +} + +pub fn get_class_weight(handle: Handle) -> f32 { + let mut weight: f32 = 0.0; + if let Element { + name: _, ref attrs, .. + } = handle.data + { + for name in ["id", "class"].iter() { + if let Some(val) = dom::attr(name, &attrs.borrow()) { + if POSITIVE.is_match(&val) { + weight += 25.0 + }; + + if NEGATIVE.is_match(&val) { + weight -= 25.0 + } + } + } + }; + + weight +} + +pub fn preprocess(dom: &mut RcDom, handle: Handle, title: &mut String) -> bool { + if let Element { + ref name, + ref attrs, + .. + } = handle.clone().data + { + let tag_name = name.local.as_ref(); + + match tag_name.to_lowercase().as_ref() { + "script" | "link" | "style" => return true, + "title" => dom::extract_text(handle.clone(), title, true), + _ => (), + } + + for name in ["id", "class"].iter() { + if let Some(val) = dom::attr(name, &attrs.borrow()) { + if tag_name != "body" && UNLIKELY.is_match(&val) && !LIKELY.is_match(&val) { + return true; + } + } + } + } + + let mut useless_nodes = vec![]; + let mut paragraph_nodes = vec![]; + let mut br_count = 0; + + for child in handle.children.borrow().iter() { + if preprocess(dom, child.clone(), title) { + useless_nodes.push(child.clone()); + } + + let c = child.clone(); + + match c.data { + Element { ref name, .. } => { + let tag_name = name.local.as_ref(); + if "br" == tag_name.to_lowercase() { + br_count += 1 + } else { + br_count = 0 + } + } + Text { ref contents } => { + let s = contents.borrow(); + if br_count >= 2 && !s.trim().is_empty() { + paragraph_nodes.push(child.clone()); + br_count = 0 + } + } + _ => (), + } + } + + for node in useless_nodes.iter() { + dom.remove_from_parent(node); + } + + for node in paragraph_nodes.iter() { + let name = QualName::new(None, ns!(), LocalName::from("p")); + let p = dom.create_element(name, vec![], ElementFlags::default()); + + dom.append_before_sibling(node, NodeOrText::AppendNode(p.clone())); + dom.remove_from_parent(node); + + if let Text { ref contents } = node.clone().data { + let text = contents.clone().into_inner().clone(); + dom.append(&p, NodeOrText::AppendText(text)) + } + } + + false +} + +pub fn find_candidates( + id: &Path, + handle: Handle, + candidates: &mut BTreeMap, + nodes: &mut BTreeMap>, +) { + if let Some(id) = id.to_str().map(|id| id.to_string()) { + nodes.insert(id, handle.clone()); + } + + if is_candidate(handle.clone()) { + let score = calc_content_score(handle.clone()); + + if let Some(c) = + id.parent().and_then(|pid| find_or_create_candidate(pid, candidates, nodes)) + { + c.score.set(c.score.get() + score) + } + + if let Some(c) = id + .parent() + .and_then(|pid| pid.parent()) + .and_then(|gpid| find_or_create_candidate(gpid, candidates, nodes)) + { + c.score.set(c.score.get() + score / 2.0) + } + } + + if is_candidate(handle.clone()) { + let score = calc_content_score(handle.clone()); + + if let Some(c) = id.to_str().map(|id| id.to_string()).and_then(|id| candidates.get(&id)) { + c.score.set(c.score.get() + score) + } + + if let Some(c) = id + .parent() + .and_then(|pid| pid.to_str()) + .map(|id| id.to_string()) + .and_then(|pid| candidates.get(&pid)) + { + c.score.set(c.score.get() + score) + } + + if let Some(c) = id + .parent() + .and_then(|p| p.parent()) + .and_then(|pid| pid.to_str()) + .map(|id| id.to_string()) + .and_then(|pid| candidates.get(&pid)) + { + c.score.set(c.score.get() + score) + } + } + + for (i, child) in handle.children.borrow().iter().enumerate() { + find_candidates( + id.join(i.to_string()).as_path(), + child.clone(), + candidates, + nodes, + ) + } +} + +fn find_or_create_candidate<'a>( + id: &Path, + candidates: &'a mut BTreeMap, + nodes: &BTreeMap>, +) -> Option<&'a Candidate> { + if let Some(id) = id.to_str().map(|id| id.to_string()) { + if let Some(node) = nodes.get(&id) { + if candidates.get(&id).is_none() { + candidates.insert( + id.clone(), + Candidate { + node: node.clone(), + score: Cell::new(init_content_score(node.clone())), + }, + ); + } + return candidates.get(&id); + } + } + + None +} diff --git a/crates/blend-feed/src/scrape.rs b/crates/blend-feed/src/scrape.rs new file mode 100644 index 00000000..245b0204 --- /dev/null +++ b/crates/blend-feed/src/scrape.rs @@ -0,0 +1,14 @@ +use crate::error::FeedResult; + +pub async fn scrape_entry(url: String) -> FeedResult> { + let res = reqwest::get(&url).await?; + + if !res.status().is_success() { + return Ok(None); + } + + let data = res.text().await?; + let article = crate::readability::extract(&data)?; + + Ok(article.map(|article| article.content)) +} diff --git a/crates/blend-web/src/context.rs b/crates/blend-web/src/context.rs index 960f5253..dd4abc45 100644 --- a/crates/blend-web/src/context.rs +++ b/crates/blend-web/src/context.rs @@ -7,6 +7,6 @@ use tokio::sync::{broadcast, mpsc, Mutex}; pub struct Context { pub blend: Config, pub db: SqlitePool, - pub jobs: Arc>>, - pub notifs: Arc>>, + pub job_tx: Arc>>, + pub notif_tx: Arc>>, } diff --git a/crates/blend-web/src/router/feed.rs b/crates/blend-web/src/router/feed.rs index 0f27e802..99b2ebbe 100644 --- a/crates/blend-web/src/router/feed.rs +++ b/crates/blend-web/src/router/feed.rs @@ -45,15 +45,17 @@ async fn create( let feed = repo::feed::FeedRepo::new(ctx.db) .create_feed(repo::feed::CreateFeedParams { id: parsed.id, - title: parsed.title, - url_feed: parsed.url, + title: parsed.title.unwrap_or_else(|| data.url.clone()), + url_feed: parsed.url_feed, + url_site: parsed.url_site, + favicon_url: parsed.favicon_url, published_at: parsed.published_at, updated_at: parsed.updated_at, }) .await?; - let worker = ctx.jobs.lock().await; - worker.send(blend_worker::Job::FetchMetadata(feed.clone())).await?; + let worker = ctx.job_tx.lock().await; + worker.send(blend_worker::Job::FetchFavicon(feed.clone())).await?; worker.send(blend_worker::Job::FetchEntries(feed.clone())).await?; Ok(Json(json!({ "data": feed }))) @@ -91,14 +93,14 @@ async fn refresh_feed( .await? .ok_or_else(|| WebError::NotFoundError)?; - let notifier = ctx.notifs.lock().await; - let dispatcher = ctx.jobs.lock().await; + let notif_tx = ctx.notif_tx.lock().await; + let job_tx = ctx.job_tx.lock().await; - notifier.send(blend_worker::Notification::StartedFeedRefresh { + notif_tx.send(blend_worker::Notification::StartedFeedRefresh { feed_uuid: feed.uuid, })?; - dispatcher.send(blend_worker::Job::FetchMetadata(feed.clone())).await?; - dispatcher.send(blend_worker::Job::FetchEntries(feed.clone())).await?; + job_tx.send(blend_worker::Job::FetchFavicon(feed.clone())).await?; + job_tx.send(blend_worker::Job::FetchEntries(feed.clone())).await?; Ok(Json(json!({ "success": true }))) } @@ -106,14 +108,13 @@ async fn refresh_feed( async fn refresh_feeds(State(ctx): State) -> WebResult { let feeds = repo::feed::FeedRepo::new(ctx.db).get_feeds().await?; - let notifier = ctx.notifs.lock().await; - let dispatcher = ctx.jobs.lock().await; + let notifier = ctx.notif_tx.lock().await; + let dispatcher = ctx.job_tx.lock().await; for feed in feeds { notifier.send(blend_worker::Notification::StartedFeedRefresh { feed_uuid: feed.uuid, })?; - dispatcher.send(blend_worker::Job::FetchMetadata(feed.clone())).await?; dispatcher.send(blend_worker::Job::FetchEntries(feed.clone())).await?; } diff --git a/crates/blend-web/src/router/ws.rs b/crates/blend-web/src/router/ws.rs index 2eb34504..5e27c8ce 100644 --- a/crates/blend-web/src/router/ws.rs +++ b/crates/blend-web/src/router/ws.rs @@ -10,12 +10,12 @@ use futures_util::{sink::SinkExt, stream::StreamExt}; pub fn router(ctx: crate::Context) -> Router { Router::new() - .route("/notifs", get(notifs)) + .route("/notifications", get(notifications)) .route_layer(from_fn_with_state(ctx.clone(), crate::middleware::auth)) .with_state(ctx) } -async fn notifs( +async fn notifications( ws: WebSocketUpgrade, State(ctx): State, ) -> WebResult { @@ -23,7 +23,7 @@ async fn notifs( } async fn handle_socket(socket: WebSocket, ctx: crate::Context) { - let mut rx = ctx.notifs.lock().await.subscribe(); + let mut rx = ctx.notif_tx.lock().await.subscribe(); let (mut ws_sender, _) = socket.split(); while let Ok(notif) = rx.recv().await { diff --git a/crates/blend-worker/Cargo.toml b/crates/blend-worker/Cargo.toml index b2664243..97020cda 100644 --- a/crates/blend-worker/Cargo.toml +++ b/crates/blend-worker/Cargo.toml @@ -7,13 +7,16 @@ edition.workspace = true blend-config = { path = "../blend-config" } blend-db = { path = "../blend-db" } blend-feed = { path = "../blend-feed" } +base64 = "0.22" futures = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +favilib = "0.5" sqlx = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } typeshare = { workspace = true } +url = { workspace = true } uuid = { workspace = true } diff --git a/crates/blend-worker/src/error.rs b/crates/blend-worker/src/error.rs index a77960e4..68973068 100644 --- a/crates/blend-worker/src/error.rs +++ b/crates/blend-worker/src/error.rs @@ -8,6 +8,12 @@ pub enum WorkerError { #[error(transparent)] RequestError(#[from] reqwest::Error), + #[error(transparent)] + UrlParseError(#[from] url::ParseError), + + #[error(transparent)] + FaviconParseError(#[from] favilib::errors::FavilibError), + #[error(transparent)] NotificationBroadcastSendError( #[from] tokio::sync::broadcast::error::SendError, diff --git a/crates/blend-worker/src/handler.rs b/crates/blend-worker/src/handler.rs index 5dff003e..1f041626 100644 --- a/crates/blend-worker/src/handler.rs +++ b/crates/blend-worker/src/handler.rs @@ -1,42 +1,111 @@ -use crate::{error::WorkerResult, Notification}; +use crate::{error::WorkerResult, Job, Notification}; +use base64::{engine::general_purpose::URL_SAFE, Engine as _}; use blend_db::{ model::Feed, - repo::entry::{CreateEntryParams, EntryRepo}, + repo::{ + entry::{CreateEntryParams, EntryRepo}, + feed::FeedRepo, + }, }; -use blend_feed::parse_entries; use sqlx::SqlitePool; use std::sync::Arc; -use tokio::sync::{broadcast, Mutex}; +use tokio::sync::{broadcast, mpsc, Mutex}; +/// Scrape favicon from feed site URL +pub async fn fetch_favicon( + feed: Feed, + db: SqlitePool, + notif_tx: Arc>>, +) -> WorkerResult<()> { + // Don't refetch the favicon if we already have one saved + if feed.favicon_b64.is_some() || feed.favicon_url.is_some() { + return Ok(()); + } + + // Scrape favicon from site directly + let url = url::Url::parse(&feed.url_site)?; + let icon = tokio::task::block_in_place(|| favilib::Favicon::fetch(url, None))?; + + // Potentially save the image as a base64 PNG data string + let data_string = icon + .clone() + .resize(favilib::ImageSize::Custom(64, 64)) + .change_format(favilib::ImageFormat::Png) + .ok() + .map(|icon| format!("data:image/png;base64,{}", URL_SAFE.encode(icon.bytes()))); + + // Save favicon URL and the data string + FeedRepo::new(db) + .update_favicon(&feed.uuid, icon.url().to_string(), data_string) + .await?; + + // Notify that we've saved the favicon + notif_tx.lock().await.send(Notification::FinishedFetchingFeedFavicon { + feed_uuid: feed.uuid, + })?; + + Ok(()) +} + +/// Parse entries from a feed, and scrape content if necessary pub async fn fetch_entries( feed: Feed, db: SqlitePool, - notifs: Arc>>, + job_tx: Arc>>, + notif_tx: Arc>>, ) -> WorkerResult<()> { - let mapped = parse_entries(&feed.url_feed) + // Parse any entries directly from the feed + let mapped = blend_feed::parse_entries(&feed.url_feed) .await? .into_iter() .map(|entry| CreateEntryParams { id: entry.id, url: entry.url, title: entry.title, - summary: entry.summary, + summary_html: entry.summary_html, content_html: entry.content_html, + media_url: entry.media_url, published_at: entry.published_at, updated_at: entry.updated_at, }) .collect::>(); - let entry_uuids = EntryRepo::new(db).upsert_entries(&feed.uuid, &mapped).await?; + // Save any entries we've successfully scraped + EntryRepo::new(db).upsert_entries(&feed.uuid, &mapped).await?; - let notifier = notifs.lock().await; - - notifier.send(Notification::FinishedFeedRefresh { + // Notify that we've finished a feed refresh + notif_tx.lock().await.send(Notification::FinishedFeedRefresh { feed_uuid: feed.uuid, })?; - notifier.send(Notification::EntriesFetched { + + // Initiate job to scrape entries + job_tx.lock().await.send(Job::ScrapeEntries(feed)).await?; + + Ok(()) +} + +/// Parse entries from a feed, and scrape content if necessary +pub async fn scrape_entries( + feed: Feed, + db: SqlitePool, + notif_tx: Arc>>, +) -> WorkerResult<()> { + let repo = EntryRepo::new(db); + + // Fetch all entries that have no content and haven't been scraped yet + let entries_to_scrape = repo.get_entries_to_scrape(&feed.uuid).await?; + + // Scrape the content for each URL and update in the DB + for entry in entries_to_scrape { + let content_scraped_html = blend_feed::scrape_entry(entry.url) + .await? + .map(|html| blend_feed::extract_html(&html)); + repo.update_scraped_entry(&entry.uuid, content_scraped_html).await?; + } + + // Notify that we've finished scraping for this feed + notif_tx.lock().await.send(Notification::FinishedScrapingEntries { feed_uuid: feed.uuid, - entry_uuids, })?; Ok(()) diff --git a/crates/blend-worker/src/job.rs b/crates/blend-worker/src/job.rs index d2c53271..f3edc3a3 100644 --- a/crates/blend-worker/src/job.rs +++ b/crates/blend-worker/src/job.rs @@ -6,7 +6,8 @@ use std::fmt::Display; #[serde(tag = "type")] pub enum Job { FetchEntries(model::Feed), - FetchMetadata(model::Feed), + FetchFavicon(model::Feed), + ScrapeEntries(model::Feed), } impl Display for Job { @@ -23,7 +24,8 @@ impl Display for Job { match self { Job::FetchEntries(feed) => write_job_str("fetch entries", feed.uuid), - Job::FetchMetadata(feed) => write_job_str("fetch metadata", feed.uuid), + Job::FetchFavicon(feed) => write_job_str("fetch favicon", feed.uuid), + Job::ScrapeEntries(feed) => write_job_str("scrape entries", feed.uuid), } } } diff --git a/crates/blend-worker/src/notification.rs b/crates/blend-worker/src/notification.rs index 4cceab2c..86489b0b 100644 --- a/crates/blend-worker/src/notification.rs +++ b/crates/blend-worker/src/notification.rs @@ -6,16 +6,10 @@ use typeshare::typeshare; #[derive(Debug, Clone, Serialize)] #[serde(tag = "type", content = "data")] pub enum Notification { - StartedFeedRefresh { - feed_uuid: uuid::Uuid, - }, - FinishedFeedRefresh { - feed_uuid: uuid::Uuid, - }, - EntriesFetched { - feed_uuid: uuid::Uuid, - entry_uuids: Vec, - }, + StartedFeedRefresh { feed_uuid: uuid::Uuid }, + FinishedFeedRefresh { feed_uuid: uuid::Uuid }, + FinishedFetchingFeedFavicon { feed_uuid: uuid::Uuid }, + FinishedScrapingEntries { feed_uuid: uuid::Uuid }, } impl Display for Notification { @@ -33,15 +27,17 @@ impl Display for Notification { std::mem::size_of_val(self), feed_uuid.hyphenated(), ), - Notification::EntriesFetched { - feed_uuid, - entry_uuids, - } => write!( + Notification::FinishedFetchingFeedFavicon { feed_uuid } => write!( f, - "[notification: entries fetched] (size = {}) feed: {}, entries: {}", + "[notification: finished fetching feed favicon] (size = {}) feed: {}", + std::mem::size_of_val(self), + feed_uuid.hyphenated(), + ), + Notification::FinishedScrapingEntries { feed_uuid } => write!( + f, + "[notification: finished scraping entries] (size = {}) feed: {}", std::mem::size_of_val(self), feed_uuid.hyphenated(), - entry_uuids.len() ), } } diff --git a/crates/blend-worker/src/worker.rs b/crates/blend-worker/src/worker.rs index cdf62a4e..edaf40d8 100644 --- a/crates/blend-worker/src/worker.rs +++ b/crates/blend-worker/src/worker.rs @@ -28,18 +28,20 @@ pub async fn start_refresh_worker( /// Process jobs added to the job queue pub async fn start_queue_worker( - job_rx: &mut mpsc::Receiver, db: sqlx::SqlitePool, - notifs: Arc>>, + job_rx: &mut mpsc::Receiver, + job_tx: Arc>>, + notif_tx: Arc>>, ) -> WorkerResult<()> { while let Some(job) = job_rx.recv().await { tracing::info!("{}", &job); let db = db.clone(); - let notifs = notifs.clone(); + let job_tx = job_tx.clone(); + let notif_tx = notif_tx.clone(); tokio::spawn(async move { - if let Err(err) = handle_job(job.clone(), db, notifs).await { + if let Err(err) = handle_job(job.clone(), db, job_tx, notif_tx).await { tracing::error!("job failed: {} with error: {}", job, err); } }); @@ -51,14 +53,18 @@ pub async fn start_queue_worker( async fn handle_job( job: Job, db: sqlx::SqlitePool, - notifs: Arc>>, + job_tx: Arc>>, + notif_tx: Arc>>, ) -> WorkerResult<()> { - match job { - Job::FetchEntries(feed) => handler::fetch_entries(feed, db, notifs.clone()).await?, - _ => {} + // Handle the job and keep track of the result + let result = match job { + Job::FetchEntries(feed) => handler::fetch_entries(feed, db, job_tx, notif_tx).await, + Job::FetchFavicon(feed) => handler::fetch_favicon(feed, db, notif_tx).await, + Job::ScrapeEntries(feed) => handler::scrape_entries(feed, db, notif_tx).await, }; // TODO: handle errors cleanly (send error notification or something) + result?; Ok(()) } diff --git a/package.json b/package.json index 19aa6393..768fd87c 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "@tailwindcss/typography": "^0.5.13", "@total-typescript/ts-reset": "^0.5.1", "@types/jest": "^29.5.12", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "autoprefixer": "^10.4.19", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1c4856f..48810fab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 5.37.1(solid-js@1.8.17) '@tanstack/solid-query-devtools': specifier: ^5.37.1 - version: 5.37.1(@tanstack/solid-query@5.37.1(solid-js@1.8.17))(solid-js@1.8.17) + version: 5.37.1(@tanstack/solid-query@5.37.1)(solid-js@1.8.17) class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -59,10 +59,10 @@ importers: devDependencies: '@swc/core': specifier: ^1.5.7 - version: 1.5.7(@swc/helpers@0.5.11) + version: 1.5.7 '@swc/jest': specifier: ^0.2.36 - version: 0.2.36(@swc/core@1.5.7(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.5.7) '@tailwindcss/forms': specifier: ^0.5.7 version: 0.5.7(tailwindcss@3.4.3) @@ -76,11 +76,11 @@ importers: specifier: ^29.5.12 version: 29.5.12 '@typescript-eslint/eslint-plugin': - specifier: ^7.9.0 - version: 7.9.0(@typescript-eslint/parser@7.9.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.10.0 + version: 7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': - specifier: ^7.9.0 - version: 7.9.0(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.10.0 + version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) @@ -92,13 +92,13 @@ importers: version: 9.1.0(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(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) eslint-plugin-solid: specifier: ^0.14.0 version: 0.14.0(eslint@8.57.0)(typescript@5.4.5) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.12.7) + version: 29.7.0 postcss: specifier: ^8.4.38 version: 8.4.38 @@ -107,7 +107,7 @@ importers: version: 0.5.14(prettier@3.2.5) solid-devtools: specifier: ^0.30.1 - version: 0.30.1(solid-js@1.8.17)(vite@5.2.11(@types/node@20.12.7)) + version: 0.30.1(solid-js@1.8.17)(vite@5.2.11) tailwindcss: specifier: ^3.4.3 version: 3.4.3 @@ -116,108 +116,104 @@ importers: version: 5.4.5 vite: specifier: ^5.2.11 - version: 5.2.11(@types/node@20.12.7) + version: 5.2.11 vite-plugin-solid: specifier: ^2.10.2 - version: 2.10.2(solid-js@1.8.17)(vite@5.2.11(@types/node@20.12.7)) + version: 2.10.2(solid-js@1.8.17)(vite@5.2.11) vite-tsconfig-paths: specifier: ^4.3.2 - version: 4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)) + version: 4.3.2(typescript@5.4.5)(vite@5.2.11) packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha1-vZFUrsmYP3ezoDTsqgFcLkIB9s8=} - engines: {node: '>=0.10.0'} - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha1-e/aLIMCjUPk2kV/K4G9Y4yAHzjA=} + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} '@ampproject/remapping@2.3.0': - resolution: {integrity: sha1-7UQbb6YAByUgzhi0PSyMyMrsx/Q=} + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} '@babel/code-frame@7.24.2': - resolution: {integrity: sha1-cYtLGYQYCaWLKbaM3oC8Xhqm2a4=} + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} '@babel/compat-data@7.24.4': - resolution: {integrity: sha1-bxAjcukJTyXZCMoNNPx0x0YGBZo=} + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.4': - resolution: {integrity: sha1-H3WEKOiODYxWOHR0G8T/xPcaRxc=} + '@babel/core@7.24.5': + resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.24.4': - resolution: {integrity: sha1-H8VVMriK35UgJdXS0ecflGyxxJg=} + '@babel/generator@7.24.5': + resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.23.6': - resolution: {integrity: sha1-TXkGmxbLzxRhKJ7M+72BUBrjmZE=} + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} engines: {node: '>=6.9.0'} '@babel/helper-environment-visitor@7.22.20': - resolution: {integrity: sha1-lhWdth00op26RUyVn1rkpkm6kWc=} + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} engines: {node: '>=6.9.0'} '@babel/helper-function-name@7.23.0': - resolution: {integrity: sha1-H5o829WyaYpnDDDSc1+a+V7VJ1k=} + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} engines: {node: '>=6.9.0'} '@babel/helper-hoist-variables@7.22.5': - resolution: {integrity: sha1-wBoAfawFwIWRTo+2UrM521DYI7s=} + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.18.6': - resolution: {integrity: sha1-Hj69u9CKrRQ3tCjFAgTbE8Wjym4=} + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.24.3': - resolution: {integrity: sha1-asR25tFox8I/87o89PeEHUasgSg=} + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.23.3': - resolution: {integrity: sha1-19EsPF0wr1s8D8qyptUhd3Pi0PE=} + '@babel/helper-module-transforms@7.24.5': + resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.24.0': - resolution: {integrity: sha1-lFaBkxpS8Vzoef1bhs4trm09fyo=} + '@babel/helper-plugin-utils@7.24.5': + resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.22.5': - resolution: {integrity: sha1-STg1fcfXgrgO1tuwOg+6PSKx1d4=} + '@babel/helper-simple-access@7.24.5': + resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.22.6': - resolution: {integrity: sha1-MixhtzEMCZf+TDI5VWZ/GPzvuRw=} + '@babel/helper-split-export-declaration@7.24.5': + resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.24.1': - resolution: {integrity: sha1-+Zw201k9uVQHBdBzmh8QteIMaW4=} + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha1-xK4ALGHSh55yRYHZZmVYPbwdwOA=} + '@babel/helper-validator-identifier@7.24.5': + resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.23.5': - resolution: {integrity: sha1-kHo/vUUjQmKFNl0SBsQjxMVSAwc=} + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.24.4': - resolution: {integrity: sha1-3ACQf9DZXadFY8FC70zSHyy4VrY=} + '@babel/helpers@7.24.5': + resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.24.2': - resolution: {integrity: sha1-P1OVA+/IPTxZCAoQ5mNDBuA3DSY=} + '@babel/highlight@7.24.5': + resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.24.4': - resolution: {integrity: sha1-I0SHoRDYmtWj7UqKVmw2uUU+jIg=} + '@babel/parser@7.24.5': + resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} engines: {node: '>=6.0.0'} hasBin: true @@ -247,7 +243,7 @@ packages: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-jsx@7.24.1': - resolution: {integrity: sha1-P2ygS4yEGBHbw8XF+DeTTg1ibBA=} + resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -289,28 +285,28 @@ packages: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-typescript@7.24.1': - resolution: {integrity: sha1-s7zFHzltFfNZFoP5AjneFDwHaEQ=} + resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/template@7.24.0': - resolution: {integrity: sha1-xqUkqpOkoF1mqvMWVCWPrmnYfVA=} + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.1': - resolution: {integrity: sha1-1lw2rJ3RcoIXXR5KPEnVt5iPUww=} + '@babel/traverse@7.24.5': + resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.0': - resolution: {integrity: sha1-O5UfQ1qS5zM+ugW3Vm/Sl5YOob8=} + '@babel/types@7.24.5': + resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@corvu/utils@0.1.1': - resolution: {integrity: sha512-NY6s6ZvOJKQw3gI6Ra9CixHslKeGTQJsaGCPBVX/K5DtDXgEPeinD5k2EnCvWmey92L2btPtasDrlGUx0sY9JA==} + '@corvu/utils@0.2.0': + resolution: {integrity: sha512-cY0w+SotjOtBX+9oE90vis1Mu2spwGhtcAn4jmrl7JPqQrm68DH/0Rh3R52dN2MbgPVZL06N3mvys18myF5/0Q==} peerDependencies: solid-js: ^1.8 @@ -453,51 +449,51 @@ packages: os: [win32] '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha1-ojUU6Pua8SadX3eIqlVnmNYca1k=} + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha1-VI9t5VaFfIu3O77nDDXcgqLnTWM=} + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha1-OIomnw8lwbatwxe1osVXFIlMcK0=} + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@eslint/js@8.57.0': - resolution: {integrity: sha1-pUF66EJ4c/HdCLcLNXS0U+Z7X38=} + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@floating-ui/core@1.6.0': - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + '@floating-ui/core@1.6.2': + resolution: {integrity: sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==} - '@floating-ui/dom@1.6.3': - resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} + '@floating-ui/dom@1.6.5': + resolution: {integrity: sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==} - '@floating-ui/utils@0.2.1': - resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + '@floating-ui/utils@0.2.2': + resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha1-145IGgOfdWbsyWYLTqf+ax/sRCs=} + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha1-r1smkaIrRL6EewyoFkHF+2rQFyw=} + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha1-Siho111taWPkI7z5C3/RvjQ0CdM=} + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - '@internationalized/date@3.5.2': - resolution: {integrity: sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ==} + '@internationalized/date@3.5.4': + resolution: {integrity: sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==} - '@internationalized/number@3.5.1': - resolution: {integrity: sha512-N0fPU/nz15SwR9IbfJ5xaS9Ss/O5h1sVXMZf43vc9mxEG48ovglvvzBjF53aHlq20uoR6c+88CrIXipU/LSzwg==} + '@internationalized/number@3.5.3': + resolution: {integrity: sha512-rd1wA3ebzlp0Mehj5YTuTI50AQEx80gWFyHcQu+u91/5NgdwBecO8BH6ipPfE+lmQ9d63vpB3H9SHoIUiupllw==} '@isaacs/cliui@8.0.2': - resolution: {integrity: sha1-s3Znt7wYHBaHgiWbq0JHT79StVA=} + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} '@istanbuljs/load-nyc-config@1.1.0': @@ -579,25 +575,25 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha1-3M5q/3S99trRqVgCtpsEovyx+zY=} + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha1-eg7mAfYPmaIMfHxf8MgDiMEYm9Y=} + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha1-VY+2Ry7RakyFC4iVMOazZDjEkoA=} + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha1-18bmdVx4VnqVHgSrUu8P0m3lnzI=} + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha1-FfGQ6YiV8/wjJ27hS8drZ1wuUPA=} + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} '@kobalte/core@0.13.1': - resolution: {integrity: sha1-hNKJ+P2iH8kc5V42yloSo85yz4k=} + resolution: {integrity: sha512-ROFTM2EZhOS+PxCTD+a2LKvzi8ZA7uiDvAt9/rAHzlaAykJPWXCpRuB/PYKiA7iPssGU3Fno3GT5bgRoZAc3KQ==} peerDependencies: solid-js: ^1.8.15 @@ -612,114 +608,105 @@ packages: solid-js: ^1.7.11 '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U=} + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos=} + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po=} + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} '@nothing-but/utils@0.12.1': - resolution: {integrity: sha1-6VVJ54c40yj+10DhBV5pa9XOkSY=} + resolution: {integrity: sha512-1qZU1Q5El0IjE7JT/ucvJNzdr2hL3W8Rm27xNf1p6gb3Nw8pGnZmxp6/GEW9h+I1k1cICxXNq25hBwknTQ7yhg==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} '@pkgr/core@0.1.1': - resolution: {integrity: sha1-HsF+LtvsJcgwbUJOz78Tx94aqjE=} + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@rollup/rollup-android-arm-eabi@4.16.4': - resolution: {integrity: sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==} + '@rollup/rollup-android-arm-eabi@4.17.2': + resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.16.4': - resolution: {integrity: sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==} + '@rollup/rollup-android-arm64@4.17.2': + resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.16.4': - resolution: {integrity: sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==} + '@rollup/rollup-darwin-arm64@4.17.2': + resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.16.4': - resolution: {integrity: sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==} + '@rollup/rollup-darwin-x64@4.17.2': + resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.16.4': - resolution: {integrity: sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==} + '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} cpu: [arm] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.16.4': - resolution: {integrity: sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==} + '@rollup/rollup-linux-arm-musleabihf@4.17.2': + resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} cpu: [arm] os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.16.4': - resolution: {integrity: sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==} + '@rollup/rollup-linux-arm64-gnu@4.17.2': + resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} cpu: [arm64] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.16.4': - resolution: {integrity: sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==} + '@rollup/rollup-linux-arm64-musl@4.17.2': + resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} cpu: [arm64] os: [linux] - libc: [musl] - '@rollup/rollup-linux-powerpc64le-gnu@4.16.4': - resolution: {integrity: sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==} + '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} cpu: [ppc64] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-riscv64-gnu@4.16.4': - resolution: {integrity: sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==} + '@rollup/rollup-linux-riscv64-gnu@4.17.2': + resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} cpu: [riscv64] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-s390x-gnu@4.16.4': - resolution: {integrity: sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==} + '@rollup/rollup-linux-s390x-gnu@4.17.2': + resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} cpu: [s390x] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.16.4': - resolution: {integrity: sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==} + '@rollup/rollup-linux-x64-gnu@4.17.2': + resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} cpu: [x64] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.16.4': - resolution: {integrity: sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==} + '@rollup/rollup-linux-x64-musl@4.17.2': + resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} cpu: [x64] os: [linux] - libc: [musl] - '@rollup/rollup-win32-arm64-msvc@4.16.4': - resolution: {integrity: sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==} + '@rollup/rollup-win32-arm64-msvc@4.17.2': + resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.16.4': - resolution: {integrity: sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==} + '@rollup/rollup-win32-ia32-msvc@4.17.2': + resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.16.4': - resolution: {integrity: sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==} + '@rollup/rollup-win32-x64-msvc@4.17.2': + resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} cpu: [x64] os: [win32] @@ -733,12 +720,12 @@ packages: resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} '@solid-devtools/debugger@0.23.4': - resolution: {integrity: sha1-B7XmycsI75YcEu/R5ZJKJc33jWI=} + resolution: {integrity: sha512-EfTB1Eo313wztQYGJ4Ec/wE70Ay2d603VCXfT3RlyqO5QfLrQGRHX5NXC07hJpQTJJJ3tbNgzO7+ZKo76MM5uA==} peerDependencies: solid-js: ^1.8.0 '@solid-devtools/shared@0.13.2': - resolution: {integrity: sha1-Bc68DINBzmGh8gSc9csZjU6wBCk=} + resolution: {integrity: sha512-Y4uaC4EfTVwBR537MZwfaY/eiWAh+hW4mbtnwNuUw/LFmitHSkQhNQTUlLQv/S0chtwrYWQBxvXos1dC7e8R9g==} peerDependencies: solid-js: ^1.8.0 @@ -748,7 +735,7 @@ packages: solid-js: ^1.6.12 '@solid-primitives/bounds@0.0.118': - resolution: {integrity: sha1-CYIp6ZliiOAiDsRjlzH4l3qQxwY=} + resolution: {integrity: sha512-Qj42w8LlnhJ3r/t+t0c0vrdwIvvQMPgjEFGmLiwREaA85ojLbgL9lSBq2tKvljeLCvRVkgj10KEUf+vc99VCIg==} peerDependencies: solid-js: ^1.6.12 @@ -758,12 +745,12 @@ packages: solid-js: ^1.6.12 '@solid-primitives/cursor@0.0.112': - resolution: {integrity: sha1-APW/VJK7+wySdAfwe+84xdU7xv0=} + resolution: {integrity: sha512-TAtU7qD7ipSLSXHnq8FhhosAPVX+dnOCb/ITcGcLlj8e/C9YKcxDhgBHJ3R/d1xDRb5/vO/szJtEz6fnQD311Q==} peerDependencies: solid-js: ^1.6.12 '@solid-primitives/event-bus@1.0.11': - resolution: {integrity: sha1-CkxC159YiiHJvwYbas4VCAgdFN8=} + resolution: {integrity: sha512-bSwVA4aI2aNHomSbEroUnisMSyDDXJbrw4U8kFEvrcYdlLrJX5i6QeCFx+vj/zdQQw62KAllrEIyWP8KMpPVnQ==} peerDependencies: solid-js: ^1.6.12 @@ -793,7 +780,7 @@ packages: solid-js: ^1.6.12 '@solid-primitives/platform@0.1.2': - resolution: {integrity: sha1-zoxpfesj0Uyw5Xp2rZwrKvE/1R4=} + resolution: {integrity: sha512-sSxcZfuUrtxcwV0vdjmGnZQcflACzMfLriVeIIWXKp8hzaS3Or3tO6EFQkTd3L8T5dTq+kTtLvPscXIpL0Wzdg==} peerDependencies: solid-js: ^1.6.12 @@ -828,7 +815,7 @@ packages: solid-js: ^1.6.12 '@solid-primitives/static-store@0.0.5': - resolution: {integrity: sha1-7T5b6OchIfkvrFTnz9TtgaouKc0=} + resolution: {integrity: sha512-ssQ+s/wrlFAEE4Zw8GV499yBfvWx7SMm+ZVc11wvao4T5xg9VfXCL9Oa+x4h+vPMvSV/Knv5LrsLiUa+wlJUXQ==} peerDependencies: solid-js: ^1.6.12 @@ -838,7 +825,7 @@ packages: solid-js: ^1.6.12 '@solid-primitives/styles@0.0.111': - resolution: {integrity: sha1-sRNy3Af2S4cELCDAvnQuLALKKGk=} + resolution: {integrity: sha512-1mBxOGAPXmfD5oYCvqjKBDN7SuNjz2qz7RdH7KtsuNLQh6lpuSKadtHnLvru0Y8Vz1InqTJisBIy/6P5kyDmPw==} peerDependencies: solid-js: ^1.6.12 @@ -942,7 +929,7 @@ packages: resolution: {integrity: sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==} '@tailwindcss/forms@0.5.7': - resolution: {integrity: sha1-21Qh8GKnV7X4KLyShrpibGaF6CE=} + resolution: {integrity: sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==} peerDependencies: tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1' @@ -952,7 +939,7 @@ packages: tailwindcss: '>=3.0.0 || insiders' '@tanstack/query-core@5.36.1': - resolution: {integrity: sha1-rkb5NcR1KBKlbGgVMFBho9qC57g=} + resolution: {integrity: sha512-BteWYEPUcucEu3NBcDAgKuI4U25R9aPrHSP6YSf2NvaD2pSlIQTdqOfLRsxH9WdRYg7k0Uom35Uacb6nvbIMJg==} '@tanstack/query-devtools@5.37.1': resolution: {integrity: sha512-XcG4IIHIv0YQKrexTqo2zogQWR1Sz672tX2KsfE9kzB+9zhx44vRKH5si4WDILE1PIWQpStFs/NnrDQrBAUQpg==} @@ -969,22 +956,22 @@ packages: solid-js: ^1.6.0 '@total-typescript/ts-reset@0.5.1': - resolution: {integrity: sha1-k7BTXQD6pYhRi8+w2zAYLmPk968=} + resolution: {integrity: sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==} '@types/babel__core@7.20.5': - resolution: {integrity: sha1-PfFfJ7qFMZyqB7oI0HIYibs5wBc=} + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} '@types/babel__generator@7.6.8': - resolution: {integrity: sha1-+DbGH0ixNG59Kw2TxtrMW5U106s=} + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} '@types/babel__template@7.4.4': - resolution: {integrity: sha1-VnJRNwHBshmbxtrWNqnXSRWGdm8=} + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} '@types/babel__traverse@7.20.5': - resolution: {integrity: sha1-e3UCvgqoDMTvIpeIRrmD7ar81N0=} + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} '@types/estree@1.0.5': - resolution: {integrity: sha1-ps4+VW4A/ZiV3Yct0XKtDUvWh/Q=} + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -1001,14 +988,8 @@ packages: '@types/jest@29.5.12': resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} - - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + '@types/node@20.12.12': + resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -1019,8 +1000,8 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.9.0': - resolution: {integrity: sha1-CTuW/E40IibmXV8Y+chwgeCwSjE=} + '@typescript-eslint/eslint-plugin@7.10.0': + resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -1030,8 +1011,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.9.0': - resolution: {integrity: sha1-+zugG3Xg5ly3gDejYJYbADAfbHA=} + '@typescript-eslint/parser@7.10.0': + resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -1040,16 +1021,12 @@ packages: 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@7.9.0': - resolution: {integrity: sha1-HdPmOkQR2zVqnQQOdYZIUbXyYZs=} + '@typescript-eslint/scope-manager@7.10.0': + resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.9.0': - resolution: {integrity: sha1-9SMmLhtmymVUC3ploSIttS4KkMk=} + '@typescript-eslint/type-utils@7.10.0': + resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -1058,25 +1035,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.8.0': - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} + '@typescript-eslint/types@7.10.0': + resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/types@7.9.0': - resolution: {integrity: sha1-tY5IXkv7oFVlnH5oOtT18IIa4uw=} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/typescript-estree@7.8.0': - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/typescript-estree@7.9.0': - resolution: {integrity: sha1-M5XidlYGDcMTprQGw6KYtyloXgc=} + '@typescript-eslint/typescript-estree@7.10.0': + resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -1084,52 +1048,42 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.8.0': - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} + '@typescript-eslint/utils@7.10.0': + resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/utils@7.9.0': - resolution: {integrity: sha1-G5ajTu/cocggyxu8J1HYSLRUCJk=} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/visitor-keys@7.8.0': - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/visitor-keys@7.9.0': - resolution: {integrity: sha1-ghYmVuM5w97wKJX1yFRvaIjZueo=} + '@typescript-eslint/visitor-keys@7.10.0': + resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha1-dWZBrbWHhRtcyz4JXa8nrlgchAY=} + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} acorn-jsx@5.3.2: - resolution: {integrity: sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=} + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn@8.11.3: - resolution: {integrity: sha1-ceCxThOk7BYHJLOPt7DyM7G4HXo=} + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true ajv@6.12.6: - resolution: {integrity: sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=} + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} ansi-regex@5.0.1: - resolution: {integrity: sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=} + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} ansi-regex@6.0.1: - resolution: {integrity: sha1-MYPjj66aZdfLXlOUXNWJfQJgoGo=} + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} ansi-styles@3.2.1: @@ -1137,7 +1091,7 @@ packages: engines: {node: '>=4'} ansi-styles@4.3.0: - resolution: {integrity: sha1-7dgDYornHATIWuegkG7a00tkiTc=} + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} ansi-styles@5.2.0: @@ -1145,31 +1099,31 @@ packages: engines: {node: '>=10'} ansi-styles@6.2.1: - resolution: {integrity: sha1-DmIyDPmcIa//OzASGSVGqsv7BcU=} + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} any-promise@1.3.0: - resolution: {integrity: sha1-q8av7tzqUugJzcA3au0845Y10X8=} + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} anymatch@3.1.3: - resolution: {integrity: sha1-eQxYsZuhcgqEIFtXxhjVrYUklz4=} + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} arg@5.0.2: - resolution: {integrity: sha1-yBQzzEJ8ksTc9IZRQtvKbxWs1Zw=} + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: - resolution: {integrity: sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=} + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} autoprefixer@10.4.19: - resolution: {integrity: sha1-rSWoVugu6deJjFlYPBr+s/pl+J8=} + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: @@ -1189,8 +1143,8 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-jsx-dom-expressions@0.37.20: - resolution: {integrity: sha1-UG/QMC1nQL3qlX1fexjsyxFzQso=} + babel-plugin-jsx-dom-expressions@0.37.21: + resolution: {integrity: sha512-WbQo1NQ241oki8bYasVzkMXOTSIri5GO/K47rYJb2ZBh8GaPUEWiWbMV3KwXz+96eU2i54N6ThzjQG/f5n8Azw==} peerDependencies: '@babel/core': ^7.20.12 @@ -1206,29 +1160,29 @@ packages: '@babel/core': ^7.0.0 babel-preset-solid@1.8.17: - resolution: {integrity: sha1-jVXo4u6AC+hVJ0JeeUNTT5hNyBU=} + resolution: {integrity: sha512-s/FfTZOeds0hYxYqce90Jb+0ycN2lrzC7VP1k1JIn3wBqcaexDKdYi6xjB+hMNkL+Q6HobKbwsriqPloasR9LA==} peerDependencies: '@babel/core': ^7.0.0 balanced-match@1.0.2: - resolution: {integrity: sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=} + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} binary-extensions@2.3.0: - resolution: {integrity: sha1-9uFKl4WNMnJSIAJC1Mz+UixEVSI=} + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} brace-expansion@1.1.11: - resolution: {integrity: sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=} + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} brace-expansion@2.0.1: - resolution: {integrity: sha1-HtxFng8MVISG7Pn8mfIiE2S5oK4=} + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} braces@3.0.2: - resolution: {integrity: sha1-NFThpGLujVmeI23zNs2epPiv4Qc=} + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} browserslist@4.23.0: - resolution: {integrity: sha1-jzrMK75zr3ITOZQwiQ+GxjpWdKs=} + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1239,11 +1193,11 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} callsites@3.1.0: - resolution: {integrity: sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=} + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} camelcase-css@2.0.1: - resolution: {integrity: sha1-7pePaUeRTMMMa0R0G27R338EP9U=} + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} camelcase@5.3.1: @@ -1254,15 +1208,15 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001612: - resolution: {integrity: sha1-00JItOwfEXtwskrZ7gTJDguKFK4=} + caniuse-lite@1.0.30001620: + resolution: {integrity: sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==} chalk@2.4.2: - resolution: {integrity: sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=} + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} chalk@4.1.2: - resolution: {integrity: sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=} + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} char-regex@1.0.2: @@ -1270,7 +1224,7 @@ packages: engines: {node: '>=10'} chokidar@3.6.0: - resolution: {integrity: sha1-GXxsxmnvKo3F57TZfuTgksPrDVs=} + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} ci-info@3.9.0: @@ -1299,27 +1253,27 @@ packages: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} color-convert@1.9.3: - resolution: {integrity: sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=} + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} color-convert@2.0.1: - resolution: {integrity: sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=} + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} color-name@1.1.3: - resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} color-name@1.1.4: - resolution: {integrity: sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=} + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} commander@4.1.1: - resolution: {integrity: sha1-n9YCvZNilOnp70aj9NaWQESxgGg=} + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} convert-source-map@2.0.0: - resolution: {integrity: sha1-S1YPZJ/E6RjdCrdc9JYei8iC2Co=} + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} @@ -1327,7 +1281,7 @@ packages: hasBin: true cross-spawn@7.0.3: - resolution: {integrity: sha1-9zqFudXUHQRVUcF34ogtSshXKKY=} + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} cssesc@3.0.0: @@ -1336,10 +1290,10 @@ packages: hasBin: true csstype@3.1.3: - resolution: {integrity: sha1-2A/ylNEU+w5qxQD7+FtgE31+/4E=} + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} debug@4.3.4: - resolution: {integrity: sha1-Exn2V5NX8jONMzfSzdSRS7XcyGU=} + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1356,7 +1310,7 @@ packages: optional: true deep-is@0.1.4: - resolution: {integrity: sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE=} + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} @@ -1367,7 +1321,7 @@ packages: engines: {node: '>=8'} didyoumean@1.2.2: - resolution: {integrity: sha1-mJNG/+noObRVXs9WZu3qDT6K0Dc=} + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} @@ -1378,17 +1332,17 @@ packages: engines: {node: '>=8'} dlv@1.1.3: - resolution: {integrity: sha1-XBmKihFFNZbnUUlNSYdLx3MvLnk=} + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} doctrine@3.0.0: - resolution: {integrity: sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=} + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} eastasianwidth@0.2.0: - resolution: {integrity: sha1-aWzi7Aqg5uqTo5f/zySqeEDIJ8s=} + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.4.747: - resolution: {integrity: sha1-43+lt7fkwiYHxfWbXPePlHJm530=} + electron-to-chromium@1.4.775: + resolution: {integrity: sha512-JpOfl1aNAiZ88wFzjPczTLwYIoPIsij8S9/XQH9lqMpiJOf23kxea68B8wje4f68t4rOIq4Bh+vP4I65njiJBw==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1398,22 +1352,22 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: - resolution: {integrity: sha1-hAyIA7DYBH9P8M+WMXazLU7z7XI=} + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} esbuild@0.20.2: - resolution: {integrity: sha1-nWsjhlYXZu5rWlUZbG12bSjIfqE=} + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} engines: {node: '>=12'} hasBin: true escalade@3.1.2: - resolution: {integrity: sha1-VAdumrKepb89jx7WKs/7uIJy3yc=} + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} escape-string-regexp@1.0.5: - resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} escape-string-regexp@2.0.0: @@ -1421,17 +1375,17 @@ packages: engines: {node: '>=8'} escape-string-regexp@4.0.0: - resolution: {integrity: sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ=} + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} eslint-config-prettier@9.1.0: - resolution: {integrity: sha1-Ma89lFeGRZZsCC/LcaWEbTyUhn8=} + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha1-F8+t6ecyzvMrX1vlO9Tgev2OZ+E=} + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1451,20 +1405,20 @@ packages: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 eslint-scope@7.2.2: - resolution: {integrity: sha1-3rT5JWM5DzIAaJSvYqItuhxGQj8=} + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@3.4.3: - resolution: {integrity: sha1-DNcv6FUOPC6uFWqWpN3c0cisWAA=} + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint@8.57.0: - resolution: {integrity: sha1-x4am/Q4LaJQar2JFlvuYcIkZVmg=} + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true espree@9.6.1: - resolution: {integrity: sha1-oqF7jkNGkKVDLy+AGM5x0zGkjG8=} + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} esprima@4.0.1: @@ -1473,19 +1427,19 @@ packages: hasBin: true esquery@1.5.0: - resolution: {integrity: sha1-bOF3ON6Fd2lO3XNhxXGCrIyw2ws=} + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: {integrity: sha1-eteWTWeauyi+5yzsY3WLHF0smSE=} + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: {integrity: sha1-LupSkHAvJquP5TcDcP+GyWXSESM=} + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} esutils@2.0.3: - resolution: {integrity: sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=} + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} event-target-shim@6.0.2: @@ -1505,33 +1459,33 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} fast-deep-equal@3.1.3: - resolution: {integrity: sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=} + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} fast-diff@1.3.0: - resolution: {integrity: sha1-7OQH+lUKZNY4U2zXJ+EpxhYW4PA=} + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} fast-glob@3.3.2: - resolution: {integrity: sha1-qQRQHlfP3S/83tRemaVP71XkYSk=} + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=} + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: - resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fastq@1.17.1: - resolution: {integrity: sha1-KlI/B6TnsegaQrkbi/IlQQd1O0c=} + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} file-entry-cache@6.0.1: - resolution: {integrity: sha1-IRst2WWcsDlLBz5zI6w8kz1SICc=} + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} fill-range@7.0.1: - resolution: {integrity: sha1-GRmmp8df44ssfHflGYU12prN2kA=} + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} find-up@4.1.0: @@ -1539,25 +1493,25 @@ packages: engines: {node: '>=8'} find-up@5.0.0: - resolution: {integrity: sha1-TJKBnstwg1YeT0okCoa+UZj1Nvw=} + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} flat-cache@3.2.0: - resolution: {integrity: sha1-LAwtUEDJmxYydxqdEFclwBFTY+4=} + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} flatted@3.3.1: - resolution: {integrity: sha1-IdtHBymmc01JlwAvQ5yzCJh/Vno=} + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} foreground-child@3.1.1: - resolution: {integrity: sha1-HRc+d2110ncv7Qjv5KDeHqGxLQ0=} + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} fraction.js@4.3.7: - resolution: {integrity: sha1-BsoAhRV+Qv2n+ecm55/vxAaIQPc=} + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} fs.realpath@1.0.0: - resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} @@ -1565,10 +1519,10 @@ packages: os: [darwin] function-bind@1.1.2: - resolution: {integrity: sha1-LALYZNl/PqbIgwxGTL0Rq26rehw=} + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} gensync@1.0.0-beta.2: - resolution: {integrity: sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA=} + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} get-caller-file@2.0.5: @@ -1584,27 +1538,27 @@ packages: engines: {node: '>=10'} glob-parent@5.1.2: - resolution: {integrity: sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=} + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} glob-parent@6.0.2: - resolution: {integrity: sha1-bSN9mQg5UMeSkPJMdkKj3poo+eM=} + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.3.12: - resolution: {integrity: sha1-OmXDY8LpmY0iAzjoil9qyXMClgs=} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.3.15: + resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==} + engines: {node: '>=16 || 14 >=14.18'} hasBin: true glob@7.2.3: - resolution: {integrity: sha1-uN8PuAK7+o6JvR2Ti04WV47UTys=} + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} globals@11.12.0: - resolution: {integrity: sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=} + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} globals@13.24.0: - resolution: {integrity: sha1-hDKhnXjODB6DOUnDats0VAC7EXE=} + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} globby@11.1.0: @@ -1612,28 +1566,28 @@ packages: engines: {node: '>=10'} globrex@0.1.2: - resolution: {integrity: sha1-3V2eyCYjJzDNZ5Ol4zqTApheYJg=} + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} graphemer@1.4.0: - resolution: {integrity: sha1-+y8dVeDjoYSa7/yQxPoN1ToOZsY=} + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} has-flag@3.0.0: - resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} has-flag@4.0.0: - resolution: {integrity: sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=} + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} hasown@2.0.2: - resolution: {integrity: sha1-AD6vkb563DcuhOxZ3DclLO24AAM=} + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} html-entities@2.3.3: - resolution: {integrity: sha1-EX12Jr7OMn/Iuqzoho+m9e+FbkY=} + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -1647,11 +1601,11 @@ packages: engines: {node: '>=10.17.0'} ignore@5.3.1: - resolution: {integrity: sha1-UHPlVM1CxbM7OUN19Ti4WT401O8=} + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} import-fresh@3.3.0: - resolution: {integrity: sha1-NxYsJfy566oublPVtNiM4X2eDCs=} + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} import-local@3.1.0: @@ -1660,14 +1614,14 @@ packages: hasBin: true imurmurhash@0.1.4: - resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} inflight@1.0.6: - resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} inherits@2.0.4: - resolution: {integrity: sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=} + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} inline-style-parser@0.2.3: resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==} @@ -1676,14 +1630,14 @@ packages: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-binary-path@2.1.0: - resolution: {integrity: sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=} + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} is-core-module@2.13.1: - resolution: {integrity: sha1-rQ11Msb+qdoevcgnQtdFJcYnM4Q=} + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} is-extglob@2.1.1: - resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} is-fullwidth-code-point@3.0.0: @@ -1695,7 +1649,7 @@ packages: engines: {node: '>=6'} is-glob@4.0.3: - resolution: {integrity: sha1-ZPYeQsu7LuwgcanawLKLoeZdUIQ=} + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} is-html@2.0.0: @@ -1703,11 +1657,11 @@ packages: engines: {node: '>=8'} is-number@7.0.0: - resolution: {integrity: sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=} + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} is-path-inside@3.0.3: - resolution: {integrity: sha1-0jE2LlOgf/Kw4Op/7QSRYf/RYoM=} + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} is-stream@2.0.1: @@ -1715,11 +1669,11 @@ packages: engines: {node: '>=8'} is-what@4.1.16: - resolution: {integrity: sha1-GthgoZ2otIla1Uldoxgs4qzdem8=} + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} isexe@2.0.0: - resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} @@ -1746,7 +1700,7 @@ packages: engines: {node: '>=8'} jackspeak@2.3.6: - resolution: {integrity: sha1-ZH7MRyI4ruSwasDkYazCGoxQXKg=} + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} jest-changed-files@29.7.0: @@ -1879,39 +1833,39 @@ packages: optional: true jiti@1.21.0: - resolution: {integrity: sha1-fJf4/gRXJOE2o5f3NAR1JEFWEF0=} + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true js-tokens@4.0.0: - resolution: {integrity: sha1-GSA/tZmR35jjoocFDUZHzerzJJk=} + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true js-yaml@4.1.0: - resolution: {integrity: sha1-wftl+PUBeQHN0slRhkuhhFihBgI=} + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true jsesc@2.5.2: - resolution: {integrity: sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=} + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true json-buffer@3.0.1: - resolution: {integrity: sha1-kziAKjDTtmBfvgYT4JQAjKjAWhM=} + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} json-schema-traverse@0.4.1: - resolution: {integrity: sha1-afaofZUTq4u4/mO9sJecRI5oRmA=} + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} json5@2.2.3: - resolution: {integrity: sha1-eM1vGhm9wStz21rQxh79ZsHikoM=} + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true @@ -1922,7 +1876,7 @@ packages: resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} keyv@4.5.4: - resolution: {integrity: sha1-qHmpnilFL5QkOfKkBeOvizHU3pM=} + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} @@ -1936,26 +1890,26 @@ packages: engines: {node: '>=6'} levn@0.4.1: - resolution: {integrity: sha1-rkViwAdHO5MqYgDUAyaN0v/8at4=} + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} lilconfig@2.1.0: - resolution: {integrity: sha1-eOI6yJ67fhv78lsYBD3nVlSOf1I=} + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} lilconfig@3.1.1: - resolution: {integrity: sha1-nYokb6dTEGz8IF/S13BC+spW5eM=} + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} engines: {node: '>=14'} lines-and-columns@1.2.4: - resolution: {integrity: sha1-7KKE910pZQeTCdwK2SVauy68FjI=} + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} locate-path@6.0.0: - resolution: {integrity: sha1-VTIeswn+u8WcSAHZMackUqaB0oY=} + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} lodash.castarray@4.4.0: @@ -1967,16 +1921,12 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lru-cache@10.2.0: - resolution: {integrity: sha1-C9RFylc2NGWQD00fm9jbNDpNlcM=} + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} lru-cache@5.1.1: - resolution: {integrity: sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -1986,18 +1936,18 @@ packages: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} merge-anything@5.1.7: - resolution: {integrity: sha1-lPNk0rDPIax2BntRIOQpNTs1Jdc=} + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} merge2@1.4.1: - resolution: {integrity: sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=} + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} micromatch@4.0.5: - resolution: {integrity: sha1-vImZp8u/d83InxMvbkZwUbSQkMY=} + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} mimic-fn@2.1.0: @@ -2005,46 +1955,46 @@ packages: engines: {node: '>=6'} mini-svg-data-uri@1.4.4: - resolution: {integrity: sha1-irCqvN+MKa1Wk8pZWvGd0urQmTk=} + resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true minimatch@3.1.2: - resolution: {integrity: sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=} + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} minimatch@9.0.4: - resolution: {integrity: sha1-jknHMdF0nL7AUFDuUUUUezJJalE=} + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} - minipass@7.0.4: - resolution: {integrity: sha1-284DdA9QpHhrqZTB+5CIRNJ7A4w=} + minipass@7.1.1: + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} engines: {node: '>=16 || 14 >=14.17'} ms@2.1.2: - resolution: {integrity: sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=} + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} mz@2.7.0: - resolution: {integrity: sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=} + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} nanoid@3.3.7: - resolution: {integrity: sha1-0MMBppG8jVTvoKIibM8/4v1la9g=} + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true natural-compare@1.4.0: - resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-releases@2.0.14: - resolution: {integrity: sha1-L/sFO864sr6Elezhq2zmAMRGGws=} + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} normalize-path@3.0.0: - resolution: {integrity: sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=} + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} normalize-range@0.1.2: - resolution: {integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=} + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} npm-run-path@4.0.1: @@ -2052,22 +2002,22 @@ packages: engines: {node: '>=8'} object-assign@4.1.1: - resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} object-hash@3.0.0: - resolution: {integrity: sha1-c/l/dT57r/wOLMnW4HkHl0Ssguk=} + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} once@1.4.0: - resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - optionator@0.9.3: - resolution: {integrity: sha1-AHOX1E7Rhy/cbtMTYBkPgYFOLGQ=} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} p-limit@2.3.0: @@ -2075,7 +2025,7 @@ packages: engines: {node: '>=6'} p-limit@3.1.0: - resolution: {integrity: sha1-4drMvnjQ0TiMoYxk/qOOPlfjcGs=} + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} p-locate@4.1.0: @@ -2083,7 +2033,7 @@ packages: engines: {node: '>=8'} p-locate@5.0.0: - resolution: {integrity: sha1-g8gxXGeFAF470CGDlBHJ4RDm2DQ=} + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} p-try@2.2.0: @@ -2091,7 +2041,7 @@ packages: engines: {node: '>=6'} parent-module@1.0.1: - resolution: {integrity: sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=} + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} parse-json@5.2.0: @@ -2102,41 +2052,41 @@ packages: resolution: {integrity: sha512-sSnLf9X0Oaxw0wXp0liKho0QQqStDJB5I4ViaqmtI4nHm6cpb2kUealErPrcQpYUF6zgTHzLQhIO++2tcJc59A==} path-exists@4.0.0: - resolution: {integrity: sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=} + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} path-is-absolute@1.0.1: - resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} path-key@3.1.1: - resolution: {integrity: sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=} + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} path-parse@1.0.7: - resolution: {integrity: sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU=} + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.2: - resolution: {integrity: sha1-j2NX6xI51fodqLn3DpwIBnVFi6c=} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - picocolors@1.0.0: - resolution: {integrity: sha1-y1vcdP8/UYkiNur3nWi8RFZKuBw=} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: - resolution: {integrity: sha1-O6ODNzNkbZ0+SZWUbBNlpn+wekI=} + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} pify@2.3.0: - resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=} + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} pirates@4.0.6: - resolution: {integrity: sha1-MBiuMuz8/2wpuiJny/IRZqwfNrk=} + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} pkg-dir@4.2.0: @@ -2144,19 +2094,19 @@ packages: engines: {node: '>=8'} postcss-import@15.1.0: - resolution: {integrity: sha1-QcZO2MwOI3NalpizJJ/9v3BK3HA=} + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: postcss: ^8.0.0 postcss-js@4.0.1: - resolution: {integrity: sha1-YVmBhvNwO6sFLxxPfYBfOZG+6dI=} + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 postcss-load-config@4.0.2: - resolution: {integrity: sha1-cVnc9iYRjTPimfSF1q/kr/fEo+M=} + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} peerDependencies: postcss: '>=8.0.9' @@ -2168,7 +2118,7 @@ packages: optional: true postcss-nested@6.0.1: - resolution: {integrity: sha1-+D3JhGyhbS9PqGTxbp2ffQlhZiw=} + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 @@ -2178,26 +2128,26 @@ packages: engines: {node: '>=4'} postcss-selector-parser@6.0.16: - resolution: {integrity: sha1-O4i59cWr2YnvTi/J7I7t00sg+wQ=} + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} engines: {node: '>=4'} postcss-value-parser@4.2.0: - resolution: {integrity: sha1-cjwJkgg2um0+WvAZ+SvAlxwC5RQ=} + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} postcss@8.4.38: - resolution: {integrity: sha1-s4fVM7ryBUKI4zcGbYHGvunbng4=} + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: - resolution: {integrity: sha1-3rxkidem5rDnYRiIzsiAM30xY5Y=} + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} prettier-linter-helpers@1.0.0: - resolution: {integrity: sha1-0j1B/hN1ZG3i0BBNNFSjAIgCz3s=} + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} prettier-plugin-tailwindcss@0.5.14: - resolution: {integrity: sha1-RILu01fV4i6sJZVBxwrKWkx7nVw=} + resolution: {integrity: sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==} engines: {node: '>=14.21.3'} peerDependencies: '@ianvs/prettier-plugin-sort-imports': '*' @@ -2262,23 +2212,23 @@ packages: engines: {node: '>= 6'} punycode@2.3.1: - resolution: {integrity: sha1-AnQi4vrsCyXhVJw+G9gwm5EztuU=} + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} queue-microtask@1.2.3: - resolution: {integrity: sha1-SSkii7xyTfrEPg77BYyve2z7YkM=} + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} read-cache@1.0.0: - resolution: {integrity: sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=} + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} readdirp@3.6.0: - resolution: {integrity: sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc=} + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} require-directory@2.1.1: @@ -2290,7 +2240,7 @@ packages: engines: {node: '>=8'} resolve-from@4.0.0: - resolution: {integrity: sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=} + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} resolve-from@5.0.0: @@ -2302,62 +2252,57 @@ packages: engines: {node: '>=10'} resolve@1.22.8: - resolution: {integrity: sha1-tsh6nyqgbfq1Lj1wrIzeMh+lpI0=} + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true reusify@1.0.4: - resolution: {integrity: sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=} + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rimraf@3.0.2: - resolution: {integrity: sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho=} + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true - rollup@4.16.4: - resolution: {integrity: sha1-/jKOtBKT8gyVk6CV7CO9xLXZMxc=} + rollup@4.17.2: + resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true run-parallel@1.2.0: - resolution: {integrity: sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4=} + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} semver@6.3.1: - resolution: {integrity: sha1-VW0u+GiRRuRtzqS/3QlfNDTf/LQ=} - hasBin: true - - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true semver@7.6.2: - resolution: {integrity: sha1-Hjs0dZ+Jbo8U1hNHMs55iusMbhM=} + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true - seroval-plugins@1.0.5: - resolution: {integrity: sha1-7t7VDXNtXh26FCpysBiN+fTkK20=} + seroval-plugins@1.0.7: + resolution: {integrity: sha512-GO7TkWvodGp6buMEX9p7tNyIkbwlyuAWbI6G9Ec5bhcm7mQdu3JOK1IXbEUwb3FVzSc363GraG/wLW23NSavIw==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.0.5: - resolution: {integrity: sha1-1x7lQNk2urrtkvVu2j5S2OKj3u0=} + seroval@1.0.7: + resolution: {integrity: sha512-n6ZMQX5q0Vn19Zq7CIKNIo7E75gPkGCFUEqDpa8jgwpYr/vScjqnQ6H09t1uIiZ0ZSK0ypEGvrYK2bhBGWsGdw==} engines: {node: '>=10'} shebang-command@2.0.0: - resolution: {integrity: sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=} + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: {integrity: sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=} + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} signal-exit@4.1.0: - resolution: {integrity: sha1-lSGIwcvVRgcOLdIND0HArgUwywQ=} + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} sisteransi@1.0.5: @@ -2368,7 +2313,7 @@ packages: engines: {node: '>=8'} solid-devtools@0.30.1: - resolution: {integrity: sha1-oGLtgdz8n/UFBLLQzQXxlIBQO2Q=} + resolution: {integrity: sha512-axpXL4JV1dnGhuei+nSGS8ewGeNkmIgFDsAlO90YyYY5t8wU1R0aYAQtL+I+5KICLKPBvfkzdcFa2br7AV4lAw==} peerDependencies: solid-js: ^1.8.0 solid-start: ^0.3.0 @@ -2380,25 +2325,25 @@ packages: optional: true solid-icons@1.1.0: - resolution: {integrity: sha1-bpFLzk+aNKZUIwtoxop9BDWf8rY=} + resolution: {integrity: sha512-IesTfr/F1ElVwH2E1110s2RPXH4pujKfSs+koT8rwuTAdleO5s26lNSpqJV7D1+QHooJj18mcOiz2PIKs0ic+A==} peerDependencies: solid-js: '*' solid-js@1.8.17: - resolution: {integrity: sha1-eA7W8P2GMwCdGzwp1Wv2trszvVA=} + resolution: {integrity: sha512-E0FkUgv9sG/gEBWkHr/2XkBluHb1fkrHywUgA6o6XolPDCJ4g1HaLmQufcBBhiF36ee40q+HpG/vCZu7fLpI3Q==} - solid-prevent-scroll@0.1.6: - resolution: {integrity: sha512-uLyVFx5bQL0/Gw3dr7BRsFiZ5CGyPUeqVW44dMxcSGt4eC7N40QJirMUTbLDaYeOTTyQ2MtXfk7Td3FdaBfAFw==} + solid-prevent-scroll@0.1.7: + resolution: {integrity: sha512-DLafct98/nCX9l54MQ+mPbUgmmskSvVr/qxtFEt89SpSvYQkjyX4uviy91TFmzslhSyiVNNBlChpVzRO8eAwzA==} peerDependencies: solid-js: ^1.8 solid-refresh@0.6.3: - resolution: {integrity: sha1-0j74DwThd2GckjSoCcVzyxY2Bic=} + resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} peerDependencies: solid-js: ^1.3 source-map-js@1.2.0: - resolution: {integrity: sha1-FrgJwWJRe1uMPn3NMVoqXCYSsq8=} + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} source-map-support@0.5.13: @@ -2424,15 +2369,15 @@ packages: engines: {node: '>=8'} string-width@5.1.2: - resolution: {integrity: sha1-FPja7G2B5yIdKjV+Zoyrc728p5Q=} + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} strip-ansi@6.0.1: - resolution: {integrity: sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=} + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} strip-ansi@7.1.0: - resolution: {integrity: sha1-1bZWjKaJ2FYTcLBwdoXSJDT6/0U=} + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} strip-bom@4.0.0: @@ -2444,23 +2389,23 @@ packages: engines: {node: '>=6'} strip-json-comments@3.1.1: - resolution: {integrity: sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY=} + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} style-to-object@1.0.6: resolution: {integrity: sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==} sucrase@3.35.0: - resolution: {integrity: sha1-V/F6PX4Zs22JlfBmedEhvpFK4mM=} + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true supports-color@5.5.0: - resolution: {integrity: sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=} + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} supports-color@7.2.0: - resolution: {integrity: sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=} + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} supports-color@8.1.1: @@ -2468,15 +2413,15 @@ packages: engines: {node: '>=10'} supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha1-btpL00SjyUrqN21MwxvHcxEDngk=} + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} synckit@0.8.8: - resolution: {integrity: sha1-/n/kRlGOPT1J9eQp9EPPCLbt/Nc=} + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} engines: {node: ^14.18.0 || >=16.0.0} tailwindcss@3.4.3: - resolution: {integrity: sha1-vkj1KD33ffztcFRRMZpd/7hiFRk=} + resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} engines: {node: '>=14.0.0'} hasBin: true @@ -2485,37 +2430,37 @@ packages: engines: {node: '>=8'} text-table@0.2.0: - resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} thenify-all@1.6.0: - resolution: {integrity: sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=} + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} thenify@3.3.1: - resolution: {integrity: sha1-iTLmhqQGYDigFt2eLKRq3Zg4qV8=} + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} to-fast-properties@2.0.0: - resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} to-regex-range@5.0.1: - resolution: {integrity: sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=} + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} ts-api-utils@1.3.0: - resolution: {integrity: sha1-S0kOJxKfHo5oa0XMSrY3FNxg7qE=} + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' ts-interface-checker@0.1.13: - resolution: {integrity: sha1-eE/T1nlyK8EDsbS4AwvN212yppk=} + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} tsconfck@3.0.3: - resolution: {integrity: sha1-2b2g6H0FscNg6ZbJBQRzx+b4CE8=} + resolution: {integrity: sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -2525,10 +2470,10 @@ packages: optional: true tslib@2.6.2: - resolution: {integrity: sha1-cDrClCXns3zW/UVukkBNRtHz5K4=} + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} type-check@0.4.0: - resolution: {integrity: sha1-B7ggO/pwVsBlcFDjzNLDdzC6uPE=} + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} type-detect@4.0.8: @@ -2536,7 +2481,7 @@ packages: engines: {node: '>=4'} type-fest@0.20.2: - resolution: {integrity: sha1-G/IH9LKPkVg2ZstfvTJ4hzAc1fQ=} + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} type-fest@0.21.3: @@ -2544,21 +2489,21 @@ packages: engines: {node: '>=10'} typescript@5.4.5: - resolution: {integrity: sha1-QszvLFcf29D2cYsdH15uXvAG9hE=} + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - update-browserslist-db@1.0.13: - resolution: {integrity: sha1-PF5PXAg2Yb0472S2Mowm7WyCSMQ=} + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' uri-js@4.4.1: - resolution: {integrity: sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=} + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -2568,10 +2513,10 @@ packages: engines: {node: '>=10.12.0'} validate-html-nesting@1.2.2: - resolution: {integrity: sha1-LXTeFLWYoN5nH60BvXHeq7k7iso=} + resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} vite-plugin-solid@2.10.2: - resolution: {integrity: sha1-GA9eydisA9GRYN1XKLMT/pti7g0=} + resolution: {integrity: sha512-AOEtwMe2baBSXMXdo+BUwECC8IFHcKS6WQV/1NEd+Q7vHPap5fmIhLcAzr+DUJ04/KHx/1UBU0l1/GWP+rMAPQ==} peerDependencies: '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* solid-js: ^1.7.2 @@ -2581,7 +2526,7 @@ packages: optional: true vite-tsconfig-paths@4.3.2: - resolution: {integrity: sha1-Mh8C5Lc2qQ/2L5CGRn+vTi2oV6k=} + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} peerDependencies: vite: '*' peerDependenciesMeta: @@ -2617,7 +2562,7 @@ packages: optional: true vitefu@0.2.5: - resolution: {integrity: sha1-wbk8N3+90+Xd1phA6jqnC0DZCWk=} + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -2628,20 +2573,24 @@ packages: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} which@2.0.2: - resolution: {integrity: sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=} + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: {integrity: sha1-VtwiNo7lcPrOG0mBmXXZuaXq0hQ=} + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} wrappy@1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} wretch@2.8.1: resolution: {integrity: sha512-as9Mta8Nrnu6mL9ApNvmKGWqZtvoQtOILEfjox1BYYBYyUSKUdATVEAlQIMGLSZyzRfNbpUvPKDcGJTGA1b5LA==} @@ -2656,13 +2605,10 @@ packages: engines: {node: '>=10'} yallist@3.1.1: - resolution: {integrity: sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=} - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.4.1: - resolution: {integrity: sha1-LlfgtemVKSwlx10mWPBmR2UhDu0=} + yaml@2.4.2: + resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==} engines: {node: '>= 14'} hasBin: true @@ -2675,13 +2621,11 @@ packages: engines: {node: '>=12'} yocto-queue@0.1.0: - resolution: {integrity: sha1-ApTrPe4FAo0x7hpfosVWpqrxChs=} + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -2691,23 +2635,23 @@ snapshots: '@babel/code-frame@7.24.2': dependencies: - '@babel/highlight': 7.24.2 - picocolors: 1.0.0 + '@babel/highlight': 7.24.5 + picocolors: 1.0.1 '@babel/compat-data@7.24.4': {} - '@babel/core@7.24.4': + '@babel/core@7.24.5': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 + '@babel/generator': 7.24.5 '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helpers': 7.24.4 - '@babel/parser': 7.24.4 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helpers': 7.24.5 + '@babel/parser': 7.24.5 '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 convert-source-map: 2.0.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -2716,9 +2660,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.24.4': + '@babel/generator@7.24.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 @@ -2736,165 +2680,166 @@ snapshots: '@babel/helper-function-name@7.23.0': dependencies: '@babel/template': 7.24.0 - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@babel/helper-hoist-variables@7.22.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@babel/helper-module-imports@7.18.6': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@babel/helper-module-imports@7.24.3': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 - '@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4)': + '@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-simple-access': 7.24.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/helper-validator-identifier': 7.24.5 - '@babel/helper-plugin-utils@7.24.0': {} + '@babel/helper-plugin-utils@7.24.5': {} - '@babel/helper-simple-access@7.22.5': + '@babel/helper-simple-access@7.24.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 - '@babel/helper-split-export-declaration@7.22.6': + '@babel/helper-split-export-declaration@7.24.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@babel/helper-string-parser@7.24.1': {} - '@babel/helper-validator-identifier@7.22.20': {} + '@babel/helper-validator-identifier@7.24.5': {} '@babel/helper-validator-option@7.23.5': {} - '@babel/helpers@7.24.4': + '@babel/helpers@7.24.5': dependencies: '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 transitivePeerDependencies: - supports-color - '@babel/highlight@7.24.2': + '@babel/highlight@7.24.5': dependencies: - '@babel/helper-validator-identifier': 7.22.20 + '@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.24.4': + '@babel/parser@7.24.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.4)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.4)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.4)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4)': + '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.4)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.4)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.4)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.4)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4)': + '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 '@babel/template@7.24.0': dependencies: '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 - '@babel/traverse@7.24.1': + '@babel/traverse@7.24.5': dependencies: '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 + '@babel/generator': 7.24.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.23.0 '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.24.0': + '@babel/types@7.24.5': dependencies: '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-validator-identifier': 7.24.5 to-fast-properties: 2.0.0 '@bcoe/v8-coverage@0.2.3': {} - '@corvu/utils@0.1.1(solid-js@1.8.17)': + '@corvu/utils@0.2.0(solid-js@1.8.17)': dependencies: + '@floating-ui/dom': 1.6.5 solid-js: 1.8.17 '@esbuild/aix-ppc64@0.20.2': @@ -2989,16 +2934,16 @@ snapshots: '@eslint/js@8.57.0': {} - '@floating-ui/core@1.6.0': + '@floating-ui/core@1.6.2': dependencies: - '@floating-ui/utils': 0.2.1 + '@floating-ui/utils': 0.2.2 - '@floating-ui/dom@1.6.3': + '@floating-ui/dom@1.6.5': dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.1 + '@floating-ui/core': 1.6.2 + '@floating-ui/utils': 0.2.2 - '@floating-ui/utils@0.2.1': {} + '@floating-ui/utils@0.2.2': {} '@humanwhocodes/config-array@0.11.14': dependencies: @@ -3012,11 +2957,11 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} - '@internationalized/date@3.5.2': + '@internationalized/date@3.5.4': dependencies: '@swc/helpers': 0.5.11 - '@internationalized/number@3.5.1': + '@internationalized/number@3.5.3': dependencies: '@swc/helpers': 0.5.11 @@ -3042,7 +2987,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -3055,14 +3000,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.12.12) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -3091,7 +3036,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -3109,7 +3054,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.7 + '@types/node': 20.12.12 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3131,7 +3076,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -3178,7 +3123,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 babel-plugin-istanbul: 6.1.1 @@ -3201,7 +3146,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 20.12.12 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -3224,12 +3169,12 @@ snapshots: '@kobalte/core@0.13.1(solid-js@1.8.17)': dependencies: - '@floating-ui/dom': 1.6.3 - '@internationalized/date': 3.5.2 - '@internationalized/number': 3.5.1 + '@floating-ui/dom': 1.6.5 + '@internationalized/date': 3.5.4 + '@internationalized/number': 3.5.3 '@kobalte/utils': 0.9.0(solid-js@1.8.17) solid-js: 1.8.17 - solid-prevent-scroll: 0.1.6(solid-js@1.8.17) + solid-prevent-scroll: 0.1.7(solid-js@1.8.17) '@kobalte/tailwindcss@0.9.0(tailwindcss@3.4.3)': dependencies: @@ -3265,52 +3210,52 @@ snapshots: '@pkgr/core@0.1.1': {} - '@rollup/rollup-android-arm-eabi@4.16.4': + '@rollup/rollup-android-arm-eabi@4.17.2': optional: true - '@rollup/rollup-android-arm64@4.16.4': + '@rollup/rollup-android-arm64@4.17.2': optional: true - '@rollup/rollup-darwin-arm64@4.16.4': + '@rollup/rollup-darwin-arm64@4.17.2': optional: true - '@rollup/rollup-darwin-x64@4.16.4': + '@rollup/rollup-darwin-x64@4.17.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.16.4': + '@rollup/rollup-linux-arm-gnueabihf@4.17.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.16.4': + '@rollup/rollup-linux-arm-musleabihf@4.17.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.16.4': + '@rollup/rollup-linux-arm64-gnu@4.17.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.16.4': + '@rollup/rollup-linux-arm64-musl@4.17.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.16.4': + '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.16.4': + '@rollup/rollup-linux-riscv64-gnu@4.17.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.16.4': + '@rollup/rollup-linux-s390x-gnu@4.17.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.16.4': + '@rollup/rollup-linux-x64-gnu@4.17.2': optional: true - '@rollup/rollup-linux-x64-musl@4.16.4': + '@rollup/rollup-linux-x64-musl@4.17.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.16.4': + '@rollup/rollup-win32-arm64-msvc@4.17.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.16.4': + '@rollup/rollup-win32-ia32-msvc@4.17.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.16.4': + '@rollup/rollup-win32-x64-msvc@4.17.2': optional: true '@sinclair/typebox@0.27.8': {} @@ -3510,7 +3455,7 @@ snapshots: '@swc/core-win32-x64-msvc@1.5.7': optional: true - '@swc/core@1.5.7(@swc/helpers@0.5.11)': + '@swc/core@1.5.7': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.7 @@ -3525,7 +3470,6 @@ snapshots: '@swc/core-win32-arm64-msvc': 1.5.7 '@swc/core-win32-ia32-msvc': 1.5.7 '@swc/core-win32-x64-msvc': 1.5.7 - '@swc/helpers': 0.5.11 '@swc/counter@0.1.3': {} @@ -3533,10 +3477,10 @@ snapshots: dependencies: tslib: 2.6.2 - '@swc/jest@0.2.36(@swc/core@1.5.7(@swc/helpers@0.5.11))': + '@swc/jest@0.2.36(@swc/core@1.5.7)': dependencies: '@jest/create-cache-key-function': 29.7.0 - '@swc/core': 1.5.7(@swc/helpers@0.5.11) + '@swc/core': 1.5.7 '@swc/counter': 0.1.3 jsonc-parser: 3.2.1 @@ -3561,7 +3505,7 @@ snapshots: '@tanstack/query-devtools@5.37.1': {} - '@tanstack/solid-query-devtools@5.37.1(@tanstack/solid-query@5.37.1(solid-js@1.8.17))(solid-js@1.8.17)': + '@tanstack/solid-query-devtools@5.37.1(@tanstack/solid-query@5.37.1)(solid-js@1.8.17)': dependencies: '@tanstack/query-devtools': 5.37.1 '@tanstack/solid-query': 5.37.1(solid-js@1.8.17) @@ -3576,30 +3520,30 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.5 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 '@types/babel__traverse@7.20.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@types/estree@1.0.5': {} '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.12.12 '@types/istanbul-lib-coverage@2.0.6': {} @@ -3616,14 +3560,10 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/json-schema@7.0.15': {} - - '@types/node@20.12.7': + '@types/node@20.12.12': dependencies: undici-types: 5.26.5 - '@types/semver@7.5.8': {} - '@types/stack-utils@2.0.3': {} '@types/yargs-parser@21.0.3': {} @@ -3632,126 +3572,81 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.9.0(@typescript-eslint/parser@7.9.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.9.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/type-utils': 7.9.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.9.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.9.0 + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.10.0 eslint: 8.57.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: - supports-color - '@typescript-eslint/parser@7.9.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.9.0 + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.10.0 debug: 4.3.4 eslint: 8.57.0 - optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.8.0': + '@typescript-eslint/scope-manager@7.10.0': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/visitor-keys': 7.10.0 - '@typescript-eslint/scope-manager@7.9.0': + '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/visitor-keys': 7.9.0 - - '@typescript-eslint/type-utils@7.9.0(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.9.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) debug: 4.3.4 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.8.0': {} - - '@typescript-eslint/types@7.9.0': {} + '@typescript-eslint/types@7.10.0': {} - '@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4 - 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/typescript-estree@7.9.0(typescript@5.4.5)': - dependencies: - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/visitor-keys': 7.9.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/visitor-keys': 7.10.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.2 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) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@7.9.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.9.0 - '@typescript-eslint/types': 7.9.0 - '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) eslint: 8.57.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.8.0': + '@typescript-eslint/visitor-keys@7.10.0': dependencies: - '@typescript-eslint/types': 7.8.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@7.9.0': - dependencies: - '@typescript-eslint/types': 7.9.0 + '@typescript-eslint/types': 7.10.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -3809,20 +3704,20 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.0 - caniuse-lite: 1.0.30001612 + caniuse-lite: 1.0.30001620 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 - babel-jest@29.7.0(@babel/core@7.24.4): + babel-jest@29.7.0(@babel/core@7.24.5): dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.4) + babel-preset-jest: 29.6.3(@babel/core@7.24.5) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -3831,7 +3726,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.24.0 + '@babel/helper-plugin-utils': 7.24.5 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -3842,45 +3737,45 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.24.0 - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.5 - babel-plugin-jsx-dom-expressions@0.37.20(@babel/core@7.24.4): + babel-plugin-jsx-dom-expressions@0.37.21(@babel/core@7.24.5): dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@babel/helper-module-imports': 7.18.6 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/types': 7.24.0 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/types': 7.24.5 html-entities: 2.3.3 validate-html-nesting: 1.2.2 - babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.4): - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4) - - babel-preset-jest@29.6.3(@babel/core@7.24.4): - dependencies: - '@babel/core': 7.24.4 + babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5): + dependencies: + '@babel/core': 7.24.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) + + babel-preset-jest@29.6.3(@babel/core@7.24.5): + dependencies: + '@babel/core': 7.24.5 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) - babel-preset-solid@1.8.17(@babel/core@7.24.4): + babel-preset-solid@1.8.17(@babel/core@7.24.5): dependencies: - '@babel/core': 7.24.4 - babel-plugin-jsx-dom-expressions: 0.37.20(@babel/core@7.24.4) + '@babel/core': 7.24.5 + babel-plugin-jsx-dom-expressions: 0.37.21(@babel/core@7.24.5) balanced-match@1.0.2: {} @@ -3901,10 +3796,10 @@ snapshots: browserslist@4.23.0: dependencies: - caniuse-lite: 1.0.30001612 - electron-to-chromium: 1.4.747 + caniuse-lite: 1.0.30001620 + electron-to-chromium: 1.4.775 node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) + update-browserslist-db: 1.0.16(browserslist@4.23.0) bser@2.1.1: dependencies: @@ -3920,7 +3815,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001612: {} + caniuse-lite@1.0.30001620: {} chalk@2.4.2: dependencies: @@ -3985,13 +3880,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@20.12.7): + create-jest@29.7.0: dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.12.12) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -4038,7 +3933,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.4.747: {} + electron-to-chromium@1.4.775: {} emittery@0.13.1: {} @@ -4088,18 +3983,17 @@ snapshots: dependencies: eslint: 8.57.0 - 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(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): dependencies: eslint: 8.57.0 + eslint-config-prettier: 9.1.0(eslint@8.57.0) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 - optionalDependencies: - eslint-config-prettier: 9.1.0(eslint@8.57.0) eslint-plugin-solid@0.14.0(eslint@8.57.0)(typescript@5.4.5): dependencies: - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 estraverse: 5.3.0 is-html: 2.0.0 @@ -4154,7 +4048,7 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: @@ -4284,13 +4178,13 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.3.12: + glob@10.3.15: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 + minipass: 7.1.1 + path-scurry: 1.11.1 glob@7.2.3: dependencies: @@ -4399,8 +4293,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.24.4 - '@babel/parser': 7.24.4 + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -4409,8 +4303,8 @@ snapshots: istanbul-lib-instrument@6.0.2: dependencies: - '@babel/core': 7.24.4 - '@babel/parser': 7.24.4 + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.2 @@ -4454,7 +4348,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -4474,16 +4368,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.12.7): + jest-cli@29.7.0: dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7) + create-jest: 29.7.0 exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.12.12) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -4493,12 +4387,13 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.12.7): + jest-config@29.7.0(@types/node@20.12.12): dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.4) + '@types/node': 20.12.12 + babel-jest: 29.7.0(@babel/core@7.24.5) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -4517,8 +4412,6 @@ snapshots: pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 20.12.7 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -4547,7 +4440,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4557,7 +4450,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.12.7 + '@types/node': 20.12.12 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -4596,11 +4489,11 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: + dependencies: jest-resolve: 29.7.0 jest-regex-util@29.6.3: {} @@ -4631,7 +4524,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -4659,7 +4552,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -4679,15 +4572,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.24.4 - '@babel/generator': 7.24.4 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) - '@babel/types': 7.24.0 + '@babel/core': 7.24.5 + '@babel/generator': 7.24.5 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) + '@babel/types': 7.24.5 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -4705,7 +4598,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -4724,7 +4617,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.12.12 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -4733,17 +4626,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.12.12 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.12.7): + jest@29.7.0: dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7) + jest-cli: 29.7.0 transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4814,16 +4707,12 @@ snapshots: lodash.merge@4.6.2: {} - lru-cache@10.2.0: {} + lru-cache@10.2.2: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - make-dir@4.0.0: dependencies: semver: 7.6.2 @@ -4857,7 +4746,7 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minipass@7.0.4: {} + minipass@7.1.1: {} ms@2.1.2: {} @@ -4895,14 +4784,14 @@ snapshots: dependencies: mimic-fn: 2.1.0 - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 p-limit@2.3.0: dependencies: @@ -4945,14 +4834,14 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.2: + path-scurry@1.11.1: dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 + lru-cache: 10.2.2 + minipass: 7.1.1 path-type@4.0.0: {} - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -4979,9 +4868,8 @@ snapshots: postcss-load-config@4.0.2(postcss@8.4.38): dependencies: lilconfig: 3.1.1 - yaml: 2.4.1 - optionalDependencies: postcss: 8.4.38 + yaml: 2.4.2 postcss-nested@6.0.1(postcss@8.4.38): dependencies: @@ -5003,7 +4891,7 @@ snapshots: postcss@8.4.38: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 prelude-ls@1.2.1: {} @@ -5069,26 +4957,26 @@ snapshots: dependencies: glob: 7.2.3 - rollup@4.16.4: + rollup@4.17.2: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.16.4 - '@rollup/rollup-android-arm64': 4.16.4 - '@rollup/rollup-darwin-arm64': 4.16.4 - '@rollup/rollup-darwin-x64': 4.16.4 - '@rollup/rollup-linux-arm-gnueabihf': 4.16.4 - '@rollup/rollup-linux-arm-musleabihf': 4.16.4 - '@rollup/rollup-linux-arm64-gnu': 4.16.4 - '@rollup/rollup-linux-arm64-musl': 4.16.4 - '@rollup/rollup-linux-powerpc64le-gnu': 4.16.4 - '@rollup/rollup-linux-riscv64-gnu': 4.16.4 - '@rollup/rollup-linux-s390x-gnu': 4.16.4 - '@rollup/rollup-linux-x64-gnu': 4.16.4 - '@rollup/rollup-linux-x64-musl': 4.16.4 - '@rollup/rollup-win32-arm64-msvc': 4.16.4 - '@rollup/rollup-win32-ia32-msvc': 4.16.4 - '@rollup/rollup-win32-x64-msvc': 4.16.4 + '@rollup/rollup-android-arm-eabi': 4.17.2 + '@rollup/rollup-android-arm64': 4.17.2 + '@rollup/rollup-darwin-arm64': 4.17.2 + '@rollup/rollup-darwin-x64': 4.17.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 + '@rollup/rollup-linux-arm-musleabihf': 4.17.2 + '@rollup/rollup-linux-arm64-gnu': 4.17.2 + '@rollup/rollup-linux-arm64-musl': 4.17.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 + '@rollup/rollup-linux-riscv64-gnu': 4.17.2 + '@rollup/rollup-linux-s390x-gnu': 4.17.2 + '@rollup/rollup-linux-x64-gnu': 4.17.2 + '@rollup/rollup-linux-x64-musl': 4.17.2 + '@rollup/rollup-win32-arm64-msvc': 4.17.2 + '@rollup/rollup-win32-ia32-msvc': 4.17.2 + '@rollup/rollup-win32-x64-msvc': 4.17.2 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5097,17 +4985,13 @@ snapshots: semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 - semver@7.6.2: {} - seroval-plugins@1.0.5(seroval@1.0.5): + seroval-plugins@1.0.7(seroval@1.0.7): dependencies: - seroval: 1.0.5 + seroval: 1.0.7 - seroval@1.0.5: {} + seroval@1.0.7: {} shebang-command@2.0.0: dependencies: @@ -5123,16 +5007,15 @@ snapshots: slash@3.0.0: {} - solid-devtools@0.30.1(solid-js@1.8.17)(vite@5.2.11(@types/node@20.12.7)): + solid-devtools@0.30.1(solid-js@1.8.17)(vite@5.2.11): dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) - '@babel/types': 7.24.0 + '@babel/core': 7.24.5 + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) + '@babel/types': 7.24.5 '@solid-devtools/debugger': 0.23.4(solid-js@1.8.17) '@solid-devtools/shared': 0.13.2(solid-js@1.8.17) solid-js: 1.8.17 - optionalDependencies: - vite: 5.2.11(@types/node@20.12.7) + vite: 5.2.11 transitivePeerDependencies: - supports-color @@ -5143,19 +5026,19 @@ snapshots: solid-js@1.8.17: dependencies: csstype: 3.1.3 - seroval: 1.0.5 - seroval-plugins: 1.0.5(seroval@1.0.5) + seroval: 1.0.7 + seroval-plugins: 1.0.7(seroval@1.0.7) - solid-prevent-scroll@0.1.6(solid-js@1.8.17): + solid-prevent-scroll@0.1.7(solid-js@1.8.17): dependencies: - '@corvu/utils': 0.1.1(solid-js@1.8.17) + '@corvu/utils': 0.2.0(solid-js@1.8.17) solid-js: 1.8.17 solid-refresh@0.6.3(solid-js@1.8.17): dependencies: - '@babel/generator': 7.24.4 + '@babel/generator': 7.24.5 '@babel/helper-module-imports': 7.24.3 - '@babel/types': 7.24.0 + '@babel/types': 7.24.5 solid-js: 1.8.17 source-map-js@1.2.0: {} @@ -5212,7 +5095,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 - glob: 10.3.12 + glob: 10.3.15 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -5252,7 +5135,7 @@ snapshots: micromatch: 4.0.5 normalize-path: 3.0.0 object-hash: 3.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) @@ -5295,7 +5178,7 @@ snapshots: ts-interface-checker@0.1.13: {} tsconfck@3.0.3(typescript@5.4.5): - optionalDependencies: + dependencies: typescript: 5.4.5 tslib@2.6.2: {} @@ -5314,11 +5197,11 @@ snapshots: undici-types@5.26.5: {} - update-browserslist-db@1.0.13(browserslist@4.23.0): + update-browserslist-db@1.0.16(browserslist@4.23.0): dependencies: browserslist: 4.23.0 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 uri-js@4.4.1: dependencies: @@ -5334,42 +5217,40 @@ snapshots: validate-html-nesting@1.2.2: {} - vite-plugin-solid@2.10.2(solid-js@1.8.17)(vite@5.2.11(@types/node@20.12.7)): + vite-plugin-solid@2.10.2(solid-js@1.8.17)(vite@5.2.11): dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.5 '@types/babel__core': 7.20.5 - babel-preset-solid: 1.8.17(@babel/core@7.24.4) + babel-preset-solid: 1.8.17(@babel/core@7.24.5) merge-anything: 5.1.7 solid-js: 1.8.17 solid-refresh: 0.6.3(solid-js@1.8.17) - vite: 5.2.11(@types/node@20.12.7) - vitefu: 0.2.5(vite@5.2.11(@types/node@20.12.7)) + vite: 5.2.11 + vitefu: 0.2.5(vite@5.2.11) transitivePeerDependencies: - supports-color - vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)): + vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.2.11): dependencies: debug: 4.3.4 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.4.5) - optionalDependencies: - vite: 5.2.11(@types/node@20.12.7) + vite: 5.2.11 transitivePeerDependencies: - supports-color - typescript - vite@5.2.11(@types/node@20.12.7): + vite@5.2.11: dependencies: esbuild: 0.20.2 postcss: 8.4.38 - rollup: 4.16.4 + rollup: 4.17.2 optionalDependencies: - '@types/node': 20.12.7 fsevents: 2.3.3 - vitefu@0.2.5(vite@5.2.11(@types/node@20.12.7)): - optionalDependencies: - vite: 5.2.11(@types/node@20.12.7) + vitefu@0.2.5(vite@5.2.11): + dependencies: + vite: 5.2.11 walker@1.0.8: dependencies: @@ -5379,6 +5260,8 @@ snapshots: dependencies: isexe: 2.0.0 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -5404,9 +5287,7 @@ snapshots: yallist@3.1.1: {} - yallist@4.0.0: {} - - yaml@2.4.1: {} + yaml@2.4.2: {} yargs-parser@21.1.1: {} diff --git a/src/main.rs b/src/main.rs index d955ec6f..26a86a4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,25 +37,30 @@ async fn main() -> error::BlendResult<()> { // Create job queue channel let (job_tx, mut job_rx) = mpsc::channel::(CHANNEL_BUFFER_SIZE); - let jobs = Arc::new(Mutex::new(job_tx)); + let job_tx = Arc::new(Mutex::new(job_tx)); // Create notification channel let (notif_tx, mut notif_rx) = broadcast::channel::(CHANNEL_BUFFER_SIZE); - let notifs = Arc::new(Mutex::new(notif_tx)); + let notif_tx = Arc::new(Mutex::new(notif_tx)); // Start queue and refresh workers - let queue_worker = - blend_worker::start_queue_worker(&mut job_rx, db.clone(), notifs.clone()).fuse(); + let queue_worker = blend_worker::start_queue_worker( + db.clone(), + &mut job_rx, + job_tx.clone(), + notif_tx.clone(), + ) + .fuse(); let refresh_worker = - blend_worker::start_refresh_worker(jobs.clone(), db.clone()).fuse(); + blend_worker::start_refresh_worker(job_tx.clone(), db.clone()).fuse(); // Start web server let web = blend_web::serve(blend_web::Context { blend, db, - jobs, - notifs, + job_tx, + notif_tx, }) .fuse(); diff --git a/tailwind.config.ts b/tailwind.config.ts index 77fb95a1..d90e2737 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -22,22 +22,22 @@ export default { sidebar: '16rem', }, keyframes: { - overlayShow: { from: { opacity: '0' }, to: { opacity: '1' } }, - overlayHide: { from: { opacity: '1' }, to: { opacity: '0' } }, - contentShow: { + 'overlay-show': { from: { opacity: '0' }, to: { opacity: '1' } }, + 'overlay-hide': { from: { opacity: '1' }, to: { opacity: '0' } }, + 'content-show': { from: { opacity: '0', transform: 'scale(0.95) translateY(0.25rem)' }, to: { opacity: '1', transform: 'scale(1) translateY(0rem)' }, }, - contentHide: { + 'content-hide': { from: { opacity: '1', transform: 'scale(1) translateY(0rem)' }, to: { opacity: '0', transform: 'scale(0.95) translateY(0.25rem)' }, }, }, animation: { - overlayShow: 'overlayShow 150ms ease-in-out', - overlayHide: 'overlayHide 150ms ease-in-out', - contentShow: 'contentShow 150ms ease-in-out', - contentHide: 'contentHide 150ms ease-in-out', + 'overlay-show': 'overlay-show 150ms ease-in-out', + 'overlay-hide': 'overlay-hide 150ms ease-in-out', + 'content-show': 'content-show 150ms ease-in-out', + 'content-hide': 'content-hide 150ms ease-in-out', }, }, }, diff --git a/ui/src/components/entry/entry-item.tsx b/ui/src/components/entry/entry-item.tsx index c13c21dc..4ac99624 100644 --- a/ui/src/components/entry/entry-item.tsx +++ b/ui/src/components/entry/entry-item.tsx @@ -1,60 +1,83 @@ -import { A } from '@solidjs/router'; +/* eslint-disable solid/no-innerhtml */ + +import { A, AnchorProps, useMatch } from '@solidjs/router'; import { createQuery } from '@tanstack/solid-query'; import { cx } from 'class-variance-authority'; -import { type Component } from 'solid-js'; +import { splitProps, type Component } from 'solid-js'; import { getEntry } from '~/api/entries'; import { DATA_ATTRIBUTES } from '~/constants/attributes'; import { QUERY_KEYS } from '~/constants/query'; import { useFeeds } from '~/hooks/queries/use-feeds'; -import { useFilterParams } from '~/hooks/use-filter-params'; +import { useQueryState } from '~/hooks/use-query-state'; import type { Entry } from '~/types/bindings'; import { formatDate } from '~/utils/date'; -type EntryItemProps = { +type EntryItemProps = Omit & { entry: Entry; }; export const EntryItem: Component = props => { - const filter = useFilterParams(); + const state = useQueryState(); const feeds = useFeeds(); + const [local, rest] = splitProps(props, ['entry', 'class']); + // Get the data for an entry to check if user marked it as read const entryData = createQuery(() => ({ - enabled: filter.params.entry_uuid === props.entry.uuid, - queryKey: [QUERY_KEYS.ENTRIES_VIEW, props.entry.uuid], - queryFn: () => getEntry(props.entry.uuid), + enabled: state.params.entry_uuid === local.entry.uuid, + queryKey: [QUERY_KEYS.ENTRIES_VIEW, local.entry.uuid], + queryFn: () => getEntry(local.entry.uuid), refetchOnWindowFocus: false, refetchOnMount: false, })); - const feed = () => feeds.findFeed(props.entry.feed_uuid); - const isRead = () => !!props.entry.read_at || !!entryData.data?.read_at; + const feed = () => feeds.findFeed(local.entry.feed_uuid); + const isRead = () => !!local.entry.read_at || !!entryData.data?.read_at; + + const getDate = () => local.entry.published_at || local.entry.updated_at; - const getDate = () => props.entry.published_at || props.entry.updated_at; + const entryRouteMatch = useMatch(() => state.getEntryUrl(local.entry.uuid, false)); + const isActive = () => Boolean(entryRouteMatch()); return ( -

{props.entry.title}

+

- - {!isRead() && } + + {!isRead() && ( + + )} - {!filter.params.feed_uuid && ( + {!state.params.feed_uuid && ( <> - {feed()?.title} - {!!getDate() && } + {feed()?.title_display || feed()?.title} + {!!getDate() && } )} diff --git a/ui/src/components/entry/entry-list.tsx b/ui/src/components/entry/entry-list.tsx index ce0ab672..e88df697 100644 --- a/ui/src/components/entry/entry-list.tsx +++ b/ui/src/components/entry/entry-list.tsx @@ -20,12 +20,12 @@ export const EntryList: Component = props => { const entries = useInfiniteEntries(); // Handle arrow navigation - useListNav(() => ({ enabled: !!props.containsActiveElement, entries: entries.localEntries() })); + useListNav(() => ({ enabled: !!props.containsActiveElement, entries: entries.getAllEntries() })); createEffect(() => { if (!listBounds.bottom || !props.containerBounds?.bottom) return; - const bottomOfListVisible = listBounds.bottom <= props.containerBounds.bottom; + const bottomOfListVisible = listBounds.bottom * 0.9 <= props.containerBounds.bottom; if (!bottomOfListVisible) return; entries.fetchMore(); @@ -46,9 +46,16 @@ export const EntryList: Component = props => { - {entries.localEntries().length ? ( -
- {entry => } + {entries.getAllEntries().length ? ( +
+ + {(entry, index) => ( + + )} +
diff --git a/ui/src/components/entry/entry-panel.tsx b/ui/src/components/entry/entry-panel.tsx index 463de366..9bd5e66c 100644 --- a/ui/src/components/entry/entry-panel.tsx +++ b/ui/src/components/entry/entry-panel.tsx @@ -6,20 +6,22 @@ import { Panel } from '~/components/layout/panel'; import { QUERY_KEYS } from '~/constants/query'; import { updateEntryAsRead } from '~/api/entries'; import { createMutation } from '@tanstack/solid-query'; -import { useFilterParams } from '~/hooks/use-filter-params'; +import { useQueryState } from '~/hooks/use-query-state'; import { Empty } from '../ui/empty'; import { useViewport } from '~/hooks/use-viewport'; import { Spinner } from '../ui/spinner'; +import { useInvalidateStats } from '~/hooks/queries/use-invalidate-stats'; export const EntryPanel = () => { - const filter = useFilterParams(); + const state = useQueryState(); const queryClient = useQueryClient(); const { gtBreakpoint } = useViewport(); + const invalidateStats = useInvalidateStats(); const entry = createQuery(() => ({ - enabled: !!filter.params.entry_uuid, - queryKey: [QUERY_KEYS.ENTRIES_VIEW, filter.params.entry_uuid], - queryFn: () => getEntry(filter.params.entry_uuid!), + enabled: !!state.params.entry_uuid, + queryKey: [QUERY_KEYS.ENTRIES_VIEW, state.params.entry_uuid], + queryFn: () => getEntry(state.params.entry_uuid!), refetchOnWindowFocus: false, refetchOnMount: false, })); @@ -33,14 +35,14 @@ export const EntryPanel = () => { if (!entry.isSuccess || !entry.data || entry.data.read_at) return; markAsRead.mutateAsync(entry.data.uuid).then(() => { - queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.FEEDS_STATS] }); + invalidateStats(); queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.ENTRIES_VIEW, entry.data.uuid] }); }); }); return ( diff --git a/ui/src/components/entry/entry-view.tsx b/ui/src/components/entry/entry-view.tsx index eba3f610..4686088e 100644 --- a/ui/src/components/entry/entry-view.tsx +++ b/ui/src/components/entry/entry-view.tsx @@ -33,23 +33,30 @@ export const EntryView: ParentComponent = props => { )}
-

{local.entry.title}

+

{!!getDate() &&
{formatDateTime(getDate()!)}
} - {local.entry.summary && ( -

{local.entry.summary}

+ {local.entry.summary_html && ( +

)}
- {local.entry.content_html || local.entry.content_scraped_html ? ( + + {local.entry.content_scraped_html || local.entry.content_html ? (
) : (
diff --git a/ui/src/components/feed/feed-header.tsx b/ui/src/components/feed/feed-header.tsx index 015029cf..9eed29bc 100644 --- a/ui/src/components/feed/feed-header.tsx +++ b/ui/src/components/feed/feed-header.tsx @@ -6,8 +6,10 @@ type FeedHeaderProps = { }; export const FeedHeader: Component = props => ( -
+

{props.title}

- {props.subtitle && {props.subtitle}} + {props.subtitle && ( + {props.subtitle} + )}
); diff --git a/ui/src/components/feed/feed-info.tsx b/ui/src/components/feed/feed-info.tsx index fd66f4fb..f2c24d59 100644 --- a/ui/src/components/feed/feed-info.tsx +++ b/ui/src/components/feed/feed-info.tsx @@ -30,8 +30,8 @@ export const FeedInfo: Component = props => { -
- +
+ = props => { const location = useLocation(); - const filter = useFilterParams(); + const state = useQueryState(); const [open, setOpen] = createSignal(false); @@ -24,14 +25,17 @@ export const FeedItem: Component = props => { const isActive = createMemo(() => location.pathname.startsWith(getPath())); const getStats = createMemo(() => stats.data?.find(item => item.uuid === props.feed.uuid)); + const getFaviconSrc = () => props.feed.favicon_b64 || props.feed.favicon_url; + return ( ( )} @@ -46,6 +50,7 @@ type BaseFeedItemProps = { active: boolean; open: boolean; setOpen: Setter; + favicon_src?: string; icon?: () => JSX.Element; menu: () => JSX.Element; }; @@ -63,27 +68,36 @@ export const BaseFeedItem: Component = props => ( : 'border-transparent hover:bg-gray-50 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-white', )} > - {/* TODO: render favicon */}
- {props.icon ? ( - - ) : ( -
- -
- )} + }> + + + + + + + + + +
{props.title} - {props.unread_count && ( - + + {props.unread_count} - )} + ); + +const RssIcon = () => ( +
+ +
+); diff --git a/ui/src/components/feed/feed-list.tsx b/ui/src/components/feed/feed-list.tsx index a7ebe0c8..6c3c6e47 100644 --- a/ui/src/components/feed/feed-list.tsx +++ b/ui/src/components/feed/feed-list.tsx @@ -3,13 +3,13 @@ import { BaseFeedItem, FeedItem } from './feed-item'; import { useFeeds } from '~/hooks/queries/use-feeds'; import { useFeedsStats } from '~/hooks/queries/use-feeds-stats'; import { useLocation } from '@solidjs/router'; -import { useFilterParams } from '~/hooks/use-filter-params'; +import { useQueryState } from '~/hooks/use-query-state'; import { HiOutlineSquare3Stack3d } from 'solid-icons/hi'; import { MenuFeeds } from '../menus/menu-feeds'; export const FeedList = () => { const location = useLocation(); - const filter = useFilterParams(); + const state = useQueryState(); const [allFeedsMenuOpen, setAllFeedsMenuOpen] = createSignal(false); @@ -19,7 +19,7 @@ export const FeedList = () => { return (
} open={allFeedsMenuOpen()} diff --git a/ui/src/components/menus/menu.tsx b/ui/src/components/menus/menu.tsx index cb7745c6..0ebeafbd 100644 --- a/ui/src/components/menus/menu.tsx +++ b/ui/src/components/menus/menu.tsx @@ -99,7 +99,7 @@ const MenuContent: ParentComponent = props => ( 'z-50 min-w-36 overflow-hidden rounded-md border shadow-sm', 'border-gray-200 bg-white text-gray-600', 'dark:border-gray-700 dark:bg-gray-900 dark:text-gray-200', - 'origin-[--kb-menu-content-transform-origin] animate-contentHide ui-expanded:animate-contentShow', + 'animate-content-hide ui-expanded:animate-content-show origin-[--kb-menu-content-transform-origin]', )} >
{props.children}
diff --git a/ui/src/components/modals/create-feed.tsx b/ui/src/components/modals/create-feed.tsx index 77b37ebc..fd003dc0 100644 --- a/ui/src/components/modals/create-feed.tsx +++ b/ui/src/components/modals/create-feed.tsx @@ -21,7 +21,7 @@ export const CreateFeed: Component = props => { const navigate = useNavigate(); const [open, setOpen] = createSignal(false); - const [value, setValue] = createSignal('https://blog.rust-lang.org/feed.xml'); + const [value, setValue] = createSignal(''); const [inputElement, setInputElement] = createSignal(); const add = createMutation(() => ({ @@ -40,8 +40,9 @@ export const CreateFeed: Component = props => { const feed = await add.mutateAsync({ url: value() }); queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.FEEDS] }); navigate(`/feeds/${feed.uuid}`); - add.reset(); setOpen(false); + add.reset(); + setValue(''); }; const handleOpenAutoFocus = (event: Event) => { @@ -67,11 +68,11 @@ export const CreateFeed: Component = props => { /> - +
diff --git a/ui/src/components/nav/nav-row.tsx b/ui/src/components/nav/nav-row.tsx index 33cf661c..799f5fa6 100644 --- a/ui/src/components/nav/nav-row.tsx +++ b/ui/src/components/nav/nav-row.tsx @@ -1,7 +1,7 @@ import { HiOutlineQueueList, HiSolidArrowLeft, HiSolidXMark } from 'solid-icons/hi'; import { Dynamic } from 'solid-js/web'; import { Button } from '@kobalte/core/button'; -import { useFilterParams } from '~/hooks/use-filter-params'; +import { useQueryState } from '~/hooks/use-query-state'; import { Component, Setter } from 'solid-js'; import { cx } from 'class-variance-authority'; import { Tooltip } from '../ui/tooltip'; @@ -18,7 +18,7 @@ type NavRowProps = { }; export const NavRow: Component = props => { - const filter = useFilterParams(); + const state = useQueryState(); const navigate = useNavigate(); return ( @@ -49,7 +49,7 @@ export const NavRow: Component = props => { as={(local: TooltipTriggerProps) => ( +