From d9a27f3dc416b8f9348c0f8d31736fe57e36dea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Thu, 7 May 2026 18:27:15 -0400 Subject: [PATCH] Initialize Rust GPUI browser shell --- .github/workflows/ci.yml | 36 + .gitignore | 7 + Cargo.lock | 7824 ++++++++++++++++++++ Cargo.toml | 33 + DESIGN.md | 537 ++ PRD.md | 1810 +++++ README.md | 18 + crates/ely_app/Cargo.toml | 16 + crates/ely_app/src/main.rs | 48 + crates/ely_app/src/shell.rs | 311 + crates/ely_browser_core/Cargo.toml | 13 + crates/ely_browser_core/src/error.rs | 14 + crates/ely_browser_core/src/lib.rs | 5 + crates/ely_browser_core/src/state.rs | 148 + crates/ely_design_system/Cargo.toml | 9 + crates/ely_design_system/src/colors.rs | 14 + crates/ely_design_system/src/lib.rs | 31 + crates/ely_design_system/src/motion.rs | 17 + crates/ely_design_system/src/spacing.rs | 11 + crates/ely_design_system/src/typography.rs | 14 + crates/ely_domain/Cargo.toml | 14 + crates/ely_domain/src/command.rs | 62 + crates/ely_domain/src/error.rs | 13 + crates/ely_domain/src/identifiers.rs | 40 + crates/ely_domain/src/lib.rs | 17 + crates/ely_domain/src/profile.rs | 42 + crates/ely_domain/src/space.rs | 54 + crates/ely_domain/src/split.rs | 60 + crates/ely_domain/src/tab.rs | 92 + crates/ely_domain/src/url_text.rs | 60 + crates/ely_servo_host/Cargo.toml | 13 + crates/ely_servo_host/src/error.rs | 11 + crates/ely_servo_host/src/host.rs | 51 + crates/ely_servo_host/src/lib.rs | 5 + docs/reference-audit.md | 28 + docs/ui-shell.md | 22 + packaging/macos/Info.plist | 33 + rust-toolchain.toml | 3 + rustfmt.toml | 3 + scripts/audit_source_lines.sh | 15 + scripts/create_macos_app_bundle.sh | 19 + 41 files changed, 11573 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 DESIGN.md create mode 100644 PRD.md create mode 100644 README.md create mode 100644 crates/ely_app/Cargo.toml create mode 100644 crates/ely_app/src/main.rs create mode 100644 crates/ely_app/src/shell.rs create mode 100644 crates/ely_browser_core/Cargo.toml create mode 100644 crates/ely_browser_core/src/error.rs create mode 100644 crates/ely_browser_core/src/lib.rs create mode 100644 crates/ely_browser_core/src/state.rs create mode 100644 crates/ely_design_system/Cargo.toml create mode 100644 crates/ely_design_system/src/colors.rs create mode 100644 crates/ely_design_system/src/lib.rs create mode 100644 crates/ely_design_system/src/motion.rs create mode 100644 crates/ely_design_system/src/spacing.rs create mode 100644 crates/ely_design_system/src/typography.rs create mode 100644 crates/ely_domain/Cargo.toml create mode 100644 crates/ely_domain/src/command.rs create mode 100644 crates/ely_domain/src/error.rs create mode 100644 crates/ely_domain/src/identifiers.rs create mode 100644 crates/ely_domain/src/lib.rs create mode 100644 crates/ely_domain/src/profile.rs create mode 100644 crates/ely_domain/src/space.rs create mode 100644 crates/ely_domain/src/split.rs create mode 100644 crates/ely_domain/src/tab.rs create mode 100644 crates/ely_domain/src/url_text.rs create mode 100644 crates/ely_servo_host/Cargo.toml create mode 100644 crates/ely_servo_host/src/error.rs create mode 100644 crates/ely_servo_host/src/host.rs create mode 100644 crates/ely_servo_host/src/lib.rs create mode 100644 docs/reference-audit.md create mode 100644 docs/ui-shell.md create mode 100644 packaging/macos/Info.plist create mode 100644 rust-toolchain.toml create mode 100644 rustfmt.toml create mode 100755 scripts/audit_source_lines.sh create mode 100755 scripts/create_macos_app_bundle.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..52c2a87 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + rust: + name: Rust workspace + runs-on: macos-15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use pinned Rust toolchain + run: rustup show + + - name: Check formatting + run: cargo fmt --all --check + + - name: Check workspace + run: cargo check --workspace --all-targets + + - name: Lint workspace + run: cargo clippy --workspace --all-targets -- -D warnings + + - name: Test workspace + run: cargo test --workspace --all-targets + + - name: Audit source file size + run: scripts/audit_source_lines.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3211efe --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/target/ +/references/ +.agents/ +.claude/ +.DS_Store +*.log +*.tmp diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8da87af --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7824 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ar_archive_writer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +dependencies = [ + "object", +] + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arc-swap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +dependencies = [ + "rustversion", +] + +[[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.117", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "ash-window" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82" +dependencies = [ + "ash", + "raw-window-handle", + "raw-window-metal", +] + +[[package]] +name = "ashpd" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.4", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.32.12", + "zbus", +] + +[[package]] +name = "ashpd" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33a3c86f3fd70c0ffa500ed189abfa90b5a52398a45d5dc372fcc38ebeb7a645" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.4", + "serde", + "serde_repr", + "url", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-compression" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +dependencies = [ + "compression-codecs", + "compression-core", + "futures-io", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.4.1", + "futures-lite 2.6.1", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite 2.6.1", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite 2.6.1", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.6.1", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite 2.6.1", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel 2.5.0", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.4.1", + "futures-lite 2.6.1", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 2.6.1", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async_zip" +version = "0.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b9f7252833d5ed4b00aa9604b563529dd5e11de9c23615de2dcdf91eb87b52" +dependencies = [ + "async-compression", + "crc32fast", + "futures-lite 2.6.1", + "pin-project", + "thiserror 1.0.69", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[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.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "base62" +version = "2.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd637ac531c60eb7fbc4684dc061c2d7d90d73d758181aa02eeff0464b9eee4b" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.11.1", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.2", + "shlex", + "syn 2.0.117", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[package]] +name = "blade-graphics" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e71cfb73b98eb9f58ee84048aa1bdf4e7497fd20c141b57523499fa066b48fed" +dependencies = [ + "ash", + "ash-window", + "bitflags 2.11.1", + "bytemuck", + "codespan-reporting", + "glow", + "gpu-alloc", + "gpu-alloc-ash", + "hidden-trait", + "js-sys", + "khronos-egl", + "libloading", + "log", + "mint", + "naga", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", + "objc2-ui-kit", + "once_cell", + "raw-window-handle", + "slab", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "blade-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27142319e2f4c264581067eaccb9f80acccdde60d8b4bf57cc50cd3152f109ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "blade-util" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6be3a82c001ba7a17b6f8e413ede5d1004e6047213f8efaf0ffc15b5c4904c" +dependencies = [ + "blade-graphics", + "bytemuck", + "log", + "profiling", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel 2.5.0", + "async-task", + "futures-io", + "futures-lite 2.6.1", + "piper", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "byteorder" +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.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cbindgen" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff" +dependencies = [ + "heck 0.4.1", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.117", + "tempfile", + "toml 0.8.23", +] + +[[package]] +name = "cc" +version = "1.2.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +dependencies = [ + "bitflags 2.11.1", + "block", + "cocoa-foundation 0.2.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "libc", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "command-fds" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b60b5124979fccd9addd89d8b97a1d6eebb4950694520c75ddd722535ea443f" +dependencies = [ + "nix 0.31.2", + "thiserror 2.0.18", +] + +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "compression-core", + "deflate64", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-helmer-fork" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32eb7c354ae9f6d437a6039099ce7ecd049337a8109b23d73e48e8ffba8e9cd5" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.10.0", + "libc", +] + +[[package]] +name = "core-graphics2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4583956b9806b69f73fcb23aee05eb3620efc282972f08f6a6db7504f8334d" +dependencies = [ + "bitflags 2.11.1", + "block", + "cfg-if", + "core-foundation 0.10.0", + "libc", +] + +[[package]] +name = "core-text" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a593227b66cbd4007b2a050dfdd9e1d1318311409c8d600dc82ba1b15ca9c130" +dependencies = [ + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-video" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45e71d5be22206bed53c3c3cb99315fc4c3d31b8963808c6bc4538168c4f8ef" +dependencies = [ + "block", + "core-foundation 0.10.0", + "core-graphics2", + "io-surface", + "libc", + "metal", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "cosmic-text" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da46a9d5a8905cc538a4a5bceb6a4510de7a51049c5588c0114efce102bcbbe8" +dependencies = [ + "bitflags 2.11.1", + "fontdb 0.16.2", + "log", + "rangemap", + "rustc-hash 1.1.0", + "rustybuzz 0.14.1", + "self_cell", + "smol_str", + "swash", + "sys-locale", + "ttf-parser 0.21.1", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec09e802f5081de6157da9a75701d6c713d8dc3ba52571fd4bd25f412644e8a6" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" + +[[package]] +name = "data-url" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" + +[[package]] +name = "deflate64" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.1", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dtor" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cbdf2ad6846025e8e25df05171abfb30e3ababa12ee0a0e44b9bbe570633a8" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dwrote" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "ely_app" +version = "0.1.0" +dependencies = [ + "ely_browser_core", + "ely_design_system", + "ely_domain", + "gpui", + "gpui-component", +] + +[[package]] +name = "ely_browser_core" +version = "0.1.0" +dependencies = [ + "ely_domain", + "thiserror 2.0.18", +] + +[[package]] +name = "ely_design_system" +version = "0.1.0" + +[[package]] +name = "ely_domain" +version = "0.1.0" +dependencies = [ + "thiserror 2.0.18", + "url", + "uuid", +] + +[[package]] +name = "ely_servo_host" +version = "0.1.0" +dependencies = [ + "ely_domain", + "thiserror 2.0.18", +] + +[[package]] +name = "embed-resource" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 1.1.2+spec-1.1.0", + "vswhom", + "winreg", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enum-iterator" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "etagere" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc89bf99e5dc15954a60f707c1e09d7540e5cd9af85fa75caa0b510bc08c5342" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.1", + "pin-project-lite", +] + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +dependencies = [ + "cfg-if", + "libc", + "libredox", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "font-types" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.20.0", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.25.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "freetype-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand 2.4.1", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-ash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbda7a18a29bc98c2e0de0435c347df935bf59489935d0cbd0b73f1679b6f79a" +dependencies = [ + "ash", + "gpu-alloc-types", + "tinyvec", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "gpui" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "979b45cfa6ec723b6f42330915a1b3769b930d02b2d505f9697f8ca602bee707" +dependencies = [ + "anyhow", + "as-raw-xcb-connection", + "ashpd 0.11.1", + "async-task", + "bindgen", + "blade-graphics", + "blade-macros", + "blade-util", + "block", + "bytemuck", + "calloop", + "calloop-wayland-source", + "cbindgen", + "cocoa 0.26.0", + "cocoa-foundation 0.2.0", + "core-foundation 0.10.0", + "core-foundation-sys", + "core-graphics 0.24.0", + "core-text", + "core-video", + "cosmic-text", + "ctor", + "derive_more", + "embed-resource", + "etagere", + "filedescriptor", + "flume", + "foreign-types", + "futures", + "gpui-macros", + "gpui_collections", + "gpui_http_client", + "gpui_media", + "gpui_refineable", + "gpui_semantic_version", + "gpui_sum_tree", + "gpui_util", + "gpui_util_macros", + "image", + "inventory", + "itertools 0.14.0", + "libc", + "log", + "lyon", + "metal", + "naga", + "num_cpus", + "objc", + "oo7", + "open", + "parking", + "parking_lot", + "pathfinder_geometry", + "pin-project", + "postage", + "profiling", + "rand 0.9.4", + "raw-window-handle", + "resvg", + "schemars", + "seahash", + "serde", + "serde_json", + "slotmap", + "smallvec", + "smol", + "stacksafe", + "strum 0.27.2", + "taffy", + "thiserror 2.0.18", + "usvg", + "uuid", + "waker-fn", + "wayland-backend", + "wayland-client", + "wayland-cursor", + "wayland-protocols 0.31.2", + "wayland-protocols-plasma", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-numerics", + "windows-registry 0.5.3", + "x11-clipboard", + "x11rb", + "xkbcommon", + "zed-font-kit", + "zed-scap", + "zed-xim", +] + +[[package]] +name = "gpui-component" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d021d46b4088d3d93a57ccdf443da85695a77272108caca2f6fe5369f584966a" +dependencies = [ + "aho-corasick", + "anyhow", + "chrono", + "core-text", + "enum-iterator", + "gpui", + "gpui-component-macros", + "gpui-macros", + "html5ever", + "itertools 0.13.0", + "lsp-types", + "markdown", + "markup5ever_rcdom", + "notify", + "num-traits", + "once_cell", + "paste", + "regex", + "ropey", + "rust-i18n", + "schemars", + "serde", + "serde_json", + "serde_repr", + "smallvec", + "smol", + "tracing", + "tree-sitter", + "tree-sitter-json", + "unicode-segmentation", + "uuid", + "zed-sum-tree", +] + +[[package]] +name = "gpui-component-macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fbc2d84bf91717b171320e6adc600d91ccb3ed259448f3b006787633c1c615" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "gpui-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcb02dd63a2859714ac7b6b476937617c3c744157af1b49f7c904023a79039be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "gpui_collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae39dc6d3d201be97e4bc08d96dbef2bc5b5c3d5734e05786e8cc3043342351c" +dependencies = [ + "indexmap", + "rustc-hash 2.1.2", +] + +[[package]] +name = "gpui_derive_refineable" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644de174341a87b3478bd65b66bca38af868bcf2b2e865700523734f83cfc664" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "gpui_http_client" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23822b0a6d2c5e6a42507980a0ab3848610ea908942c8ef98187f646f690335e" +dependencies = [ + "anyhow", + "async-compression", + "async-fs", + "bytes", + "derive_more", + "futures", + "gpui_util", + "http", + "http-body", + "log", + "parking_lot", + "serde", + "serde_json", + "sha2", + "tempfile", + "url", + "zed-async-tar", + "zed-reqwest", +] + +[[package]] +name = "gpui_media" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cb8912ae17371725132d2b7eec6797a255accc95d58ee5c1134b529810f14b" +dependencies = [ + "anyhow", + "bindgen", + "core-foundation 0.10.0", + "core-video", + "ctor", + "foreign-types", + "metal", + "objc", +] + +[[package]] +name = "gpui_perf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40a0961dcf598955130e867f4b731150a20546427b41b1a63767c1037a86d77" +dependencies = [ + "gpui_collections", + "serde", + "serde_json", +] + +[[package]] +name = "gpui_refineable" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258cb099254e9468181aee5614410fba61db4ae115fc1d51b4a0b985f60d6641" +dependencies = [ + "gpui_derive_refineable", +] + +[[package]] +name = "gpui_semantic_version" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201e45eff7b695528fb3af6560a534943fbc2db5323d755b9d198bd743948e35" +dependencies = [ + "anyhow", + "serde", +] + +[[package]] +name = "gpui_sum_tree" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4f3bedd573fafafa13d1200b356c588cf094fb2786e3684bb3f5ea59b549fa9" +dependencies = [ + "arrayvec", + "log", + "rayon", +] + +[[package]] +name = "gpui_util" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68faea25903ae524de9af83990b9aa51bcbc8dd085929ac0aea7fd41905e05c3" +dependencies = [ + "anyhow", + "async-fs", + "async_zip", + "command-fds", + "dirs 4.0.0", + "dunce", + "futures", + "futures-lite 1.13.0", + "globset", + "gpui_collections", + "itertools 0.14.0", + "libc", + "log", + "nix 0.29.0", + "regex", + "rust-embed", + "schemars", + "serde", + "serde_json", + "serde_json_lenient", + "shlex", + "smol", + "take-until", + "tempfile", + "tendril", + "unicase", + "walkdir", + "which", +] + +[[package]] +name = "gpui_util_macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c28f65ef47fb97e21e82fd4dd75ccc2506eda010c846dc8054015ea234f1a22" +dependencies = [ + "gpui_perf", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "grid" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12101ecc8225ea6d675bc70263074eab6169079621c2186fe0c66590b2df9681" + +[[package]] +name = "h2" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hidden-trait" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ed9e850438ac849bec07e7d09fbe9309cbd396a5988c30b010580ce08860df" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imagesize" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" + +[[package]] +name = "imgref" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "inotify" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[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.117", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "io-surface" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554b8c5d64ec09a3a520fe58e4d48a73e00ff32899cdcbe32a4877afd4968b8e" +dependencies = [ + "cgl", + "core-foundation 0.10.0", + "core-foundation-sys", + "leaky-cow", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", +] + +[[package]] +name = "kqueue" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b65860415f949f23fa882e669f2dbd4a0f0eeb1acdd56790b30494afd7da2f" +dependencies = [ + "bitflags 2.11.1", + "libc", +] + +[[package]] +name = "kurbo" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leak" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" + +[[package]] +name = "leaky-cow" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" +dependencies = [ + "leak", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "bitflags 2.11.1", + "libc", + "plain", + "redox_syscall 0.7.5", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +dependencies = [ + "serde_core", + "value-bag", +] + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "lsp-types" +version = "0.97.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53353550a17c04ac46c585feb189c2db82154fc84b79c7a66c96c2c644f66071" +dependencies = [ + "bitflags 1.3.2", + "fluent-uri", + "serde", + "serde_json", + "serde_repr", +] + +[[package]] +name = "lyon" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0578bdecb7d6d88987b8b2b1e3a4e2f81df9d0ece1078623324a567904e7b7" +dependencies = [ + "lyon_algorithms", + "lyon_tessellation", +] + +[[package]] +name = "lyon_algorithms" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8575c0d003ae459399623c4def180c63b77f343b1a7fee64f249b349e7699a31" +dependencies = [ + "lyon_path", + "num-traits", +] + +[[package]] +name = "lyon_geom" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4336502e29e32af93cf2dad2214ed6003c17ceb5bd499df77b1de663b9042b92" +dependencies = [ + "arrayvec", + "euclid", + "num-traits", +] + +[[package]] +name = "lyon_path" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c463f9c428b7fc5ec885dcd39ce4aa61e29111d0e33483f6f98c74e89d8621e" +dependencies = [ + "lyon_geom", + "num-traits", +] + +[[package]] +name = "lyon_tessellation" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e43b7e44161571868f5c931d12583592c223c5583eef86b08aa02b7048a3552" +dependencies = [ + "float_next_after", + "lyon_path", + "num-traits", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markdown" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5cab8f2cadc416a82d2e783a1946388b31654d391d1c7d92cc1f03e295b1deb" +dependencies = [ + "unicode-id", +] + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf", + "phf_codegen", + "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", + "markup5ever", + "tendril", + "xml5ever", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-graphics-types 0.1.3", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "25.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b977c445f26e49757f9aca3631c3b8b836942cb278d69a92e7b80d3b24da632" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.1", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.15.5", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "strum 0.26.3", + "thiserror 2.0.18", + "unicode-ident", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "normpath" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9985ef7269fa99f3b12437bb698381da2428743ab90f20393f399fa14cab21a" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "notify" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" +dependencies = [ + "bitflags 2.11.1", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.52.0", +] + +[[package]] +name = "notify-types" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" +dependencies = [ + "instant", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.6", + "serde", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +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 = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.1", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oo7" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3299dd401feaf1d45afd8fd1c0586f10fcfb22f244bb9afa942cec73503b89d" +dependencies = [ + "aes", + "ashpd 0.12.3", + "async-fs", + "async-io", + "async-lock", + "blocking", + "cbc", + "cipher", + "digest", + "endi", + "futures-lite 2.6.1", + "futures-util", + "getrandom 0.3.4", + "hkdf", + "hmac", + "md-5", + "num", + "num-bigint-dig", + "pbkdf2", + "rand 0.9.4", + "serde", + "sha2", + "subtle", + "zbus", + "zbus_macros", + "zeroize", + "zvariant", +] + +[[package]] +name = "open" +version = "5.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3bab717c29a857abf75fcef718d441ec7cb2725f937343c734740a985d37fd" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pathfinder_geometry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" +dependencies = [ + "log", + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_simd" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4500030c302e4af1d423f36f3b958d1aecb6c04184356ed5a833bf6b60435777" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.6", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand 2.4.1", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + +[[package]] +name = "postage" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1" +dependencies = [ + "atomic", + "crossbeam-queue", + "futures", + "log", + "parking_lot", + "pin-project", + "pollster", + "static_assertions", + "thiserror 1.0.69", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.11+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "psm" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" +dependencies = [ + "ar_archive_writer", + "cc", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[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.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721da970c312655cde9b4ffe0547f20a8494866a4af5ff51f18b7c633d0c870b" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.2", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.14.0", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1" +dependencies = [ + "cocoa 0.25.0", + "core-graphics 0.23.2", + "objc", + "raw-window-handle", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "redox_syscall" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "resvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" +dependencies = [ + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", +] + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ropey" +version = "2.0.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4045a00dc327d084a2bbf126976e14125b54f23bd30511d45b842eba76c52d74" +dependencies = [ + "str_indices", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "rust-embed" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.117", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1" +dependencies = [ + "globset", + "sha2", + "walkdir", +] + +[[package]] +name = "rust-i18n" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332" +dependencies = [ + "globwalk", + "once_cell", + "regex", + "rust-i18n-macro", + "rust-i18n-support", + "smallvec", +] + +[[package]] +name = "rust-i18n-macro" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965" +dependencies = [ + "glob", + "once_cell", + "proc-macro2", + "quote", + "rust-i18n-support", + "serde", + "serde_json", + "serde_yaml", + "syn 2.0.117", +] + +[[package]] +name = "rust-i18n-support" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19" +dependencies = [ + "arc-swap", + "base62", + "globwalk", + "itertools 0.11.0", + "lazy_static", + "normpath", + "once_cell", + "proc-macro2", + "regex", + "serde", + "serde_json", + "serde_yaml", + "siphasher", + "toml 0.8.23", + "triomphe", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rustybuzz" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +dependencies = [ + "bitflags 2.11.1", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.21.1", + "unicode-bidi-mirroring 0.2.0", + "unicode-ccc 0.2.0", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "rustybuzz" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" +dependencies = [ + "bitflags 2.11.1", + "bytemuck", + "core_maths", + "log", + "smallvec", + "ttf-parser 0.25.1", + "unicode-bidi-mirroring 0.4.0", + "unicode-ccc 0.4.0", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "indexmap", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.117", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "screencapturekit" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5eeeb57ac94960cfe5ff4c402be6585ae4c8d29a2cf41b276048c2e849d64e" +dependencies = [ + "screencapturekit-sys", +] + +[[package]] +name = "screencapturekit-sys" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22411b57f7d49e7fe08025198813ee6fd65e1ee5eff4ebc7880c12c82bde4c60" +dependencies = [ + "block", + "dispatch", + "objc", + "objc-foundation", + "objc_id", + "once_cell", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.10.0", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_fmt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e497af288b3b95d067a23a4f749f2861121ffcb2f6d8379310dcda040c345ed" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_json_lenient" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e033097bf0d2b59a62b42c18ebbb797503839b26afdda2c4e1415cb6c813540" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simplecss" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite 2.6.1", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stacker" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.61.2", +] + +[[package]] +name = "stacksafe" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9c1172965d317e87ddb6d364a040d958b40a1db82b6ef97da26253a8b3d090" +dependencies = [ + "stacker", + "stacksafe-macro", +] + +[[package]] +name = "stacksafe-macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172175341049678163e979d9107ca3508046d4d2a7c6682bee46ac541b17db69" +dependencies = [ + "proc-macro-error2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str_indices" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros 0.27.2", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.117", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "sval" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb9318255ebd817902d7e279d8f8e39b35b1b9954decd5eb9ea0e30e5fd2b6a" + +[[package]] +name = "sval_buffer" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12571299185e653fdb0fbfe36cd7f6529d39d4e747a60b15a3f34574b7b97c61" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39526f24e997706c0de7f03fb7371f7f5638b66a504ded508e20ad173d0a3677" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "933dd3bb26965d682280fcc49400ac2a05036f4ee1e6dbd61bf8402d5a5c3a54" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0cda08f6d5c9948024a6551077557b1fdcc3880ff2f20ae839667d2ec2d87ed" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d49d5e6c1f9fd0e53515819b03a97ca4eb1bff5c8ee097c43391c09ecfb19f" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f876c5a78405375b4e19cbb9554407513b59c93dea12dc6a4af4e1d30899ca" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9ccd3b7f7200239a655e517dd3fd48d960b9111ad24bd6a5e055bef17607c7" +dependencies = [ + "serde_core", + "sval", + "sval_nested", +] + +[[package]] +name = "svg_fmt" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" + +[[package]] +name = "svgtypes" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" +dependencies = [ + "kurbo", + "siphasher", +] + +[[package]] +name = "swash" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842f3cd369c2ba38966204f983eaa5e54a8e84a7d7159ed36ade2b6c335aae64" +dependencies = [ + "skrifa", + "yazi", + "zeno", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "taffy" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13e5d13f79d558b5d353a98072ca8ca0e99da429467804de959aa8c83c9a004" +dependencies = [ + "arrayvec", + "grid", + "serde", + "slotmap", +] + +[[package]] +name = "take-until" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bdb6fa0dfa67b38c1e66b7041ba9dcf23b99d8121907cd31c807a332f7a0bbb" + +[[package]] +name = "tao-core-video-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271450eb289cb4d8d0720c6ce70c72c8c858c93dd61fc625881616752e6b98f6" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "objc", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand 2.4.1", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[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 = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png 0.17.16", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.52.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.2", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.2", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tree-sitter" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" +dependencies = [ + "cc", + "regex", + "regex-syntax", + "serde_json", + "streaming-iterator", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-json" +version = "0.24.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d727acca406c0020cffc6cf35516764f36c8e3dc4408e5ebe2cb35a947ec471" +dependencies = [ + "cc", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-language" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" + +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +dependencies = [ + "arc-swap", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" + +[[package]] +name = "unicode-ccc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" + +[[package]] +name = "unicode-ccc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" + +[[package]] +name = "unicode-id" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ba288e709927c043cbe476718d37be306be53fb1fafecd0dbe36d072be2580" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-script" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "usvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb 0.23.0", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree", + "rustybuzz 0.20.1", + "simplecss", + "siphasher", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "serde_core", + "sha1_smol", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16530907bfe2999a1773ca5900a65101e092c70f642f25cc23ca0c43573262c5" +dependencies = [ + "erased-serde", + "serde_core", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00ae130edd690eaa877e4f40605d534790d1cf1d651e7685bd6a144521b251f" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.11.1", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.31.2", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml 0.39.3", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix 0.38.44", + "winsafe", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-capture" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4df73e95feddb9ec1a7e9c2ca6323b8c97d5eeeff78d28f1eccdf19c882b24" +dependencies = [ + "parking_lot", + "rayon", + "thiserror 2.0.18", + "windows 0.61.3", + "windows-future", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result 0.3.4", + "windows-strings 0.3.1", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "workspace-hack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beffa227304dbaea3ad6a06ac674f9bc83a3dec3b7f63eeb442de37e7cb6bb01" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-clipboard" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3" +dependencies = [ + "libc", + "x11rb", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "rustix 1.1.4", + "x11rb-protocol", + "xcursor", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + +[[package]] +name = "xcb" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" +dependencies = [ + "bitflags 1.3.2", + "libc", + "quick-xml 0.30.0", + "x11", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xim-ctext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac61a7062c40f3c37b6e82eeeef835d5cc7824b632a72784a89b3963c33284c" +dependencies = [ + "encoding_rs", +] + +[[package]] +name = "xim-parser" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcee45f89572d5a65180af3a84e7ddb24f5ea690a6d3aa9de231281544dd7b7" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "xkbcommon" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" +dependencies = [ + "as-raw-xcb-connection", + "libc", + "memmap2", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml5ever" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69" +dependencies = [ + "log", + "mac", + "markup5ever", +] + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yazi" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" + +[[package]] +name = "yeslogic-fontconfig-sys" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8b8abf912b9a29ff112e1671c97c33636903d13a69712037190e6805af4f76" +dependencies = [ + "dlib", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener 5.4.1", + "futures-core", + "futures-lite 2.6.1", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.4", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.2", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" +dependencies = [ + "serde", + "winnow 1.0.2", + "zvariant", +] + +[[package]] +name = "zed-async-tar" +version = "0.5.0-zed" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cf4b5f655e29700e473cb1acd914ab112b37b62f96f7e642d5fc6a0c02eb881" +dependencies = [ + "async-std", + "filetime", + "libc", + "pin-project", + "redox_syscall 0.2.16", + "xattr", +] + +[[package]] +name = "zed-font-kit" +version = "0.14.1-zed" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3898e450f36f852edda72e3f985c34426042c4951790b23b107f93394f9bff5" +dependencies = [ + "bitflags 2.11.1", + "byteorder", + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "core-text", + "dirs 5.0.1", + "dwrote", + "float-ord", + "freetype-sys", + "lazy_static", + "libc", + "log", + "pathfinder_geometry", + "pathfinder_simd", + "walkdir", + "winapi", + "yeslogic-fontconfig-sys", +] + +[[package]] +name = "zed-reqwest" +version = "0.12.15-zed" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2d05756ff48539950c3282ad7acf3817ad3f08797c205ad1c34a2ce03b9970" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-socks", + "tokio-util", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry 0.4.0", +] + +[[package]] +name = "zed-scap" +version = "0.0.8-zed" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b338d705ae33a43ca00287c11129303a7a0aa57b101b72a1c08c863f698ac8" +dependencies = [ + "anyhow", + "cocoa 0.25.0", + "core-graphics-helmer-fork", + "log", + "objc", + "rand 0.8.6", + "screencapturekit", + "screencapturekit-sys", + "sysinfo", + "tao-core-video-sys", + "windows 0.61.3", + "windows-capture", + "x11", + "xcb", +] + +[[package]] +name = "zed-sum-tree" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d490156d0d7311855564d6e1d6dccab992405a0c0e15e1c8ef18920c02177e35" +dependencies = [ + "arrayvec", + "log", + "rayon", + "workspace-hack", +] + +[[package]] +name = "zed-xim" +version = "0.4.0-zed" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0b46ed118eba34d9ba53d94ddc0b665e0e06a2cf874cfa2dd5dec278148642" +dependencies = [ + "ahash", + "hashbrown 0.14.5", + "log", + "x11rb", + "xim-ctext", + "xim-parser", +] + +[[package]] +name = "zeno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[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.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" +dependencies = [ + "endi", + "enumflags2", + "serde", + "url", + "winnow 1.0.2", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.117", + "winnow 1.0.2", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cddbf9b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,33 @@ +[workspace] +members = [ + "crates/ely_app", + "crates/ely_browser_core", + "crates/ely_design_system", + "crates/ely_domain", + "crates/ely_servo_host", +] +resolver = "2" + +[workspace.package] +edition = "2024" +license = "Apache-2.0" +rust-version = "1.95" + +[workspace.dependencies] +gpui = "0.2.2" +gpui-component = "0.5.1" +thiserror = "2.0.12" +url = "2.5.4" +uuid = { version = "1.12.1", features = ["v7"] } + +[workspace.lints.rust] +unsafe_code = "deny" + +[workspace.lints.clippy] +dbg_macro = "deny" +todo = "deny" +unwrap_used = "deny" +expect_used = "deny" +panic = "deny" +large_futures = "warn" +large_stack_frames = "warn" diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..7d598b0 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,537 @@ +--- +version: alpha +name: Cursor +description: An AI-first code editor whose marketing site reads like a quietly-confident developer-tools brand with a warm-cream editorial canvas (`#f7f7f4`) instead of the typical dark IDE atmosphere. Near-black warm ink (`#26251e`) carries body and display alike — display sits at weight 400 with negative letter-spacing for a magazine feel rather than a bold tech voice. The single brand voltage is **Cursor Orange** (`#f54e00`) reserved for primary CTAs and the wordmark. A signature pastel timeline palette (peach, mint, blue, lavender, gold) marks AI-action stages (Thinking / Reading / Editing / Grepping / Done) — only inside in-product timeline visualizations. Cards use minimal hairlines, no shadows, generous 80px section rhythm. CursorGothic for display/body, JetBrains Mono on every code surface (which is roughly half the page). + +colors: + primary: "#f54e00" + primary-active: "#d04200" + ink: "#26251e" + body: "#5a5852" + body-strong: "#26251e" + muted: "#807d72" + muted-soft: "#a09c92" + hairline: "#e6e5e0" + hairline-soft: "#efeee8" + hairline-strong: "#cfcdc4" + canvas: "#f7f7f4" + canvas-soft: "#fafaf7" + surface-card: "#ffffff" + surface-strong: "#e6e5e0" + on-primary: "#ffffff" + timeline-thinking: "#dfa88f" + timeline-grep: "#9fc9a2" + timeline-read: "#9fbbe0" + timeline-edit: "#c0a8dd" + timeline-done: "#c08532" + semantic-error: "#cf2d56" + semantic-success: "#1f8a65" + +typography: + display-mega: + fontFamily: "'CursorGothic', system-ui, 'Helvetica Neue', Helvetica, Arial, sans-serif" + fontSize: 72px + fontWeight: 400 + lineHeight: 1.1 + letterSpacing: -2.16px + display-lg: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 36px + fontWeight: 400 + lineHeight: 1.2 + letterSpacing: -0.72px + display-md: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 26px + fontWeight: 400 + lineHeight: 1.25 + letterSpacing: -0.325px + display-sm: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 22px + fontWeight: 400 + lineHeight: 1.3 + letterSpacing: -0.11px + title-md: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 18px + fontWeight: 600 + lineHeight: 1.4 + letterSpacing: 0 + title-sm: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 16px + fontWeight: 600 + lineHeight: 1.4 + letterSpacing: 0 + body-md: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 16px + fontWeight: 400 + lineHeight: 1.5 + letterSpacing: 0 + body-tracked: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 16px + fontWeight: 400 + lineHeight: 1.5 + letterSpacing: 0.08px + body-sm: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 14px + fontWeight: 400 + lineHeight: 1.5 + letterSpacing: 0 + caption: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 13px + fontWeight: 400 + lineHeight: 1.4 + letterSpacing: 0 + caption-uppercase: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 11px + fontWeight: 600 + lineHeight: 1.4 + letterSpacing: 0.88px + textTransform: uppercase + code: + fontFamily: "'JetBrains Mono', 'Fira Code', monospace" + fontSize: 13px + fontWeight: 400 + lineHeight: 1.5 + letterSpacing: 0 + button: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 14px + fontWeight: 500 + lineHeight: 1.0 + letterSpacing: 0 + nav-link: + fontFamily: "'CursorGothic', sans-serif" + fontSize: 14px + fontWeight: 500 + lineHeight: 1.4 + letterSpacing: 0 + +rounded: + none: 0px + xs: 4px + sm: 6px + md: 8px + lg: 12px + xl: 16px + pill: 9999px + full: 9999px + +spacing: + xxs: 4px + xs: 8px + sm: 12px + base: 16px + md: 20px + lg: 24px + xl: 32px + xxl: 48px + section: 80px + +components: + top-nav: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + typography: "{typography.nav-link}" + height: 64px + button-primary: + backgroundColor: "{colors.primary}" + textColor: "{colors.on-primary}" + typography: "{typography.button}" + rounded: "{rounded.md}" + padding: 10px 18px + height: 40px + button-primary-active: + backgroundColor: "{colors.primary-active}" + textColor: "{colors.on-primary}" + rounded: "{rounded.md}" + button-secondary: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.button}" + rounded: "{rounded.md}" + padding: 9px 17px + height: 40px + button-tertiary-text: + backgroundColor: transparent + textColor: "{colors.ink}" + typography: "{typography.button}" + button-download: + backgroundColor: "{colors.ink}" + textColor: "{colors.canvas}" + typography: "{typography.button}" + rounded: "{rounded.md}" + padding: 12px 20px + height: 44px + hero-band: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + typography: "{typography.display-mega}" + padding: 80px + ide-mockup-card: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + rounded: "{rounded.lg}" + padding: 0 + ide-pane: + backgroundColor: "{colors.canvas-soft}" + textColor: "{colors.body}" + typography: "{typography.code}" + rounded: "{rounded.md}" + padding: 16px + feature-card: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.title-md}" + rounded: "{rounded.lg}" + padding: 24px + comparison-card: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.body-md}" + rounded: "{rounded.lg}" + padding: 24px + timeline-pill-thinking: + backgroundColor: "{colors.timeline-thinking}" + textColor: "{colors.ink}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + timeline-pill-grep: + backgroundColor: "{colors.timeline-grep}" + textColor: "{colors.ink}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + timeline-pill-read: + backgroundColor: "{colors.timeline-read}" + textColor: "{colors.ink}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + timeline-pill-edit: + backgroundColor: "{colors.timeline-edit}" + textColor: "{colors.ink}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + timeline-pill-done: + backgroundColor: "{colors.timeline-done}" + textColor: "{colors.on-primary}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + code-block: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.code}" + rounded: "{rounded.lg}" + padding: 20px + pricing-tier-card: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.body-md}" + rounded: "{rounded.lg}" + padding: 32px + pricing-tier-featured: + backgroundColor: "{colors.ink}" + textColor: "{colors.canvas}" + typography: "{typography.body-md}" + rounded: "{rounded.lg}" + padding: 32px + text-input: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.ink}" + typography: "{typography.body-md}" + rounded: "{rounded.md}" + padding: 12px 16px + height: 44px + badge-pill: + backgroundColor: "{colors.surface-strong}" + textColor: "{colors.ink}" + typography: "{typography.caption-uppercase}" + rounded: "{rounded.pill}" + padding: 4px 10px + cta-band: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + typography: "{typography.display-lg}" + padding: 96px + testimonial-card: + backgroundColor: "{colors.surface-card}" + textColor: "{colors.body}" + typography: "{typography.body-md}" + rounded: "{rounded.lg}" + padding: 24px + footer: + backgroundColor: "{colors.canvas}" + textColor: "{colors.body}" + typography: "{typography.body-sm}" + padding: 64px 48px + footer-link: + backgroundColor: transparent + textColor: "{colors.body}" + typography: "{typography.body-sm}" +--- + +## Overview + +Cursor's marketing site reads as a quietly-confident developer brand that believes in editorial calm over IDE-darkness. The base canvas is **warm cream** (`{colors.canvas}` — #f7f7f4) holding warm near-black ink (`{colors.ink}` — #26251e) for body and display alike. The single brand voltage is **Cursor Orange** (`{colors.primary}` — #f54e00) reserved for primary CTAs and the wordmark — used scarcely. + +Type runs **CursorGothic** as the single sans family. Display sits at weight 400 with negative letter-spacing — a magazine-editorial voice rather than tech-bombastic. JetBrains Mono carries every code surface (and code surfaces are roughly half the page). + +The brand's strongest visual signature is the **AI-timeline pill palette**: five pastel pills (peach `{colors.timeline-thinking}`, mint `{colors.timeline-grep}`, blue `{colors.timeline-read}`, lavender `{colors.timeline-edit}`, gold `{colors.timeline-done}`) marking AI-action stages inside in-product timeline visualizations. Used only in product UI — never as system action colors. + +**Key Characteristics:** +- Warm cream canvas, not white. Ink is warm (#26251e), not pure black. +- Single CTA color: `{colors.primary}` (Cursor Orange #f54e00). Used scarcely. +- Display weight stays at 400 — never bold. Magazine voice. +- AI timeline pastels: 5 dedicated tokens for in-product agent action stages. +- Compact 8px CTA radius — developer dialect. +- Hairline-only depth; no drop shadows. +- 80px section rhythm. + +## Colors + +### Brand & Accent +- **Cursor Orange** (`{colors.primary}` — #f54e00): Primary CTA pills, wordmark, hero accent. Used scarcely. +- **Cursor Orange Active** (`{colors.primary-active}` — #d04200): Press state. + +### Surface +- **Canvas** (`{colors.canvas}` — #f7f7f4): Warm cream page floor. +- **Canvas Soft** (`{colors.canvas-soft}` — #fafaf7): IDE-pane background inside mockups. +- **Surface Card** (`{colors.surface-card}` — #ffffff): Pure white card surface — slight contrast against the cream canvas. +- **Surface Strong** (`{colors.surface-strong}` — #e6e5e0): Badges, tag pills. + +### Hairlines +- **Hairline** (`{colors.hairline}` — #e6e5e0): 1px divider. +- **Hairline Soft** (`{colors.hairline-soft}` — #efeee8): Lighter divider. +- **Hairline Strong** (`{colors.hairline-strong}` — #cfcdc4): Stronger panel outline. + +### Text +- **Ink** (`{colors.ink}` — #26251e): Display, body emphasis. Warm near-black. +- **Body** (`{colors.body}` — #5a5852): Default running-text. +- **Body Strong** (`{colors.body-strong}` — #26251e): Same as ink. +- **Muted** (`{colors.muted}` — #807d72): Sub-titles. +- **Muted Soft** (`{colors.muted-soft}` — #a09c92): Disabled text. +- **On Primary** (`{colors.on-primary}` — #ffffff): White text on Cursor Orange. + +### Timeline (AI-action signature) +- **Thinking** (`{colors.timeline-thinking}` — #dfa88f): Peach. Used inside in-product agent timeline only. +- **Grep** (`{colors.timeline-grep}` — #9fc9a2): Mint. +- **Read** (`{colors.timeline-read}` — #9fbbe0): Pastel blue. +- **Edit** (`{colors.timeline-edit}` — #c0a8dd): Lavender. +- **Done** (`{colors.timeline-done}` — #c08532): Warm gold. + +### Semantic +- **Success** (`{colors.semantic-success}` — #1f8a65): Confirmation indicators. +- **Error** (`{colors.semantic-error}` — #cf2d56): Validation errors. + +## Typography + +### Font Family +**CursorGothic** is the licensed display + body family. Fallback: `system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif`. Code surfaces switch to **JetBrains Mono**. + +### Hierarchy + +| Token | Size | Weight | Line Height | Letter Spacing | Use | +|---|---|---|---|---|---| +| `{typography.display-mega}` | 72px | 400 | 1.1 | -2.16px | Homepage hero h1 | +| `{typography.display-lg}` | 36px | 400 | 1.2 | -0.72px | Section heads | +| `{typography.display-md}` | 26px | 400 | 1.25 | -0.325px | Sub-section heads | +| `{typography.display-sm}` | 22px | 400 | 1.3 | -0.11px | Card group titles | +| `{typography.title-md}` | 18px | 600 | 1.4 | 0 | Component titles | +| `{typography.title-sm}` | 16px | 600 | 1.4 | 0 | List labels | +| `{typography.body-md}` | 16px | 400 | 1.5 | 0 | Default body | +| `{typography.body-tracked}` | 16px | 400 | 1.5 | 0.08px | Tracked editorial body | +| `{typography.body-sm}` | 14px | 400 | 1.5 | 0 | Footer body | +| `{typography.caption}` | 13px | 400 | 1.4 | 0 | Photo captions | +| `{typography.caption-uppercase}` | 11px | 600 | 1.4 | 0.88px | Section labels, timeline pill labels | +| `{typography.code}` | 13px | 400 | 1.5 | 0 | Code blocks — JetBrains Mono | +| `{typography.button}` | 14px | 500 | 1.0 | 0 | CTA pill labels | +| `{typography.nav-link}` | 14px | 500 | 1.4 | 0 | Top-nav menu | + +### Principles +- **Display weight stays at 400.** Magazine voice, never bold. +- **Negative letter-spacing on display only.** -0.11px to -2.16px tracking. +- **JetBrains Mono on every code surface.** + +### Note on Font Substitutes +CursorGothic is licensed. Open-source substitute: **Inter** at weight 400 with letter-spacing -1.5%. Or **GT Sectra** for a more editorial feel. + +## Layout + +### Spacing System +- **Base unit:** 4px. +- **Tokens:** `{spacing.xxs}` 4px · `{spacing.xs}` 8px · `{spacing.sm}` 12px · `{spacing.base}` 16px · `{spacing.md}` 20px · `{spacing.lg}` 24px · `{spacing.xl}` 32px · `{spacing.xxl}` 48px · `{spacing.section}` 80px. +- **Section padding:** 80px. + +### Grid & Container +- Max content width: ~1200px. +- Editorial body: 12-column grid. +- Feature card grids: 2-up at desktop for splits, 3-up for benefits. +- Footer: 5-column at desktop. + +### Whitespace Philosophy +Generous editorial pacing — closer to a print magazine than a tech site. The cream canvas has plenty of breathing room; cards within bands sit close (16-24px gap). + +## Elevation & Depth + +The system uses **hairline-only depth**. No drop shadows, no elevation tiers. Cards float above the canvas via 1px hairlines and the slight white-on-cream contrast. + +| Level | Treatment | Use | +|---|---|---| +| Flat (canvas) | `{colors.canvas}` (#f7f7f4) | Body bands, footer | +| Card | `{colors.surface-card}` (#ffffff) | Content cards | +| Hairline border | 1px `{colors.hairline}` | Card outlines, dividers | +| IDE pane | `{colors.canvas-soft}` (#fafaf7) | Inside IDE mockup cards | + +### Decorative Depth +- **IDE-mockup cards** are the only "elevated" element. White card on cream canvas with internal pane structure mimicking the actual Cursor editor. +- **Timeline pastel pills** add chromatic depth without surface elevation. + +## Shapes + +### Border Radius Scale + +| Token | Value | Use | +|---|---|---| +| `{rounded.none}` | 0px | Reserved | +| `{rounded.xs}` | 4px | Inline tags | +| `{rounded.sm}` | 6px | Compact rows | +| `{rounded.md}` | 8px | CTA buttons, form inputs | +| `{rounded.lg}` | 12px | Cards, IDE panes | +| `{rounded.xl}` | 16px | Larger feature cards (rare) | +| `{rounded.pill}` | 9999px | Timeline pills, badges | +| `{rounded.full}` | 9999px | Avatars (rare) | + +## Components + +### Top Navigation + +**`top-nav`** — Background `{colors.canvas}`, text `{colors.ink}`, height 64px. Layout: Cursor wordmark left, primary horizontal menu (Pricing / Features / Enterprise / Blog / Forum / Careers), Sign In + Download primary CTA right. + +### Buttons + +**`button-primary`** — The signature Cursor Orange CTA. Background `{colors.primary}`, text `{colors.on-primary}`, type `{typography.button}` (14px / 500), padding 10px × 18px, height 40px, rounded `{rounded.md}` (8px). + +**`button-primary-active`** — Press state. Background `{colors.primary-active}`. + +**`button-secondary`** — White card pill on cream canvas. Background `{colors.surface-card}`, text `{colors.ink}`, 1px `{colors.hairline-strong}` border. + +**`button-tertiary-text`** — Inline ink text link. + +**`button-download`** — Larger ink-canvas CTA. Background `{colors.ink}`, text `{colors.canvas}`, padding 12px × 20px, height 44px. Used for "Download for macOS" type CTAs. + +### Hero & IDE Mockups + +**`hero-band`** — Background `{colors.canvas}`, full-width display headline in `{typography.display-mega}` (72px / 400 / -2.16px), subhead in `{typography.body-md}`, two CTAs (`button-download` + `button-tertiary-text`), and a centered IDE-mockup card below the hero copy. + +**`ide-mockup-card`** — A white card containing a multi-pane IDE mockup (sidebar + main editor + chat panel + terminal). Background `{colors.surface-card}`, rounded `{rounded.lg}` (12px), 1px `{colors.hairline}` border, no padding (panes fill the card edge-to-edge). + +**`ide-pane`** — Individual IDE pane inside the mockup. Background `{colors.canvas-soft}`, text `{colors.body}` in `{typography.code}` (JetBrains Mono 13px), rounded `{rounded.md}` (8px), padding 16px. + +### Cards + +**`feature-card`** — Background `{colors.surface-card}`, text `{colors.ink}`, type `{typography.title-md}`, rounded `{rounded.lg}`, padding 24px. 1px `{colors.hairline}` border. + +**`comparison-card`** — Side-by-side "Cursor vs other tools" card. Same surface and rounding; internally split into 2 columns. + +**`testimonial-card`** — Quote card. Background `{colors.surface-card}`, text `{colors.body}`, rounded `{rounded.lg}`, padding 24px. + +### AI Timeline (signature) + +**`timeline-pill-thinking`** — Peach pill. Background `{colors.timeline-thinking}`, text `{colors.ink}`, type `{typography.caption-uppercase}` (11px / 600 / 0.88px tracking, uppercase), rounded `{rounded.pill}`, padding 4px × 10px. Marks "Thinking" stage in product timeline. + +**`timeline-pill-grep`** — Mint pill. Same shape, background `{colors.timeline-grep}`. Marks "Grepping" stage. + +**`timeline-pill-read`** — Pastel-blue pill. Background `{colors.timeline-read}`. Marks "Reading" stage. + +**`timeline-pill-edit`** — Lavender pill. Background `{colors.timeline-edit}`. Marks "Editing" stage. + +**`timeline-pill-done`** — Gold pill. Background `{colors.timeline-done}`, text `{colors.on-primary}` white. Marks "Done" stage. + +### Code + +**`code-block`** — Inline code block. Background `{colors.surface-card}`, text `{colors.ink}` in `{typography.code}`, rounded `{rounded.lg}`, padding 20px, 1px `{colors.hairline}` border. + +### Pricing + +**`pricing-tier-card`** — Background `{colors.surface-card}`, rounded `{rounded.lg}`, padding 32px, 1px `{colors.hairline}` border. + +**`pricing-tier-featured`** — Featured tier inverts to ink. Background `{colors.ink}`, text `{colors.canvas}`. Same shape, dark inversion signals "highlighted" without colored ribbon. + +### Forms & Tags + +**`text-input`** — Background `{colors.surface-card}`, text `{colors.ink}`, rounded `{rounded.md}` (8px), padding 12px × 16px, height 44px. + +**`badge-pill`** — Small uppercase pill. Background `{colors.surface-strong}`, text `{colors.ink}`, type `{typography.caption-uppercase}`, rounded `{rounded.pill}`, padding 4px × 10px. + +### CTA / Footer + +**`cta-band`** — Pre-footer "Try Cursor now" band. Background `{colors.canvas}`, centered display headline in `{typography.display-lg}`, single Cursor Orange CTA. 96px vertical padding. + +**`footer`** — Closing footer. Background `{colors.canvas}`, text `{colors.body}`. 5-column link list. 64×48px padding. + +**`footer-link`** — Background transparent, text `{colors.body}`, type `{typography.body-sm}`. + +## Do's and Don'ts + +### Do +- Reserve `{colors.primary}` (Cursor Orange) for primary CTAs and brand wordmark. +- Keep display weight at 400. The editorial voice depends on this. +- Use the cream `{colors.canvas}` page floor — never pure white. +- Render every code surface (inline, blocks, IDE panes) in JetBrains Mono. +- Use timeline pastels only inside in-product agent visualizations — never as system action colors. + +### Don't +- Don't introduce a secondary brand action color. Cursor Orange is the only one. +- Don't drop display to bold weights (700+). Magazine voice depends on 400. +- Don't add drop shadows. Hairlines + ink-on-cream contrast carry the depth. +- Don't use timeline pastels on non-timeline UI. They're scoped to the agent timeline only. +- Don't extract a CTA color from a third-party widget (cookie consent, OneTrust). The brand's CTA is what appears on actual product CTAs. + +## Responsive Behavior + +### Breakpoints + +| Name | Width | Key Changes | +|---|---|---| +| Mobile | < 640px | Hero h1 72→32px; IDE mockup collapses to single pane preview; feature grid 1-up; nav hamburger. | +| Tablet | 640–1024px | Hero h1 56px; IDE mockup compresses; feature grid 2-up. | +| Desktop | 1024–1280px | Full hero h1 72px; full multi-pane IDE mockup; feature grid 3-up. | +| Wide | > 1280px | Content caps at 1200px. | + +### Touch Targets +- Primary CTA at 40px height — at WCAG AA, padded for AAA. +- Download CTA at 44px — at AAA. + +### Collapsing Strategy +- Top nav switches to hamburger below 768px. +- IDE mockup multi-pane collapses to a single primary pane preview on mobile. +- Feature grid: 3-up → 2-up → 1-up. + +## Iteration Guide + +1. Focus on a single component at a time. +2. CTAs default to `{rounded.md}` (8px). Cards use `{rounded.lg}` (12px). +3. Variants live as separate entries inside `components:`. +4. Use `{token.refs}` everywhere — never inline hex. +5. Hover state never documented. +6. CursorGothic 400 for display, 400/500/600 for body. JetBrains Mono on every code surface. +7. Cursor Orange stays scarce. +8. Timeline pastels stay scoped to in-product agent visualizations. + +## Known Gaps + +- CursorGothic is a licensed typeface; Inter is the substitute. +- Animation timings (timeline pill entrance, IDE pane reveal) out of scope. +- In-app surfaces (code editor, chat panel, agent timeline) only partially captured via marketing IDE mockups. +- Form validation states beyond focus not visible on captured surfaces. diff --git a/PRD.md b/PRD.md new file mode 100644 index 0000000..116849e --- /dev/null +++ b/PRD.md @@ -0,0 +1,1810 @@ +# PRD.md — ELY Browser by Elydora + +文档日期:2026-05-07 +状态:完整产品规格 +产品名称:ELY Browser +品牌归属:Elydora +产品形态:跨平台 Native Rust 桌面浏览器 +核心技术:Rust、GPUI、Servo WebView、gpui-component、awesome-gpui 生态组件 +云端基础设施:Cloudflare Workers、Cloudflare D1、Cloudflare R2、Cloudflare Workers KV、Better Auth +核心能力:垂直标签页、Spaces、Profiles、Split View、登录、端到端加密 Sync、自有插件系统、隐私与性能控制 +产品定位:clean browser;默认安静、界面克制、行为透明、数据可控 + +--- + +## 1. 产品结论 + +ELY Browser by Elydora 是一款纯净、快速、低打扰的 Native Rust 桌面浏览器。它以左侧垂直标签页作为默认信息架构,以 Spaces 承载任务上下文,以 Profiles 隔离账号、Cookie、历史与站点权限,以 Split View 支持同窗多网页并排工作,以端到端加密 Sync 保持多设备状态一致,以自有 `.rplug` Wasm 插件系统提供可审计、可撤销、可签名发布的扩展能力。 + +浏览器引擎使用 Servo。桌面 Shell 使用 GPUI。主组件库使用 gpui-component,并通过 awesome-gpui 生态中的 adabraka-ui、ferrum-flow、gpui-flow、gpui-form、gpui-hooks、gpui-nav、gpui-router、gpui-storybook、gpui-symbols、gpui-d3rs、gpui-px、gpui-video-player、plotters-gpui 完成完整桌面产品能力建设。 + +登录和 Sync 使用 Elydora Cloud,运行在 Cloudflare Workers。Better Auth 负责身份、账号、会话、OAuth、设备登录与会话安全;Cloudflare D1 负责结构化账号数据、设备索引、Sync 对象索引、变更日志、插件注册表元数据;Cloudflare R2 负责加密后的大对象、Sync 快照、头像、插件包、崩溃附件和导出文件;Cloudflare Workers KV 负责读多写少的全局配置、会话缓存、插件市场索引缓存、公开密钥缓存、更新清单缓存和短期同步游标缓存。 + +产品对标方向是 Zed 式 Native Rust/GPUI 高性能软件体验、Arc 的 Spaces / Profiles / Favorites / Split View / Auto Archive、Dia 的清爽任务表面与分屏入口、Zen Browser 的垂直标签与工作区、Vivaldi 的深度标签管理、Edge 与 Chrome 的主流化垂直标签体验。产品边界始终围绕 clean browser:界面克制、用户可控、隐私优先、插件安全、默认安静。 + +完整交付边界: + +- 桌面端 macOS、Windows、Linux 原生安装包、签名、自动更新、崩溃恢复。 +- Servo WebView 嵌入、导航、输入、缩放、截图、站点权限、下载、历史、书签、阅读模式、DevTools 入口。 +- 左侧垂直标签系统、Spaces、Profiles、Favorites、Pinned Tabs、Tab Groups、Split View、自动归档、会话恢复。 +- 登录、设备管理、端到端加密 Sync、本地加密数据库、冲突处理、离线可用。 +- 自有 `.rplug` 插件系统、Wasm Component Model、WIT 接口、权限弹窗、插件管理器、插件市场、签名发布、审计日志。 +- GPUI 设计系统、Storybook、设置中心、命令面板、键盘快捷键、菜单栏、托盘/通知、无障碍、国际化。 +- Cloudflare Workers API、Better Auth、D1 schema、R2 bucket、KV namespace、密钥轮换、备份、监控、限流。 +- 浏览器安全模型、隐私控制、遥测最小化、站点兼容性面板、性能任务管理器、发布验收矩阵。 + +本 PRD 只定义完整产品形态和完整实现要求。研发任务可以并行拆解,但产品规格本身保持单一完整交付边界。 + +--- + +## 2. Deep Research 依据 + +### 2.1 垂直标签页已经进入主流浏览器体验 + +Google Chrome 在 2026-04-07 发布的产品更新中推出“Show Tabs Vertically”,官方说明侧边标签可以读取完整页面标题并更容易管理标签组,尤其适合双位数标签场景。[R1] + +Microsoft Edge 官方将 Vertical Tabs 定义为让用户在侧边栏中更容易扫描、组织和管理大量标签页的功能,覆盖 Windows 与 macOS。[R2] + +Vivaldi 长期提供 Workspaces、Tab Stacks 与 Tab Tiling。官方说明 Workspaces 可以按类别分组标签和标签堆,Tab Tiling 可以把多个标签平铺到同一窗口内,减少反复切换。[R5][R6] + +结论:垂直标签本身已经成为主流浏览器能力。ELY 的差异需要落在“垂直标签 + 任务空间 + 隐私同步 + 原生性能 + 插件安全 + 低打扰体验”的组合上。 + +### 2.2 Arc、Dia、Zen、Vivaldi 的可采纳体验 + +Arc 的 Favorites 是跨所有 Spaces 常驻的顶部标签;Auto Archive 会按用户设置清理 idle unpinned tabs,并支持按 Profile 调整归档时机。[R3][R4] + +Vivaldi 的 Workspaces 让用户切换工作区时只看到该类别下的标签;Tab Tiling 支持垂直、水平、网格和自定义布局,并支持拖拽调整。[R5][R6] + +Dia 的产品体验可作为清爽任务表面和分屏入口的参考:导航区尽量轻,内容区优先,分屏操作应在当前任务中就地完成。ELY 采纳其布局克制和任务连续性,产品能力仍保持 clean browser 边界。 + +结论:ELY 的 clean 浏览体验需要把 Arc 的上下文模型、Dia 的低噪声表面、Zen 的侧栏优先和 Vivaldi 的深度标签管理统一成一套更克制的 Native Rust 桌面交互。 + +### 2.3 GPUI 与 Native Rust 桌面 Shell + +GPUI 官方定义为来自 Zed 创建者的快速、高生产力 Rust UI 框架;docs.rs 将 GPUI 描述为 hybrid immediate/retained mode、GPU accelerated 的 Rust UI 框架。[R7][R8] + +Zed 团队公开说明,Zed 以类似游戏渲染管线的方式使用 Rust 和 GPU 构建高响应 UI;这为 ELY 的浏览器 Shell 提供性能和交互基准。[R9] + +gpui-component 提供 60+ 跨平台桌面 UI 组件,包含虚拟化 Table/List、Dock 布局、主题系统、输入控件、弹窗、菜单等能力,适合作为浏览器设置页、侧栏、弹窗、列表、下载管理、历史记录、插件管理器的主组件库。[R10] + +awesome-gpui 收录了 GPUI 应用、组件库、路由、表单、Hooks、图表、Storybook、符号、视频播放器和 Plotters 后端等生态项目。指定库均可映射到浏览器的实际产品模块。[R11] + +结论:GPUI 承担原生 Shell,Servo 承担网页渲染,gpui-component 承担主要 UI 组件,awesome-gpui 生态补齐路由、表单、可视化、Storybook、图标、视频、图表与状态组织。 + +### 2.4 Servo 嵌入能力与约束 + +Servo 是 Rust 编写的 Web 渲染引擎,支持 WebGL/WebGPU,面向桌面、移动和嵌入式,并提供 WebView API 让应用嵌入 Web 内容。[R12] + +Servo 在 2026-04-13 发布 `servo` crate,官方说明这是第一个允许 Servo 作为 library 使用的 crates.io release,同时说明该 release 仍处在 `1.0` 前,embedding API 仍会演进,并提供 LTS 轨道承接安全修复与迁移指导。[R13] + +结论:ELY 需要把 Servo 当作浏览器引擎子系统集成。GPUI 与 Servo 之间需要专门的 WebView Host、输入桥、渲染桥、焦点桥、IME 桥、权限桥、下载桥和崩溃恢复桥。 + +### 2.5 Cloudflare + Better Auth 适合登录与 Sync 后端 + +Cloudflare D1 是托管 serverless SQL database,使用 SQLite 语义,支持 Workers 和 HTTP API 访问,并提供 Time Travel 与 read replication 能力。[R14] + +Cloudflare 官方数据产品说明中,D1 适合持久化、关系型用户数据和账号数据;R2 是 S3-compatible blob storage,适合大对象和静态资源,并提供 per-object strong consistency;Workers KV 是 eventually consistent 的低延迟键值存储,适合高读取量配置、会话和分布式配置。[R15] + +Workers KV 的一致性模型是 eventually consistent,跨地区可见性可能需要 60 秒或更久,因此 ELY 把 KV 用于缓存和读多写少数据,把 D1 作为结构化事实源,把 R2 作为加密大对象事实源。[R16] + +Better Auth 1.5 已将 Cloudflare D1 作为 first-class database option,允许直接传入 D1 binding;官方也说明 D1 不支持 interactive transactions,Better Auth 使用 D1 `batch()` API 处理原子性。[R17] + +第一版需要支持 Google,Github,Email OTP signin。 + +D1 当前单数据库上限为 Workers Paid 10 GB / Free 500 MB,账号级上限和数据库数量需要按 Cloudflare 限制设计;ELY 的 Sync schema 因此按账户、地区和对象类型预留拆分策略。[R18] + +结论:ELY Cloud 使用 Cloudflare Workers + Better Auth + D1/R2/KV 可覆盖登录、设备、安全会话、同步索引、加密对象存储、插件市场和发布资产,同时需要严格区分事实源、缓存和对象存储。 + +### 2.6 自有插件系统采用 Wasm Component Model + +WebAssembly Component Model 提供可移植、跨语言组合的组件架构,并使用 WIT 描述组件与 host 之间的接口;Wasmtime 提供 Component Model 嵌入 API。[R19][R20] + +Wasmtime 安全文档说明 WebAssembly 的目标之一是以沙箱方式运行不受信代码,Wasm 默认需要显式 import 才能获得 host 能力。[R21] + +结论:ELY 插件系统采用 `.rplug` 包、`plugin.toml` 清单、WIT 接口、Wasmtime Host、能力授权和签名发布。插件 API 完全由 ELY 定义,面向浏览器 UI、标签、书签、历史、下载、命令、侧栏、页面桥接和设置扩展。 + +--- + +## 3. 产品定位 + +### 3.1 目标用户 + +核心用户是长期依赖浏览器完成知识工作的人群,包括软件工程师、产品经理、设计师、研究人员、运营、创作者、学生和重度网页应用用户。共同特征是常开 20–200 个标签页,经常在项目、账号、文档、工具、资料之间切换,并需要低干扰、可恢复、可同步的浏览环境。 + +### 3.2 价值主张 + +用户通过左侧垂直工作台管理大量网页,通过 Spaces 将标签按任务上下文聚合,通过 Profiles 分离工作/个人/客户/项目账号,通过 Split View 在同一窗口并排处理资料,通过端到端加密 Sync 在多设备间恢复状态,通过自有插件系统扩展工作流,同时保持界面清爽、动作透明和数据可控。 + +### 3.3 产品原则 + +- Clean first:默认界面克制,空白、层级、动效、通知和入口数量受控。 +- Local first:标签、历史、书签、会话、设置、插件配置先写本地数据库,云端承担同步与备份。 +- Privacy first:Sync 数据端到端加密,遥测默认最小化,敏感数据使用系统钥匙串保存。 +- Keyboard first:核心浏览动作均可通过命令面板和快捷键完成。 +- Vertical first:垂直标签页是默认信息架构,顶部区域只保留地址栏、命令入口和必要状态。 +- Profile strict:Cookie、Storage、历史、权限、证书例外、下载策略按 Profile 明确隔离。 +- Plugin safe:插件通过显式权限、Wasm 沙箱、签名、审计、资源限额和可撤销授权运行。 +- Engine honest:Servo 兼容性以可见状态、反馈入口和站点诊断面板展示。 +- Desktop native:窗口、菜单、快捷键、拖拽、文件、通知、系统主题、IME 和无障碍遵循平台习惯。 + +--- + +## 4. 品牌与命名 + +产品正式名称为 ELY Browser by Elydora。界面中主名称使用 “ELY Browser”,品牌页、关于页、法律页和安装包发行方使用 “Elydora”。短名称使用 “ELY”。 + +命名规范: + +- App name:ELY Browser +- Company / brand:Elydora +- Short display name:ELY +- macOS bundle id:`com.elydora.ely-browser` +- Windows app id:`Elydora.ELYBrowser` +- Linux desktop id:`com.elydora.ely-browser.desktop` +- Sync service name:Elydora Cloud +- Plugin package suffix:`.rplug` +- Plugin registry name:Elydora Plugin Registry +- Protocol handler:`ely://` +- Auth callback:`ely://auth/callback` +- Plugin deep link:`ely://plugin/` +- Settings deep link:`ely://settings/
` + +视觉方向:ELY 使用冷静、轻量、低饱和的桌面应用气质。品牌表达偏专业,不使用过度拟物、重渐变和高频动效。默认主题遵循系统浅色/深色,允许用户设置 Space 级强调色。 + +--- + +## 5. 用户画像与关键场景 + +### 5.1 软件工程师 + +工程师在浏览器中频繁打开 GitHub、GitLab、Linear、Jira、文档、本地开发地址、日志平台和云控制台。浏览器需要把一个项目的所有网页放在同一 Space 中,并允许使用 Split View 同时查看本地页面、PR、接口文档和日志。 + +关键需求: + +- 每个项目一个 Space,每个客户或公司账号一个 Profile。 +- Localhost、PR、Issue、文档、Dashboard 可固定在同一 Space。 +- 地址栏支持命令、URL、书签、历史和打开标签搜索。 +- 标签支持按域名、项目、标题规则自动归组。 +- 下载、证书例外、站点权限与 Profile 绑定。 +- 插件可提供本地开发面板、API 收藏、Mock 切换、路由查看、日志链接解析。 + +### 5.2 产品经理 / 项目管理者 + +产品经理需要在任务系统、文档、表格、会议记录、设计稿和数据看板间切换。浏览器需要减少标签噪声,并保留每个项目上下文。 + +关键需求: + +- Space 支持图标、颜色、顺序、固定页、分组、自动归档。 +- Split View 支持文档 + 看板、需求 + 设计、表格 + 数据页。 +- 书签支持项目级集合,历史支持按 Space 过滤。 +- 同步可恢复其他设备上未完成的工作空间。 +- 插件可扩展项目看板入口、状态徽标、页面右键操作。 + +### 5.3 UI/UX 设计师 + +设计师需要浏览竞品、Figma、文档、原型、视频素材和评论。浏览器需要更好的分屏、截图、媒体预览和页面信息收集。 + +关键需求: + +- Split View 支持最多四个网页区域,并可保存为复合标签。 +- 侧栏支持页面截图、颜色采样、字体信息、可访问性摘要。 +- 内置媒体预览支持视频文件和网页下载内容。 +- 工作区图谱可显示竞品页、参考页、设计稿与备注之间的关系。 +- 插件可扩展页面审查、截图导出、链接收集和设计资源标记。 + +### 5.4 研究人员 / 内容创作者 + +研究人员需要保存大量资料、阅读长文、管理引用、记录来源并跨设备继续阅读。浏览器需要高质量阅读模式、书签集合、摘录、历史搜索和 Sync。 + +关键需求: + +- 阅读模式保留标题、作者、时间、正文、图片、链接来源。 +- 书签集合支持标签、备注、排序、导出。 +- 历史搜索支持域名、标题、正文索引和 Space 过滤。 +- 侧栏支持当前页面备注和摘录。 +- 插件可扩展文献管理、RSS、导出器和外部笔记系统。 + +--- + +## 6. 信息架构 + +```text +ELY Browser +├─ Identity +│ ├─ Account +│ ├─ Sessions +│ ├─ Devices +│ ├─ Recovery Keys +│ └─ Sync Vault +├─ Windows +│ └─ Browser Window +│ ├─ Title Bar / Traffic Controls +│ ├─ Command Bar +│ ├─ Vertical Workspace +│ │ ├─ Favorites +│ │ ├─ Spaces +│ │ ├─ Tab Groups +│ │ ├─ Pinned Tabs +│ │ ├─ Unpinned Tabs +│ │ └─ Archived Tabs +│ ├─ WebView Canvas +│ │ ├─ Single WebView +│ │ ├─ Split View +│ │ └─ Error / Recovery View +│ ├─ Side Panels +│ │ ├─ Bookmarks +│ │ ├─ History +│ │ ├─ Downloads +│ │ ├─ Reading List +│ │ ├─ Notes +│ │ ├─ Plugin Panels +│ │ └─ Task Manager +│ └─ Status Bar +├─ Browser Data +│ ├─ Profiles +│ ├─ Site Data +│ ├─ Permissions +│ ├─ Certificates +│ ├─ Bookmarks +│ ├─ History +│ ├─ Downloads +│ ├─ Reading List +│ ├─ Notes +│ └─ Sessions +├─ Plugin System +│ ├─ Plugin Registry +│ ├─ Wasm Host +│ ├─ Permission Broker +│ ├─ UI Contributions +│ ├─ Page Bridge +│ ├─ Package Store +│ ├─ Signature Verifier +│ └─ Audit Log +├─ Elydora Cloud +│ ├─ Cloudflare Workers API +│ ├─ Better Auth +│ ├─ Cloudflare D1 +│ ├─ Cloudflare R2 +│ ├─ Cloudflare Workers KV +│ └─ Observability +└─ Platform Services + ├─ Keychain + ├─ Notifications + ├─ Menus + ├─ Clipboard + ├─ File Picker + ├─ Protocol Handler + ├─ Auto Update + └─ Accessibility +``` + +--- + +## 7. 核心 UI/UX + +### 7.1 主窗口布局 + +```text +┌──────────────────────────────────────────────────────────────────────────────┐ +│ ELY [Space: Work ▾] [Search or enter address........................] ⋯ │ +├───────────────┬──────────────────────────────────────────────────────────────┤ +│ ★ Favorites │ │ +│ ○ Mail │ │ +│ ○ Calendar │ │ +│ ○ Docs │ │ +│───────────────│ │ +│ Work │ │ +│ ▾ Project A │ │ +│ ● PR #241 │ Servo WebView Canvas │ +│ ● API Docs │ │ +│ ● Logs │ │ +│ ▸ Design │ │ +│───────────────│ │ +│ Spaces │ │ +│ Work │ │ +│ Personal │ │ +│ Research │ │ +│───────────────│ │ +│ + New Tab │ │ +└───────────────┴──────────────────────────────────────────────────────────────┘ +``` + +布局要求: + +- 左侧侧栏默认宽度 280px,可收缩到 56px 图标态。 +- 顶部地址栏固定在内容区顶部,避免顶部标签挤压。 +- 垂直标签列表使用虚拟化渲染,支持 1,000 个标签对象仍保持流畅滚动。 +- 当前标签、悬浮标签、未读变化、加载中、错误态、静音态、固定态、归档态都有清晰视觉标识。 +- 在全屏和专注模式下,侧栏可自动隐藏,鼠标靠近左缘或快捷键唤起。 +- 所有浏览动作均可通过命令面板执行。 + +### 7.2 Split View + +```text +┌──────────────────────────────────────────────────────────────────────────────┐ +│ [Address / Command Bar] [Split ▾] │ +├───────────────┬─────────────────────────────┬────────────────────────────────┤ +│ Vertical Tabs │ │ │ +│ │ WebView A │ WebView B │ +│ │ │ │ +│ ├─────────────────────────────┴────────────────────────────────┤ +│ │ Split Controls: swap | duplicate | detach | save | close │ +└───────────────┴──────────────────────────────────────────────────────────────┘ +``` + +Split View 要求: + +- 支持 2、3、4 个 WebView。 +- 支持横向、纵向、网格和自定义拖拽布局。 +- Split View 作为一个复合标签保存在垂直侧栏中。 +- 复合标签可固定、归档、移动到其他 Space、参与 Sync。 +- 每个子 WebView 独立导航、刷新、下载、站点权限和错误恢复。 +- 地址栏对当前聚焦子 WebView 生效。 +- 链接右键支持“在 Split View 中打开”。 +- 标签拖入内容区边缘时显示 Split Drop Target。 + +### 7.3 Command Bar + +Command Bar 是 ELY 的统一入口,支持 URL、搜索、命令、书签、历史、打开标签、设置项、插件命令。 + +输入行为: + +- `github.com`:导航到 URL。 +- `? rust async book`:使用默认搜索引擎。 +- `>`:进入命令模式。 +- `@tabs`:只搜已打开标签。 +- `@bookmarks`:只搜书签。 +- `@history`:只搜历史。 +- `@settings`:只搜设置项。 +- `@plugins`:只搜插件命令。 + +命令示例: + +- `New Space` +- `Switch Profile` +- `Open Downloads` +- `Clear Site Data for This Profile` +- `Save Split View` +- `Move Tab to Space` +- `Archive Idle Tabs` +- `Install Plugin from File` +- `Open Sync Status` + +### 7.4 Settings + +Settings 使用 `gpui-router` 管理路由,使用 `gpui-form` 管理表单,使用 gpui-component 提供 Tabs、Form、Switch、Select、Table、Dialog、Toast、List、Sidebar、Search。 + +设置页结构: + +```text +Settings +├─ General +├─ Appearance +├─ Sidebar & Tabs +├─ Spaces +├─ Profiles +├─ Search +├─ Privacy & Security +├─ Sync +├─ Downloads +├─ Site Permissions +├─ Plugins +├─ Shortcuts +├─ Updates +├─ Advanced +└─ About ELY Browser +``` + +设置页要求: + +- 每个设置项必须有即时校验、保存状态、恢复默认值。 +- 参与 Sync 的设置必须显示同步状态。 +- 高风险设置必须二次确认。 +- 设置搜索支持标题、说明、关键词、快捷键。 +- About 页展示 ELY Browser、Elydora、构建号、Servo 构建信息、GPUI 构建信息、许可证入口。 + +--- + +## 8. 浏览器功能规格 + +### 8.1 垂直标签系统 + +标签对象字段: + +| 字段 | 说明 | +|---|---| +| `tab_id` | 本地唯一 ID | +| `space_id` | 所属 Space | +| `profile_id` | 所属 Profile | +| `parent_tab_id` | opener 来源 | +| `title` | 页面标题 | +| `url` | 当前 URL | +| `display_url` | 脱敏展示 URL | +| `favicon_key` | favicon 本地缓存 key | +| `state` | loading / ready / crashed / discarded / archived | +| `is_pinned` | 是否固定 | +| `is_favorite` | 是否跨 Space 常驻 | +| `group_id` | 所属 Tab Group | +| `split_id` | 所属 Split View | +| `last_active_at` | 最近使用时间 | +| `created_at` | 创建时间 | +| `sort_key` | CRDT ordered list 排序键 | +| `sync_enabled` | 是否参与 Sync | + +标签行为: + +- 新标签默认插入当前标签下方。 +- 从当前页面打开的新标签保留 opener 关系。 +- 支持拖拽排序、拖拽到 Space、拖拽成 Split View、拖拽成 Tab Group。 +- 支持批量选择、批量移动、批量归档、批量关闭。 +- 支持搜索当前窗口、当前 Space、全部窗口中的打开标签。 +- 支持标签休眠,休眠后释放 Servo WebView 资源,仅保留会话数据。 +- 支持崩溃恢复,崩溃标签保留 URL、标题、favicon 和表单恢复提示。 + +### 8.2 Spaces + +Space 是任务上下文。每个 Space 拥有自己的标签、固定区、分组、自动归档策略、主题强调色、默认 Profile 和侧栏状态。 + +Space 字段: + +| 字段 | 说明 | +|---|---| +| `space_id` | 全局唯一 ID | +| `name` | 名称 | +| `icon` | 图标 | +| `accent_color` | 强调色 | +| `default_profile_id` | 默认 Profile | +| `archive_policy` | 自动归档策略 | +| `sidebar_width` | 侧栏宽度 | +| `sort_key` | 排序键 | +| `created_at` | 创建时间 | +| `updated_at` | 更新时间 | + +Space 行为: + +- Space 切换只改变可见标签集合,不强制打开新窗口。 +- 一个窗口可以持有多个 Space。 +- 同一 Space 可在多个窗口打开,但编辑冲突必须可恢复。 +- Space 可导出为 `.elyspace` 文件。 +- Space 可导入,导入时可选择是否保留 Profile 映射。 +- Space 删除进入本地回收站,保留 30 天。 + +### 8.3 Profiles + +Profile 是站点数据隔离边界。Profile 隔离 Cookie、Storage、Cache、History scope、Permissions、Certificates、Downloads policy、Search engine preference。 + +Profile 字段: + +| 字段 | 说明 | +|---|---| +| `profile_id` | 全局唯一 ID | +| `name` | 名称 | +| `color` | 颜色 | +| `icon` | 图标 | +| `cookie_store_id` | Cookie 容器 | +| `history_policy` | 历史策略 | +| `download_policy` | 下载策略 | +| `permission_policy` | 权限策略 | +| `is_private` | 是否隐私 Profile | +| `sync_policy` | 同步策略 | + +Profile 行为: + +- 每个 Space 绑定一个默认 Profile。 +- 单个标签可覆盖 Profile。 +- Profile 切换需要明确展示视觉标识,避免用户在错误账号环境下操作。 +- 隐私 Profile 关闭后清理 Cookie、Storage、Cache、临时下载索引和页面会话。 +- Profile 可暂停 Sync。 +- Profile 删除需要先展示受影响站点数据、历史、权限和下载策略。 + +### 8.4 Favorites / Pinned / Archived + +Favorites 是跨所有 Spaces 常驻的顶部标签,适合邮箱、日历、任务系统、常用文档和音乐。Pinned Tabs 是 Space 内常驻标签。Archived Tabs 是被关闭或自动归档但可恢复的标签。 + +要求: + +- Favorites 上限默认 12,可在设置中调整。 +- Favorites 始终显示 favicon,悬浮显示标题和 Profile。 +- Pinned Tabs 展示在当前 Space 顶部。 +- Unpinned Tabs 按使用顺序和分组展示。 +- 自动归档只作用于 Unpinned Tabs。 +- 归档记录保留 URL、标题、favicon、Space、Profile、关闭时间、来源。 +- 归档搜索支持域名、标题、Space、Profile、日期。 + +### 8.5 Tab Groups + +Tab Group 用于 Space 内的二级组织。 + +能力: + +- 支持名称、颜色、折叠、排序。 +- 支持拖拽标签进出 Group。 +- 支持 Group 内批量刷新、关闭、休眠、归档。 +- 支持按域名自动归组。 +- 支持把 Group 转成 Split View。 +- 支持把 Split View 解散成 Group。 + +### 8.6 History + +历史记录按 Profile 隔离,并可按 Space 建立上下文索引。 + +能力: + +- 记录 URL、标题、访问时间、来源标签、Space、Profile、favicon、访问次数。 +- 支持全文索引页面标题和 URL。 +- 阅读模式页面支持正文索引,用户可关闭。 +- 支持按域名清理、按时间清理、按 Profile 清理。 +- 支持历史 Sync,默认关闭正文索引同步。 +- 隐私 Profile 不写入持久历史。 + +### 8.7 Bookmarks / Reading List / Notes + +书签支持集合、标签、备注和导入导出。Reading List 用于稍后阅读。Notes 是页面侧栏轻量备注。 + +能力: + +- 书签集合可绑定 Space。 +- 书签可保存页面截图缩略图。 +- Reading List 保存阅读进度、页面标题、来源 URL、添加时间。 +- Notes 绑定 URL 或具体标签对象。 +- Notes 支持 Markdown 子集。 +- 书签、Reading List、Notes 均参与端到端加密 Sync。 + +### 8.8 Downloads + +下载管理器提供下载生命周期控制和安全提示。 + +能力: + +- start / pause / resume / cancel / retry / open / reveal。 +- 下载路径按 Profile 设置。 +- 危险扩展名提示。 +- 文件 checksum 可选计算。 +- 下载历史可按 Profile 清理。 +- 下载文件本体默认不参与 Sync,下载元数据可参与 Sync。 +- 下载完成后可触发插件事件。 + +### 8.9 Site Permissions + +站点权限按 Profile 隔离。 + +权限类型: + +- Camera +- Microphone +- Screen capture +- Location +- Notifications +- Clipboard read +- Clipboard write +- Downloads +- Popups +- Autoplay +- WebUSB / WebHID / WebSerial +- Storage persistence +- Insecure content +- Certificate exception + +要求: + +- 权限弹窗显示站点、Profile、权限类型、风险说明。 +- 用户可选择一次允许、始终允许、始终拒绝。 +- 权限变更写入审计日志。 +- Site Settings 可按站点查看所有授权。 + +### 8.10 Reading Mode + +Reading Mode 提供低干扰阅读体验。 + +能力: + +- 提取标题、作者、发布时间、正文、图片、链接。 +- 支持字体、字号、行高、页面宽度、主题。 +- 支持目录导航。 +- 支持保存到 Reading List。 +- 支持复制引用信息。 +- 支持导出 Markdown。 +- 支持按 Profile 和 Space 记录阅读进度。 + +### 8.11 Private Windows + +Private Window 使用临时 Profile。 + +要求: + +- 不写持久历史。 +- 不持久化 Cookie、Storage、Cache。 +- 下载文件保留在用户选择位置,下载索引关闭窗口后清理。 +- 插件默认禁用,用户可为单个插件开启 Private Window 权限。 +- Sync 在 Private Window 中默认禁用。 + +--- + +## 9. 登录与 Sync + +### 9.1 总体原则 + +ELY 使用账户登录建立设备身份,使用端到端加密保护 Sync 内容。身份系统和 Sync 加密系统职责独立:Better Auth 确认“谁登录”,Sync Vault 决定“谁能解密”。Elydora Cloud 永远只保存密文 payload、索引、游标和必要元数据。 + +本地优先写入流程: + +```text +User Action + ↓ +Local Encrypted Store + ↓ +Sync Queue + ↓ +Client-side Encryption + ↓ +Cloudflare Workers Sync API + ↓ +D1 Object Index + R2 Encrypted Payload + KV Cache + ↓ +Other Devices Pull Delta + ↓ +Decrypt + Merge + Apply +``` + +### 9.2 登录能力 + +登录入口: + +- Email + password。 +- OAuth provider,可配置 Apple、Google、GitHub。 +- Passkey。 +- 设备二维码登录。 +- Recovery key 登录恢复。 + +登录 UX: + +- 首次打开 ELY 可跳过登录,浏览器完整离线可用。 +- 登录后进入 Sync 设置向导。 +- 用户可选择同步范围。 +- 登录会话保存在系统钥匙串。 +- 本地浏览器数据库密钥保存在系统钥匙串。 +- 账号注销时可以选择保留本地数据或清理本地数据。 + +Better Auth 职责: + +- 用户注册、登录、邮箱验证、OAuth、Passkey、会话刷新、会话撤销。 +- 设备登录授权。 +- 账号删除流程。 +- 安全事件记录。 +- 与 D1 绑定,存储用户、账号、会话和验证相关表。 + +Desktop auth callback: + +```text +ELY Browser → Open auth page in WebView or system browser +Auth completed on Elydora Cloud +Cloudflare Worker redirects to ely://auth/callback?code=... +ELY exchanges code for session +Session token stored in platform keychain +Sync setup starts inside ELY settings +``` + +### 9.3 Sync 数据对象 + +| 对象 | 默认同步 | 加密 | 冲突策略 | +|---|---:|---:|---| +| Account profile display info | 是 | 部分 | Last writer wins | +| Devices | 是 | 否 | Server authority | +| Spaces | 是 | 是 | CRDT ordered list | +| Tabs | 是 | 是 | CRDT ordered list + focus timestamp | +| Split Views | 是 | 是 | Object merge | +| Tab Groups | 是 | 是 | CRDT ordered list | +| Favorites | 是 | 是 | CRDT ordered list | +| Pinned Tabs | 是 | 是 | CRDT ordered list | +| Archived Tabs | 是 | 是 | Append-only log | +| Profiles metadata | 是 | 是 | Object merge | +| Cookies | 否 | 是 | 用户显式开启 | +| Site permissions | 是 | 是 | Last writer wins + audit | +| Bookmarks | 是 | 是 | CRDT tree | +| Reading List | 是 | 是 | Object merge | +| Notes | 是 | 是 | CRDT text | +| History | 可选 | 是 | Append-only log | +| Downloads metadata | 可选 | 是 | Append-only log | +| Browser settings | 是 | 是 | Last writer wins | +| Shortcuts | 是 | 是 | Last writer wins | +| Plugin list | 是 | 是 | Object merge | +| Plugin settings | 可选 | 是 | Plugin-defined merge | + +### 9.4 Sync 加密模型 + +密钥结构: + +```text +User Secret + ├─ Account Recovery Key + ├─ Device Key Pair + └─ Sync Root Key + ├─ Spaces Key + ├─ Tabs Key + ├─ Bookmarks Key + ├─ History Key + ├─ Settings Key + ├─ Plugin Data Key + └─ Snapshot Key +``` + +要求: + +- Sync Root Key 在客户端生成。 +- Better Auth 密码、OAuth 账号和服务器会话均不能直接解密 Sync payload。 +- 新设备加入时,需要已登录设备批准、Recovery Key 或 Passkey + Recovery Key 组合。 +- 密文 payload 使用 AEAD 加密。 +- 每个对象保存 `object_id`、`object_type`、`encrypted_payload`、`payload_hash`、`schema_rev`、`created_at`、`updated_at`。 +- D1 只存索引和小型密文;大型密文写入 R2。 +- R2 object key 不直接暴露 URL、标题、站点名等敏感信息。 +- 服务端日志不得记录 URL 明文、标题明文、书签明文、历史明文。 + +### 9.5 Sync 冲突处理 + +冲突来源: + +- 两台设备同时移动同一标签。 +- 同一 Space 在多设备同时重命名。 +- 同一书签树节点同时移动。 +- 同一设置项同时修改。 +- 某设备离线数天后重新上线。 + +处理方式: + +- 有序列表使用 CRDT ordered list,保留稳定排序键。 +- 普通对象使用 `updated_at + device_id + logical_clock` 解决。 +- 不可自动合并的冲突进入 Conflict Center。 +- Conflict Center 展示对象类型、设备、时间、差异和操作按钮。 +- 用户可保留本机、保留远端、手动合并或复制副本。 + +### 9.6 Sync 状态 UI + +```text +Settings / Sync +┌────────────────────────────────────────────────────┐ +│ Account: zachary@example.com │ +│ Device: MacBook Pro │ +│ Sync: Connected │ +├────────────────────────────────────────────────────┤ +│ Spaces [on] Last synced: just now │ +│ Tabs [on] Last synced: just now │ +│ Bookmarks [on] Last synced: 2 min ago │ +│ History [off] Privacy controlled │ +│ Plugin settings [on] Last synced: just now │ +├────────────────────────────────────────────────────┤ +│ Devices │ +│ • MacBook Pro current │ +│ • Windows Desktop active │ +│ • Linux Laptop last seen yesterday │ +├────────────────────────────────────────────────────┤ +│ [Add Device] [View Recovery Key] [Reset Sync Data] │ +└────────────────────────────────────────────────────┘ +``` + +状态要求: + +- 顶栏只在 Sync 异常时显示小型状态图标。 +- 设置页展示最近同步时间、队列长度、失败对象数量。 +- Sync 失败不阻塞本地浏览。 +- 用户可以按对象类型暂停同步。 +- 用户可以导出加密 Sync 备份。 +- 用户可以从云端删除全部 Sync 数据。 + +--- + +## 10. Elydora Cloud 后端规格 + +### 10.1 架构 + +```text +ELY Desktop Client + ↓ HTTPS +Cloudflare Workers API + ├─ /api/auth/* Better Auth + ├─ /api/sync/push Sync object upload + ├─ /api/sync/pull Delta pull + ├─ /api/sync/snapshot Snapshot upload/download + ├─ /api/devices/* Device management + ├─ /api/plugins/* Plugin registry + ├─ /api/releases/* Update manifest + └─ /api/telemetry/* Minimal diagnostics + ↓ +Cloudflare D1 + ├─ better_auth_* tables + ├─ user_devices + ├─ sync_objects + ├─ sync_change_log + ├─ sync_snapshots + ├─ plugin_registry + ├─ plugin_reviews + └─ audit_events + ↓ +Cloudflare R2 + ├─ sync-payloads/ + ├─ sync-snapshots/ + ├─ plugin-packages/ + ├─ user-avatars/ + ├─ crash-attachments/ + └─ exports/ + ↓ +Cloudflare Workers KV + ├─ public_config + ├─ auth_session_cache + ├─ plugin_registry_cache + ├─ public_signing_keys + ├─ release_manifest_cache + └─ sync_cursor_cache +``` + +### 10.2 Cloudflare D1 使用边界 + +D1 是结构化事实源。 + +D1 存储: + +- Better Auth 用户、账号、会话、验证相关表。 +- 设备记录:设备 ID、设备公钥、设备名称、平台、最后活跃时间。 +- Sync 对象索引:对象 ID、对象类型、owner、payload 位置、hash、schema、时间戳。 +- Sync 变更日志:用于增量拉取。 +- Sync 快照索引:指向 R2 snapshot object。 +- 插件注册表元数据:插件 ID、名称、作者、权限声明、签名状态、包位置。 +- 审计事件:登录、设备加入、设备撤销、权限变更、插件安装、Sync reset。 + +D1 不存储: + +- URL 明文。 +- 页面标题明文。 +- 书签明文。 +- 历史明文。 +- Notes 明文。 +- Cookie 明文。 +- 插件私有配置明文。 + +D1 schema 设计要求: + +- 所有用户数据表必须有 `user_id`。 +- 所有 Sync 事实表必须有 `object_id`、`object_type`、`logical_clock`、`device_id`。 +- 所有可删除对象必须有 `deleted_at` tombstone。 +- 所有增量拉取必须通过 `sync_change_log` 读取。 +- 所有 D1 写入必须可幂等重放。 +- 单个 D1 数据库接近容量阈值时按地区或账户拆分。 + +### 10.3 Cloudflare R2 使用边界 + +R2 是加密大对象事实源。 + +R2 存储: + +- 大型 Sync payload。 +- 周期性 Sync snapshot。 +- 插件 `.rplug` 包。 +- 插件图标、截图和说明文件。 +- 用户头像。 +- 加密导出文件。 +- 用户主动提交的崩溃附件。 + +R2 object key 规范: + +```text +sync-payloads/{region}/{user_hash}/{object_type}/{object_id}/{payload_hash}.bin +sync-snapshots/{region}/{user_hash}/{snapshot_id}.bin +plugin-packages/{plugin_id}/{package_hash}.rplug +plugin-assets/{plugin_id}/{asset_hash} +user-avatars/{user_hash}/{avatar_hash} +crash-attachments/{report_id}/{attachment_hash} +exports/{user_hash}/{export_id}.bin +``` + +要求: + +- 所有 Sync payload 上传前在客户端加密。 +- R2 metadata 不写敏感明文。 +- Worker 只签发短期上传/下载访问。 +- 插件包必须通过签名验证后才进入 registry 可见状态。 +- 用户删除账号时触发 R2 对象清理任务。 + +### 10.4 Cloudflare Workers KV 使用边界 + +KV 是缓存和读多写少配置存储。 + +KV 存储: + +- `public_config`:公开运行配置、服务端开关、地区路由提示。 +- `auth_session_cache`:短期会话验证缓存。 +- `plugin_registry_cache`:插件市场列表缓存。 +- `public_signing_keys`:插件签名公钥、服务端公钥。 +- `release_manifest_cache`:自动更新清单缓存。 +- `sync_cursor_cache`:短期同步游标缓存。 + +KV 使用规则: + +- KV 不作为 Sync 事实源。 +- KV 不存储端到端加密密钥。 +- KV 不存储需要强一致的对象状态。 +- KV 缓存可随时失效,所有关键数据必须可从 D1/R2 重建。 +- KV key 设计必须包含 namespace 和环境前缀。 +- KV TTL 必须按用途设置,默认不得无限期保存短期状态。 + +### 10.5 Better Auth 集成 + +Better Auth 在 Cloudflare Workers 中初始化,D1 binding 作为 database 传入。 + +能力要求: + +- Email/password 注册登录。 +- OAuth provider 配置。 +- Passkey 支持。 +- 邮箱验证。 +- 会话刷新。 +- 会话撤销。 +- 设备登录授权。 +- 安全事件记录。 +- 账号删除。 +- 管理所有 `/api/auth/*` 路由。 + +会话策略: + +- Access session 短期有效。 +- Refresh session 存放在系统钥匙串。 +- 服务端可以撤销单设备或全部设备会话。 +- Desktop client 每次启动执行 session validation。 +- 高风险操作要求重新验证。 + +### 10.6 API 规格 + +Auth: + +| Endpoint | Method | 说明 | +|---|---|---| +| `/api/auth/*` | Any | Better Auth handler | +| `/api/devices` | GET | 当前账号设备列表 | +| `/api/devices/register` | POST | 注册当前设备公钥 | +| `/api/devices/approve` | POST | 批准新设备加入 | +| `/api/devices/revoke` | POST | 撤销设备 | + +Sync: + +| Endpoint | Method | 说明 | +|---|---|---| +| `/api/sync/push` | POST | 上传对象变更 | +| `/api/sync/pull` | GET | 按 cursor 拉取增量 | +| `/api/sync/snapshot` | POST | 上传加密快照 | +| `/api/sync/snapshot` | GET | 下载加密快照 | +| `/api/sync/reset` | POST | 删除云端 Sync 数据 | +| `/api/sync/status` | GET | 获取队列和游标状态 | + +Plugin: + +| Endpoint | Method | 说明 | +|---|---|---| +| `/api/plugins` | GET | 插件列表 | +| `/api/plugins/:id` | GET | 插件详情 | +| `/api/plugins/:id/package` | GET | 获取签名包下载信息 | +| `/api/plugins/publish` | POST | 发布插件包 | +| `/api/plugins/revoke` | POST | 撤销插件包 | + +Update: + +| Endpoint | Method | 说明 | +|---|---|---| +| `/api/releases/manifest` | GET | 自动更新清单 | +| `/api/releases/signature` | GET | 发布包签名信息 | + +### 10.7 后端数据表 + +Better Auth 表由 Better Auth schema 管理。ELY 自定义表如下: + +| 表 | 用途 | +|---|---| +| `user_devices` | 用户设备、公钥、平台、活跃状态 | +| `device_approvals` | 新设备加入批准记录 | +| `sync_objects` | Sync 对象索引 | +| `sync_change_log` | Sync 增量日志 | +| `sync_snapshots` | Sync 快照索引 | +| `sync_tombstones` | 删除标记 | +| `plugin_registry` | 插件注册表 | +| `plugin_packages` | 插件包和签名 | +| `plugin_reviews` | 插件审核记录 | +| `audit_events` | 安全审计事件 | +| `release_manifests` | 发布清单索引 | + +`sync_objects` 字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `object_id` | text | 对象 ID | +| `user_id` | text | 用户 ID | +| `object_type` | text | 对象类型 | +| `payload_inline` | blob nullable | 小型密文 | +| `payload_r2_key` | text nullable | R2 key | +| `payload_hash` | text | payload hash | +| `schema_rev` | integer | schema 修订号 | +| `logical_clock` | integer | 逻辑时钟 | +| `device_id` | text | 来源设备 | +| `created_at` | integer | 创建时间 | +| `updated_at` | integer | 更新时间 | +| `deleted_at` | integer nullable | 删除时间 | + +`sync_change_log` 字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `change_id` | integer | 自增变更 ID | +| `user_id` | text | 用户 ID | +| `object_id` | text | 对象 ID | +| `object_type` | text | 对象类型 | +| `operation` | text | upsert / delete | +| `payload_hash` | text | payload hash | +| `logical_clock` | integer | 逻辑时钟 | +| `device_id` | text | 来源设备 | +| `created_at` | integer | 创建时间 | + +--- + +## 11. 自有插件系统 + +### 11.1 插件定位 + +ELY 只支持自有 `.rplug` 插件协议。插件用于扩展浏览器命令、侧栏、设置页、上下文菜单、下载处理、书签导出、页面信息读取、开发工具和工作流集成。 + +插件设计目标: + +- 安全:默认无能力,所有能力显式授权。 +- 可审计:所有权限声明、运行事件、用户授权和异常都记录。 +- 可撤销:用户可以随时停用插件或撤销单项权限。 +- 可移植:插件以 Wasm Component Model 作为运行边界。 +- 可签名:市场插件必须签名,侧载插件显示风险提示。 +- 可恢复:插件崩溃不得影响浏览器主进程和网页渲染。 + +### 11.2 `.rplug` 包结构 + +```text +my-plugin.rplug +├─ plugin.toml +├─ component.wasm +├─ wit/ +│ └─ ely-browser.wit +├─ assets/ +│ ├─ icon.svg +│ └─ preview.png +├─ README.md +├─ LICENSE +└─ signatures/ + └─ ed25519.sig +``` + +`plugin.toml` 字段: + +| 字段 | 说明 | +|---|---| +| `id` | 插件唯一 ID | +| `name` | 插件名 | +| `description` | 简介 | +| `author` | 作者 | +| `homepage` | 主页 | +| `permissions` | 权限声明 | +| `contributes` | UI / command / menu 贡献点 | +| `min_ely_build` | 最低 ELY 构建要求 | +| `checksum` | Wasm checksum | +| `signature` | 签名信息 | + +### 11.3 插件权限 + +权限清单: + +| 权限 | 能力 | +|---|---| +| `tabs:read` | 读取标签元数据 | +| `tabs:write` | 创建、移动、关闭标签 | +| `spaces:read` | 读取 Space 元数据 | +| `spaces:write` | 创建、修改、删除 Space | +| `bookmarks:read` | 读取书签 | +| `bookmarks:write` | 写入书签 | +| `history:read` | 读取历史 | +| `downloads:read` | 读取下载列表 | +| `downloads:write` | 控制下载 | +| `page:metadata` | 读取当前页面标题、URL、favicon | +| `page:screenshot` | 获取当前页面截图 | +| `page:script` | 注入受限页面脚本 | +| `clipboard:read` | 读取剪贴板 | +| `clipboard:write` | 写入剪贴板 | +| `filesystem:read` | 读取用户选择的文件 | +| `filesystem:write` | 写入用户选择的位置 | +| `network:fetch` | 插件发起网络请求 | +| `settings:read` | 读取插件设置 | +| `settings:write` | 写入插件设置 | +| `sync:plugin` | 插件配置参与 Sync | +| `ui:panel` | 注册侧栏 Panel | +| `ui:command` | 注册命令 | +| `ui:context_menu` | 注册右键菜单 | + +授权要求: + +- 首次安装展示权限列表。 +- 高风险权限单独确认。 +- 页面脚本权限必须按域名授权。 +- 网络权限必须声明目标域名或使用用户确认。 +- 文件权限必须通过系统文件选择器授予。 +- 插件权限变更必须重新确认。 + +### 11.4 插件 UI 贡献点 + +贡献点: + +- Command Bar commands。 +- Tab context menu。 +- Page context menu。 +- Sidebar panels。 +- Settings pages。 +- Status bar indicators。 +- Download actions。 +- Bookmark actions。 +- Reading Mode exporters。 + +插件 UI 使用 GPUI Host 提供的声明式组件接口,不允许直接访问主进程内部对象。插件 UI 只能通过 WIT host calls 请求数据和提交事件。 + +### 11.5 插件市场 + +插件市场提供: + +- 列表、搜索、分类、详情页。 +- 权限摘要。 +- 签名状态。 +- 作者信息。 +- 安装量。 +- 最近更新。 +- 用户评分。 +- 安全审核状态。 +- 安装、禁用、卸载、更新。 + +插件详情页必须展示: + +- 插件名称、作者、描述。 +- 权限清单和解释。 +- 数据访问范围。 +- 是否参与 Sync。 +- 包 checksum。 +- 签名状态。 +- 举报入口。 + +--- + +## 12. 技术架构 + +### 12.1 本地架构 + +```text +ELY Desktop +├─ App Shell (Rust + GPUI) +│ ├─ Window Manager +│ ├─ Command Bar +│ ├─ Sidebar +│ ├─ Settings +│ ├─ Panels +│ └─ Notifications +├─ Browser Core +│ ├─ Tab Manager +│ ├─ Space Manager +│ ├─ Profile Manager +│ ├─ Session Manager +│ ├─ Permission Manager +│ ├─ Download Manager +│ ├─ History Manager +│ ├─ Bookmark Manager +│ └─ Reading Mode +├─ Servo Host +│ ├─ WebView Host +│ ├─ Rendering Bridge +│ ├─ Input Bridge +│ ├─ Focus Bridge +│ ├─ IME Bridge +│ ├─ Permission Bridge +│ ├─ Download Bridge +│ └─ DevTools Bridge +├─ Data Layer +│ ├─ Local Encrypted SQLite +│ ├─ Object Store +│ ├─ Search Index +│ ├─ Keychain Adapter +│ └─ Migration Engine +├─ Sync Core +│ ├─ Queue +│ ├─ Crypto +│ ├─ Merge Engine +│ ├─ Conflict Center +│ └─ Cloud API Client +├─ Plugin Host +│ ├─ Wasmtime Runtime +│ ├─ WIT Bindings +│ ├─ Permission Broker +│ ├─ UI Host +│ ├─ Event Bus +│ └─ Audit Log +└─ Platform Adapters + ├─ macOS + ├─ Windows + └─ Linux +``` + +### 12.2 GPUI 生态映射 + +| 库 | 用途 | 验收要求 | +|---|---|---| +| gpui-component | 主组件库,设置页、列表、弹窗、菜单、表格、Dock | 所有核心 UI 使用统一主题、间距、焦点态 | +| adabraka-ui | 视觉增强组件、空状态、卡片、按钮组 | 只用于提升 clean UI 表达,不引入视觉噪声 | +| ferrum-flow | 工作区图谱、插件可视化配置、导入导出流程 | 节点编辑场景可拖拽、缩放、保存 | +| gpui-flow | 轻量可视化节点编辑 | 用于规则编辑器和插件工作流图 | +| gpui-form | 设置表单、Profile 表单、插件权限表单 | 表单字段自动校验、错误提示、重置 | +| gpui-hooks | 组件内部状态复用 | Hook 边界清晰,避免跨模块隐式状态 | +| gpui-nav | 设置导航、侧栏导航、面板导航 | 支持键盘导航和焦点恢复 | +| gpui-router | Settings、internal pages、plugin pages | `ely://settings/*` 可直接打开 | +| gpui-storybook | 设计系统和组件验收 | 每个核心组件有 Story | +| gpui-symbols | 平台符号图标 | macOS 使用 SF Symbols 风格,其他平台 fallback | +| gpui-tea | 浏览器 Shell 状态循环 | 适用于 Tab/Space/Window 事件模型 | +| gpui-d3rs | 低层图表 | 性能任务管理器与诊断图表 | +| gpui-px | 高层图表 | 历史趋势、下载速度、Sync 状态 | +| plotters-gpui | plotters 后端 | 高级性能分析图 | +| gpui-video-player | 本地视频下载预览 | 下载完成后可预览视频文件 | + +### 12.3 Servo 集成 + +Servo Host 需要实现: + +- WebView 生命周期:create、attach、detach、sleep、restore、destroy。 +- 导航:load URL、back、forward、reload、stop、same-document navigation。 +- 输入:mouse、keyboard、touch、wheel、drag、drop。 +- IME:composition start/update/end、candidate window placement。 +- 渲染:texture handoff、resize、damage tracking、frame scheduling。 +- 焦点:WebView focus、address bar focus、plugin panel focus。 +- 权限:permission request → GPUI dialog → profile policy → Servo response。 +- 下载:download start → Download Manager → file picker / policy。 +- 截图:tab thumbnail、reading capture、plugin screenshot permission。 +- DevTools:打开当前 WebView 调试入口。 +- 崩溃恢复:WebView crash event → tab recovery view。 + +站点兼容性要求: + +- 内置 Site Compatibility Panel。 +- 用户可复制诊断信息。 +- 诊断信息包括 Servo build、URL host、Profile、权限、错误码、控制台摘要。 +- 用户可选择提交匿名站点兼容报告。 +- 报告默认去除 URL path 和 query。 + +### 12.4 本地数据 + +本地数据使用加密 SQLite + 对象文件夹。 + +本地库: + +- `ely_browser.db`:核心关系数据。 +- `ely_search.db`:搜索索引。 +- `ely_sync.db`:Sync 队列和游标。 +- `objects/`:截图、favicon、阅读缓存、插件包。 +- `profiles/`:Profile 级 Servo site data。 + +本地加密要求: + +- 数据库密钥存储于系统钥匙串。 +- 用户可启用启动密码。 +- 隐私 Profile 使用临时密钥。 +- 退出时清理隐私 Profile 临时数据。 +- 崩溃恢复文件同样加密。 + +--- + +## 13. 安全与隐私 + +### 13.1 安全边界 + +- GPUI Shell 与 Servo WebView 分离。 +- Web 内容与插件运行时分离。 +- 插件默认无权限。 +- Profile 之间站点数据隔离。 +- Sync 密文与账号会话分离。 +- 本地密钥与云端会话分离。 +- 高风险操作有显式确认和审计日志。 + +### 13.2 隐私默认值 + +- 遥测默认最小化。 +- 历史 Sync 默认由用户选择。 +- Cookie Sync 默认关闭。 +- 插件网络权限默认关闭。 +- 插件页面脚本权限默认关闭。 +- 站点通知默认询问。 +- 位置权限默认询问。 +- 第三方插件市场安装默认显示风险提示。 + +### 13.3 审计日志 + +本地审计日志记录: + +- 登录和注销。 +- 新设备加入。 +- 设备撤销。 +- Sync reset。 +- 插件安装、启用、禁用、卸载。 +- 插件权限授权和撤销。 +- 站点权限授权和撤销。 +- 证书例外。 +- 私有数据清理。 + +审计日志默认只保存在本地,可选择端到端加密同步。 + +--- + +## 14. 性能指标 + +| 指标 | 要求 | +|---|---:| +| 冷启动到首窗可交互 | P95 < 1.5s | +| 新建标签响应 | P95 < 80ms | +| Command Bar 打开 | P95 < 50ms | +| 侧栏滚动 | 60fps 目标 | +| 1,000 标签侧栏内存增量 | < 80MB | +| 标签切换 Shell 响应 | P95 < 80ms | +| WebView 崩溃恢复 UI | < 300ms | +| Sync 10k 对象增量应用 | P95 < 2s | +| 插件启动 | P95 < 300ms | +| 插件单次 host call | P95 < 20ms | +| 设置页路由切换 | P95 < 80ms | +| 下载列表 10k 项滚动 | 60fps 目标 | + +性能工具: + +- 内置 Task Manager。 +- Tab memory usage。 +- WebView CPU / memory。 +- Plugin CPU / memory / calls。 +- Sync queue length。 +- Download throughput。 +- GPUI frame time。 +- Servo frame time。 + +--- + +## 15. 跨平台要求 + +### 15.1 macOS + +- Universal binary。 +- Notarization。 +- Native menu bar。 +- Traffic lights integration。 +- Keychain。 +- Notification Center。 +- Services menu。 +- Drag/drop files and URLs。 +- Fullscreen and Spaces behavior。 +- Touchpad gestures。 +- IME support。 + +### 15.2 Windows + +- x64 installer。 +- Code signing。 +- Windows Credential Manager。 +- Jump List。 +- System notifications。 +- Snap layout support。 +- High contrast mode。 +- Per-monitor DPI。 +- IME support。 +- Protocol handler registration。 + +### 15.3 Linux + +- AppImage / deb / rpm。 +- Secret Service integration。 +- Wayland + X11。 +- Desktop file。 +- Portal file picker。 +- Notifications。 +- System theme detection。 +- IME support。 +- Protocol handler registration。 + +--- + +## 16. 可访问性与国际化 + +### 16.1 可访问性 + +要求: + +- 所有可交互控件提供 accessible name。 +- 侧栏标签可键盘遍历。 +- Command Bar 支持屏幕阅读器。 +- 弹窗焦点 trap。 +- Dialog 关闭后焦点返回触发元素。 +- 高对比主题。 +- Reduced motion。 +- 可配置字号和 UI density。 +- Split View 子区域有明确焦点边框。 +- 错误提示使用文本和图标双重表达。 + +### 16.2 国际化 + +默认语言:English、简体中文。 +后续语言通过资源文件扩展。 + +要求: + +- 文案不硬编码。 +- 日期、时间、数字格式本地化。 +- 快捷键显示按平台本地化。 +- RTL 布局预留。 +- 插件市场支持插件多语言说明。 + +--- + +## 17. 内置页面 + +内置页面使用 `ely://` 协议。 + +| 路由 | 页面 | +|---|---| +| `ely://new-tab` | 新标签页 | +| `ely://settings` | 设置 | +| `ely://settings/sync` | Sync 设置 | +| `ely://settings/profiles` | Profiles 设置 | +| `ely://settings/plugins` | 插件设置 | +| `ely://history` | 历史 | +| `ely://bookmarks` | 书签 | +| `ely://downloads` | 下载 | +| `ely://reading-list` | Reading List | +| `ely://archive` | Archived Tabs | +| `ely://task-manager` | 任务管理器 | +| `ely://plugins` | 插件市场 | +| `ely://plugin/` | 插件详情 | +| `ely://sync/status` | Sync 状态 | +| `ely://about` | 关于 ELY Browser | +| `ely://crash/` | 标签崩溃恢复 | +| `ely://site/` | 站点设置 | + +--- + +## 18. 键盘快捷键 + +| 动作 | macOS | Windows/Linux | +|---|---|---| +| Command Bar | `Cmd+L` / `Cmd+T` | `Ctrl+L` / `Ctrl+T` | +| 命令模式 | `Cmd+Shift+P` | `Ctrl+Shift+P` | +| 新建标签 | `Cmd+T` | `Ctrl+T` | +| 关闭标签 | `Cmd+W` | `Ctrl+W` | +| 恢复关闭标签 | `Cmd+Shift+T` | `Ctrl+Shift+T` | +| 切换下一个标签 | `Cmd+Option+↓` | `Ctrl+Alt+↓` | +| 切换上一个标签 | `Cmd+Option+↑` | `Ctrl+Alt+↑` | +| 切换 Space | `Cmd+Option+←/→` | `Ctrl+Alt+←/→` | +| Toggle Sidebar | `Cmd+B` | `Ctrl+B` | +| Split Right | `Cmd+\` | `Ctrl+\` | +| Open Downloads | `Cmd+Shift+J` | `Ctrl+Shift+J` | +| Open History | `Cmd+Y` | `Ctrl+H` | +| Open Settings | `Cmd+,` | `Ctrl+,` | +| Task Manager | `Cmd+Esc` | `Shift+Esc` | + +快捷键要求: + +- 所有快捷键可自定义。 +- 冲突检测必须实时提示。 +- 插件快捷键必须进入同一冲突检测系统。 +- 用户可导入导出快捷键配置。 + +--- + +## 19. 验收矩阵 + +### 19.1 产品验收 + +| ID | 模块 | 验收标准 | +|---|---|---| +| P-001 | Brand | 应用、安装包、关于页、协议、服务名统一为 ELY Browser by Elydora | +| P-002 | Vertical Tabs | 1,000 标签可滚动、搜索、拖拽、批量操作 | +| P-003 | Spaces | 创建、切换、排序、导出、导入、删除恢复完整可用 | +| P-004 | Profiles | Cookie、Storage、History、Permissions 严格隔离 | +| P-005 | Split View | 2/3/4 WebView 支持保存为复合标签 | +| P-006 | Favorites | 跨 Space 常驻并可 Sync | +| P-007 | Archive | Unpinned Tabs 自动归档并可搜索恢复 | +| P-008 | Command Bar | URL、搜索、命令、书签、历史、标签统一搜索 | +| P-009 | Downloads | 生命周期控制、Profile 策略、安全提示完整 | +| P-010 | Reading Mode | 正文提取、样式设置、阅读进度、导出完整 | +| P-011 | Settings | 所有设置项可搜索、校验、保存、恢复默认 | +| P-012 | Login | Better Auth 登录、OAuth、Passkey、设备管理可用 | +| P-013 | Sync | Spaces、tabs、bookmarks、settings、plugin settings 可端到端加密同步 | +| P-014 | Cloudflare | D1/R2/KV 边界清晰,所有 API 可观测、可限流、可恢复 | +| P-015 | Plugins | `.rplug` 安装、授权、运行、停用、卸载、市场完整 | +| P-016 | Privacy | 用户可查看、导出、删除本地和云端数据 | +| P-017 | Cross-platform | macOS、Windows、Linux 构建、签名、安装、更新可用 | + +### 19.2 安全验收 + +| ID | 模块 | 验收标准 | +|---|---|---| +| S-001 | Sync encryption | 服务端无法解密 Sync payload | +| S-002 | Keychain | session token 和本地数据库密钥存入系统钥匙串 | +| S-003 | Device revoke | 撤销设备后无法继续拉取 Sync delta | +| S-004 | Plugin sandbox | 插件无声明权限时无法访问 tabs/bookmarks/history/page | +| S-005 | Plugin signature | 市场插件必须签名验证通过 | +| S-006 | Site permissions | 所有站点权限按 Profile 隔离 | +| S-007 | Private Window | 关闭后无持久 Cookie、Storage、History | +| S-008 | Audit log | 高风险操作全部写入本地审计日志 | +| S-009 | Cloud logs | 服务端日志不得记录敏感明文 URL、标题、历史、书签 | +| S-010 | Account deletion | 删除账号触发 D1/R2/KV 数据清理 | + +### 19.3 性能验收 + +| ID | 指标 | 验收标准 | +|---|---|---:| +| F-001 | Cold start | P95 < 1.5s | +| F-002 | New tab | P95 < 80ms | +| F-003 | Command Bar | P95 < 50ms | +| F-004 | Sidebar scroll | 60fps 目标 | +| F-005 | Tab switch | P95 < 80ms | +| F-006 | Sync apply | 10k delta P95 < 2s | +| F-007 | Plugin launch | P95 < 300ms | +| F-008 | Settings route | P95 < 80ms | +| F-009 | Downloads list | 10k rows 60fps 目标 | +| F-010 | Split resize | 60fps 目标 | + +--- + +## 20. 工程组织与开发规范 + +### 20.1 Rust workspace + +```text +ely-browser/ +├─ crates/ +│ ├─ ely_app/ +│ ├─ ely_ui/ +│ ├─ ely_design_system/ +│ ├─ ely_browser_core/ +│ ├─ ely_servo_host/ +│ ├─ ely_profiles/ +│ ├─ ely_tabs/ +│ ├─ ely_spaces/ +│ ├─ ely_history/ +│ ├─ ely_bookmarks/ +│ ├─ ely_downloads/ +│ ├─ ely_permissions/ +│ ├─ ely_sync/ +│ ├─ ely_crypto/ +│ ├─ ely_plugins/ +│ ├─ ely_plugin_wit/ +│ ├─ ely_cloud_client/ +│ ├─ ely_storage/ +│ ├─ ely_search/ +│ ├─ ely_platform/ +│ └─ ely_telemetry/ +├─ cloudflare/ +│ ├─ worker/ +│ ├─ migrations/ +│ ├─ wrangler.toml +│ └─ tests/ +├─ plugins/ +│ ├─ examples/ +│ └─ sdk/ +├─ assets/ +├─ stories/ +├─ tests/ +└─ docs/ +``` + +### 20.2 Cloudflare worker workspace + +```text +cloudflare/ +├─ worker/ +│ ├─ src/ +│ │ ├─ index.ts +│ │ ├─ auth.ts +│ │ ├─ sync.ts +│ │ ├─ devices.ts +│ │ ├─ plugins.ts +│ │ ├─ releases.ts +│ │ ├─ audit.ts +│ │ └─ bindings.ts +│ ├─ package.json +│ └─ tsconfig.json +├─ migrations/ +│ ├─ 0001_auth.sql +│ ├─ 0002_devices.sql +│ ├─ 0003_sync.sql +│ ├─ 0004_plugins.sql +│ └─ 0005_audit.sql +├─ wrangler.toml +└─ tests/ +``` + +Cloudflare 绑定: + +```text +D1 binding: ELY_DB +R2 bucket: ELY_STORAGE +KV namespace: ELY_KV +``` + +环境要求: + +- `local`:本地开发。 +- `staging`:预发布验证。 +- `production`:正式服务。 + +每个环境必须拥有独立 D1 database、R2 bucket、KV namespace 和 Better Auth secret。 + +### 20.3 代码规范 + +- Rust 使用 workspace lint。 +- 所有跨模块事件使用 typed event。 +- 所有 Sync object 变更必须有 migration、merge、encryption test。 +- 所有插件 host call 必须有权限测试。 +- 所有设置项必须有 schema、默认值、校验器、UI story。 +- 所有 Cloudflare API 必须有 auth、rate limit、schema validation、audit。 +- 所有 D1 migration 必须可回放。 +- 所有 R2 object write 必须校验 checksum。 +- 所有 KV 写入必须设置命名空间前缀。 + +### 20.4 测试要求 + +测试类型: + +- Unit tests。 +- Integration tests。 +- Snapshot tests。 +- UI story tests。 +- Sync conflict tests。 +- Encryption tests。 +- Plugin sandbox tests。 +- Cloudflare Worker API tests。 +- D1 migration tests。 +- R2 upload/download tests。 +- KV cache invalidation tests。 +- Cross-platform smoke tests。 +- Servo site compatibility smoke tests。 + +测试数据: + +- 10 tabs。 +- 100 tabs。 +- 1,000 tabs。 +- 10,000 history rows。 +- 10,000 bookmarks。 +- 10,000 Sync objects。 +- 100 plugins installed but inactive。 +- 10 active plugins。 +- 4 Split View panes。 +- 3 Profiles。 +- 20 Spaces。 + +--- + +## 21. 运营、监控与发布 + +### 21.1 遥测最小化 + +默认收集: + +- App 启动成功/失败。 +- 崩溃报告。 +- WebView crash 类型。 +- Sync 错误码。 +- 插件崩溃事件。 +- 更新成功/失败。 + +默认不收集: + +- URL 明文。 +- 页面标题。 +- 搜索词。 +- 书签内容。 +- 历史内容。 +- Notes 内容。 +- Cookie。 +- 表单输入。 + +用户可在 Settings / Privacy & Security 中关闭诊断上报。 + +### 21.2 Cloudflare 监控 + +监控项: + +- Worker request rate。 +- Worker error rate。 +- Auth success/failure rate。 +- D1 query latency。 +- D1 write failure。 +- R2 upload/download failure。 +- KV cache hit rate。 +- Sync push/pull latency。 +- Sync conflict rate。 +- Device revoke events。 +- Plugin install failure。 +- Plugin signature failure。 + +告警: + +- Auth failure spike。 +- Sync 5xx spike。 +- D1 query latency spike。 +- R2 write failure spike。 +- KV stale cache anomaly。 +- Plugin signature verification failure spike。 + +### 21.3 更新系统 + +更新系统要求: + +- 发布包签名验证。 +- 更新清单通过 Cloudflare Workers 提供,并缓存到 KV。 +- 发布包存储在 R2。 +- 客户端下载后验证 checksum 和签名。 +- 更新失败回滚到上一可用构建。 +- 用户可选择自动更新或手动更新。 + +--- + +## 22. 风险与应对 + +| 风险 | 影响 | 应对 | +|---|---|---| +| Servo 站点兼容不足 | 复杂网页渲染、登录、媒体可能异常 | 站点兼容面板、Top sites smoke、错误恢复、诊断提交 | +| GPUI 生态仍在快速演进 | API 变动影响 UI 工程 | 锁定依赖 commit、封装 UI facade、Storybook 覆盖核心组件 | +| D1 单数据库容量限制 | 大规模 Sync 元数据增长 | 按账户、地区、对象类型拆分;R2 承担大 payload | +| KV eventual consistency | 用户看到短期缓存滞后 | KV 只做缓存,D1/R2 作为事实源 | +| Better Auth 与 Workers 运行差异 | Auth callback、session、cookie 策略复杂 | 独立 Auth 集成测试,Desktop callback smoke | +| 插件滥用权限 | 用户数据风险 | Wasm 沙箱、权限 broker、审计日志、签名市场、资源限额 | +| Sync 冲突 | 多设备状态混乱 | CRDT ordered list、Conflict Center、对象级审计 | +| 跨平台输入法问题 | 中文、日文、韩文输入体验受损 | IME 桥专项测试、平台适配器、候选框定位测试 | +| Split View 资源消耗 | 多 WebView 内存上涨 | 休眠策略、任务管理器、资源提示 | +| 下载安全风险 | 恶意文件执行 | 危险扩展名提示、checksum、下载来源展示 | + +--- + +## 23. 关键决策 + +| 决策 | 结果 | +|---|---| +| 产品名称 | ELY Browser by Elydora | +| 产品定位 | clean browser | +| UI 框架 | GPUI | +| 主组件库 | gpui-component | +| Web 引擎 | Servo | +| 标签形态 | 左侧垂直标签为默认信息架构 | +| 任务上下文 | Spaces | +| 账号/站点隔离 | Profiles | +| 多网页并排 | Split View | +| 登录 | Better Auth on Cloudflare Workers | +| 数据库 | Cloudflare D1 | +| 对象存储 | Cloudflare R2 | +| 缓存/配置 | Cloudflare Workers KV | +| Sync | 本地优先 + 端到端加密 + D1/R2/KV | +| 插件系统 | 自有 `.rplug` Wasm Component Model | +| 插件市场 | Elydora Plugin Registry | +| 外部浏览器插件运行时 | 不纳入产品接口 | +| 遥测 | 默认最小化,可关闭 | + +--- + +## 24. Reference + +[R1] Google Chrome — Get more done with new vertical tabs and immersive reading mode in Chrome — https://blog.google/products-and-platforms/products/chrome/new-chrome-productivity-features/ +[R2] Microsoft Edge — Vertical Tabs — https://www.microsoft.com/en-us/edge/features/vertical-tabs +[R3] Arc Help Center — Favorites: Top Tabs Across Every Space — https://resources.arc.net/hc/en-us/articles/19230755904151-Favorites-Top-Tabs-Across-Every-Space +[R4] Arc Help Center — Auto Archive: Clean as you go — https://resources.arc.net/hc/en-us/articles/19228855311127-Auto-Archive-Clean-as-you-go +[R5] Vivaldi — Workspaces — https://vivaldi.com/features/workspaces/ +[R6] Vivaldi Help — Tab Tiling — https://help.vivaldi.com/desktop/tabs/tab-tiling/ +[R7] GPUI official — https://www.gpui.rs/ +[R8] docs.rs — GPUI — https://docs.rs/gpui +[R9] Zed Blog — Leveraging Rust and the GPU to render user interfaces at 120 FPS — https://zed.dev/blog/videogame +[R10] gpui-component — https://github.com/longbridge/gpui-component +[R11] zed-industries/awesome-gpui — https://github.com/zed-industries/awesome-gpui +[R12] Servo official — https://servo.org/ +[R13] Servo Blog — Servo is now available on crates.io — https://servo.org/blog/2026/04/13/servo-0.1.0-release/ +[R14] Cloudflare D1 docs — https://developers.cloudflare.com/d1/ +[R15] Cloudflare Workers docs — Choose a data or storage product — https://developers.cloudflare.com/workers/platform/storage-options/ +[R16] Cloudflare Workers KV docs — How KV works — https://developers.cloudflare.com/kv/concepts/how-kv-works/ +[R17] Better Auth 1.5 — Cloudflare D1 Support — https://better-auth.com/blog/1-5 +[R18] Cloudflare D1 limits — https://developers.cloudflare.com/d1/platform/limits/ +[R19] WebAssembly Component Model — https://component-model.bytecodealliance.org/ +[R20] Wasmtime Component Model embedding API — https://docs.wasmtime.dev/api/wasmtime/component/index.html +[R21] Wasmtime Security — https://docs.wasmtime.dev/security.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..de46fb6 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# ELY Browser + +Native Rust + GPUI browser workspace for ELY Browser by Elydora. + +The repository is organized around explicit product boundaries from `PRD.md`: +domain state, browser orchestration, design tokens, GPUI shell, and Servo host contracts. +Reference GPUI ecosystem repositories live under `references/` for local review and are excluded +from version control. + +## Local Commands + +```bash +cargo fmt --all --check +cargo check --workspace --all-targets +cargo clippy --workspace --all-targets -- -D warnings +cargo test --workspace --all-targets +cargo run -p ely_app +``` diff --git a/crates/ely_app/Cargo.toml b/crates/ely_app/Cargo.toml new file mode 100644 index 0000000..b2bd3d1 --- /dev/null +++ b/crates/ely_app/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ely_app" +version = "0.1.0" +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] +ely_browser_core = { path = "../ely_browser_core" } +ely_design_system = { path = "../ely_design_system" } +ely_domain = { path = "../ely_domain" } +gpui.workspace = true +gpui-component.workspace = true + +[lints] +workspace = true diff --git a/crates/ely_app/src/main.rs b/crates/ely_app/src/main.rs new file mode 100644 index 0000000..ca38614 --- /dev/null +++ b/crates/ely_app/src/main.rs @@ -0,0 +1,48 @@ +mod shell; + +use gpui::{ + App, AppContext, Application, Bounds, KeyBinding, Menu, MenuItem, SystemMenuType, WindowBounds, + WindowOptions, actions, px, size, +}; +use shell::ElyShell; + +actions!(ely_app, [Quit]); + +fn main() { + Application::new().run(|cx: &mut App| { + gpui_component::init(cx); + cx.on_action(quit); + cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]); + cx.set_menus(vec![Menu { + name: "ELY Browser".into(), + items: vec![ + MenuItem::os_submenu("Services", SystemMenuType::Services), + MenuItem::separator(), + MenuItem::action("Quit ELY Browser", Quit), + ], + }]); + + let bounds = Bounds::centered(None, size(px(1240.0), px(780.0)), cx); + let opened = cx.open_window( + WindowOptions { + titlebar: None, + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..WindowOptions::default() + }, + |window, cx| { + let shell = cx.new(|cx| ElyShell::new(window, cx)); + cx.new(|cx| gpui_component::Root::new(shell, window, cx)) + }, + ); + + if opened.is_ok() { + cx.activate(true); + } else { + cx.quit(); + } + }); +} + +fn quit(_: &Quit, cx: &mut App) { + cx.quit(); +} diff --git a/crates/ely_app/src/shell.rs b/crates/ely_app/src/shell.rs new file mode 100644 index 0000000..81c93d7 --- /dev/null +++ b/crates/ely_app/src/shell.rs @@ -0,0 +1,311 @@ +use ely_browser_core::{BrowserCore, BrowserSnapshot, InitialBrowserConfig}; +use ely_design_system::{ELY_THEME, colors, spacing}; +use ely_domain::{BrowserTab, CommandIntent, TabId, UrlText}; +use gpui::{ + AnyElement, AppContext, Context, Entity, InteractiveElement, IntoElement, ParentElement, + Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Window, div, px, rgb, +}; +use gpui_component::{ + Sizable, StyledExt, + button::{Button, ButtonVariants}, + input::{Input, InputEvent, InputState}, +}; + +enum ShellState { + Ready(BrowserCore), + StartupError(String), +} + +pub struct ElyShell { + state: ShellState, + command_input: Entity, + last_intent: Option, + _command_subscription: Subscription, +} + +impl ElyShell { + pub fn new(window: &mut Window, cx: &mut Context) -> Self { + let command_input = + cx.new(|cx| InputState::new(window, cx).placeholder("Search or enter address")); + + let command_subscription = + cx.subscribe(&command_input, |shell: &mut Self, input, event: &InputEvent, cx| { + let ShellState::Ready(core) = &mut shell.state else { + return; + }; + + let value = input.read(cx).value().to_string(); + core.set_command_query(value); + + if matches!(event, InputEvent::PressEnter { .. }) { + shell.last_intent = core.submit_command().ok().flatten(); + } + + cx.notify(); + }); + + let state = match InitialBrowserConfig::ely_defaults().and_then(|config| { + BrowserCore::new(config).map_err(|error| match error { + ely_browser_core::CoreError::Domain(source) => source, + _ => ely_domain::DomainError::InvalidCommand, + }) + }) { + Ok(core) => ShellState::Ready(core), + Err(error) => ShellState::StartupError(error.to_string()), + }; + + Self { + state, + command_input, + last_intent: None, + _command_subscription: command_subscription, + } + } + + fn open_new_tab(&mut self, cx: &mut Context) { + if let ShellState::Ready(core) = &mut self.state + && let Ok(url) = UrlText::parse("ely://new-tab") + { + core.open_tab(url); + cx.notify(); + } + } + + fn select_tab(&mut self, tab_id: &TabId, cx: &mut Context) { + if let ShellState::Ready(core) = &mut self.state + && core.select_tab(tab_id).is_ok() + { + cx.notify(); + } + } +} + +impl Render for ElyShell { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + match &self.state { + ShellState::Ready(core) => match (core.snapshot(), core.active_tab().cloned()) { + (Ok(snapshot), Ok(active_tab)) => self.render_browser(snapshot, active_tab, cx), + (Err(error), _) | (_, Err(error)) => render_error(error.to_string()), + }, + ShellState::StartupError(message) => render_error(message.clone()), + } + } +} + +impl ElyShell { + fn render_browser( + &mut self, + snapshot: BrowserSnapshot, + active_tab: BrowserTab, + cx: &mut Context, + ) -> AnyElement { + div() + .size_full() + .bg(rgb(ELY_THEME.canvas)) + .text_color(rgb(ELY_THEME.ink)) + .flex() + .flex_col() + .child(self.render_command_bar(&snapshot, cx)) + .child( + div() + .flex() + .flex_1() + .overflow_hidden() + .child(self.render_sidebar(&snapshot, cx)) + .child(render_web_canvas(&active_tab)), + ) + .into_any_element() + } + + fn render_command_bar( + &mut self, + snapshot: &BrowserSnapshot, + cx: &mut Context, + ) -> AnyElement { + div() + .h(px(spacing::COMMAND_BAR_HEIGHT)) + .px_4() + .gap_3() + .flex() + .items_center() + .border_b_1() + .border_color(rgb(colors::HAIRLINE)) + .child( + div() + .w(px(spacing::SIDEBAR_WIDTH - spacing::XL)) + .flex() + .items_center() + .gap_2() + .child(div().text_size(px(18.0)).font_semibold().child("ELY Browser")) + .child( + div() + .text_xs() + .text_color(rgb(colors::MUTED)) + .child(snapshot.active_space_name.clone()), + ), + ) + .child( + div() + .flex_1() + .h(px(40.0)) + .rounded_md() + .border_1() + .border_color(rgb(colors::HAIRLINE_STRONG)) + .bg(rgb(colors::SURFACE_CARD)) + .px_3() + .child(Input::new(&self.command_input).appearance(false).cleanable(true)), + ) + .child( + Button::new("new-tab") + .primary() + .small() + .label("+") + .tooltip("New Tab") + .on_click(cx.listener(|shell, _, _, cx| shell.open_new_tab(cx))), + ) + .into_any_element() + } + + fn render_sidebar(&mut self, snapshot: &BrowserSnapshot, cx: &mut Context) -> AnyElement { + div() + .w(px(spacing::SIDEBAR_WIDTH)) + .h_full() + .flex() + .flex_col() + .gap_3() + .p_3() + .border_r_1() + .border_color(rgb(colors::HAIRLINE)) + .bg(rgb(colors::CANVAS)) + .child(section_label("Favorites")) + .child(empty_line("Pinned cross-space tabs appear here")) + .child(section_label("Space")) + .child( + div() + .rounded_md() + .bg(rgb(colors::SURFACE_CARD)) + .border_1() + .border_color(rgb(colors::HAIRLINE)) + .px_3() + .py_2() + .child(snapshot.active_space_name.clone()), + ) + .child(section_label("Tabs")) + .children( + snapshot + .tabs + .iter() + .map(|tab| self.render_tab_row(tab, tab.id() == &snapshot.active_tab_id, cx)), + ) + .child(div().flex_1()) + .child(section_label("Profile")) + .child( + div() + .text_sm() + .text_color(rgb(colors::BODY)) + .child(snapshot.active_profile_name.clone()), + ) + .into_any_element() + } + + fn render_tab_row( + &mut self, + tab: &BrowserTab, + active: bool, + cx: &mut Context, + ) -> AnyElement { + let tab_id = tab.id().clone(); + let background = if active { colors::SURFACE_CARD } else { colors::CANVAS }; + let border = if active { colors::HAIRLINE_STRONG } else { colors::HAIRLINE }; + + div() + .id(SharedString::from(tab.id().as_str().to_string())) + .rounded_md() + .border_1() + .border_color(rgb(border)) + .bg(rgb(background)) + .px_3() + .py_2() + .gap_1() + .flex() + .flex_col() + .cursor_pointer() + .hover(|style| style.bg(rgb(colors::SURFACE_CARD))) + .active(|style| style.opacity(0.82)) + .on_click(cx.listener(move |shell, _, _, cx| shell.select_tab(&tab_id, cx))) + .child( + div() + .text_sm() + .font_semibold() + .text_color(rgb(colors::INK)) + .child(tab.title().to_string()), + ) + .child( + div() + .text_xs() + .text_color(rgb(colors::MUTED)) + .child(tab.url().as_str().to_string()), + ) + .into_any_element() + } +} + +fn render_web_canvas(tab: &BrowserTab) -> AnyElement { + div() + .flex_1() + .h_full() + .p_6() + .bg(rgb(colors::CANVAS_SOFT)) + .child( + div() + .size_full() + .rounded_lg() + .border_1() + .border_color(rgb(colors::HAIRLINE)) + .bg(rgb(colors::SURFACE_CARD)) + .p_8() + .flex() + .flex_col() + .gap_4() + .child( + div() + .text_size(px(26.0)) + .text_color(rgb(colors::INK)) + .child(tab.title().to_string()), + ) + .child( + div() + .text_sm() + .text_color(rgb(colors::MUTED)) + .child(tab.url().as_str().to_string()), + ) + .child( + div() + .mt_4() + .text_sm() + .text_color(rgb(colors::BODY)) + .child("Servo host boundary owns webpage rendering, input, permissions, downloads, and recovery."), + ), + ) + .into_any_element() +} + +fn render_error(message: String) -> AnyElement { + div() + .size_full() + .bg(rgb(colors::CANVAS)) + .text_color(rgb(colors::ERROR)) + .flex() + .items_center() + .justify_center() + .child(message) + .into_any_element() +} + +fn section_label(label: &'static str) -> impl IntoElement { + div().text_xs().font_semibold().text_color(rgb(colors::MUTED)).child(label) +} + +fn empty_line(text: &'static str) -> impl IntoElement { + div().text_xs().text_color(rgb(colors::MUTED_SOFT)).child(text) +} diff --git a/crates/ely_browser_core/Cargo.toml b/crates/ely_browser_core/Cargo.toml new file mode 100644 index 0000000..0b18c3e --- /dev/null +++ b/crates/ely_browser_core/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ely_browser_core" +version = "0.1.0" +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] +ely_domain = { path = "../ely_domain" } +thiserror.workspace = true + +[lints] +workspace = true diff --git a/crates/ely_browser_core/src/error.rs b/crates/ely_browser_core/src/error.rs new file mode 100644 index 0000000..05f02fa --- /dev/null +++ b/crates/ely_browser_core/src/error.rs @@ -0,0 +1,14 @@ +use ely_domain::{DomainError, TabId}; +use thiserror::Error; + +#[derive(Clone, Debug, Error, Eq, PartialEq)] +pub enum CoreError { + #[error(transparent)] + Domain(#[from] DomainError), + + #[error("tab not found: {id}")] + TabNotFound { id: TabId }, + + #[error("browser state has no active tab")] + MissingActiveTab, +} diff --git a/crates/ely_browser_core/src/lib.rs b/crates/ely_browser_core/src/lib.rs new file mode 100644 index 0000000..3fdcdc1 --- /dev/null +++ b/crates/ely_browser_core/src/lib.rs @@ -0,0 +1,5 @@ +mod error; +mod state; + +pub use error::CoreError; +pub use state::{BrowserCore, BrowserSnapshot, InitialBrowserConfig}; diff --git a/crates/ely_browser_core/src/state.rs b/crates/ely_browser_core/src/state.rs new file mode 100644 index 0000000..ceae3c8 --- /dev/null +++ b/crates/ely_browser_core/src/state.rs @@ -0,0 +1,148 @@ +use ely_domain::{ + BrowserTab, CommandIntent, DomainError, Profile, ProfileId, ProfileKind, Space, SpaceId, TabId, + UrlText, +}; + +use crate::CoreError; + +#[derive(Clone, Debug)] +pub struct InitialBrowserConfig { + pub space_name: String, + pub space_icon: String, + pub profile_name: String, + pub initial_url: UrlText, +} + +impl InitialBrowserConfig { + pub fn ely_defaults() -> Result { + Ok(Self { + space_name: "Work".to_string(), + space_icon: "W".to_string(), + profile_name: "Default".to_string(), + initial_url: UrlText::parse("ely://new-tab")?, + }) + } +} + +#[derive(Clone, Debug)] +pub struct BrowserSnapshot { + pub tabs: Vec, + pub active_tab_id: TabId, + pub active_space_name: String, + pub active_profile_name: String, + pub command_query: String, +} + +#[derive(Debug)] +pub struct BrowserCore { + spaces: Vec, + profiles: Vec, + tabs: Vec, + active_space_id: SpaceId, + active_profile_id: ProfileId, + active_tab_id: TabId, + command_query: String, +} + +impl BrowserCore { + pub fn new(config: InitialBrowserConfig) -> Result { + let space = Space::new(config.space_name, config.space_icon, 0xf54e00); + let profile = Profile::new(config.profile_name, 0x26251e, ProfileKind::Standard); + let tab = BrowserTab::new( + TabId::new(), + space.id().clone(), + profile.id().clone(), + "New Tab", + config.initial_url, + ); + + Ok(Self { + active_space_id: space.id().clone(), + active_profile_id: profile.id().clone(), + active_tab_id: tab.id().clone(), + spaces: vec![space], + profiles: vec![profile], + tabs: vec![tab], + command_query: String::new(), + }) + } + + pub fn open_tab(&mut self, url: UrlText) -> TabId { + let title = tab_title(&url); + let tab = BrowserTab::new( + TabId::new(), + self.active_space_id.clone(), + self.active_profile_id.clone(), + title, + url, + ); + let tab_id = tab.id().clone(); + self.tabs.push(tab); + self.active_tab_id = tab_id.clone(); + tab_id + } + + pub fn select_tab(&mut self, tab_id: &TabId) -> Result<(), CoreError> { + if self.tabs.iter().any(|tab| tab.id() == tab_id) { + self.active_tab_id = tab_id.clone(); + return Ok(()); + } + + Err(CoreError::TabNotFound { id: tab_id.clone() }) + } + + pub fn set_command_query(&mut self, query: impl Into) { + self.command_query = query.into(); + } + + pub fn submit_command(&mut self) -> Result, CoreError> { + let query = self.command_query.trim(); + if query.is_empty() { + return Ok(None); + } + + let intent = CommandIntent::parse(query)?; + if let CommandIntent::Navigate(url) = &intent { + self.open_tab(url.clone()); + self.command_query.clear(); + } + + Ok(Some(intent)) + } + + pub fn snapshot(&self) -> Result { + let active_space = self + .spaces + .iter() + .find(|space| space.id() == &self.active_space_id) + .ok_or(CoreError::MissingActiveTab)?; + let active_profile = self + .profiles + .iter() + .find(|profile| profile.id() == &self.active_profile_id) + .ok_or(CoreError::MissingActiveTab)?; + + Ok(BrowserSnapshot { + tabs: self.tabs.clone(), + active_tab_id: self.active_tab_id.clone(), + active_space_name: active_space.name().to_string(), + active_profile_name: active_profile.name().to_string(), + command_query: self.command_query.clone(), + }) + } + + pub fn active_tab(&self) -> Result<&BrowserTab, CoreError> { + self.tabs + .iter() + .find(|tab| tab.id() == &self.active_tab_id) + .ok_or(CoreError::MissingActiveTab) + } +} + +fn tab_title(url: &UrlText) -> String { + if url.as_str() == "ely://new-tab" { + return "New Tab".to_string(); + } + + url.display_host() +} diff --git a/crates/ely_design_system/Cargo.toml b/crates/ely_design_system/Cargo.toml new file mode 100644 index 0000000..714a937 --- /dev/null +++ b/crates/ely_design_system/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ely_design_system" +version = "0.1.0" +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[lints] +workspace = true diff --git a/crates/ely_design_system/src/colors.rs b/crates/ely_design_system/src/colors.rs new file mode 100644 index 0000000..71d1d00 --- /dev/null +++ b/crates/ely_design_system/src/colors.rs @@ -0,0 +1,14 @@ +pub const PRIMARY: u32 = 0xf54e00; +pub const PRIMARY_ACTIVE: u32 = 0xd04200; +pub const INK: u32 = 0x26251e; +pub const BODY: u32 = 0x5a5852; +pub const MUTED: u32 = 0x807d72; +pub const MUTED_SOFT: u32 = 0xa09c92; +pub const HAIRLINE: u32 = 0xe6e5e0; +pub const HAIRLINE_STRONG: u32 = 0xcfcdc4; +pub const CANVAS: u32 = 0xf7f7f4; +pub const CANVAS_SOFT: u32 = 0xfafaf7; +pub const SURFACE_CARD: u32 = 0xffffff; +pub const SURFACE_STRONG: u32 = 0xe6e5e0; +pub const SUCCESS: u32 = 0x1f8a65; +pub const ERROR: u32 = 0xcf2d56; diff --git a/crates/ely_design_system/src/lib.rs b/crates/ely_design_system/src/lib.rs new file mode 100644 index 0000000..e08270d --- /dev/null +++ b/crates/ely_design_system/src/lib.rs @@ -0,0 +1,31 @@ +pub mod colors; +pub mod motion; +pub mod spacing; +pub mod typography; + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Theme { + pub canvas: u32, + pub canvas_soft: u32, + pub surface: u32, + pub ink: u32, + pub body: u32, + pub muted: u32, + pub hairline: u32, + pub accent: u32, + pub success: u32, + pub error: u32, +} + +pub const ELY_THEME: Theme = Theme { + canvas: colors::CANVAS, + canvas_soft: colors::CANVAS_SOFT, + surface: colors::SURFACE_CARD, + ink: colors::INK, + body: colors::BODY, + muted: colors::MUTED, + hairline: colors::HAIRLINE, + accent: colors::PRIMARY, + success: colors::SUCCESS, + error: colors::ERROR, +}; diff --git a/crates/ely_design_system/src/motion.rs b/crates/ely_design_system/src/motion.rs new file mode 100644 index 0000000..53e3cc1 --- /dev/null +++ b/crates/ely_design_system/src/motion.rs @@ -0,0 +1,17 @@ +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum MotionRegister { + Productive, + Expressive, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct MotionToken { + pub register: MotionRegister, + pub duration_ms: u16, +} + +pub const HOVER_FEEDBACK: MotionToken = + MotionToken { register: MotionRegister::Productive, duration_ms: 120 }; + +pub const PANEL_TRANSITION: MotionToken = + MotionToken { register: MotionRegister::Productive, duration_ms: 180 }; diff --git a/crates/ely_design_system/src/spacing.rs b/crates/ely_design_system/src/spacing.rs new file mode 100644 index 0000000..9fc710f --- /dev/null +++ b/crates/ely_design_system/src/spacing.rs @@ -0,0 +1,11 @@ +pub const XXS: f32 = 4.0; +pub const XS: f32 = 8.0; +pub const SM: f32 = 12.0; +pub const BASE: f32 = 16.0; +pub const MD: f32 = 20.0; +pub const LG: f32 = 24.0; +pub const XL: f32 = 32.0; +pub const XXL: f32 = 48.0; +pub const SIDEBAR_WIDTH: f32 = 280.0; +pub const SIDEBAR_COLLAPSED_WIDTH: f32 = 56.0; +pub const COMMAND_BAR_HEIGHT: f32 = 64.0; diff --git a/crates/ely_design_system/src/typography.rs b/crates/ely_design_system/src/typography.rs new file mode 100644 index 0000000..9670326 --- /dev/null +++ b/crates/ely_design_system/src/typography.rs @@ -0,0 +1,14 @@ +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct TypeToken { + pub size_px: f32, + pub line_height: f32, + pub weight: u16, +} + +pub const DISPLAY_MD: TypeToken = TypeToken { size_px: 26.0, line_height: 1.25, weight: 400 }; + +pub const TITLE_MD: TypeToken = TypeToken { size_px: 18.0, line_height: 1.4, weight: 600 }; + +pub const BODY_MD: TypeToken = TypeToken { size_px: 16.0, line_height: 1.5, weight: 400 }; + +pub const CAPTION: TypeToken = TypeToken { size_px: 13.0, line_height: 1.4, weight: 400 }; diff --git a/crates/ely_domain/Cargo.toml b/crates/ely_domain/Cargo.toml new file mode 100644 index 0000000..a150fff --- /dev/null +++ b/crates/ely_domain/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ely_domain" +version = "0.1.0" +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] +thiserror.workspace = true +url.workspace = true +uuid.workspace = true + +[lints] +workspace = true diff --git a/crates/ely_domain/src/command.rs b/crates/ely_domain/src/command.rs new file mode 100644 index 0000000..9331048 --- /dev/null +++ b/crates/ely_domain/src/command.rs @@ -0,0 +1,62 @@ +use crate::{DomainError, UrlText}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum CommandScope { + Tabs, + Bookmarks, + History, + Settings, + Plugins, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum CommandIntent { + Navigate(UrlText), + Search(String), + Command(String), + ScopedSearch { scope: CommandScope, query: String }, +} + +impl CommandIntent { + pub fn parse(input: &str) -> Result { + let trimmed = input.trim(); + if trimmed.is_empty() { + return Err(DomainError::InvalidCommand); + } + + if let Some(command) = trimmed.strip_prefix('>') { + return non_empty_text(command).map(Self::Command); + } + + if let Some(query) = trimmed.strip_prefix('?') { + return non_empty_text(query).map(Self::Search); + } + + if let Some((scope, query)) = parse_scope(trimmed) { + return non_empty_text(query).map(|query| Self::ScopedSearch { scope, query }); + } + + UrlText::from_address_text(trimmed).map(Self::Navigate) + } +} + +fn parse_scope(value: &str) -> Option<(CommandScope, &str)> { + let (scope, query) = value.split_once(' ')?; + let scope = match scope { + "@tabs" => CommandScope::Tabs, + "@bookmarks" => CommandScope::Bookmarks, + "@history" => CommandScope::History, + "@settings" => CommandScope::Settings, + "@plugins" => CommandScope::Plugins, + _ => return None, + }; + Some((scope, query)) +} + +fn non_empty_text(value: &str) -> Result { + let trimmed = value.trim(); + if trimmed.is_empty() { + return Err(DomainError::InvalidCommand); + } + Ok(trimmed.to_string()) +} diff --git a/crates/ely_domain/src/error.rs b/crates/ely_domain/src/error.rs new file mode 100644 index 0000000..da6913d --- /dev/null +++ b/crates/ely_domain/src/error.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Clone, Debug, Error, Eq, PartialEq)] +pub enum DomainError { + #[error("{field} cannot be empty")] + EmptyField { field: &'static str }, + + #[error("invalid URL: {value}")] + InvalidUrl { value: String }, + + #[error("invalid command query")] + InvalidCommand, +} diff --git a/crates/ely_domain/src/identifiers.rs b/crates/ely_domain/src/identifiers.rs new file mode 100644 index 0000000..cd69a0c --- /dev/null +++ b/crates/ely_domain/src/identifiers.rs @@ -0,0 +1,40 @@ +use std::fmt; + +use uuid::Uuid; + +macro_rules! entity_id { + ($name:ident, $prefix:literal) => { + #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct $name(String); + + impl $name { + #[must_use] + pub fn new() -> Self { + Self(format!("{}_{}", $prefix, Uuid::now_v7().simple())) + } + + #[must_use] + pub fn as_str(&self) -> &str { + &self.0 + } + } + + impl Default for $name { + fn default() -> Self { + Self::new() + } + } + + impl fmt::Display for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } + } + }; +} + +entity_id!(TabId, "tab"); +entity_id!(SpaceId, "space"); +entity_id!(ProfileId, "profile"); +entity_id!(SplitId, "split"); +entity_id!(WebViewId, "webview"); diff --git a/crates/ely_domain/src/lib.rs b/crates/ely_domain/src/lib.rs new file mode 100644 index 0000000..335c6f7 --- /dev/null +++ b/crates/ely_domain/src/lib.rs @@ -0,0 +1,17 @@ +mod command; +mod error; +mod identifiers; +mod profile; +mod space; +mod split; +mod tab; +mod url_text; + +pub use command::{CommandIntent, CommandScope}; +pub use error::DomainError; +pub use identifiers::{ProfileId, SpaceId, SplitId, TabId, WebViewId}; +pub use profile::{Profile, ProfileKind}; +pub use space::{ArchivePolicy, Space}; +pub use split::{SplitAxis, SplitLayout, SplitPane}; +pub use tab::{BrowserTab, TabFlags, TabState}; +pub use url_text::UrlText; diff --git a/crates/ely_domain/src/profile.rs b/crates/ely_domain/src/profile.rs new file mode 100644 index 0000000..b236f6c --- /dev/null +++ b/crates/ely_domain/src/profile.rs @@ -0,0 +1,42 @@ +use crate::ProfileId; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ProfileKind { + Standard, + Private, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Profile { + id: ProfileId, + name: String, + color_hex: u32, + kind: ProfileKind, +} + +impl Profile { + #[must_use] + pub fn new(name: impl Into, color_hex: u32, kind: ProfileKind) -> Self { + Self { id: ProfileId::new(), name: name.into(), color_hex, kind } + } + + #[must_use] + pub fn id(&self) -> &ProfileId { + &self.id + } + + #[must_use] + pub fn name(&self) -> &str { + &self.name + } + + #[must_use] + pub fn color_hex(&self) -> u32 { + self.color_hex + } + + #[must_use] + pub fn kind(&self) -> &ProfileKind { + &self.kind + } +} diff --git a/crates/ely_domain/src/space.rs b/crates/ely_domain/src/space.rs new file mode 100644 index 0000000..403f7d8 --- /dev/null +++ b/crates/ely_domain/src/space.rs @@ -0,0 +1,54 @@ +use crate::SpaceId; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ArchivePolicy { + Manual, + IdleDays(u16), +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Space { + id: SpaceId, + name: String, + icon: String, + accent_hex: u32, + archive_policy: ArchivePolicy, +} + +impl Space { + #[must_use] + pub fn new(name: impl Into, icon: impl Into, accent_hex: u32) -> Self { + Self { + id: SpaceId::new(), + name: name.into(), + icon: icon.into(), + accent_hex, + archive_policy: ArchivePolicy::Manual, + } + } + + #[must_use] + pub fn id(&self) -> &SpaceId { + &self.id + } + + #[must_use] + pub fn name(&self) -> &str { + &self.name + } + + #[must_use] + pub fn icon(&self) -> &str { + &self.icon + } + + #[must_use] + pub fn accent_hex(&self) -> u32 { + self.accent_hex + } + + #[must_use] + pub fn archive_policy(&self) -> &ArchivePolicy { + &self.archive_policy + } +} diff --git a/crates/ely_domain/src/split.rs b/crates/ely_domain/src/split.rs new file mode 100644 index 0000000..7923137 --- /dev/null +++ b/crates/ely_domain/src/split.rs @@ -0,0 +1,60 @@ +use crate::{SplitId, TabId}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum SplitAxis { + Horizontal, + Vertical, + Grid, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SplitPane { + tab_id: TabId, + weight: u16, +} + +impl SplitPane { + #[must_use] + pub fn new(tab_id: TabId, weight: u16) -> Self { + Self { tab_id, weight } + } + + #[must_use] + pub fn tab_id(&self) -> &TabId { + &self.tab_id + } + + #[must_use] + pub fn weight(&self) -> u16 { + self.weight + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SplitLayout { + id: SplitId, + axis: SplitAxis, + panes: Vec, +} + +impl SplitLayout { + #[must_use] + pub fn new(axis: SplitAxis, panes: Vec) -> Self { + Self { id: SplitId::new(), axis, panes } + } + + #[must_use] + pub fn id(&self) -> &SplitId { + &self.id + } + + #[must_use] + pub fn axis(&self) -> &SplitAxis { + &self.axis + } + + #[must_use] + pub fn panes(&self) -> &[SplitPane] { + &self.panes + } +} diff --git a/crates/ely_domain/src/tab.rs b/crates/ely_domain/src/tab.rs new file mode 100644 index 0000000..7f1ae23 --- /dev/null +++ b/crates/ely_domain/src/tab.rs @@ -0,0 +1,92 @@ +use crate::{ProfileId, SpaceId, SplitId, TabId, UrlText}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum TabState { + Loading, + Ready, + Crashed, + Discarded, + Archived, +} + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct TabFlags { + pub pinned: bool, + pub favorite: bool, + pub muted: bool, + pub unread: bool, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct BrowserTab { + id: TabId, + space_id: SpaceId, + profile_id: ProfileId, + title: String, + url: UrlText, + state: TabState, + flags: TabFlags, + split_id: Option, +} + +impl BrowserTab { + #[must_use] + pub fn new( + id: TabId, + space_id: SpaceId, + profile_id: ProfileId, + title: impl Into, + url: UrlText, + ) -> Self { + Self { + id, + space_id, + profile_id, + title: title.into(), + url, + state: TabState::Ready, + flags: TabFlags::default(), + split_id: None, + } + } + + #[must_use] + pub fn id(&self) -> &TabId { + &self.id + } + + #[must_use] + pub fn space_id(&self) -> &SpaceId { + &self.space_id + } + + #[must_use] + pub fn profile_id(&self) -> &ProfileId { + &self.profile_id + } + + #[must_use] + pub fn title(&self) -> &str { + &self.title + } + + #[must_use] + pub fn url(&self) -> &UrlText { + &self.url + } + + #[must_use] + pub fn state(&self) -> &TabState { + &self.state + } + + #[must_use] + pub fn flags(&self) -> &TabFlags { + &self.flags + } + + #[must_use] + pub fn split_id(&self) -> Option<&SplitId> { + self.split_id.as_ref() + } +} diff --git a/crates/ely_domain/src/url_text.rs b/crates/ely_domain/src/url_text.rs new file mode 100644 index 0000000..f005d6a --- /dev/null +++ b/crates/ely_domain/src/url_text.rs @@ -0,0 +1,60 @@ +use std::fmt; + +use url::Url; + +use crate::DomainError; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct UrlText { + value: String, +} + +impl UrlText { + pub fn parse(value: impl Into) -> Result { + let value = value.into(); + let trimmed = value.trim(); + if trimmed.is_empty() { + return Err(DomainError::EmptyField { field: "url" }); + } + + Url::parse(trimmed).map_err(|_| DomainError::InvalidUrl { value: trimmed.to_string() })?; + + Ok(Self { value: trimmed.to_string() }) + } + + pub fn from_address_text(value: &str) -> Result { + let trimmed = value.trim(); + if trimmed.is_empty() { + return Err(DomainError::EmptyField { field: "url" }); + } + + if Url::parse(trimmed).is_ok() { + return Self::parse(trimmed); + } + + if trimmed.contains('.') && !trimmed.contains(char::is_whitespace) { + return Self::parse(format!("https://{trimmed}")); + } + + Err(DomainError::InvalidUrl { value: trimmed.to_string() }) + } + + #[must_use] + pub fn as_str(&self) -> &str { + &self.value + } + + #[must_use] + pub fn display_host(&self) -> String { + Url::parse(&self.value) + .ok() + .and_then(|url| url.host_str().map(str::to_string)) + .unwrap_or_else(|| self.value.clone()) + } +} + +impl fmt::Display for UrlText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.value) + } +} diff --git a/crates/ely_servo_host/Cargo.toml b/crates/ely_servo_host/Cargo.toml new file mode 100644 index 0000000..3b81b2b --- /dev/null +++ b/crates/ely_servo_host/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ely_servo_host" +version = "0.1.0" +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] +ely_domain = { path = "../ely_domain" } +thiserror.workspace = true + +[lints] +workspace = true diff --git a/crates/ely_servo_host/src/error.rs b/crates/ely_servo_host/src/error.rs new file mode 100644 index 0000000..9c08d1e --- /dev/null +++ b/crates/ely_servo_host/src/error.rs @@ -0,0 +1,11 @@ +use ely_domain::WebViewId; +use thiserror::Error; + +#[derive(Clone, Debug, Error, Eq, PartialEq)] +pub enum ServoHostError { + #[error("webview not found: {id}")] + WebViewNotFound { id: WebViewId }, + + #[error("permission request missing profile context")] + MissingProfileContext, +} diff --git a/crates/ely_servo_host/src/host.rs b/crates/ely_servo_host/src/host.rs new file mode 100644 index 0000000..998a6c8 --- /dev/null +++ b/crates/ely_servo_host/src/host.rs @@ -0,0 +1,51 @@ +use ely_domain::{ProfileId, TabId, UrlText, WebViewId}; + +use crate::ServoHostError; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum WebViewState { + Created, + Attached, + Sleeping, + Crashed, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct NavigationRequest { + pub webview_id: WebViewId, + pub tab_id: TabId, + pub url: UrlText, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PermissionRequest { + pub webview_id: WebViewId, + pub tab_id: TabId, + pub profile_id: ProfileId, + pub feature: String, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum PermissionDecision { + AllowOnce, + AllowAlways, + DenyAlways, +} + +pub trait ServoHost { + fn create_webview( + &mut self, + tab_id: TabId, + profile_id: ProfileId, + ) -> Result; + + fn navigate(&mut self, request: NavigationRequest) -> Result<(), ServoHostError>; + + fn set_permission( + &mut self, + request: PermissionRequest, + decision: PermissionDecision, + ) -> Result<(), ServoHostError>; + + fn state(&self, webview_id: &WebViewId) -> Result; +} diff --git a/crates/ely_servo_host/src/lib.rs b/crates/ely_servo_host/src/lib.rs new file mode 100644 index 0000000..e37f97f --- /dev/null +++ b/crates/ely_servo_host/src/lib.rs @@ -0,0 +1,5 @@ +mod error; +mod host; + +pub use error::ServoHostError; +pub use host::{NavigationRequest, PermissionDecision, PermissionRequest, ServoHost, WebViewState}; diff --git a/docs/reference-audit.md b/docs/reference-audit.md new file mode 100644 index 0000000..f96f331 --- /dev/null +++ b/docs/reference-audit.md @@ -0,0 +1,28 @@ +# GPUI Reference Audit + +Local reference repositories: + +| Reference | Local path | Product use | +|---|---|---| +| gpui-component | `references/gpui-component` | Root window, input, button, sidebar, dock, list patterns | +| awesome-gpui | `references/awesome-gpui` | Ecosystem index and repository mapping | +| adabraka-ui | `references/adabraka-ui` | Clean desktop component patterns | +| ferrum-flow | `references/ferrum-flow` | Future visual workflow panels | +| gpui-flow | `references/gpui-flow` | Future rule/workflow graph panels | +| gpui-form | `references/gpui-form` | Future settings form derive patterns | +| gpui-hooks | `references/gpui-hooks` | Future reusable component state patterns | +| gpui-nav | `references/gpui-nav` | Future settings/sidebar navigation | +| gpui-router | `references/gpui-router` | Future `ely://settings/*` routing | +| gpui-storybook | `references/gpui-storybook` | Future component story validation | +| gpui-symbols | `references/gpui-symbols` | Future platform symbol integration | +| gpui-tea | `references/gpui-tea` | Future event-loop state model | +| gpui-video-player | `references/gpui-video-player` | Future downloaded media preview | +| plotters-gpui | `references/plotters-gpui` | Future performance charts | +| sotf | `references/sotf` | `gpui-d3rs` and `gpui-px` references | + +Copied patterns in the current implementation: + +- `gpui-component::Root` as the first window view. +- `gpui_component::input::InputState` with typed `InputEvent` subscription. +- `gpui_component::button::Button` for command actions. +- GPUI model discipline: core state mutates once per user action, then the view calls `cx.notify()`. diff --git a/docs/ui-shell.md b/docs/ui-shell.md new file mode 100644 index 0000000..be5f68e --- /dev/null +++ b/docs/ui-shell.md @@ -0,0 +1,22 @@ +# ELY Browser Shell + +```text +┌──────────────────────────────────────────────────────────────────────────────┐ +│ ELY Browser [ Search or enter address.............................. ] [+] │ +├──────────────────────────────┬───────────────────────────────────────────────┤ +│ ★ Favorites │ ely://new-tab │ +│ │ │ +│ Space │ ┌─────────────────────────────────────────┐ │ +│ Work │ │ New Tab │ │ +│ │ │ Clean browser surface for the current │ │ +│ Tabs │ │ Space and Profile. │ │ +│ ● New Tab │ └─────────────────────────────────────────┘ │ +│ │ │ +│ Profile │ Servo host boundary owns webpage rendering. │ +│ Default │ │ +└──────────────────────────────┴───────────────────────────────────────────────┘ +``` + +Motion register: productive. Command and tab interactions use immediate state changes with +hover/press feedback through GPUI styles; future pane transitions should use transform/opacity and +respect reduced-motion settings. diff --git a/packaging/macos/Info.plist b/packaging/macos/Info.plist new file mode 100644 index 0000000..62887cb --- /dev/null +++ b/packaging/macos/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ELY Browser + CFBundleExecutable + ely_app + CFBundleIdentifier + com.elydora.ely-browser + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ELY Browser + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.productivity + LSMinimumSystemVersion + 14.0 + NSHighResolutionCapable + + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..38ab2c6 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.95.0" +components = ["clippy", "rustfmt"] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..38cba21 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +edition = "2024" +max_width = 100 +use_small_heuristics = "Max" diff --git a/scripts/audit_source_lines.sh b/scripts/audit_source_lines.sh new file mode 100755 index 0000000..155e2c1 --- /dev/null +++ b/scripts/audit_source_lines.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +max_lines=500 +status=0 + +while IFS= read -r -d '' file; do + lines="$(wc -l < "${file}" | tr -d ' ')" + if [[ "${lines}" -gt "${max_lines}" ]]; then + echo "${file}: ${lines} lines exceeds ${max_lines}" + status=1 + fi +done < <(find crates -name '*.rs' -print0) + +exit "${status}" diff --git a/scripts/create_macos_app_bundle.sh b/scripts/create_macos_app_bundle.sh new file mode 100755 index 0000000..0977a75 --- /dev/null +++ b/scripts/create_macos_app_bundle.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +binary_path="${repo_root}/target/debug/ely_app" +bundle_root="${repo_root}/target/macos/ELY Browser.app" +contents_dir="${bundle_root}/Contents" +macos_dir="${contents_dir}/MacOS" +resources_dir="${contents_dir}/Resources" + +cargo build -p ely_app + +rm -rf "${bundle_root}" +mkdir -p "${macos_dir}" "${resources_dir}" +cp "${repo_root}/packaging/macos/Info.plist" "${contents_dir}/Info.plist" +cp "${binary_path}" "${macos_dir}/ely_app" +chmod 755 "${macos_dir}/ely_app" + +echo "${bundle_root}"