diff --git a/Cargo.lock b/Cargo.lock index 0e7e8d2d7..d3afa8eae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -22,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ "anstyle", "anstyle-parse", @@ -89,7 +95,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -176,9 +182,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" @@ -271,9 +277,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytecount" @@ -326,13 +332,13 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -341,9 +347,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" dependencies = [ "clap_builder", "clap_derive", @@ -352,9 +358,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", @@ -365,31 +371,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "colorchoice" @@ -427,15 +423,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.5" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -515,50 +511,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "darling" version = "0.14.4" @@ -640,9 +592,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -757,7 +709,7 @@ dependencies = [ name = "file_upload" version = "0.1.0" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "gloo", "js-sys", "web-sys", @@ -912,7 +864,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -982,9 +934,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7905cdfe33d31a88bb2e8419ddd054451f5432d1da9eaf2ac7804ee1ea12d5" +checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044" dependencies = [ "bitflags", "libc", @@ -1188,9 +1140,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" dependencies = [ "bytes", "fnv", @@ -1365,12 +1317,11 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] @@ -1420,11 +1371,12 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.3" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" +checksum = "db45317f37ef454e6519b6c3ed7d377e5f23346f0823f86e65ca36912d1d0ef8" dependencies = [ "console", + "instant", "number_prefix", "portable-atomic", "unicode-width", @@ -1453,9 +1405,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -1588,15 +1540,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libgit2-sys" -version = "0.15.1+1.6.4" +version = "0.15.2+1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4577bde8cdfc7d6a2a4bcb7b049598597de33ffd337276e9c7db6cd4a2cee7" +checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa" dependencies = [ "cc", "libc", @@ -1608,9 +1560,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libssh2-sys" @@ -1638,20 +1590,11 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "linux-raw-sys" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lipsum" @@ -1675,12 +1618,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "matchit" @@ -1712,14 +1652,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1794,16 +1733,6 @@ dependencies = [ "yew", ] -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -1832,15 +1761,15 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" [[package]] name = "openssl" -version = "0.10.52" +version = "0.10.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" +checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" dependencies = [ "bitflags", "cfg-if", @@ -1859,7 +1788,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -1870,9 +1799,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" dependencies = [ "cc", "libc", @@ -1920,7 +1849,7 @@ version = "0.1.0" dependencies = [ "chrono", "js-sys", - "time 0.3.20", + "time 0.3.21", "wasm-bindgen", "web-sys", "yew", @@ -1935,22 +1864,22 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.18", ] [[package]] @@ -1978,15 +1907,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "portable-atomic" -version = "0.3.19" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" +checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794" [[package]] name = "portals" @@ -2006,12 +1935,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058" +checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1" dependencies = [ "proc-macro2", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2040,9 +1969,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -2075,9 +2004,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ "bitflags", "memchr", @@ -2149,9 +2078,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ "aho-corasick", "memchr", @@ -2160,17 +2089,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "reqwest" -version = "0.11.17" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -2235,9 +2164,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.17" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc809f704c03a812ac71f22456c857be34185cac691a4316f27ab0f633bb9009" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", @@ -2253,7 +2182,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", ] [[package]] @@ -2289,17 +2218,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "security-framework" -version = "2.8.2" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ "bitflags", "core-foundation", @@ -2310,9 +2233,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" dependencies = [ "core-foundation-sys", "libc", @@ -2326,9 +2249,9 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] @@ -2346,13 +2269,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2528,9 +2451,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -2606,7 +2529,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2622,9 +2545,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" dependencies = [ "serde", "time-core", @@ -2632,9 +2555,9 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "timer" @@ -2685,9 +2608,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.28.1" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", @@ -2710,7 +2633,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2833,14 +2756,14 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", ] @@ -2916,9 +2839,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -2972,9 +2895,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ "serde", ] @@ -3065,7 +2988,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", "wasm-bindgen-shared", ] @@ -3099,7 +3022,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3147,9 +3070,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", @@ -3450,7 +3373,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.15", + "syn 2.0.18", "trybuild", "yew", ] @@ -3479,7 +3402,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.15", + "syn 2.0.18", "trybuild", "yew-router", ] @@ -3509,5 +3432,5 @@ dependencies = [ "lazy_static", "quick-error", "regex", - "time 0.3.20", + "time 0.3.21", ] diff --git a/examples/contexts/src/msg_ctx.rs b/examples/contexts/src/msg_ctx.rs index 3a24deebb..ceebd199d 100644 --- a/examples/contexts/src/msg_ctx.rs +++ b/examples/contexts/src/msg_ctx.rs @@ -20,7 +20,7 @@ pub type MessageContext = UseReducerHandle; #[derive(Properties, Debug, PartialEq)] pub struct MessageProviderProps { #[prop_or_default] - pub children: Children, + pub children: Html, } #[function_component] diff --git a/examples/function_todomvc/src/state.rs b/examples/function_todomvc/src/state.rs index 8a635fed8..1a461b59e 100644 --- a/examples/function_todomvc/src/state.rs +++ b/examples/function_todomvc/src/state.rs @@ -42,6 +42,12 @@ impl Filter { } } +impl ToHtml for Filter { + fn to_html(&self) -> Html { + html! {<>{self.to_string()}} + } +} + pub enum Action { Add(String), Edit((usize, String)), diff --git a/examples/futures/src/markdown.rs b/examples/futures/src/markdown.rs index e51729308..5c85b7a55 100644 --- a/examples/futures/src/markdown.rs +++ b/examples/futures/src/markdown.rs @@ -54,10 +54,12 @@ pub fn render_markdown(src: &str) -> Html { top = pre; } else if let Tag::Table(aligns) = tag { if let Some(top_children) = top.children_mut() { - for r in top_children.iter_mut() { + for r in top_children.to_vlist_mut().iter_mut() { if let VNode::VTag(ref mut vtag) = r { if let Some(vtag_children) = vtag.children_mut() { - for (i, c) in vtag_children.iter_mut().enumerate() { + for (i, c) in + vtag_children.to_vlist_mut().iter_mut().enumerate() + { if let VNode::VTag(ref mut vtag) = c { match aligns[i] { Alignment::None => {} @@ -73,7 +75,7 @@ pub fn render_markdown(src: &str) -> Html { } } else if let Tag::TableHead = tag { if let Some(top_children) = top.children_mut() { - for c in top_children.iter_mut() { + for c in top_children.to_vlist_mut().iter_mut() { if let VNode::VTag(ref mut vtag) = c { // TODO // vtag.tag = "th".into(); diff --git a/examples/nested_list/src/main.rs b/examples/nested_list/src/main.rs index 881c0471b..3f8a93def 100644 --- a/examples/nested_list/src/main.rs +++ b/examples/nested_list/src/main.rs @@ -8,7 +8,8 @@ use std::fmt; use std::ops::Deref; use std::rc::Rc; -use yew::html::{Component, ImplicitClone, Scope}; +use yew::html::{ImplicitClone, Scope}; +use yew::prelude::*; pub struct WeakComponentLink(Rc>>>); @@ -62,6 +63,12 @@ impl fmt::Display for Hovered { } } +impl ToHtml for Hovered { + fn to_html(&self) -> yew::Html { + html! {<>{self.to_string()}} + } +} + fn main() { wasm_logger::init(wasm_logger::Config::default()); yew::Renderer::::new().render(); diff --git a/examples/portals/src/main.rs b/examples/portals/src/main.rs index c8eb6132e..611939717 100644 --- a/examples/portals/src/main.rs +++ b/examples/portals/src/main.rs @@ -1,11 +1,11 @@ use wasm_bindgen::JsCast; use web_sys::{Element, ShadowRootInit, ShadowRootMode}; -use yew::{create_portal, html, Children, Component, Context, Html, NodeRef, Properties}; +use yew::{create_portal, html, Component, Context, Html, NodeRef, Properties}; #[derive(Properties, PartialEq)] pub struct ShadowDOMProps { #[prop_or_default] - pub children: Children, + pub children: Html, } pub struct ShadowDOMHost { @@ -50,12 +50,7 @@ impl Component for ShadowDOMHost { fn view(&self, ctx: &Context) -> Html { let contents = if let Some(ref inner_host) = self.inner_host { - create_portal( - html! { - {for ctx.props().children.iter()} - }, - inner_host.clone(), - ) + create_portal(ctx.props().children.clone(), inner_host.clone()) } else { html! { <> } }; diff --git a/examples/todomvc/src/state.rs b/examples/todomvc/src/state.rs index 9c0640612..251c4925e 100644 --- a/examples/todomvc/src/state.rs +++ b/examples/todomvc/src/state.rs @@ -1,5 +1,6 @@ use serde_derive::{Deserialize, Serialize}; use strum_macros::{Display, EnumIter}; +use yew::prelude::*; #[derive(Debug, Serialize, Deserialize)] pub struct State { @@ -140,3 +141,9 @@ impl Filter { } } } + +impl ToHtml for Filter { + fn to_html(&self) -> yew::Html { + html! { <>{self.to_string()} } + } +} diff --git a/packages/yew-macro/src/html_tree/html_component.rs b/packages/yew-macro/src/html_tree/html_component.rs index d030e24d3..58e589883 100644 --- a/packages/yew-macro/src/html_tree/html_component.rs +++ b/packages/yew-macro/src/html_tree/html_component.rs @@ -133,11 +133,7 @@ impl ToTokens for HtmlComponent { let ty_span = ty.span().resolved_at(Span::call_site()); let props_ty = quote_spanned!(ty_span=> <#ty as ::yew::html::BaseComponent>::Properties); - let children_renderer = if children.is_empty() { - None - } else { - Some(quote! { ::yew::html::ChildrenRenderer::new(#children) }) - }; + let children_renderer = children.to_children_renderer_tokens(); let build_props = props.build_properties_tokens(&props_ty, children_renderer); let key = props.special().wrap_key_attr(); let use_close_tag = close diff --git a/packages/yew-macro/src/html_tree/html_element.rs b/packages/yew-macro/src/html_tree/html_element.rs index 999a2afeb..cbe75b38c 100644 --- a/packages/yew-macro/src/html_tree/html_element.rs +++ b/packages/yew-macro/src/html_tree/html_element.rs @@ -313,12 +313,7 @@ impl ToTokens for HtmlElement { // TODO: if none of the children have possibly None expressions or literals as keys, we can // compute `VList.fully_keyed` at compile time. - let child_list = quote! { - ::yew::virtual_dom::VList::with_children( - #children, - ::std::option::Option::None, - ) - }; + let children = children.to_vnode_tokens(); tokens.extend(match &name { TagName::Lit(dashedname) => { @@ -370,7 +365,7 @@ impl ToTokens for HtmlElement { #key, #attributes, #listeners, - #child_list, + #children, ), ) } @@ -392,6 +387,8 @@ impl ToTokens for HtmlElement { let expr = &name.expr; let vtag_name = Ident::new("__yew_vtag_name", expr.span()); + let void_children = Ident::new("__yew_void_children", Span::mixed_site()); + // handle special attribute value let handle_value_attr = props.value.as_ref().map(|prop| { let v = prop.value.optimize_literals(); @@ -455,7 +452,7 @@ impl ToTokens for HtmlElement { #key, #attributes, #listeners, - #child_list, + #children, ); #handle_value_attr @@ -468,7 +465,10 @@ impl ToTokens for HtmlElement { // For literal tags this is already done at compile-time. // // check void element - if !#vtag.children().is_empty() { + if !::std::matches!( + ::yew::virtual_dom::VTag::children(&#vtag), + ::std::option::Option::Some(::yew::virtual_dom::VNode::VList(ref #void_children)) if ::std::vec::Vec::is_empty(#void_children) + ) { ::std::debug_assert!( !::std::matches!(#vtag.tag().to_ascii_lowercase().as_str(), "area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input" diff --git a/packages/yew-macro/src/html_tree/mod.rs b/packages/yew-macro/src/html_tree/mod.rs index f023b239b..0361231b6 100644 --- a/packages/yew-macro/src/html_tree/mod.rs +++ b/packages/yew-macro/src/html_tree/mod.rs @@ -29,6 +29,8 @@ use html_list::HtmlList; use html_node::HtmlNode; use tag::TagTokens; +use self::html_block::BlockContent; + pub enum HtmlType { Block, Component, @@ -280,6 +282,64 @@ impl HtmlChildrenTree { Ok(children) } + + pub fn to_children_renderer_tokens(&self) -> Option { + match self.0[..] { + [] => None, + [HtmlTree::Component(ref children)] => Some(quote! { #children }), + [HtmlTree::Element(ref children)] => Some(quote! { #children }), + [HtmlTree::Block(ref m)] => { + // We only want to process `{vnode}` and not `{for vnodes}`. + // This should be converted into a if let guard once https://github.com/rust-lang/rust/issues/51114 is stable. + // Or further nested once deref pattern (https://github.com/rust-lang/rust/issues/87121) is stable. + if let HtmlBlock { + content: BlockContent::Node(children), + .. + } = m.as_ref() + { + Some(quote! { #children }) + } else { + Some(quote! { ::yew::html::ChildrenRenderer::new(#self) }) + } + } + _ => Some(quote! { ::yew::html::ChildrenRenderer::new(#self) }), + } + } + + pub fn to_vnode_tokens(&self) -> TokenStream { + match self.0[..] { + [] => quote! {::std::default::Default::default() }, + [HtmlTree::Component(ref children)] => { + quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) } + } + [HtmlTree::Element(ref children)] => { + quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) } + } + [HtmlTree::Block(ref m)] => { + // We only want to process `{vnode}` and not `{for vnodes}`. + // This should be converted into a if let guard once https://github.com/rust-lang/rust/issues/51114 is stable. + // Or further nested once deref pattern (https://github.com/rust-lang/rust/issues/87121) is stable. + if let HtmlBlock { + content: BlockContent::Node(children), + .. + } = m.as_ref() + { + quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) } + } else { + quote! { + ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value( + ::yew::html::ChildrenRenderer::new(#self) + ) + } + } + } + _ => quote! { + ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value( + ::yew::html::ChildrenRenderer::new(#self) + ) + }, + } + } } impl ToTokens for HtmlChildrenTree { diff --git a/packages/yew-macro/src/props/component.rs b/packages/yew-macro/src/props/component.rs index 3d76090e2..3c0984e61 100644 --- a/packages/yew-macro/src/props/component.rs +++ b/packages/yew-macro/src/props/component.rs @@ -131,7 +131,7 @@ impl ComponentProps { }); let set_children = children_renderer.map(|children| { quote_spanned! {props_ty.span()=> - #ident.children = #children; + #ident.children = ::yew::html::IntoPropValue::into_prop_value(#children); } }); let init_base = quote_spanned! {expr.span().resolved_at(Span::call_site())=> diff --git a/packages/yew-macro/tests/html_macro/block-fail.stderr b/packages/yew-macro/tests/html_macro/block-fail.stderr index 2ef397854..e659ec66f 100644 --- a/packages/yew-macro/tests/html_macro/block-fail.stderr +++ b/packages/yew-macro/tests/html_macro/block-fail.stderr @@ -13,21 +13,6 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` = note: required because of the requirements on the impl of `Into>` for `()` = note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: `()` doesn't implement `std::fmt::Display` - --> tests/html_macro/block-fail.rs:12:16 - | -12 |
{ not_tree() }
- | ^^^^^^^^ `()` cannot be formatted with the default formatter - | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required because of the requirements on the impl of `ToString` for `()` - = note: required because of the requirements on the impl of `From<()>` for `VNode` - = note: required because of the requirements on the impl of `Into` for `()` - = note: 2 redundant requirements hidden - = note: required because of the requirements on the impl of `Into>` for `()` - = note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0277]: `()` doesn't implement `std::fmt::Display` --> tests/html_macro/block-fail.rs:15:17 | diff --git a/packages/yew-macro/tests/html_macro/component-any-children-pass.rs b/packages/yew-macro/tests/html_macro/component-any-children-pass.rs new file mode 100644 index 000000000..cf5a924e5 --- /dev/null +++ b/packages/yew-macro/tests/html_macro/component-any-children-pass.rs @@ -0,0 +1,332 @@ +#![no_implicit_prelude] + +// Shadow primitives +#[allow(non_camel_case_types)] +pub struct bool; +#[allow(non_camel_case_types)] +pub struct char; +#[allow(non_camel_case_types)] +pub struct f32; +#[allow(non_camel_case_types)] +pub struct f64; +#[allow(non_camel_case_types)] +pub struct i128; +#[allow(non_camel_case_types)] +pub struct i16; +#[allow(non_camel_case_types)] +pub struct i32; +#[allow(non_camel_case_types)] +pub struct i64; +#[allow(non_camel_case_types)] +pub struct i8; +#[allow(non_camel_case_types)] +pub struct isize; +#[allow(non_camel_case_types)] +pub struct str; +#[allow(non_camel_case_types)] +pub struct u128; +#[allow(non_camel_case_types)] +pub struct u16; +#[allow(non_camel_case_types)] +pub struct u32; +#[allow(non_camel_case_types)] +pub struct u64; +#[allow(non_camel_case_types)] +pub struct u8; +#[allow(non_camel_case_types)] +pub struct usize; + +#[derive( + ::std::clone::Clone, ::yew::Properties, ::std::default::Default, ::std::cmp::PartialEq, +)] +pub struct ContainerProperties { + pub int: ::std::primitive::i32, + // You can use Html as Children. + #[prop_or_default] + pub children: ::yew::Html, + #[prop_or_default] + pub header: ::yew::Html, +} + +pub struct Container; +impl ::yew::Component for Container { + type Message = (); + type Properties = ContainerProperties; + + fn create(_ctx: &::yew::Context) -> Self { + ::std::unimplemented!() + } + + fn view(&self, _ctx: &::yew::Context) -> ::yew::Html { + ::std::unimplemented!() + } +} + +#[derive(::std::clone::Clone, ::std::cmp::PartialEq)] +pub enum ChildrenVariants { + Child(::yew::virtual_dom::VChild), + AltChild(::yew::virtual_dom::VChild), +} + +impl ::std::convert::From<::yew::virtual_dom::VChild> for ChildrenVariants { + fn from(comp: ::yew::virtual_dom::VChild) -> Self { + ChildrenVariants::Child(comp) + } +} + +impl ::std::convert::From<::yew::virtual_dom::VChild> for ChildrenVariants { + fn from(comp: ::yew::virtual_dom::VChild) -> Self { + ChildrenVariants::AltChild(comp) + } +} + +impl ::std::convert::Into<::yew::virtual_dom::VNode> for ChildrenVariants { + fn into(self) -> ::yew::virtual_dom::VNode { + match self { + Self::Child(comp) => ::yew::virtual_dom::VNode::VComp(::std::convert::Into::< + ::yew::virtual_dom::VComp, + >::into(comp)), + Self::AltChild(comp) => ::yew::virtual_dom::VNode::VComp(::std::convert::Into::< + ::yew::virtual_dom::VComp, + >::into(comp)), + } + } +} + +#[derive( + ::std::clone::Clone, ::yew::Properties, ::std::default::Default, ::std::cmp::PartialEq, +)] +pub struct ChildProperties { + #[prop_or_default] + pub string: ::std::string::String, + #[prop_or_default] + pub r#fn: ::std::primitive::i32, + #[prop_or_default] + pub r#ref: ::yew::NodeRef, + pub int: ::std::primitive::i32, + #[prop_or_default] + pub opt_str: ::std::option::Option<::std::string::String>, + #[prop_or_default] + pub vec: ::std::vec::Vec<::std::primitive::i32>, + #[prop_or_default] + pub optional_callback: ::std::option::Option<::yew::Callback<()>>, +} + +pub struct Child; +impl ::yew::Component for Child { + type Message = (); + type Properties = ChildProperties; + + fn create(_ctx: &::yew::Context) -> Self { + ::std::unimplemented!() + } + + fn view(&self, _ctx: &::yew::Context) -> ::yew::Html { + ::std::unimplemented!() + } +} + +pub struct AltChild; +impl ::yew::Component for AltChild { + type Message = (); + type Properties = (); + + fn create(_ctx: &::yew::Context) -> Self { + ::std::unimplemented!() + } + + fn view(&self, _ctx: &::yew::Context) -> ::yew::Html { + ::std::unimplemented!() + } +} + +mod scoped { + pub use super::{Child, Container}; +} + +#[derive( + ::std::clone::Clone, ::yew::Properties, ::std::default::Default, ::std::cmp::PartialEq, +)] +pub struct RenderPropProps { + // You can use Callback<()> as Children. + #[prop_or_default] + pub children: ::yew::Callback<()>, +} + +#[::yew::function_component] +pub fn RenderPropComp(_props: &RenderPropProps) -> ::yew::Html { + ::yew::html! {} +} + +fn compile_pass() { + ::yew::html! { }; + ::yew::html! { }; + + ::yew::html! { + <> + + + + }; + + let props = <::Properties as ::std::default::Default>::default(); + let node_ref = <::yew::NodeRef as ::std::default::Default>::default(); + ::yew::html! { + <> + + + + + + ::Properties as ::std::default::Default>::default() /> + ::Properties as ::std::default::Default>::default() /> + + }; + + ::yew::html! { + <> + + + + + >::from("child")} int=1 /> + + + >::from("child")} int=1 /> + + >::from("child"))} int=1 /> + + }; + + let name_expr = "child"; + ::yew::html! { + + }; + + let string = "child"; + let int = 1; + ::yew::html! { + + }; + + ::yew::html! { + <> + + as ::std::convert::From<_>>::from(|_| ()))} /> + as ::std::convert::From<_>>::from(|_| ())} /> + >} /> + + }; + + let node_ref = <::yew::NodeRef as ::std::default::Default>::default(); + ::yew::html! { + <> + + + }; + + let int = 1; + let node_ref = <::yew::NodeRef as ::std::default::Default>::default(); + ::yew::html! { + <> + + + }; + + let props = <::Properties as ::std::default::Default>::default(); + let child_props = + <::Properties as ::std::default::Default>::default(); + ::yew::html! { + <> + + + + +
{ "hello world" }
+
+ + +
{ "hello world" }
+
+ + + + + + + + + + + + + + + + + + + + + + + + + }} /> + + }; + + let variants = || -> ::std::vec::Vec { + ::std::vec![ + ChildrenVariants::Child(::yew::virtual_dom::VChild::new( + ::default(), + ::std::option::Option::None, + )), + ChildrenVariants::AltChild(::yew::virtual_dom::VChild::new( + (), + ::std::option::Option::None + )), + ] + }; + + ::yew::html! { + <> + { + ::std::iter::Iterator::collect::<::yew::virtual_dom::VNode>( + ::std::iter::Iterator::filter( + ::std::iter::IntoIterator::into_iter(variants()), + |c| match c { + ChildrenVariants::Child(_) => true, + _ => false, + } + ) + ) + } +
+ { + ::std::iter::Iterator::collect::<::yew::virtual_dom::VNode>( + ::std::iter::Iterator::filter( + ::std::iter::IntoIterator::into_iter(variants()), + |c| match c { + ChildrenVariants::AltChild(_) => true, + _ => false, + } + ) + ) + } +
+ + }; + + ::yew::html_nested! { 1 }; + + ::yew::html! { + + {|_arg| {}} + + }; +} +fn main() {} diff --git a/packages/yew-macro/tests/html_macro/component-fail.stderr b/packages/yew-macro/tests/html_macro/component-fail.stderr index fd104518c..40917e85a 100644 --- a/packages/yew-macro/tests/html_macro/component-fail.stderr +++ b/packages/yew-macro/tests/html_macro/component-fail.stderr @@ -481,6 +481,12 @@ error[E0277]: the trait bound `{integer}: IntoPropValue` is not satisfie | | | required by a bound introduced by this call | + = help: the following implementations were found: + >> + >> + >> + >> + and $N others note: required by a bound in `ChildPropertiesBuilder::string` --> tests/html_macro/component-fail.rs:4:17 | @@ -499,6 +505,12 @@ error[E0277]: the trait bound `{integer}: IntoPropValue` is not satisfie | | | required by a bound introduced by this call | + = help: the following implementations were found: + >> + >> + >> + >> + and $N others note: required by a bound in `ChildPropertiesBuilder::string` --> tests/html_macro/component-fail.rs:4:17 | @@ -534,6 +546,12 @@ error[E0277]: the trait bound `u32: IntoPropValue` is not satisfied | | | required by a bound introduced by this call | + = help: the following implementations were found: + >> + >> + >> + >> + and $N others note: required by a bound in `ChildPropertiesBuilder::int` --> tests/html_macro/component-fail.rs:4:17 | @@ -630,13 +648,25 @@ note: required by a bound in `yew::html::component::properties::__macro::PreBuil | ^^^^^^^^^^^^^^^^^^^ required by this bound in `yew::html::component::properties::__macro::PreBuild::::build` = note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `VChild: From` is not satisfied +error[E0277]: the trait bound `yew::virtual_dom::VText: IntoPropValue>>` is not satisfied --> tests/html_macro/component-fail.rs:117:31 | 117 | html! { { "Not allowed" } }; - | ^^^^^^^^^^^^^ the trait `From` is not implemented for `VChild` + | -------------- ^^^^^^^^^^^^^ the trait `IntoPropValue>>` is not implemented for `yew::virtual_dom::VText` + | | + | required by a bound introduced by this call | - = note: required because of the requirements on the impl of `Into>` for `yew::virtual_dom::VText` + = help: the following implementations were found: + >> +note: required by a bound in `ChildContainerPropertiesBuilder::children` + --> tests/html_macro/component-fail.rs:24:17 + | +24 | #[derive(Clone, Properties, PartialEq)] + | ^^^^^^^^^^ required by this bound in `ChildContainerPropertiesBuilder::children` +25 | pub struct ChildContainerProperties { +26 | pub children: ChildrenWithProps, + | -------- required by a bound in this + = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `VChild: From` is not satisfied --> tests/html_macro/component-fail.rs:118:29 @@ -646,10 +676,22 @@ error[E0277]: the trait bound `VChild: From` is not satisfied | = note: required because of the requirements on the impl of `Into>` for `VNode` -error[E0277]: the trait bound `VChild: From` is not satisfied +error[E0277]: the trait bound `VNode: IntoPropValue>>` is not satisfied --> tests/html_macro/component-fail.rs:119:30 | 119 | html! { }; - | ^^^^^ the trait `From` is not implemented for `VChild` + | -------------- ^^^^^ the trait `IntoPropValue>>` is not implemented for `VNode` + | | + | required by a bound introduced by this call | - = note: required because of the requirements on the impl of `Into>` for `VNode` + = help: the following implementations were found: + >> +note: required by a bound in `ChildContainerPropertiesBuilder::children` + --> tests/html_macro/component-fail.rs:24:17 + | +24 | #[derive(Clone, Properties, PartialEq)] + | ^^^^^^^^^^ required by this bound in `ChildContainerPropertiesBuilder::children` +25 | pub struct ChildContainerProperties { +26 | pub children: ChildrenWithProps, + | -------- required by a bound in this + = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/packages/yew-macro/tests/html_macro/element-fail.stderr b/packages/yew-macro/tests/html_macro/element-fail.stderr index 76a4c31c6..ecb38f61c 100644 --- a/packages/yew-macro/tests/html_macro/element-fail.stderr +++ b/packages/yew-macro/tests/html_macro/element-fail.stderr @@ -436,9 +436,9 @@ error[E0277]: the trait bound `Option: IntoPropValue as IntoPropValue>> - as IntoPropValue>> as IntoPropValue>> as IntoPropValue>>> + > as IntoPropValue>> and $N others error[E0277]: the trait bound `Option<{integer}>: IntoPropValue>` is not satisfied @@ -452,9 +452,9 @@ error[E0277]: the trait bound `Option<{integer}>: IntoPropValue as IntoPropValue>> - as IntoPropValue>> as IntoPropValue>> as IntoPropValue>>> + > as IntoPropValue>> and $N others error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `{integer}` @@ -550,9 +550,9 @@ error[E0277]: the trait bound `Option: IntoPropValue | = help: the following implementations were found: as IntoPropValue>> - as IntoPropValue>> as IntoPropValue>> as IntoPropValue>>> + > as IntoPropValue>> and $N others error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `yew::Callback` diff --git a/packages/yew-router/src/components/link.rs b/packages/yew-router/src/components/link.rs index 3ea72ca39..cf94c92b1 100644 --- a/packages/yew-router/src/components/link.rs +++ b/packages/yew-router/src/components/link.rs @@ -28,7 +28,7 @@ where #[prop_or_default] pub anchor_ref: NodeRef, #[prop_or_default] - pub children: Children, + pub children: Html, } /// A wrapper around `` tag to be used with [`Router`](crate::Router) diff --git a/packages/yew-router/src/router.rs b/packages/yew-router/src/router.rs index 75ed3a75d..b3becda9e 100644 --- a/packages/yew-router/src/router.rs +++ b/packages/yew-router/src/router.rs @@ -11,7 +11,8 @@ use crate::utils::{base_url, strip_slash_suffix}; /// Props for [`Router`]. #[derive(Properties, PartialEq, Clone)] pub struct RouterProps { - pub children: Children, + #[prop_or_default] + pub children: Html, pub history: AnyHistory, #[prop_or_default] pub basename: Option, @@ -129,7 +130,7 @@ pub fn router(props: &RouterProps) -> Html { /// Props for [`BrowserRouter`] and [`HashRouter`]. #[derive(Properties, PartialEq, Clone)] pub struct ConcreteRouterProps { - pub children: Children, + pub children: Html, #[prop_or_default] pub basename: Option, } diff --git a/packages/yew/src/context.rs b/packages/yew/src/context.rs index 74514002b..1b77f104b 100644 --- a/packages/yew/src/context.rs +++ b/packages/yew/src/context.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use slab::Slab; use crate::html::Scope; -use crate::{html, Callback, Children, Component, Context, Html, Properties}; +use crate::{Callback, Component, Context, Html, Properties}; /// Props for [`ContextProvider`] #[derive(Debug, Clone, PartialEq, Properties)] @@ -13,7 +13,7 @@ pub struct ContextProviderProps { /// Context value to be passed down pub context: T, /// Children - pub children: Children, + pub children: Html, } /// The context provider component. @@ -103,6 +103,6 @@ impl Component for ContextProvider { } fn view(&self, ctx: &Context) -> Html { - html! { <>{ ctx.props().children.clone() } } + ctx.props().children.clone() } } diff --git a/packages/yew/src/dom_bundle/btag/mod.rs b/packages/yew/src/dom_bundle/btag/mod.rs index 57afcce4a..fca3b5213 100644 --- a/packages/yew/src/dom_bundle/btag/mod.rs +++ b/packages/yew/src/dom_bundle/btag/mod.rs @@ -15,7 +15,7 @@ pub use listeners::Registry; use wasm_bindgen::JsCast; use web_sys::{Element, HtmlTextAreaElement as TextAreaElement}; -use super::{BList, BNode, BSubtree, DomSlot, Reconcilable, ReconcileTarget}; +use super::{BNode, BSubtree, DomSlot, Reconcilable, ReconcileTarget}; use crate::html::AnyScope; use crate::virtual_dom::vtag::{InputFields, VTagInner, Value, MATHML_NAMESPACE, SVG_NAMESPACE}; use crate::virtual_dom::{Attributes, Key, VTag}; @@ -52,8 +52,8 @@ enum BTagInner { Other { /// A tag of the element. tag: Cow<'static, str>, - /// List of child nodes - child_bundle: BList, + /// Child node. + child_bundle: BNode, }, } @@ -297,10 +297,10 @@ impl BTag { #[cfg(target_arch = "wasm32")] #[cfg(test)] - fn children(&self) -> &[BNode] { + fn children(&self) -> Option<&BNode> { match &self.inner { - BTagInner::Other { child_bundle, .. } => child_bundle, - _ => &[], + BTagInner::Other { child_bundle, .. } => Some(child_bundle), + _ => None, } } @@ -610,7 +610,7 @@ mod tests { let svg_tag = assert_vtag(svg_node); let (_, svg_tag) = svg_tag.attach(&root, &scope, &parent, DomSlot::at_end()); assert_namespace(&svg_tag, SVG_NAMESPACE); - let path_tag = assert_btag_ref(svg_tag.children().get(0).unwrap()); + let path_tag = assert_btag_ref(svg_tag.children().unwrap()); assert_namespace(path_tag, SVG_NAMESPACE); let g_tag = assert_vtag(g_node.clone()); @@ -631,7 +631,7 @@ mod tests { let math_tag = assert_vtag(math_node); let (_, math_tag) = math_tag.attach(&root, &scope, &parent, DomSlot::at_end()); assert_namespace(&math_tag, MATHML_NAMESPACE); - let mfrac_tag = assert_btag_ref(math_tag.children().get(0).unwrap()); + let mfrac_tag = assert_btag_ref(math_tag.children().unwrap()); assert_namespace(mfrac_tag, MATHML_NAMESPACE); } diff --git a/packages/yew/src/html/component/children.rs b/packages/yew/src/html/component/children.rs index 911cd91fa..94f6dc0d2 100644 --- a/packages/yew/src/html/component/children.rs +++ b/packages/yew/src/html/component/children.rs @@ -3,8 +3,8 @@ use std::fmt; use crate::html::Html; -use crate::virtual_dom::VChild; -use crate::Properties; +use crate::virtual_dom::{VChild, VComp, VList, VNode}; +use crate::{BaseComponent, Properties}; /// A type used for accepting children elements in Component::Properties. /// @@ -233,12 +233,48 @@ impl IntoIterator for ChildrenRenderer { } } +impl From> for Html { + fn from(mut val: ChildrenRenderer) -> Self { + if val.children.len() == 1 { + if let Some(m) = val.children.pop() { + return m; + } + } + + Html::VList(val.into()) + } +} + +impl From> for VList { + fn from(val: ChildrenRenderer) -> Self { + if val.is_empty() { + return VList::new(); + } + VList::with_children(val.children, None) + } +} + +impl From>> for ChildrenRenderer +where + COMP: BaseComponent, +{ + fn from(value: ChildrenRenderer>) -> Self { + Self::new( + value + .into_iter() + .map(VComp::from) + .map(VNode::from) + .collect(), + ) + } +} + /// A [Properties] type with Children being the only property. #[derive(Debug, Properties, PartialEq)] pub struct ChildrenProps { /// The Children of a Component. #[prop_or_default] - pub children: Children, + pub children: Html, } #[cfg(test)] diff --git a/packages/yew/src/html/component/marker.rs b/packages/yew/src/html/component/marker.rs index 9a970b6d2..abd2d152d 100644 --- a/packages/yew/src/html/component/marker.rs +++ b/packages/yew/src/html/component/marker.rs @@ -1,7 +1,7 @@ //! Primitive Components & Properties Types +use crate::function_component; use crate::html::{BaseComponent, ChildrenProps, Html}; -use crate::{function_component, html}; /// A Component to represent a component that does not exist in current implementation. /// @@ -142,5 +142,5 @@ pub fn PhantomComponent(props: &ChildrenProps) -> Html where T: BaseComponent, { - html! { <>{props.children.clone()} } + props.children.clone() } diff --git a/packages/yew/src/html/conversion.rs b/packages/yew/src/html/conversion/into_prop_value.rs similarity index 81% rename from packages/yew/src/html/conversion.rs rename to packages/yew/src/html/conversion/into_prop_value.rs index 21d7851f4..8489900f1 100644 --- a/packages/yew/src/html/conversion.rs +++ b/packages/yew/src/html/conversion/into_prop_value.rs @@ -3,9 +3,10 @@ use std::rc::Rc; use implicit_clone::unsync::{IArray, IMap}; pub use implicit_clone::ImplicitClone; -use super::super::callback::Callback; -use super::{BaseComponent, Children, ChildrenRenderer, Component, NodeRef, Scope}; -use crate::virtual_dom::{AttrValue, VChild, VNode}; +use super::ToHtml; +use crate::callback::Callback; +use crate::html::{BaseComponent, ChildrenRenderer, Component, NodeRef, Scope}; +use crate::virtual_dom::{AttrValue, VChild, VNode, VText}; impl ImplicitClone for NodeRef {} impl ImplicitClone for Scope {} @@ -81,63 +82,74 @@ where } } -impl IntoPropValue>> for VChild +impl IntoPropValue> for VChild where T: BaseComponent, + C: Clone + Into, + VChild: Into, { #[inline] - fn into_prop_value(self) -> ChildrenRenderer> { + fn into_prop_value(self) -> ChildrenRenderer { + ChildrenRenderer::new(vec![self.into()]) + } +} + +impl IntoPropValue>> for VChild +where + T: BaseComponent, + C: Clone + Into, + VChild: Into, +{ + #[inline] + fn into_prop_value(self) -> Option> { + Some(ChildrenRenderer::new(vec![self.into()])) + } +} + +impl IntoPropValue>> for Option> +where + T: BaseComponent, + C: Clone + Into, + VChild: Into, +{ + #[inline] + fn into_prop_value(self) -> Option> { + self.map(|m| ChildrenRenderer::new(vec![m.into()])) + } +} + +impl IntoPropValue> for Vec +where + T: Into, + R: Clone + Into, +{ + #[inline] + fn into_prop_value(self) -> ChildrenRenderer { + ChildrenRenderer::new(self.into_iter().map(|m| m.into()).collect()) + } +} + +impl IntoPropValue for T +where + T: ToHtml, +{ + #[inline] + fn into_prop_value(self) -> VNode { + self.into_html() + } +} + +impl IntoPropValue> for VNode { + #[inline] + fn into_prop_value(self) -> ChildrenRenderer { ChildrenRenderer::new(vec![self]) } } -impl IntoPropValue>>> for VChild -where - T: BaseComponent, -{ +impl IntoPropValue> for VText { #[inline] - fn into_prop_value(self) -> Option>> { - Some(ChildrenRenderer::new(vec![self])) - } -} - -impl IntoPropValue>>> for Option> -where - T: BaseComponent, -{ - #[inline] - fn into_prop_value(self) -> Option>> { - self.map(|m| ChildrenRenderer::new(vec![m])) - } -} - -impl IntoPropValue>> for Vec> -where - T: BaseComponent, -{ - #[inline] - fn into_prop_value(self) -> ChildrenRenderer> { - ChildrenRenderer::new(self) - } -} - -impl IntoPropValue>>> for Vec> -where - T: BaseComponent, -{ - #[inline] - fn into_prop_value(self) -> Option>> { - Some(ChildrenRenderer::new(self)) - } -} - -impl IntoPropValue>>> for Option>> -where - T: BaseComponent, -{ - #[inline] - fn into_prop_value(self) -> Option>> { - self.map(ChildrenRenderer::new) + fn into_prop_value(self) -> ChildrenRenderer { + ChildrenRenderer::new(vec![self.into()]) } } @@ -171,14 +183,9 @@ macro_rules! impl_into_prop { // implemented with literals in mind impl_into_prop!(|value: &'static str| -> String { value.to_owned() }); - impl_into_prop!(|value: &'static str| -> AttrValue { AttrValue::Static(value) }); impl_into_prop!(|value: String| -> AttrValue { AttrValue::Rc(Rc::from(value)) }); impl_into_prop!(|value: Rc| -> AttrValue { AttrValue::Rc(value) }); -impl_into_prop!(|value: VNode| -> Children { Children::new(vec![value]) }); -impl_into_prop!(|value: &'static str| -> VNode { crate::html!(value) }); -impl_into_prop!(|value: String| -> VNode { crate::html!(value) }); -impl_into_prop!(|value: AttrValue| -> VNode { crate::html!(value) }); impl IntoPropValue> for &'static [T] { fn into_prop_value(self) -> IArray { @@ -309,13 +316,13 @@ mod test { html! {
- {header} + {for header}
{children}
- {footer} + {for footer}
} diff --git a/packages/yew/src/html/conversion/mod.rs b/packages/yew/src/html/conversion/mod.rs new file mode 100644 index 000000000..70181c553 --- /dev/null +++ b/packages/yew/src/html/conversion/mod.rs @@ -0,0 +1,5 @@ +mod into_prop_value; +mod to_html; + +pub use into_prop_value::*; +pub use to_html::*; diff --git a/packages/yew/src/html/conversion/to_html.rs b/packages/yew/src/html/conversion/to_html.rs new file mode 100644 index 000000000..c7d3eeaa5 --- /dev/null +++ b/packages/yew/src/html/conversion/to_html.rs @@ -0,0 +1,203 @@ +use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; + +use crate::html::{ChildrenRenderer, IntoPropValue}; +use crate::virtual_dom::{VChild, VList, VNode, VText}; +use crate::{AttrValue, BaseComponent, Html}; + +/// A trait implemented for types be rendered as a part of a Html. +/// +/// Types that implements this trait can define a virtual dom layout that itself should be rendered +/// into via `html!` and can be referenced / consumed as `{value}` in an `html!` macro invocation. +pub trait ToHtml { + /// Converts this type to a [`Html`]. + fn to_html(&self) -> Html; + + /// Converts this type into a [`Html`]. + fn into_html(self) -> Html + where + Self: Sized, + { + self.to_html() + } +} + +// Implementations for common data types. + +impl ToHtml for Option +where + T: ToHtml, +{ + #[inline(always)] + fn to_html(&self) -> Html { + self.as_ref().map(ToHtml::to_html).unwrap_or_default() + } + + #[inline(always)] + fn into_html(self) -> Html { + self.map(ToHtml::into_html).unwrap_or_default() + } +} + +impl ToHtml for Vec +where + T: ToHtml, +{ + #[inline(always)] + fn to_html(&self) -> Html { + Html::VList(VList::with_children( + self.iter().map(ToHtml::to_html).collect(), + None, + )) + } + + #[inline(always)] + fn into_html(self) -> Html { + Html::VList(VList::with_children( + self.into_iter().map(ToHtml::into_html).collect(), + None, + )) + } +} + +impl ToHtml for Option { + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into_html() + } + + #[inline(always)] + fn into_html(self) -> Html { + self.unwrap_or_default() + } +} + +impl ToHtml for Vec { + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into_html() + } + + #[inline(always)] + fn into_html(self) -> Html { + Html::VList(VList::with_children(self, None)) + } +} + +impl ToHtml for VText { + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into() + } + + #[inline(always)] + fn into_html(self) -> Html { + Html::VText(self) + } +} + +impl ToHtml for VList { + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into() + } + + #[inline(always)] + fn into_html(self) -> Html { + Html::VList(self) + } +} + +impl ToHtml for ChildrenRenderer { + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into() + } + + #[inline(always)] + fn into_html(self) -> Html { + self.into() + } +} + +impl ToHtml for VChild +where + T: BaseComponent, +{ + #[inline(always)] + fn to_html(&self) -> Html { + self.clone().into() + } + + #[inline(always)] + fn into_html(self) -> Html { + VNode::VComp(self.into()) + } +} + +impl ToHtml for () { + #[inline(always)] + fn to_html(&self) -> Html { + VNode::default() + } + + #[inline(always)] + fn into_html(self) -> Html { + VNode::default() + } +} + +impl ToHtml for &'_ T +where + T: ToHtml, +{ + fn to_html(&self) -> Html { + (*self).to_html() + } +} + +macro_rules! impl_to_html_via_display { + ($from_ty: ty) => { + impl ToHtml for $from_ty { + #[inline(always)] + fn to_html(&self) -> Html { + Html::VText(VText::from(self)) + } + } + + // Mirror ToHtml to Children implementation. + impl IntoPropValue> for $from_ty { + #[inline(always)] + fn into_prop_value(self) -> ChildrenRenderer { + ChildrenRenderer::new(vec![VText::from(self).into()]) + } + } + }; +} + +// These are a selection of types implemented via display. +impl_to_html_via_display!(bool); +impl_to_html_via_display!(char); +impl_to_html_via_display!(String); +impl_to_html_via_display!(&str); +impl_to_html_via_display!(Rc); +impl_to_html_via_display!(Rc); +impl_to_html_via_display!(Arc); +impl_to_html_via_display!(Arc); +impl_to_html_via_display!(AttrValue); +impl_to_html_via_display!(Cow<'_, str>); +impl_to_html_via_display!(u8); +impl_to_html_via_display!(u16); +impl_to_html_via_display!(u32); +impl_to_html_via_display!(u64); +impl_to_html_via_display!(u128); +impl_to_html_via_display!(usize); +impl_to_html_via_display!(i8); +impl_to_html_via_display!(i16); +impl_to_html_via_display!(i32); +impl_to_html_via_display!(i64); +impl_to_html_via_display!(i128); +impl_to_html_via_display!(isize); +impl_to_html_via_display!(f32); +impl_to_html_via_display!(f64); diff --git a/packages/yew/src/lib.rs b/packages/yew/src/lib.rs index 257d62aa2..65a5cdd45 100644 --- a/packages/yew/src/lib.rs +++ b/packages/yew/src/lib.rs @@ -336,7 +336,7 @@ pub mod prelude { pub use crate::functional::*; pub use crate::html::{ create_portal, BaseComponent, Children, ChildrenWithProps, Classes, Component, Context, - Html, HtmlResult, NodeRef, Properties, + Html, HtmlResult, NodeRef, Properties, ToHtml, }; pub use crate::macros::{classes, html, html_nested}; pub use crate::suspense::Suspense; diff --git a/packages/yew/src/server_renderer.rs b/packages/yew/src/server_renderer.rs index b716bc9a5..7086349a1 100644 --- a/packages/yew/src/server_renderer.rs +++ b/packages/yew/src/server_renderer.rs @@ -91,14 +91,7 @@ where } } - /// Renders Yew Application into a string Stream - #[tracing::instrument( - level = tracing::Level::DEBUG, - name = "render", - skip(self), - fields(hydratable = self.hydratable), - )] - pub fn render_stream(self) -> impl Stream { + fn render_stream_inner(self) -> impl Stream { let scope = Scope::::new(None); let outer_span = tracing::Span::current(); @@ -111,6 +104,36 @@ where .await; }) } + + // The duplicate implementation below is to selectively suppress clippy lints. + // These implementations should be merged once https://github.com/tokio-rs/tracing/issues/2503 is resolved. + + /// Renders Yew Application into a string Stream + #[rustversion::since(1.70)] + #[allow(clippy::let_with_type_underscore)] + #[tracing::instrument( + level = tracing::Level::DEBUG, + name = "render_stream", + skip(self), + fields(hydratable = self.hydratable), + )] + #[inline(always)] + pub fn render_stream(self) -> impl Stream { + self.render_stream_inner() + } + + /// Renders Yew Application into a string Stream + #[rustversion::before(1.70)] + #[tracing::instrument( + level = tracing::Level::DEBUG, + name = "render_stream", + skip(self), + fields(hydratable = self.hydratable), + )] + #[inline(always)] + pub fn render_stream(self) -> impl Stream { + self.render_stream_inner() + } } /// A Yew Server-side Renderer. diff --git a/packages/yew/src/suspense/component.rs b/packages/yew/src/suspense/component.rs index 2312c5a3a..17c68053f 100644 --- a/packages/yew/src/suspense/component.rs +++ b/packages/yew/src/suspense/component.rs @@ -1,11 +1,11 @@ -use crate::html::{Children, Html, Properties}; +use crate::html::{Html, Properties}; /// Properties for [Suspense]. #[derive(Properties, PartialEq, Debug, Clone)] pub struct SuspenseProps { /// The Children of the current Suspense Component. #[prop_or_default] - pub children: Children, + pub children: Html, /// The Fallback UI of the current Suspense Component. #[prop_or_default] @@ -15,7 +15,7 @@ pub struct SuspenseProps { #[cfg(any(feature = "csr", feature = "ssr"))] mod feat_csr_ssr { use super::*; - use crate::html::{Children, Component, Context, Html, Scope}; + use crate::html::{Component, Context, Html, Scope}; use crate::suspense::Suspension; #[cfg(feature = "hydration")] use crate::suspense::SuspensionHandle; @@ -24,7 +24,7 @@ mod feat_csr_ssr { #[derive(Properties, PartialEq, Debug, Clone)] pub(crate) struct BaseSuspenseProps { - pub children: Children, + pub children: Html, pub fallback: Option, } diff --git a/packages/yew/src/utils/mod.rs b/packages/yew/src/utils/mod.rs index 56926bfb6..6cdb04768 100644 --- a/packages/yew/src/utils/mod.rs +++ b/packages/yew/src/utils/mod.rs @@ -41,15 +41,6 @@ impl, OUT> From> for NodeSeq { } } -impl, OUT> From> for NodeSeq { - fn from(val: ChildrenRenderer) -> Self { - Self( - val.into_iter().map(|x| x.into()).collect(), - PhantomData::default(), - ) - } -} - impl + Clone, OUT> From<&ChildrenRenderer> for NodeSeq { fn from(val: &ChildrenRenderer) -> Self { Self( diff --git a/packages/yew/src/virtual_dom/vnode.rs b/packages/yew/src/virtual_dom/vnode.rs index b93f4ea5e..87b571f8b 100644 --- a/packages/yew/src/virtual_dom/vnode.rs +++ b/packages/yew/src/virtual_dom/vnode.rs @@ -1,8 +1,8 @@ //! This module contains the implementation of abstract virtual node. use std::cmp::PartialEq; -use std::fmt; use std::iter::FromIterator; +use std::{fmt, mem}; use web_sys::Node; @@ -53,6 +53,20 @@ impl VNode { self.key().is_some() } + /// Acquires a mutable reference of current VNode as a VList. + /// + /// Creates a VList with the current node as the first child if current VNode is not a VList. + pub fn to_vlist_mut(&mut self) -> &mut VList { + loop { + match *self { + Self::VList(ref mut m) => return m, + _ => { + *self = VNode::VList(VList::with_children(vec![mem::take(self)], None)); + } + } + } + } + /// Create a [`VNode`] from a string of HTML /// /// # Behavior in browser diff --git a/packages/yew/src/virtual_dom/vtag.rs b/packages/yew/src/virtual_dom/vtag.rs index 46b9c70f1..07de0263d 100644 --- a/packages/yew/src/virtual_dom/vtag.rs +++ b/packages/yew/src/virtual_dom/vtag.rs @@ -9,7 +9,7 @@ use std::rc::Rc; use web_sys::{HtmlInputElement as InputElement, HtmlTextAreaElement as TextAreaElement}; -use super::{ApplyAttributeAs, AttrValue, Attributes, Key, Listener, Listeners, VList, VNode}; +use super::{ApplyAttributeAs, AttrValue, Attributes, Key, Listener, Listeners, VNode}; use crate::html::{IntoPropValue, NodeRef}; /// SVG namespace string used for creating svg elements @@ -112,8 +112,8 @@ pub(crate) enum VTagInner { Other { /// A tag of the element. tag: Cow<'static, str>, - /// List of child nodes - children: VList, + /// children of the element. + children: VNode, }, } @@ -232,7 +232,7 @@ impl VTag { // at bottom for more readable macro-expanded coded attributes: Attributes, listeners: Listeners, - children: VList, + children: VNode, ) -> Self { VTag::new_base( VTagInner::Other { tag, children }, @@ -274,45 +274,41 @@ impl VTag { /// Add [VNode] child. pub fn add_child(&mut self, child: VNode) { if let VTagInner::Other { children, .. } = &mut self.inner { - children.add_child(child) + children.to_vlist_mut().add_child(child) } } /// Add multiple [VNode] children. pub fn add_children(&mut self, children: impl IntoIterator) { if let VTagInner::Other { children: dst, .. } = &mut self.inner { - dst.add_children(children) + dst.to_vlist_mut().add_children(children) } } - /// Returns a reference to the children of this [VTag] - pub fn children(&self) -> &VList { + /// Returns a reference to the children of this [VTag], if the node can have + /// children + pub fn children(&self) -> Option<&VNode> { match &self.inner { - VTagInner::Other { children, .. } => children, - _ => { - // This is mutable because the VList is not Sync - static mut EMPTY: VList = VList::new(); - - // SAFETY: The EMPTY value is always read-only - unsafe { &EMPTY } - } + VTagInner::Other { children, .. } => Some(children), + _ => None, } } /// Returns a mutable reference to the children of this [VTag], if the node can have /// children - pub fn children_mut(&mut self) -> Option<&mut VList> { + pub fn children_mut(&mut self) -> Option<&mut VNode> { match &mut self.inner { VTagInner::Other { children, .. } => Some(children), _ => None, } } - /// Returns the children of this [VTag] - pub fn into_children(self) -> VList { + /// Returns the children of this [VTag], if the node can have + /// children + pub fn into_children(self) -> Option { match self.inner { - VTagInner::Other { children, .. } => children, - _ => VList::new(), + VTagInner::Other { children, .. } => Some(children), + _ => None, } } @@ -530,7 +526,13 @@ mod feat_ssr { let _ = w.write_str(">"); } else { // We don't write children of void elements nor closing tags. - debug_assert!(children.is_empty(), "{tag} cannot have any children!"); + debug_assert!( + match children { + VNode::VList(m) => m.is_empty(), + _ => false, + }, + "{tag} cannot have any children!" + ); } } } diff --git a/packages/yew/src/virtual_dom/vtext.rs b/packages/yew/src/virtual_dom/vtext.rs index 2337f90c5..30f0b2467 100644 --- a/packages/yew/src/virtual_dom/vtext.rs +++ b/packages/yew/src/virtual_dom/vtext.rs @@ -32,6 +32,12 @@ impl PartialEq for VText { } } +impl From for VText { + fn from(value: T) -> Self { + VText::new(value.to_string()) + } +} + #[cfg(feature = "ssr")] mod feat_ssr { diff --git a/tools/benchmark-ssr/src/main.rs b/tools/benchmark-ssr/src/main.rs index e9ed25576..011194e22 100644 --- a/tools/benchmark-ssr/src/main.rs +++ b/tools/benchmark-ssr/src/main.rs @@ -88,14 +88,14 @@ async fn bench_many_providers() -> Duration { #[derive(Properties, PartialEq, Clone)] struct ProviderProps { - children: Children, + children: Html, } #[function_component] fn Provider(props: &ProviderProps) -> Html { let ProviderProps { children } = props.clone(); - html! {<>{children}} + children } #[function_component] diff --git a/website/docs/concepts/function-components/generics.mdx b/website/docs/concepts/function-components/generics.mdx index eae3c3ed2..758757b5a 100644 --- a/website/docs/concepts/function-components/generics.mdx +++ b/website/docs/concepts/function-components/generics.mdx @@ -10,7 +10,7 @@ The `#[function_component]` attribute also works with generic functions for crea ```rust use std::fmt::Display; -use yew::{function_component, html, Properties, Html}; +use yew::{function_component, html, Properties, Html, ToHtml}; #[derive(Properties, PartialEq)] pub struct Props @@ -23,7 +23,7 @@ where #[function_component] pub fn MyGenericComponent(props: &Props) -> Html where - T: PartialEq + Display, + T: PartialEq + ToHtml, { html! {