From ce2f7b174b1493d7c4b0441e525fa74f125c9ddc Mon Sep 17 00:00:00 2001 From: spushk Date: Sun, 11 Oct 2026 22:57:27 +0300 Subject: [PATCH] fix!: bring `const` scopes back - replace grass with sasso - drop lightningcss - rearrange crate and workspace hierarchy & features --- .gitignore | 1 - Cargo.lock | 2030 +++++++++++++++++ Cargo.toml | 62 +- sabry/Cargo.toml | 28 + sabry/src/lib.rs | 4 + sabry_build/Cargo.toml | 7 +- sabry_build/src/buildmagic.rs | 70 +- sabry_build/src/lib.rs | 3 + sabry_intrnl/Cargo.toml | 26 +- sabry_intrnl/src/compiler/mod.rs | 139 -- sabry_intrnl/src/{config => conf}/manifest.rs | 0 sabry_intrnl/src/conf/mod.rs | 210 ++ sabry_intrnl/src/config/mod.rs | 246 -- sabry_intrnl/src/lib.rs | 8 +- sabry_intrnl/src/scoper/hash.rs | 95 - sabry_intrnl/src/style/compiler.rs | 49 + sabry_intrnl/src/style/mod.rs | 5 + .../src/{scoper/mod.rs => style/scope.rs} | 123 +- .../src/{syntax/mod.rs => style/syntax.rs} | 88 +- sabry_intrnl/src/syntax/ostrta.rs | 61 - sabry_procmacro/Cargo.toml | 1 - sabry_procmacro_impl/Cargo.toml | 15 +- sabry_procmacro_impl/src/impls/mod.rs | 13 +- sabry_procmacro_impl/src/impls/scssy.rs | 11 +- sabry_procmacro_impl/src/impls/styly.rs | 73 +- src/lib.rs | 18 - 26 files changed, 2616 insertions(+), 770 deletions(-) create mode 100644 Cargo.lock create mode 100644 sabry/Cargo.toml create mode 100644 sabry/src/lib.rs delete mode 100644 sabry_intrnl/src/compiler/mod.rs rename sabry_intrnl/src/{config => conf}/manifest.rs (100%) create mode 100644 sabry_intrnl/src/conf/mod.rs delete mode 100644 sabry_intrnl/src/config/mod.rs delete mode 100644 sabry_intrnl/src/scoper/hash.rs create mode 100644 sabry_intrnl/src/style/compiler.rs create mode 100644 sabry_intrnl/src/style/mod.rs rename sabry_intrnl/src/{scoper/mod.rs => style/scope.rs} (84%) rename sabry_intrnl/src/{syntax/mod.rs => style/syntax.rs} (78%) delete mode 100644 sabry_intrnl/src/syntax/ostrta.rs delete mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore index 5a8005a..24b4f0e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ rust-toolchain.toml .vscode .profile .envrc -/Cargo.lock /tests/sabry_intermediate /tests/sabry_output /playground diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..aeed6ed --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2030 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "any_spawner" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1384d3fe1eecb464229fcf6eebb72306591c56bf27b373561489458a7c73027d" +dependencies = [ + "futures", + "thiserror 2.0.21", + "wasm-bindgen-futures", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-once-cell" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "attribute-derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f9ef7a68684657ce9da341c934c73b63df7a3585a61e366d84c84ed5d3d167" +dependencies = [ + "attribute-derive-macro", + "manyhow", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "attribute-derive-macro" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d426e5e73549125bb8e4649bdd5508f82c94ddf898fb0517246e71dfb8e98" +dependencies = [ + "collection_literals", + "interpolator", + "manyhow", + "proc-macro-utils", + "proc-macro2", + "quote", + "quote-use", + "syn 3.0.6", +] + +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[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 = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "serde_core", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "camino" +version = "1.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "codee" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9dbbdc4b4d349732bc6690de10a9de952bd39ba6a065c586e26600b6b0b91f5" +dependencies = [ + "serde", + "serde_json", + "thiserror 2.0.21", +] + +[[package]] +name = "collection_literals" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" + +[[package]] +name = "config" +version = "0.15.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e9fbc53afcec54441422f1c596cd054655b32e70e1cbac956651b7b175a404" +dependencies = [ + "convert_case 0.6.0", + "pathdiff", + "serde_core", + "toml", + "winnow", +] + +[[package]] +name = "console" +version = "0.16.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" +dependencies = [ + "encode_unicode", + "libc", + "windows-sys", +] + +[[package]] +name = "const-str" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f" + +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "const_str_slice_concat" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case_extras" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c70f0faf8aa9d17787557d5eae854d7755cac50f5c3d12c81d3d57661cebb" +dependencies = [ + "convert_case 0.11.0", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derive-where" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e2b94854e8576378ccda7c8de8a66ed8b4e8acbd2c50ec3418ea6c8aaf4b567" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "drain_filter_polyfill" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" + +[[package]] +name = "either" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "either_of" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5060e0a4cbf26a87550792688ade88e6b8aec9208613631a7a363bda7bc2d4cd" +dependencies = [ + "paste", + "pin-project-lite", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1731451909bde27714eacba19c2566362a7f35224f52b153d3f42cf60f72472" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "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", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[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 = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +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 = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + +[[package]] +name = "globset" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "guardian" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "html-escape" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9356095b4b41197bba32173600e1582792cda618f65d12f68e2e77d273413c5" + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "hydration_context" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285b05858fe7d58c5eff059f7b46c228fd86996d996c59eb35fc0340d174f640" +dependencies = [ + "futures", + "or_poisoned", + "pin-project-lite", + "serde", + "throw_error", +] + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[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 = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "insta" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67d3d2e287e4b86c10b3f3b641033d1f89b74bdb39d05f34952e2b9a6fe21cd" +dependencies = [ + "console", + "globset", + "once_cell", + "similar", + "tempfile", + "walkdir", +] + +[[package]] +name = "interpolator" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "leptos" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713ee6895e3d1126ea9781280d01414f5643f3f201a949b71efffac07d735f00" +dependencies = [ + "any_spawner", + "cfg-if", + "either_of", + "futures", + "hydration_context", + "leptos_config", + "leptos_dom", + "leptos_hot_reload", + "leptos_macro", + "leptos_server", + "oco_ref", + "or_poisoned", + "paste", + "reactive_graph", + "rustc-hash", + "rustc_version", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "server_fn", + "slotmap", + "tachys", + "thiserror 2.0.21", + "throw_error", + "typed-builder", + "typed-builder-macro", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm_split_helpers", + "web-sys", +] + +[[package]] +name = "leptos_config" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c06f751315bccc0d193fab302ac01d25bcfcd97474d4676440e7e3250dc3fc3" +dependencies = [ + "config", + "regex", + "serde", + "thiserror 2.0.21", + "typed-builder", +] + +[[package]] +name = "leptos_dom" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35742e9ed8f8aaf9e549b454c68a7ac0992536e06856365639b111f72ab07884" +dependencies = [ + "js-sys", + "or_poisoned", + "reactive_graph", + "send_wrapper", + "tachys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "leptos_hot_reload" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84989bd3d604e66adbfe13a32bec2ea47bdcb6c9fcd643f784facbb32f6ef10" +dependencies = [ + "anyhow", + "camino", + "indexmap", + "or_poisoned", + "proc-macro2", + "quote", + "rstml", + "serde", + "syn 3.0.6", + "walkdir", +] + +[[package]] +name = "leptos_macro" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0902af1e6947ffc7e906b7003a165f76f178dc711a47b74241025090b0c32a72" +dependencies = [ + "attribute-derive", + "cfg-if", + "convert_case 0.11.0", + "convert_case_extras", + "html-escape", + "itertools 0.14.0", + "leptos_hot_reload", + "prettyplease", + "proc-macro2", + "quote", + "rstml", + "rustc_version", + "server_fn_macro", + "syn 3.0.6", + "uuid", +] + +[[package]] +name = "leptos_server" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202b2d1261c22d886f307934760a6bb566444f68f39b24f6f10defdc23633049" +dependencies = [ + "any_spawner", + "base64 0.22.1", + "codee", + "futures", + "hydration_context", + "or_poisoned", + "reactive_graph", + "send_wrapper", + "serde", + "serde_json", + "server_fn", + "tachys", +] + +[[package]] +name = "libc" +version = "0.2.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "manyhow" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c69ea6e469ca785c846b25dd69eac9e9c916b51d8ada1f212866787ee1da12d" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "manyhow-macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc5c1b2c4000056dae3619fea36e79ce79dabfee4907d2dcad6612b189e370" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "next_tuple" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60993920e071b0c9b66f14e2b32740a4e27ffc82854dcd72035887f336a09a28" + +[[package]] +name = "oco_ref" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0423ff9973dea4d6bd075934fdda86ebb8c05bdf9d6b0507067d4a1226371d" +dependencies = [ + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "or_poisoned" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "prettyplease" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" +dependencies = [ + "proc-macro2", + "syn 3.0.6", +] + +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df921e1ef974ebc8dd9effdb0c037a96928ae8cbf871438e02d6fd67204b595e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "version_check", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quote-use" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48356e493823dc3c1d7e9fc7b3ff204ecec48afbdd718fc4134091b88eb63f3d" +dependencies = [ + "quote", + "quote-use-macros", +] + +[[package]] +name = "quote-use-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf1c5de6a7cc231c71e03c77aa4c7019097859ea7029156b54d2894a8430704" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "raffia" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a83eb5987650fcfc3f2e912d3a718f19b8e87c0d980e12e36edf79fa0221d93" +dependencies = [ + "raffia_macro", + "smallvec", +] + +[[package]] +name = "raffia_macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ac21f5e4bc6b29ea5d5e691a9aa08b2b9fd8891f48a99157b9f02d8a48e1318" +dependencies = [ + "heck", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "reactive_graph" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79f11fac67625645add76313dab8dae510fca0654d96ef98fd8f961a7d2e22c1" +dependencies = [ + "any_spawner", + "async-lock", + "futures", + "guardian", + "hydration_context", + "indexmap", + "or_poisoned", + "paste", + "pin-project-lite", + "rustc-hash", + "rustc_version", + "send_wrapper", + "serde", + "slotmap", + "thiserror 2.0.21", + "web-sys", +] + +[[package]] +name = "reactive_stores" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a29e469b556f25486678e9f5f65fa21a0351d98affde9a7eea9fee286bf8ebd6" +dependencies = [ + "guardian", + "indexmap", + "itertools 0.14.0", + "or_poisoned", + "paste", + "reactive_graph", + "reactive_stores_macro", + "rustc-hash", + "send_wrapper", +] + +[[package]] +name = "reactive_stores_macro" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d11f1b82859d94577892b8037c35f8a4f066cbb3864583e22e68def0af49a88" +dependencies = [ + "convert_case 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rstml" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6bd1bfba3c4c0b57aae906204d9e5744f3f65800ce6c75bd4cc162f2c26f3aa" +dependencies = [ + "derive-where", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 3.0.6", + "thiserror 2.0.21", +] + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[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 = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "sabry" +version = "0.0.7" +dependencies = [ + "insta", + "leptos", + "sabry_intrnl", + "sabry_procmacro", +] + +[[package]] +name = "sabry_build" +version = "0.0.7" +dependencies = [ + "proc-macro2", + "sabry_intrnl", + "sabry_procmacro", + "sabry_procmacro_impl", + "syn 3.0.6", + "thiserror 2.0.21", + "walkdir", +] + +[[package]] +name = "sabry_intrnl" +version = "0.0.7" +dependencies = [ + "base64 0.23.1", + "raffia", + "sasso", + "serde", + "syn 3.0.6", + "thiserror 2.0.21", + "toml", +] + +[[package]] +name = "sabry_procmacro" +version = "0.0.7" +dependencies = [ + "sabry_procmacro_impl", +] + +[[package]] +name = "sabry_procmacro_impl" +version = "0.0.7" +dependencies = [ + "itertools 0.15.0", + "proc-macro2", + "quote", + "raffia", + "regex", + "sabry_intrnl", + "syn 3.0.6", + "thiserror 2.0.21", +] + +[[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 = "sasso" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de32df330f2607c02458791223064ee98752e719e6f85804953229533c32448" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +dependencies = [ + "futures-core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_qs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "serde_spanned" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "server_fn" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8559dd05af1b5b7e363a150616589d5a88af5187273f7f331ba0dae8922812" +dependencies = [ + "base64 0.22.1", + "bytes", + "const-str", + "const_format", + "futures", + "gloo-net", + "http", + "js-sys", + "or_poisoned", + "pin-project-lite", + "rustc_version", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "server_fn_macro_default", + "thiserror 2.0.21", + "throw_error", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce79d7b6ab93f7994e5ff4999eb962f2aea370d7c3b91986eb75da738a8e65f9" +dependencies = [ + "const_format", + "convert_case 0.11.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 3.0.6", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro_default" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9a4f81a0d855f279c3448243138a55cbfdd9851da9341b9c1e5971b90089e61" +dependencies = [ + "server_fn_macro", + "syn 3.0.6", +] + +[[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 = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[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.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "tachys" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e47e2220bb9d2a3be976a22a0fb7685a0b84499bb11ea5cb3bbc82907675ac68" +dependencies = [ + "any_spawner", + "async-trait", + "const_str_slice_concat", + "drain_filter_polyfill", + "either_of", + "erased", + "futures", + "html-escape", + "indexmap", + "itertools 0.14.0", + "js-sys", + "next_tuple", + "oco_ref", + "or_poisoned", + "paste", + "reactive_graph", + "reactive_stores", + "rustc-hash", + "rustc_version", + "send_wrapper", + "slotmap", + "throw_error", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[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.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl 2.0.21", +] + +[[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.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "throw_error" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0ed6038fcbc0795aca7c92963ddda636573b956679204e044492d2b13c8f64" +dependencies = [ + "pin-project-lite", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" +dependencies = [ + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "1.1.8+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" + +[[package]] +name = "typed-builder" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31aa81521b70f94402501d848ccc0ecaa8f93c8eb6999eb9747e72287757ffda" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[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", +] + +[[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.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a" +dependencies = [ + "getrandom", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[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 = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" +dependencies = [ + "js-sys", + "tokio", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.6", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasm_split_helpers" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab578aae2fe2916edaea06843187d50f87b0965622da0ceef648edca27b385ba" +dependencies = [ + "async-once-cell", + "wasm_split_macros", +] + +[[package]] +name = "wasm_split_macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e653af7ee4a9ef0fce481a9ec6f43cb78de20d0cdb4f4f5862e1dc6e407e6c8" +dependencies = [ + "base16", + "quote", + "sha2", + "syn 2.0.119", +] + +[[package]] +name = "web-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "xxhash-rust" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7" + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 78f0188..2c46e0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,6 @@ [workspace] resolver = "3" -members = [ - "sabry_procmacro", - "sabry_procmacro_impl", - "sabry_intrnl", - "sabry_build", -] +members = ["sabry", "sabry_procmacro", "sabry_procmacro_impl", "sabry_intrnl", "sabry_build"] exclude = ["examples"] [workspace.package] @@ -19,15 +14,21 @@ publish = true [workspace.dependencies] ## Workspace -sabry_intrnl = { path = "sabry_intrnl", version = "0.0.7" } -sabry_procmacro = { path = "sabry_procmacro", version = "0.0.7" } -sabry_procmacro_impl = { path = "sabry_procmacro_impl", version = "0.0.7" } -sabry_build = { path = "sabry_build", version = "0.0.7" } +sabry.path = "sabry" +sabry.version = "0.0.7" +sabry_intrnl.path = "sabry_intrnl" +sabry_intrnl.version = "0.0.7" +sabry_procmacro.path = "sabry_procmacro" +sabry_procmacro.version = "0.0.7" +sabry_procmacro_impl.path = "sabry_procmacro_impl" +sabry_procmacro_impl.version = "0.0.7" +sabry_build.path = "sabry_build" +sabry_build.version = "0.0.7" ## CSS lightningcss.version = "1.0.0-alpha.72" lightningcss.default-features = false -grass.version = "^0.13" -grass.default-features = false +sasso.version = "^0.21" +sasso.default-features = false raffia.version = "^0.13" ## Marshall serde.version = "^1" @@ -43,38 +44,5 @@ thiserror.version = "^2" proc-macro2.version = "^1" quote.version = "^1" syn.version = "^3" - -[package] -name = "sabry" -description = "Syntactically Awesome But RustY - crate that brings SCSS/SASS into rust" -keywords = ["web", "sass", "scss", "macro"] -repository.workspace = true -version.workspace = true -edition.workspace = true -rust-version.workspace = true -authors.workspace = true -license.workspace = true -publish.workspace = true - -[dependencies] -## Workspace -sabry_procmacro = { workspace = true, optional = true } -sabry_build = { workspace = true, optional = true } -sabry_intrnl = { workspace = true } - -[dev-dependencies] -leptos = { version = "^0.8" } -insta = { version = "^1", features = ["glob"] } - -[features] -default = ["procmacro"] -const-scoping = ["sabry_procmacro?/const-compile"] -procmacro = ["dep:sabry_procmacro"] -build = ["dep:sabry_build"] -net-files = ["sabry_build/net-files"] -internals = [] -nightly = ["sabry_procmacro?/nightly"] - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] +## Testing +insta.version = "^1" diff --git a/sabry/Cargo.toml b/sabry/Cargo.toml new file mode 100644 index 0000000..084c066 --- /dev/null +++ b/sabry/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "sabry" +description = "Syntactically Awesome But RustY - crate that brings SCSS/SASS into rust" +keywords = ["web", "sass", "scss", "macro"] +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +publish.workspace = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +## Workspace +sabry_procmacro.workspace = true +sabry_intrnl.workspace = true + +[dev-dependencies] +leptos.version = "^0.8" +insta.workspace = true +insta.features = ["glob"] + +[features] +nightly = ["sabry_procmacro/nightly", "sabry_intrnl/nightly"] diff --git a/sabry/src/lib.rs b/sabry/src/lib.rs new file mode 100644 index 0000000..152c401 --- /dev/null +++ b/sabry/src/lib.rs @@ -0,0 +1,4 @@ +#![doc = include_str!("../../README.md")] +#![cfg_attr(docsrs, feature(doc_cfg))] + +pub use sabry_procmacro::*; diff --git a/sabry_build/Cargo.toml b/sabry_build/Cargo.toml index 3ac6e7f..5648a52 100644 --- a/sabry_build/Cargo.toml +++ b/sabry_build/Cargo.toml @@ -14,10 +14,9 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] sabry_intrnl.workspace = true -sabry_intrnl.features = ["compile", "scope"] +sabry_intrnl.features = ["config-manifest", "style-compiler"] +sabry_procmacro.workspace = true sabry_procmacro_impl.workspace = true -sabry_procmacro_impl.features = ["const-compile"] - proc-macro2.workspace = true proc-macro2.features = ["span-locations"] syn.workspace = true @@ -26,4 +25,4 @@ thiserror.workspace = true walkdir.workspace = true [features] -net-files = [] +nightly = ["sabry_procmacro/nightly", "sabry_procmacro_impl/nightly"] diff --git a/sabry_build/src/buildmagic.rs b/sabry_build/src/buildmagic.rs index bd476a7..eb43b2f 100644 --- a/sabry_build/src/buildmagic.rs +++ b/sabry_build/src/buildmagic.rs @@ -3,17 +3,17 @@ use std::{ convert::Infallible, fs::{self, OpenOptions}, io::{self, Write}, - path::PathBuf, - str::FromStr, vec, }; use sabry_intrnl::{ - compiler::{CompilerAdapter, SabryCompilerError}, - config::{manifest::ManifestError, BehavHashCollision, BehavSassModCollision, SabryConfig}, - scoper::{hash::ScopeHash, ArbitraryScope, ScopeError}, + conf::{BehavHashCollision, BehavSassModCollision, SabryConfig, manifest::ManifestError}, + style::{ + compiler::{CompilerAdapter, SabryCompilerError}, + scope::{ArbitraryScope, ScopeError, ScopeHash}, + }, }; -use sabry_procmacro_impl::impls::{styly, ArbitraryStyleSyntax}; +use sabry_procmacro_impl::impls::{ArbitraryStyleSyntax, styly}; use walkdir::WalkDir; use crate::filevisit::{self, FileVisitError}; @@ -71,7 +71,6 @@ pub struct SabryBuilder { state: SabryBuildState, } -//🧙 impl SabryBuilder { /// Construct new [SabryBuilder] from the config /// @@ -124,42 +123,40 @@ impl SabryBuilder { pub fn generate_output(&mut self) -> BuilderResult { // warn on empty loaded_css_modules if self.state.loaded_css_modules.is_empty() { - println!("🧙 sabry didn't compile any CSS. Perhaps the crate has no styles? Lets write some!\nAlso you should check that you do use `styly!` macro properly - at the top level as an item."); + println!( + "🧙 sabry didn't compile any CSS. Perhaps the crate has no styles? Lets write some!\nAlso you should check that you do use `styly!` macro properly - at the top level as an item." + ); } if let Some(scope_dir) = &self.config.css.scopes { - println!("🧙 writing CSS files for each of loaded scopes into {scope_dir}"); + println!("🧙 writing CSS files for each of loaded scopes into {scope_dir:?}"); fs::create_dir_all(scope_dir)?; for (scope, code) in &self.state.loaded_css_modules { - let scope_path = format!("{}/{}.css", scope_dir, scope); + let scope_path = scope_dir.join(scope).with_extension("css"); fs::write(scope_path, code)?; } } if let Some(bundle_file) = &self.config.css.bundle { - println!("🧙 writing merged CSS for the entire crate into {bundle_file}"); - - let path = PathBuf::from_str(bundle_file)?; - - if let Some(dir) = path.parent() { + println!("🧙 writing merged CSS for the entire crate into {bundle_file:?}"); + if let Some(dir) = bundle_file.parent() { fs::create_dir_all(dir)?; } // remove the file to write new fresh tasty CSS - let _ = fs::remove_file(&path); + let _ = fs::remove_file(bundle_file); // and then reopen it let mut file = OpenOptions::new() .create_new(true) .append(true) - .open(path)?; + .open(bundle_file)?; // merged bundle CSS does require another lightningcss pass let mut buffer = String::new(); for (_, code) in &self.state.loaded_css_modules { buffer.push_str(code); } - buffer = self.css_compiler.lightningcss(&buffer)?; write!(file, "{buffer}")?; } @@ -258,13 +255,12 @@ impl SabryBuilder { let mut modules: Vec = vec![]; if let Some(sass_mods) = &self.config.sass.modules { for pre in sass_mods { - let pre_path = PathBuf::from_str(pre)?; - let pre_name = pre_path + let pre_name = pre .file_name() .ok_or(SabryBuildError::FileName())? .to_string_lossy() .to_string(); - let code = fs::read_to_string(pre_path)?; + let code = fs::read_to_string(pre)?; modules.push((pre_name, code)); } } @@ -276,9 +272,7 @@ impl SabryBuilder { if let Some(sass_pres) = &self.config.sass.prelude { let mut sass_preludes: Vec = vec![]; for pre in sass_pres { - let pre_path = PathBuf::from_str(pre)?; - - let syntax = pre_path + let syntax = pre .extension() .unwrap_or_default() .to_str() @@ -287,23 +281,21 @@ impl SabryBuilder { Ok(s) => s, Err(_) => { return Err(SabryBuildError::Another(format!( - "Unknown syntax for sass prelude {pre}" - ))) + "Unknown syntax for sass prelude {pre:?}" + ))); } }; - let code = fs::read_to_string(pre_path)?; + let code = fs::read_to_string(pre)?; sass_preludes.push(SassPreludeModule { syntax, code }); } self.state.sass_prelude.extend(sass_preludes); } // load css preludes - if let Some(css_pre) = &self.config.css.prelude { - for pre in css_pre { - let code = fs::read_to_string(pre)?; - self.state.css_prelude.push_str(&code); - } + for pre in &self.config.css.prelude { + let code = fs::read_to_string(pre)?; + self.state.css_prelude.push_str(&code); } Ok(()) @@ -319,9 +311,9 @@ impl SabryBuilder { /// This function will not overwrite the module file. Never. /// pub fn load_side_module(&mut self, name: ModuleName, code: ModuleCode) -> BuilderResult { - println!("🧙 loading side module '{}'", &name); + println!("🧙 loading side module '{}'", name); - let module_file_path = format!("{}/{}", &self.config.sass.intermediate_dir, &name); + let module_file_path = self.config.sass.intermediate_dir.join(&name); let mut open_options = OpenOptions::new(); let mut open_options = open_options.write(true); @@ -333,10 +325,12 @@ impl SabryBuilder { open_options = if self.state.known_side_modules.contains(&name) { match &self.config.sass.module_name_collision { BehavSassModCollision::Error => { - return Err(SabryBuildError::ModuleCollision { module: name }) + return Err(SabryBuildError::ModuleCollision { module: name }); } BehavSassModCollision::Merge => { - println!("🧙 sabry found duplicate module name '{name}': merging code, as configured"); + println!( + "🧙 sabry found duplicate module name '{name}': merging code, as configured" + ); open_options.append(true) } } @@ -399,7 +393,9 @@ pub enum SabryBuildError { FileVisit(#[from] FileVisitError), #[error("Syntax of style can not be parsed")] SyntaxError(#[from] ScopeError), - #[error("Another scope has the same hash, and sabry is configured to raise an error. Try to adjust config, increase hash size, or change the style code")] + #[error( + "Another scope has the same hash, and sabry is configured to raise an error. Try to adjust config, increase hash size, or change the style code" + )] HashCollision { scope: ModuleName }, #[error("Something's wrong with file path")] Path(#[from] Infallible), diff --git a/sabry_build/src/lib.rs b/sabry_build/src/lib.rs index b2d511e..d8e6863 100644 --- a/sabry_build/src/lib.rs +++ b/sabry_build/src/lib.rs @@ -2,3 +2,6 @@ pub mod buildmagic; pub mod filevisit; + +pub use buildmagic::buildy; +pub use sabry_procmacro::usey; diff --git a/sabry_intrnl/Cargo.toml b/sabry_intrnl/Cargo.toml index d6e7339..01ecd91 100644 --- a/sabry_intrnl/Cargo.toml +++ b/sabry_intrnl/Cargo.toml @@ -13,21 +13,21 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] +## Css +raffia.version = "^0.13" +sasso.workspace = true +sasso.optional = true base64.workspace = true -base64.optional = true -grass.workspace = true -grass.optional = true -lightningcss.workspace = true -lightningcss.optional = true -raffia.workspace = true -syn.workspace = true - -cfg-if.workspace = true -serde.workspace = true -serde.features = ["derive"] +## Codegen thiserror.workspace = true +syn.workspace = true +## Manifets seri +serde.workspace = true +serde.optional = true +serde.features = ["derive"] toml.workspace = true +toml.optional = true [features] -compile = ["dep:grass", "dep:lightningcss"] -scope = ["dep:base64"] +config-manifest = ["dep:toml", "dep:serde"] +style-compiler = ["dep:sasso"] diff --git a/sabry_intrnl/src/compiler/mod.rs b/sabry_intrnl/src/compiler/mod.rs deleted file mode 100644 index adc398f..0000000 --- a/sabry_intrnl/src/compiler/mod.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::config::SabryConfig; - -/// Convenience wrapper on Grass and Lightningcss -pub struct CompilerAdapter { - #[allow(dead_code)] // without 'compile' feature, still want to set this - config: SabryConfig, -} - -impl CompilerAdapter { - pub fn new(config: SabryConfig) -> Self { - Self { config } - } - - /// Compile given SASS/SCSS into CSS - /// with respect to self.config - #[cfg(feature = "compile")] - pub fn compile_module( - &self, - syntax: crate::syntax::ostrta::OneSyntaxToRuleThemAll, - code: &str, - ) -> Result { - let options = grass::Options::from(&self.config).input_syntax(syntax.into()); - - let css = self.lightningcss(&grass::from_string(code, &options)?)?; - - Ok(css) - } - - /// Perform lightningcss transformations on given css - /// with respect to self.config.css.minify on minification - #[cfg(feature = "compile")] - pub fn lightningcss(&self, css: &str) -> Result { - use lightningcss::{printer::PrinterOptions, stylesheet::MinifyOptions, targets::Targets}; - - let mut lightsheet = match lightningcss::stylesheet::StyleSheet::parse( - css, - lightningcss::stylesheet::ParserOptions::default(), - ) { - Ok(s) => s, - Err(e) => { - return Err(SabryCompilerError::LightParse { - kind: e.kind.to_string(), - loc: e.loc, - }) - } - }; - - let targets = Targets { - browsers: Some(self.config.lightningcss.targets.clone().into()), - ..Default::default() - }; - - let printer_options = PrinterOptions { - minify: self.config.css.minify, - targets, - ..Default::default() - }; - - let minify_options = MinifyOptions { - targets, - ..Default::default() - }; - - if self.config.css.minify { - lightsheet.minify(minify_options)? - } - - let css = match lightsheet.to_css(printer_options) { - Ok(c) => { - drop(lightsheet); - c.code - } - Err(e) => return Err(SabryCompilerError::LightPrint(e)), - }; - - Ok(css) - } -} - -#[cfg(feature = "compile")] -impl From<&SabryConfig> for grass::Options<'_> { - fn from(config: &SabryConfig) -> Self { - let mut options = grass::Options::default(); - options = options.style(if config.css.minify { - grass::OutputStyle::Compressed - } else { - grass::OutputStyle::Expanded - }); - options = options.load_path(&config.sass.intermediate_dir); - - options - } -} - -#[cfg(feature = "compile")] -#[derive(thiserror::Error)] -pub enum SabryCompilerError { - #[error("Could not compile into CSS with grass")] - GrassCompile(#[from] Box), - #[error("Could not print compiled CSS with lightningcss")] - LightPrint(#[from] lightningcss::error::Error), - #[error("Could not minify CSS with lightningcss")] - LightMinify(#[from] lightningcss::error::Error), - #[error("Could not parse CSS with lightningcss")] - LightParse { - kind: String, - loc: Option, - }, -} - -#[cfg(feature = "compile")] -impl std::fmt::Debug for SabryCompilerError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let explain = match self { - Self::LightPrint(e) => format!( - "{} at {:?}", - e.kind, - e.loc - .clone() - .map(|l| format!("file {}, line {}, col {}", l.filename, l.line, l.column)) - ), - Self::GrassCompile(err) => format!("{err}"), - Self::LightMinify(e) => format!( - "{} at {:?}", - e.kind, - e.loc - .clone() - .map(|l| format!("file {}, line {}, col {}", l.filename, l.line, l.column)) - ), - Self::LightParse { kind, loc } => format!( - "{kind} at {:?}", - loc.clone() - .map(|l| format!("file {}, line {}, col {}", l.filename, l.line, l.column)) - ), - }; - - write!(f, "{explain}") - } -} diff --git a/sabry_intrnl/src/config/manifest.rs b/sabry_intrnl/src/conf/manifest.rs similarity index 100% rename from sabry_intrnl/src/config/manifest.rs rename to sabry_intrnl/src/conf/manifest.rs diff --git a/sabry_intrnl/src/conf/mod.rs b/sabry_intrnl/src/conf/mod.rs new file mode 100644 index 0000000..7140697 --- /dev/null +++ b/sabry_intrnl/src/conf/mod.rs @@ -0,0 +1,210 @@ +use std::{path::PathBuf, str::FromStr}; + +#[cfg(feature = "config-manifest")] +pub mod manifest; + +/// Sabry configuration, as it is from package.metadata.sabry +#[derive(Default, Clone)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(default))] +pub struct SabryConfig { + pub css: SabryCssConfig, + pub sass: SabrySassConfig, + pub hash: SabryHashConfig, +} + +impl SabryConfig { + /// Require sabry configuration for the current project from every place in the code + #[cfg(feature = "config-manifest")] + pub fn require() -> Result { + let manifest = manifest::read_manifest()?; + Ok(Self::from(&manifest)) + } +} + +#[cfg(feature = "config-manifest")] +impl From<&manifest::ValuableManifest> for SabryConfig { + fn from(value: &manifest::ValuableManifest) -> Self { + value + .package + .as_ref() + .and_then(|p| p.metadata.as_ref()) + .and_then(|m| m.sabry.as_ref()) + .map_or(Self::default(), |sbr| sbr.clone()) + } +} + +/// Sabry `css` configuration table +#[derive(Clone)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(default))] +pub struct SabryCssConfig { + pub bundle: Option, + pub scopes: Option, + pub prelude: Vec, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryCssConfig::default_minify") + )] + pub minify: bool, +} + +impl SabryCssConfig { + fn default_minify() -> bool { + true + } +} + +impl Default for SabryCssConfig { + fn default() -> Self { + Self { + bundle: None, + scopes: None, + prelude: vec![], + minify: Self::default_minify(), + } + } +} + +/// Sabry `sass` configuration table +/// +/// (SASS/SCSS related config) +#[derive(Clone)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(default))] +pub struct SabrySassConfig { + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabrySassConfig::default_scanroot") + )] + pub scanroot: PathBuf, + pub modules: Option>, + pub prelude: Option>, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabrySassConfig::default_intermediate_dir") + )] + pub intermediate_dir: PathBuf, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabrySassConfig::default_module_name_collision") + )] + pub module_name_collision: BehavSassModCollision, +} + +impl SabrySassConfig { + fn default_scanroot() -> PathBuf { + PathBuf::from_str("src") + .expect("Infallible: default SabrySassConfig::scanroot into PathBuf") + } + fn default_intermediate_dir() -> PathBuf { + PathBuf::from_str("target/.sabry/sass") + .expect("Infallibe: default SabrySassConfig::intermediate_dir into PathBuf") + } + fn default_module_name_collision() -> BehavSassModCollision { + BehavSassModCollision::default() + } +} + +impl Default for SabrySassConfig { + fn default() -> Self { + Self { + scanroot: Self::default_scanroot(), + modules: None, + prelude: None, + intermediate_dir: Self::default_intermediate_dir(), + module_name_collision: Self::default_module_name_collision(), + } + } +} + +/// Sabry `hash` configuration table +#[derive(Clone)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(default))] +pub struct SabryHashConfig { + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_size") + )] + pub size: usize, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_collision") + )] + pub collision: BehavHashCollision, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_use_scope_name") + )] + pub use_scope_name: bool, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_use_item_names") + )] + pub use_item_names: bool, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_use_code_size") + )] + pub use_code_size: bool, + #[cfg_attr( + feature = "config-manifest", + serde(default = "SabryHashConfig::default_use_code_text") + )] + pub use_code_text: bool, +} + +impl SabryHashConfig { + fn default_size() -> usize { + 6 + } + fn default_collision() -> BehavHashCollision { + BehavHashCollision::default() + } + fn default_use_scope_name() -> bool { + true + } + fn default_use_item_names() -> bool { + false + } + fn default_use_code_size() -> bool { + true + } + fn default_use_code_text() -> bool { + false + } +} + +impl Default for SabryHashConfig { + fn default() -> Self { + Self { + size: Self::default_size(), + collision: Self::default_collision(), + use_scope_name: Self::default_use_scope_name(), + use_code_size: Self::default_use_code_size(), + use_code_text: Self::default_use_code_text(), + use_item_names: Self::default_use_item_names(), + } + } +} + +/// \[package.metadata.sabry.sass\].module_name_collision option +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(rename_all = "lowercase"))] +pub enum BehavSassModCollision { + #[default] + Merge, + Error, +} + +/// \[package.metadata.sabry.hash\].collision option +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "config-manifest", derive(serde::Deserialize))] +#[cfg_attr(feature = "config-manifest", serde(rename_all = "lowercase"))] +pub enum BehavHashCollision { + #[default] + Ignore, + Error, +} diff --git a/sabry_intrnl/src/config/mod.rs b/sabry_intrnl/src/config/mod.rs deleted file mode 100644 index 5c4f63b..0000000 --- a/sabry_intrnl/src/config/mod.rs +++ /dev/null @@ -1,246 +0,0 @@ -pub mod manifest; -use manifest::{ManifestError, ValuableManifest}; -use serde::Deserialize; - -/// Sabry configuration, as it is from package.metadata.sabry -#[derive(Default, Deserialize, Clone)] -pub struct SabryConfig { - #[serde(default = "SabryCssConfig::default")] - pub css: SabryCssConfig, - #[serde(default = "SabrySassConfig::default")] - pub sass: SabrySassConfig, - #[serde(default = "SabryHashConfig::default")] - pub hash: SabryHashConfig, - #[serde(default = "SabryGrassConfig::default")] - pub grass: SabryGrassConfig, - #[serde(default = "SabryLightCssConfig::default")] - pub lightningcss: SabryLightCssConfig, -} - -impl SabryConfig { - /// Require sabry configuration for the current project from every place in the code - pub fn require() -> Result { - let manifest = manifest::read_manifest()?; - Ok(Self::from(&manifest)) - } -} - -impl From<&ValuableManifest> for SabryConfig { - fn from(value: &ValuableManifest) -> Self { - value - .package - .as_ref() - .and_then(|p| p.metadata.as_ref()) - .and_then(|m| m.sabry.as_ref()) - .map_or(Self::default(), |sbr| sbr.clone()) - } -} - -/// Sabry `css` configuration table -#[derive(Deserialize, Clone)] -pub struct SabryCssConfig { - pub bundle: Option, - pub scopes: Option, - pub prelude: Option>, - #[serde(default = "SabryCssConfig::default_minify")] - pub minify: bool, -} - -impl SabryCssConfig { - fn default_minify() -> bool { - true - } -} - -impl Default for SabryCssConfig { - fn default() -> Self { - Self { - bundle: None, - scopes: None, - prelude: None, - minify: Self::default_minify(), - } - } -} - -/// Sabry `sass` configuration table -/// -/// (SASS/SCSS related config) -#[derive(Deserialize, Clone)] -pub struct SabrySassConfig { - #[serde(default = "SabrySassConfig::default_scanroot")] - pub scanroot: String, - pub modules: Option>, - pub prelude: Option>, - #[serde(default = "SabrySassConfig::default_intermediate_dir")] - pub intermediate_dir: String, - #[serde(default = "SabrySassConfig::default_module_name_collision")] - pub module_name_collision: BehavSassModCollision, -} - -impl SabrySassConfig { - fn default_scanroot() -> String { - "src".into() - } - fn default_intermediate_dir() -> String { - "target/.sabry/sass".into() - } - fn default_module_name_collision() -> BehavSassModCollision { - BehavSassModCollision::default() - } -} - -impl Default for SabrySassConfig { - fn default() -> Self { - Self { - scanroot: Self::default_scanroot(), - modules: None, - prelude: None, - intermediate_dir: Self::default_intermediate_dir(), - module_name_collision: Self::default_module_name_collision(), - } - } -} - -/// Sabry `hash` configuration table -#[derive(Deserialize, Clone)] -pub struct SabryHashConfig { - #[serde(default = "SabryHashConfig::default_size")] - pub size: usize, - #[serde(default = "SabryHashConfig::default_collision")] - pub collision: BehavHashCollision, - #[serde(default = "SabryHashConfig::default_use_scope_name")] - pub use_scope_name: bool, - #[serde(default = "SabryHashConfig::default_use_item_names")] - pub use_item_names: bool, - #[serde(default = "SabryHashConfig::default_use_code_size")] - pub use_code_size: bool, - #[serde(default = "SabryHashConfig::default_use_code_text")] - pub use_code_text: bool, -} - -impl SabryHashConfig { - fn default_size() -> usize { - 6 - } - fn default_collision() -> BehavHashCollision { - BehavHashCollision::default() - } - fn default_use_scope_name() -> bool { - true - } - fn default_use_item_names() -> bool { - false - } - fn default_use_code_size() -> bool { - true - } - fn default_use_code_text() -> bool { - false - } -} - -impl Default for SabryHashConfig { - fn default() -> Self { - Self { - size: Self::default_size(), - collision: Self::default_collision(), - use_scope_name: Self::default_use_scope_name(), - use_code_size: Self::default_use_code_size(), - use_code_text: Self::default_use_code_text(), - use_item_names: Self::default_use_item_names(), - } - } -} - -/// [grass] specific configuration for sabry -#[derive(Default, Deserialize, Clone)] -pub struct SabryGrassConfig {} - -/// [lightningcss] specific configuration for sabry -#[derive(Default, Deserialize, Clone)] -pub struct SabryLightCssConfig { - pub targets: SabryLightTargets, -} - -/// \[package.metadata.sabry.lightningcss.targets\] configuration. -/// -/// This is a convenience layer under [lightningcss::targets::Browsers] structure accepted -/// by lightningcss. -/// -/// This structure is a part of [SabryConfig], which faces developer with more convenient -/// `safari = "13.2"` syntax. -#[derive(Default, Deserialize, Clone)] -pub struct SabryLightTargets { - pub android: Option, - pub chrome: Option, - pub edge: Option, - pub firefox: Option, - pub ie: Option, - pub ios_saf: Option, - pub opera: Option, - pub safari: Option, - pub samsung: Option, -} - -impl SabryLightTargets { - pub fn parse_ver(ver: &str) -> u32 { - let mut vercode: u32 = 0; - let vers = ver.split('.'); - for (i, dig) in vers.into_iter().enumerate() { - let dignum = dig - .parse::() - .unwrap_or_else(|_| panic!("Invalid browser specifier: '{dig}'")); - - let shift = 16 - 8 * i; - vercode |= dignum << shift; - } - vercode - } -} - -#[cfg(feature = "compile")] -impl From for lightningcss::targets::Browsers { - fn from(value: SabryLightTargets) -> Self { - Self { - android: value.android.map(|s| SabryLightTargets::parse_ver(&s)), - chrome: value.chrome.map(|s| SabryLightTargets::parse_ver(&s)), - edge: value.edge.map(|s| SabryLightTargets::parse_ver(&s)), - firefox: value.firefox.map(|s| SabryLightTargets::parse_ver(&s)), - ie: value.ie.map(|s| SabryLightTargets::parse_ver(&s)), - ios_saf: value.ios_saf.map(|s| SabryLightTargets::parse_ver(&s)), - opera: value.opera.map(|s| SabryLightTargets::parse_ver(&s)), - safari: value.safari.map(|s| SabryLightTargets::parse_ver(&s)), - samsung: value.samsung.map(|s| SabryLightTargets::parse_ver(&s)), - } - } -} - -/// \[package.metadata.sabry.sass\].module_name_collision option -#[derive(Default, Deserialize, Clone, Copy)] -#[serde(rename_all = "lowercase")] -pub enum BehavSassModCollision { - #[default] - Merge, - Error, -} - -/// \[package.metadata.sabry.hash\].collision option -#[derive(Default, Deserialize, Clone, Copy)] -#[serde(rename_all = "lowercase")] -pub enum BehavHashCollision { - #[default] - Ignore, - Error, -} - -#[cfg(test)] -mod test { - use super::{manifest, SabryConfig}; - - #[test] - fn empty_manifest_still_worth_a_read() { - let manifest = manifest::read_manifest().unwrap(); - let _conf = SabryConfig::from(&manifest); - } -} diff --git a/sabry_intrnl/src/lib.rs b/sabry_intrnl/src/lib.rs index 495a300..e23b628 100644 --- a/sabry_intrnl/src/lib.rs +++ b/sabry_intrnl/src/lib.rs @@ -1,6 +1,2 @@ -#![doc = include_str!("../README.md")] - -pub mod compiler; -pub mod config; -pub mod scoper; -pub mod syntax; +pub mod conf; +pub mod style; diff --git a/sabry_intrnl/src/scoper/hash.rs b/sabry_intrnl/src/scoper/hash.rs deleted file mode 100644 index c6e6844..0000000 --- a/sabry_intrnl/src/scoper/hash.rs +++ /dev/null @@ -1,95 +0,0 @@ -/// Convenience wrapper for String-being-a-hash -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ScopeHash(String); - -impl ScopeHash { - #[cfg(feature = "scope")] - pub fn new(scope: &super::ArbitraryScope, config: &crate::config::SabryHashConfig) -> Self { - use base64::Engine; - use raffia::ast::InterpolableIdent; - use std::hash::Hasher; - - use crate::scoper::sanitize_css_member; - - let mut hasher = std::hash::DefaultHasher::new(); - - if config.use_scope_name { - hasher.write(scope.name.to_string().as_bytes()); - } - if config.use_code_text { - hasher.write(scope.adapter().source().as_bytes()); - } - if config.use_code_size { - hasher.write(&scope.adapter().source().len().to_ne_bytes()); - } - if config.use_item_names { - let classes = scope.adapter().class_selectors(); - let ids = scope.adapter().id_selectors(); - //# types/tags dont participate - //# child-parent dont participate - - let merged_items = classes - .iter() - .map(|s| &s.name) - .chain(ids.iter().map(|i| &i.name)) - .map(|ident| match ident { - InterpolableIdent::Literal(lit) => Some(lit), - _ => None, - }) - .filter_map(|mbl| mbl.map(|l| l.raw)) - .collect::(); - - hasher.write(merged_items.as_bytes()); - } - - let hash = hasher.finish().to_be_bytes(); - - let hash = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(hash); - let hash = sanitize_css_member(&hash); - - Self(hash) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - - #[cfg(test)] - pub fn test_init(v: String) -> Self { - Self(v) - } -} - -#[cfg(test)] -mod test { - use syn::Ident; - - use crate::{ - config::SabryHashConfig, scoper::ArbitraryScope, syntax::ostrta::OneSyntaxToRuleThemAll, - }; - - use super::ScopeHash; - - #[test] - fn hash_matches() { - let source = ".cls1{color:red; &-dark{color: black} #id1 {color:green;} div {color:blue;}} .cls3#id2{color: black;}"; - - let scope1 = ArbitraryScope::from_source( - OneSyntaxToRuleThemAll::Scss, - syn::parse_str::("lasifudm").unwrap(), - source, - ) - .unwrap(); - let hash1 = ScopeHash::new(&scope1, &SabryHashConfig::default()); - - let scope2 = ArbitraryScope::from_source( - OneSyntaxToRuleThemAll::Scss, - syn::parse_str::("lasifudm").unwrap(), - source, - ) - .unwrap(); - let hash2 = ScopeHash::new(&scope2, &SabryHashConfig::default()); - - assert_eq!(hash1, hash2); - } -} diff --git a/sabry_intrnl/src/style/compiler.rs b/sabry_intrnl/src/style/compiler.rs new file mode 100644 index 0000000..c875e73 --- /dev/null +++ b/sabry_intrnl/src/style/compiler.rs @@ -0,0 +1,49 @@ +use crate::{conf::SabryConfig, style::syntax::SyntaxKind}; + +/// Convenience wrapper on Grass and Lightningcss +pub struct CompilerAdapter { + #[allow(dead_code)] // without 'compile' feature, still want to set this + config: SabryConfig, +} + +impl CompilerAdapter { + pub fn new(config: SabryConfig) -> Self { + Self { config } + } + + /// Compile given SASS/SCSS into CSS + /// with respect to self.config + pub fn compile_module( + &self, + syntax: SyntaxKind, + code: &str, + ) -> Result { + let importer = sasso::FsImporter::new(self.config.sass.modules.clone().unwrap_or_default()); + let options = sasso::Options::new() + .with_style(if self.config.css.minify { + sasso::OutputStyle::Compressed + } else { + sasso::OutputStyle::Expanded + }) + .with_importer(&importer) + .with_syntax(syntax.into()); + + Ok(sasso::compile(code, &options)?) + } +} + +#[derive(thiserror::Error)] +pub enum SabryCompilerError { + #[error("Could not compile into CSS with sasso")] + Compile(#[from] sasso::Error), +} + +impl std::fmt::Debug for SabryCompilerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let explain = match self { + Self::Compile(err) => format!("{err}"), + }; + + write!(f, "{explain}") + } +} diff --git a/sabry_intrnl/src/style/mod.rs b/sabry_intrnl/src/style/mod.rs new file mode 100644 index 0000000..3d7d6dc --- /dev/null +++ b/sabry_intrnl/src/style/mod.rs @@ -0,0 +1,5 @@ +pub mod scope; +pub mod syntax; + +#[cfg(feature = "style-compiler")] +pub mod compiler; diff --git a/sabry_intrnl/src/scoper/mod.rs b/sabry_intrnl/src/style/scope.rs similarity index 84% rename from sabry_intrnl/src/scoper/mod.rs rename to sabry_intrnl/src/style/scope.rs index 4d6ad29..f6b79f5 100644 --- a/sabry_intrnl/src/scoper/mod.rs +++ b/sabry_intrnl/src/style/scope.rs @@ -1,14 +1,14 @@ use std::fmt::Debug; -use hash::ScopeHash; use raffia::{ Span, Spanned, ast::{InterpolableIdent, TypeSelector}, }; -use crate::syntax::{StylesheetAdapter, ostrta::OneSyntaxToRuleThemAll}; - -pub mod hash; +use crate::{ + conf::SabryHashConfig, + style::syntax::{StylesheetAdapter, SyntaxKind}, +}; #[derive(thiserror::Error)] pub enum ScopeError { @@ -36,7 +36,7 @@ pub struct ArbitraryScope<'s> { impl<'s> ArbitraryScope<'s> { /// Parse given source code with given syntax and assign given name pub fn from_source( - syntax: OneSyntaxToRuleThemAll, + syntax: SyntaxKind, name: syn::Ident, source: &'s str, ) -> Result { @@ -54,11 +54,7 @@ impl<'s> ArbitraryScope<'s> { /// Consume arbitrary scope and create a [HashedScope] in its basis /// /// This function calls [HashedScope::new] under the hood - #[cfg(feature = "scope")] - pub fn hashed( - self, - config: &crate::config::SabryHashConfig, - ) -> Result, ScopeError> { + pub fn hashed(self, config: &SabryHashConfig) -> Result, ScopeError> { let hash = ScopeHash::new(&self, config); HashedScope::new(hash, self) } @@ -309,7 +305,6 @@ impl ScopedSelector { } /// Generate rusty member ident based on selector type and CSS ident - #[cfg(feature = "scope")] pub fn gen_rusty_ident(&self) -> Option { let arb = &self.as_arbitrary().ident; let basic = sanitize_css_member(arb); @@ -375,7 +370,6 @@ impl ScopedSelector { } } -#[cfg(feature = "scope")] pub fn sanitize_css_member(source: &str) -> String { let mut target = String::with_capacity(source.len() + 1); @@ -417,18 +411,77 @@ pub fn sanitize_css_member(source: &str) -> String { target } +/// Convenience wrapper for String-being-a-hash +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ScopeHash(String); + +impl ScopeHash { + pub fn new(scope: &ArbitraryScope, config: &SabryHashConfig) -> Self { + use base64::Engine; + use raffia::ast::InterpolableIdent; + use std::hash::Hasher; + + let mut hasher = std::hash::DefaultHasher::new(); + + if config.use_scope_name { + hasher.write(scope.name.to_string().as_bytes()); + } + if config.use_code_text { + hasher.write(scope.adapter().source().as_bytes()); + } + if config.use_code_size { + hasher.write(&scope.adapter().source().len().to_ne_bytes()); + } + if config.use_item_names { + let classes = scope.adapter().class_selectors(); + let ids = scope.adapter().id_selectors(); + //# types/tags dont participate + //# child-parent dont participate + + let merged_items = classes + .iter() + .map(|s| &s.name) + .chain(ids.iter().map(|i| &i.name)) + .map(|ident| match ident { + InterpolableIdent::Literal(lit) => Some(lit), + _ => None, + }) + .filter_map(|mbl| mbl.map(|l| l.raw)) + .collect::(); + + hasher.write(merged_items.as_bytes()); + } + + let hash = hasher.finish().to_be_bytes(); + + let hash = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(hash); + let hash = sanitize_css_member(&hash); + + Self(hash) + } + + pub fn as_str(&self) -> &str { + &self.0 + } + + #[cfg(test)] + pub fn test_init(v: String) -> Self { + Self(v) + } +} + #[cfg(test)] mod test { + use crate::{ + conf::SabryHashConfig, + style::{scope::HashedScope, syntax::SyntaxKind}, + }; + + use super::ScopeHash; use std::collections::HashSet; use syn::Ident; - use crate::{ - config::SabryHashConfig, - scoper::{HashedScope, hash::ScopeHash}, - syntax::ostrta::OneSyntaxToRuleThemAll, - }; - use super::ArbitraryScope; #[test] @@ -446,12 +499,9 @@ mod test { "".to_string(), // comes from `div` which has no html hashed code, still want to check presense ]); - let scope = ArbitraryScope::from_source( - OneSyntaxToRuleThemAll::Scss, - syn::parse_str("scope1").unwrap(), - code, - ) - .unwrap(); + let scope = + ArbitraryScope::from_source(SyntaxKind::Scss, syn::parse_str("scope1").unwrap(), code) + .unwrap(); let scope = HashedScope::new(hash, scope).unwrap(); let scope_selector_htmls = scope .hashed_selectors @@ -495,7 +545,7 @@ mod test { let hash_cfg = SabryHashConfig::default(); let scope = ArbitraryScope::from_source( - OneSyntaxToRuleThemAll::Scss, + SyntaxKind::Scss, syn::parse_str::("scope2oiej").unwrap(), code, ) @@ -512,4 +562,27 @@ mod test { assert_eq!(expect_ident_names, sels); } + + #[test] + fn hash_matches() { + let source = ".cls1{color:red; &-dark{color: black} #id1 {color:green;} div {color:blue;}} .cls3#id2{color: black;}"; + + let scope1 = ArbitraryScope::from_source( + SyntaxKind::Scss, + syn::parse_str::("lasifudm").unwrap(), + source, + ) + .unwrap(); + let hash1 = ScopeHash::new(&scope1, &SabryHashConfig::default()); + + let scope2 = ArbitraryScope::from_source( + SyntaxKind::Scss, + syn::parse_str::("lasifudm").unwrap(), + source, + ) + .unwrap(); + let hash2 = ScopeHash::new(&scope2, &SabryHashConfig::default()); + + assert_eq!(hash1, hash2); + } } diff --git a/sabry_intrnl/src/syntax/mod.rs b/sabry_intrnl/src/style/syntax.rs similarity index 78% rename from sabry_intrnl/src/syntax/mod.rs rename to sabry_intrnl/src/style/syntax.rs index d1d8c67..c2997c8 100644 --- a/sabry_intrnl/src/syntax/mod.rs +++ b/sabry_intrnl/src/style/syntax.rs @@ -1,26 +1,20 @@ -use ostrta::OneSyntaxToRuleThemAll; use raffia::{ + ParserBuilder, ast::{ ClassSelector, ComplexSelectorChild, CompoundSelector, IdSelector, InterpolableIdent, NestingSelector, PseudoClassSelector, SimpleSelector, Statement, Stylesheet, TypeSelector, }, - ParserBuilder, }; -pub mod ostrta; - /// Convenience wrapper for [Stylesheet] pub struct StylesheetAdapter<'s> { - pub syntax: OneSyntaxToRuleThemAll, + pub syntax: SyntaxKind, source: &'s str, stylesheet: Stylesheet<'s>, } impl<'s> StylesheetAdapter<'s> { - pub fn new( - source: &'s str, - syntax: OneSyntaxToRuleThemAll, - ) -> Result { + pub fn new(source: &'s str, syntax: SyntaxKind) -> Result { Ok(Self { stylesheet: ParserBuilder::new(source) .ignore_comments() @@ -141,16 +135,82 @@ impl<'s> StylesheetAdapter<'s> { } } +/// Convenience unification entrypoint +/// to make friends with all the different syntax-consumers +#[derive(Default, Debug, Clone, Copy)] +pub enum SyntaxKind { + #[default] + Scss, + Sass, + Css, +} + +impl TryFrom<&str> for SyntaxKind { + type Error = (); + fn try_from(value: &str) -> Result { + match value { + "sass" => Ok(Self::Sass), + "scss" => Ok(Self::Scss), + "css" => Ok(Self::Css), + _ => Err(()), + } + } +} + +impl TryFrom for SyntaxKind { + type Error = (); + fn try_from(value: raffia::Syntax) -> Result { + match value { + raffia::Syntax::Sass => Ok(Self::Sass), + raffia::Syntax::Scss => Ok(Self::Scss), + raffia::Syntax::Css => Ok(Self::Css), + _ => Err(()), + } + } +} + +#[cfg(feature = "style-compiler")] +impl From for SyntaxKind { + fn from(value: sasso::Syntax) -> Self { + match value { + sasso::Syntax::Sass => Self::Sass, + sasso::Syntax::Scss => Self::Scss, + sasso::Syntax::Css => Self::Css, + } + } +} + +impl From for raffia::Syntax { + fn from(value: SyntaxKind) -> Self { + match value { + SyntaxKind::Sass => Self::Sass, + SyntaxKind::Scss => Self::Scss, + SyntaxKind::Css => Self::Css, + } + } +} + +#[cfg(feature = "style-compiler")] +impl From for sasso::Syntax { + fn from(value: SyntaxKind) -> Self { + match value { + SyntaxKind::Scss => Self::Scss, + SyntaxKind::Sass => Self::Sass, + SyntaxKind::Css => Self::Css, + } + } +} + #[cfg(test)] mod test { use std::collections::HashSet; use raffia::{ - ast::{InterpolableIdent, TypeSelector}, Spanned, + ast::{InterpolableIdent, TypeSelector}, }; - use crate::syntax::ostrta::OneSyntaxToRuleThemAll; + use crate::style::syntax::SyntaxKind; use super::StylesheetAdapter; @@ -206,7 +266,7 @@ div#id2 let expect_tags = HashSet::from(["ul", "div", "span"]); //scss - let adp = StylesheetAdapter::new(source_scss, OneSyntaxToRuleThemAll::Scss).unwrap(); + let adp = StylesheetAdapter::new(source_scss, SyntaxKind::Scss).unwrap(); let classes = adp .class_selectors() @@ -244,7 +304,7 @@ div#id2 assert_eq!(expect_tags, tags); //sass - let adp = StylesheetAdapter::new(source_sass, OneSyntaxToRuleThemAll::Sass).unwrap(); + let adp = StylesheetAdapter::new(source_sass, SyntaxKind::Sass).unwrap(); let classes = adp .class_selectors() @@ -288,7 +348,7 @@ div#id2 let newname = "cls203-jg7ihgjhftyfhjh"; let expect = ".cls1{color:red; .cls203-jg7ihgjhftyfhjh{color:green;}}"; - let adp = StylesheetAdapter::new(scss, OneSyntaxToRuleThemAll::Scss).unwrap(); + let adp = StylesheetAdapter::new(scss, SyntaxKind::Scss).unwrap(); let classes = adp.class_selectors(); let target_class = classes[0].clone(); diff --git a/sabry_intrnl/src/syntax/ostrta.rs b/sabry_intrnl/src/syntax/ostrta.rs deleted file mode 100644 index bf320a0..0000000 --- a/sabry_intrnl/src/syntax/ostrta.rs +++ /dev/null @@ -1,61 +0,0 @@ -/// Convenience unification entrypoint -/// to make friends with all the different syntax-consumers -#[derive(Default, Debug, Clone, Copy)] -pub enum OneSyntaxToRuleThemAll { - #[default] - Scss, - Sass, -} - -impl TryFrom<&str> for OneSyntaxToRuleThemAll { - type Error = (); - fn try_from(value: &str) -> Result { - match value { - "sass" => Ok(Self::Sass), - "scss" => Ok(Self::Scss), - _ => Err(()), - } - } -} - -impl TryFrom for OneSyntaxToRuleThemAll { - type Error = (); - fn try_from(value: raffia::Syntax) -> Result { - match value { - raffia::Syntax::Sass => Ok(Self::Sass), - raffia::Syntax::Scss => Ok(Self::Scss), - _ => Err(()), - } - } -} - -#[cfg(feature = "compile")] -impl TryFrom for OneSyntaxToRuleThemAll { - type Error = (); - fn try_from(value: grass::InputSyntax) -> Result { - match value { - grass::InputSyntax::Sass => Ok(Self::Sass), - grass::InputSyntax::Scss => Ok(Self::Scss), - _ => Err(()), - } - } -} - -impl From for raffia::Syntax { - fn from(value: OneSyntaxToRuleThemAll) -> Self { - match value { - OneSyntaxToRuleThemAll::Sass => Self::Sass, - OneSyntaxToRuleThemAll::Scss => Self::Scss, - } - } -} - -#[cfg(feature = "compile")] -impl From for grass::InputSyntax { - fn from(value: OneSyntaxToRuleThemAll) -> Self { - match value { - OneSyntaxToRuleThemAll::Scss => Self::Scss, - OneSyntaxToRuleThemAll::Sass => Self::Sass, - } - } -} diff --git a/sabry_procmacro/Cargo.toml b/sabry_procmacro/Cargo.toml index 99262d8..caff4a6 100644 --- a/sabry_procmacro/Cargo.toml +++ b/sabry_procmacro/Cargo.toml @@ -19,5 +19,4 @@ proc-macro = true sabry_procmacro_impl.workspace = true [features] -const-compile = ["sabry_procmacro_impl/const-compile"] nightly = ["sabry_procmacro_impl/nightly"] diff --git a/sabry_procmacro_impl/Cargo.toml b/sabry_procmacro_impl/Cargo.toml index 229540a..551237e 100644 --- a/sabry_procmacro_impl/Cargo.toml +++ b/sabry_procmacro_impl/Cargo.toml @@ -13,18 +13,21 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cfg-if.workspace = true +## Workspace +sabry_intrnl.workspace = true +sabry_intrnl.features = ["config-manifest", "style-compiler"] +## Css +raffia.workspace = true +## Util itertools.workspace = true +regex.workspace = true +## Codegen +thiserror.workspace = true proc-macro2.workspace = true proc-macro2.features = ["span-locations"] quote.workspace = true -raffia.workspace = true -regex.workspace = true -sabry_intrnl.workspace = true -sabry_intrnl.features = ["scope"] syn.workspace = true syn.features = ["parsing"] [features] -const-compile = ["sabry_intrnl/compile"] nightly = [] diff --git a/sabry_procmacro_impl/src/impls/mod.rs b/sabry_procmacro_impl/src/impls/mod.rs index eaac922..a82dcb4 100644 --- a/sabry_procmacro_impl/src/impls/mod.rs +++ b/sabry_procmacro_impl/src/impls/mod.rs @@ -3,7 +3,7 @@ use std::{fmt::Debug, fs, path::PathBuf, str::FromStr}; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use regex::Regex; -use sabry_intrnl::syntax::ostrta::OneSyntaxToRuleThemAll; +use sabry_intrnl::style::syntax::SyntaxKind; use syn::{Ident, LitStr, Token, braced, parse::Parse}; pub mod scssy; @@ -96,9 +96,9 @@ impl ToString for ArbitraryStyleBlock { } #[derive(Default, Debug, Clone, Copy)] -pub struct ArbitraryStyleSyntax(OneSyntaxToRuleThemAll); +pub struct ArbitraryStyleSyntax(SyntaxKind); -impl From for OneSyntaxToRuleThemAll { +impl From for SyntaxKind { fn from(value: ArbitraryStyleSyntax) -> Self { value.0 } @@ -107,8 +107,9 @@ impl From for OneSyntaxToRuleThemAll { impl ToTokens for ArbitraryStyleSyntax { fn to_tokens(&self, tokens: &mut TokenStream) { match self.0 { - OneSyntaxToRuleThemAll::Sass => tokens.append_all(quote! {"sass"}), - OneSyntaxToRuleThemAll::Scss => tokens.append_all(quote! {"scss"}), + SyntaxKind::Sass => tokens.append_all(quote! {"sass"}), + SyntaxKind::Scss => tokens.append_all(quote! {"scss"}), + SyntaxKind::Css => tokens.append_all(quote! {"css"}), } } } @@ -116,7 +117,7 @@ impl ToTokens for ArbitraryStyleSyntax { impl TryFrom<&str> for ArbitraryStyleSyntax { type Error = (); fn try_from(value: &str) -> Result { - Ok(Self(OneSyntaxToRuleThemAll::try_from(value)?)) + Ok(Self(SyntaxKind::try_from(value)?)) } } diff --git a/sabry_procmacro_impl/src/impls/scssy.rs b/sabry_procmacro_impl/src/impls/scssy.rs index 7ab9854..c3eb91d 100644 --- a/sabry_procmacro_impl/src/impls/scssy.rs +++ b/sabry_procmacro_impl/src/impls/scssy.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use proc_macro2::TokenStream; use quote::quote; -use sabry_intrnl::scoper::ArbitraryScope; +use sabry_intrnl::style::scope::ArbitraryScope; use syn::{Ident, parse::ParseStream}; use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax}; @@ -67,12 +67,3 @@ impl MacroSyntax { }) } } - -// impl Parse for MacroSyntax { -// fn parse(input: syn::parse::ParseStream) -> syn::Result { -// Self::parse_syn(input, None) -// } -// } - -#[cfg(test)] -mod test {} diff --git a/sabry_procmacro_impl/src/impls/styly.rs b/sabry_procmacro_impl/src/impls/styly.rs index cf0d81b..459e175 100644 --- a/sabry_procmacro_impl/src/impls/styly.rs +++ b/sabry_procmacro_impl/src/impls/styly.rs @@ -1,12 +1,14 @@ use std::path::PathBuf; -use cfg_if::cfg_if; use itertools::Itertools; use proc_macro2::{Span, TokenStream}; use quote::quote; use sabry_intrnl::{ - config::SabryConfig, - scoper::{ArbitraryScope, ScopedSelector, sanitize_css_member}, + conf::SabryConfig, + style::{ + compiler::CompilerAdapter, + scope::{ArbitraryScope, ScopedSelector, sanitize_css_member}, + }, }; use syn::{ Ident, Token, @@ -102,7 +104,7 @@ pub fn styly_macro_impl(input: TokenStream, source_path: PathBuf) -> TokenStream let ident = sanitize_css_member(&s); let fnident = syn::parse_str::(format!("_{ident}").as_str()) .expect("BUG: invalid ident for nesting selector formed"); - let formatstr = format!("{{c}}{}", &s); + let formatstr = format!("{{c}}{}", s); let doc = format!("Nesting selector. Originated from '&{s}'"); quote! { @@ -152,53 +154,42 @@ pub fn styly_macro_impl(input: TokenStream, source_path: PathBuf) -> TokenStream let mod_docs = format!( "'{}' style scope. The hash class is `{}`", - &scope_ident, &scope_wrapper_ident + scope_ident, scope_wrapper_ident ); let wrp_docs = format!( "hash class for '{}' scope. All HTML elements should have this class applied", - &scope_ident + scope_ident ); if constant { - cfg_if! { - if #[cfg(feature = "const-compile")] { - use sabry_intrnl::compiler::CompilerAdapter; - let compiler = CompilerAdapter::new(config.clone()); - let css = match compiler.compile_module(ms.syntax.0, &scope.hashed_code) { - Ok(c) => c, - Err(e) => { - return syn::Error::new( - ms.code.span, - format!("Could not compile const inline: {e:?}"), - ) - .to_compile_error() - } - }; - - let const_docs = format!("The compiled CSS style for {} scope", &scope_ident); - let const_wrapper_ident = syn::parse_str::( - format!("{}_CSS", &scope_ident.to_string().to_uppercase()).as_str(), - ) - .expect("BUG: We just converted valid Ident to string and uppercased"); - - quote! { - #[doc = #const_docs] - #scope_vis const #const_wrapper_ident: &str = #css ; - #[doc = #wrp_docs] - #scope_vis const #scope_wrapper_ident : &str = #scope_hash ; - #[doc = #mod_docs] - #scope_vis mod #scope_ident { - #(#scope_members)* - #(#special_nesting_members)* - } - } - } else { + let compiler = CompilerAdapter::new(config.clone()); + let css = match compiler.compile_module(ms.syntax.0, &scope.hashed_code) { + Ok(c) => c, + Err(e) => { return syn::Error::new( - Span::call_site(), - "`styly!(const scope...` requires `experimental-const-scoping` feature flag", + ms.code.span, + format!("Could not compile const inline: {e:?}"), ) .to_compile_error(); } + }; + + let const_docs = format!("The compiled CSS style for {} scope", scope_ident); + let const_wrapper_ident = syn::parse_str::( + format!("{}_CSS", scope_ident.to_string().to_uppercase()).as_str(), + ) + .expect("BUG: We just converted valid Ident to string and uppercased"); + + quote! { + #[doc = #const_docs] + #scope_vis const #const_wrapper_ident: &str = #css ; + #[doc = #wrp_docs] + #scope_vis const #scope_wrapper_ident : &str = #scope_hash ; + #[doc = #mod_docs] + #scope_vis mod #scope_ident { + #(#scope_members)* + #(#special_nesting_members)* + } } } else { quote! { diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 4cc9d27..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![doc = include_str!("../README.md")] -#![cfg_attr(docsrs, feature(doc_cfg))] - -#[cfg_attr(docsrs, doc(cfg(feature = "build")))] -#[cfg(feature = "build")] -pub use sabry_build::buildmagic::buildy; -#[cfg_attr(docsrs, doc(cfg(feature = "procmacro")))] -#[cfg(feature = "procmacro")] -pub use sabry_procmacro::*; - -// reexports -#[cfg_attr(docsrs, doc(cfg(all(feature = "build", feature = "internals"))))] -#[cfg(all(feature = "build", feature = "internals"))] -pub use sabry_build::*; - -#[cfg_attr(docsrs, doc(cfg(all(feature = "procmacro", feature = "internals"))))] -#[cfg(all(feature = "procmacro", feature = "internals"))] -pub use sabry_intrnl::*;