diff --git a/Cargo.lock b/Cargo.lock index f3ecb7a58..6a17fb136 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bitflags" version = "2.6.0" @@ -28,6 +34,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cfg-if" version = "1.0.0" @@ -121,6 +139,12 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.9" @@ -137,6 +161,118 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "glob-match" version = "0.2.1" @@ -167,6 +303,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "ignore" version = "0.4.23" @@ -183,6 +325,22 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "lazy_static" version = "1.4.0" @@ -202,7 +360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.0", + "windows-targets", ] [[package]] @@ -317,6 +475,30 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -328,13 +510,43 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "rayon" version = "1.10.0" @@ -404,12 +616,68 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rstest" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b423f0e62bdd61734b67cd21ff50871dfaeb9cc74f869dcd6af974fbcb19936" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e1711e7d14f74b12a58411c542185ef7fb7f2e7f8ee6e2940a883628522b42" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rstest_reuse" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8fb4672e840a587a66fc577a5491375df51ddb88f2a2c2a792598c326fe14" +dependencies = [ + "quote", + "rand", + "syn", +] + [[package]] name = "rustc-hash" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.37" @@ -423,6 +691,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "same-file" version = "1.0.6" @@ -440,9 +714,35 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] [[package]] name = "sharded-slab" @@ -453,6 +753,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -461,9 +770,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "2.0.18" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -481,6 +790,18 @@ dependencies = [ "tailwindcss-oxide", ] +[[package]] +name = "tailwindcss-core" +version = "0.1.0" +dependencies = [ + "bstr", + "log", + "rstest", + "rstest_reuse", + "serde_json", + "wasm-bindgen", +] + [[package]] name = "tailwindcss-oxide" version = "0.1.0" @@ -523,6 +844,23 @@ dependencies = [ "once_cell", ] +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" @@ -612,6 +950,67 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + [[package]] name = "winapi" version = "0.3.9" @@ -649,7 +1048,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -658,22 +1057,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows-targets", ] [[package]] @@ -682,46 +1066,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -734,50 +1100,56 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml new file mode 100644 index 000000000..ef2d27aed --- /dev/null +++ b/crates/core/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "tailwindcss-core" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[profile.release] +lto = true +opt-level = "s" +panic = "abort" +strip = true +codegen-units = 1 + +[dependencies] +serde_json = "1.0.127" +log = "0.4.22" +wasm-bindgen = "0.2.93" +bstr = "1.10.0" + +[dev-dependencies] +rstest = "0.22.0" +rstest_reuse = "0.7.0" diff --git a/crates/core/src/css/ast.rs b/crates/core/src/css/ast.rs new file mode 100644 index 000000000..30274408a --- /dev/null +++ b/crates/core/src/css/ast.rs @@ -0,0 +1,156 @@ +use std::{collections::HashMap, fmt, unreachable}; + +/// Represents the AST of a CSS stylesheet +#[derive(Clone, PartialEq)] +pub struct Stylesheet { + pub(crate) rules: CssNode, +} + +/// A node in a CSS Stylesheet +#[derive(Clone, PartialEq)] +pub enum CssNode { + /// A context block used to provide shared data to subtrees + Context { + data: HashMap, + nodes: Vec, + }, + + /// A CSS at rule + AtRule { + name: Vec, + params: Vec, + nodes: Vec, + }, + + /// A CSS style rule + StyleRule { + selector: Vec, + nodes: Vec, + }, + + /// A CSS declaration + Declaration { + property: Vec, + value: Vec, + important: bool, + }, + + /// A comment + Comment { + value: Vec, + }, + + /// Represents multiple CSS nodes + /// This is used when replacing a single node with multiple nodes + Contents { + nodes: Vec, + }, +} + +pub fn style_rule(selector: impl Into>, nodes: impl Into>) -> CssNode { + CssNode::StyleRule { + selector: selector.into(), + nodes: nodes.into(), + } +} + +pub fn at_rule(name: impl Into>, params: impl Into>, nodes: impl Into>) -> CssNode { + CssNode::AtRule { + name: name.into(), + params: params.into(), + nodes: nodes.into() + } +} + + +pub fn decl(property: impl Into>, value: impl Into>, important: bool) -> CssNode { + CssNode::Declaration { + property: property.into(), + value: value.into(), + important, + } +} + +pub fn comment(value: impl Into>) -> CssNode { + CssNode::Comment { value: value.into() } +} + +impl From for CssNode where T: Into> { + fn from(nodes: T) -> Self { + CssNode::Contents { nodes: nodes.into() } + } +} + +impl From for Stylesheet where T: Into> { + fn from(nodes: T) -> Self { + Stylesheet { + rules: CssNode::from(nodes.into()) + } + } +} + +impl CssNode { + pub fn empty() -> Self { + CssNode::from([]) + } +} + +impl fmt::Debug for Stylesheet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Stylesheet {{ rules: {:?} }}", self.rules) + } +} + +impl fmt::Debug for CssNode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CssNode::Context { data, nodes } => { + write!(f, "Context {{ data: {:?}, nodes: {:?} }}", data, nodes) + }, + + CssNode::AtRule { name, params, nodes } => { + write!(f, "AtRule {{ name: {:?}, params: {:?}, nodes: {:?} }}", String::from_utf8_lossy(name), String::from_utf8_lossy(params), nodes) + }, + + CssNode::StyleRule { selector, nodes } => { + write!(f, "StyleRule {{ selector: {:?}, nodes: {:?} }}", String::from_utf8_lossy(selector), nodes) + }, + + CssNode::Declaration { property, value, important } => { + write!(f, "Declaration {{ property: {:?}, value: {:?}, important: {:?} }}", String::from_utf8_lossy(property), String::from_utf8_lossy(value), important) + }, + + CssNode::Comment { value } => { + write!(f, "Comment {{ value: {:?} }}", String::from_utf8_lossy(value)) + }, + + CssNode::Contents { nodes } => { + write!(f, "Contents {{ nodes: {:?} }}", nodes) + }, + } + } +} + +impl CssNode { + #[inline(always)] + pub fn push(&mut self, node: CssNode) { + match self { + CssNode::AtRule { nodes, .. } => { + nodes.push(node); + }, + CssNode::StyleRule { nodes, .. } => { + nodes.push(node); + }, + CssNode::Contents { nodes, .. } => { + nodes.push(node); + }, + _ => { + if cfg!(debug_assertions) { + panic!("Cannot push to a non-container node."); + } else { + unreachable!(); + } + } + } + } +} diff --git a/crates/core/src/css/mod.rs b/crates/core/src/css/mod.rs new file mode 100644 index 000000000..ff50e5d1f --- /dev/null +++ b/crates/core/src/css/mod.rs @@ -0,0 +1,2 @@ +pub mod ast; +pub mod visit; diff --git a/crates/core/src/css/visit.rs b/crates/core/src/css/visit.rs new file mode 100644 index 000000000..edd639156 --- /dev/null +++ b/crates/core/src/css/visit.rs @@ -0,0 +1,192 @@ +use super::ast::{CssNode, Stylesheet}; + +#[derive(Debug, Clone, PartialEq)] +pub enum WalkAction { + // Continue walking, which is the default + Continue, + + // Skip visiting the children of this node + Skip, + + // Stop the walk entirely + Stop, +} + +impl Stylesheet { + pub fn walk(&self, cb: &V) + where + V: Fn(&CssNode) -> WalkAction + { + self.rules.walk(cb) + } +} + +impl CssNode { + pub fn walk(&self, cb: &V) + where + V: Fn(&CssNode) -> WalkAction + { + _ = self.walk_impl(cb); + } + + fn walk_impl(&self, cb: &V) -> WalkAction + where + V: Fn(&CssNode) -> WalkAction + { + match cb(self) { + WalkAction::Stop => return WalkAction::Stop, + WalkAction::Skip => return WalkAction::Skip, + WalkAction::Continue => {} + } + + for node in self.children() { + match node.walk_impl(cb) { + WalkAction::Stop => return WalkAction::Stop, + WalkAction::Skip => {} + WalkAction::Continue => {} + } + } + + WalkAction::Continue + } + + fn children(&self) -> impl Iterator { + match self { + CssNode::Context { nodes, .. } => nodes.iter(), + CssNode::AtRule { nodes, .. } => nodes.iter(), + CssNode::StyleRule { nodes, .. } => nodes.iter(), + CssNode::Contents { nodes, .. } => nodes.iter(), + CssNode::Declaration { .. } => [].iter(), + CssNode::Comment { .. } => [].iter(), + } + } +} + +impl Stylesheet { + pub fn walk_mut(&mut self, cb: &mut V) + where + V: FnMut(&mut CssNode) -> WalkAction + { + self.rules.walk_mut(cb) + } +} + +impl CssNode { + pub fn walk_mut(&mut self, cb: &mut V) + where + V: FnMut(&mut CssNode) -> WalkAction + { + _ = self.walk_mut_impl(cb); + } + + fn walk_mut_impl(&mut self, cb: &mut V) -> WalkAction + where + V: FnMut(&mut CssNode) -> WalkAction + { + match cb(self) { + WalkAction::Stop => return WalkAction::Stop, + WalkAction::Skip => return WalkAction::Skip, + WalkAction::Continue => {} + } + + for node in self.children_mut() { + match node.walk_mut_impl(cb) { + WalkAction::Stop => return WalkAction::Stop, + WalkAction::Skip => {} + WalkAction::Continue => {} + } + } + + WalkAction::Continue + } + + pub fn children_mut(&mut self) -> impl Iterator { + match self { + CssNode::Context { nodes, .. } => nodes.iter_mut(), + CssNode::AtRule { nodes, .. } => nodes.iter_mut(), + CssNode::StyleRule { nodes, .. } => nodes.iter_mut(), + CssNode::Contents { nodes, .. } => nodes.iter_mut(), + CssNode::Declaration { .. } => [].iter_mut(), + CssNode::Comment { .. } => [].iter_mut(), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::css::ast::*; + use std::cell::Cell; + + #[test] + fn test_walk() { + let ast = Stylesheet::from([ + style_rule("h1", [ + decl("color", "red", false), + decl("font-size", "2em", false), + ]), + style_rule("h2", [ + decl("color", "blue", false), + decl("font-size", "1.5em", false), + ]), + ]); + + let count = Cell::new(0); + + ast.walk(&|node| { + if let CssNode::Declaration { property, .. } = node { + if property == b"color" { + count.set(count.get() + 1); + } + } + + WalkAction::Continue + }); + + assert_eq!(count.get(), 2); + } + + #[test] + fn test_walk_mut() { + let mut ast = Stylesheet::from([ + style_rule("h1", [ + decl("color", "red", false), + decl("font-size", "2em", false), + ]), + style_rule("h2", [ + decl("color", "blue", false), + decl("font-size", "1.5em", false), + ]), + ]); + + // 1. Change all color properties to green + ast.walk_mut(&mut |node| { + let CssNode::Declaration { property, value, .. } = node else { + return WalkAction::Continue; + }; + + if property != b"color" { + return WalkAction::Continue; + } + + *value = "green".into(); + + return WalkAction::Continue; + }); + + // 2. Re-walk the AST and check that all color properties are green + let count = Cell::new(0); + + ast.walk(&|node| { + if let CssNode::Declaration { property, value, .. } = node { + if property == b"color" && value == b"green" { + count.set(count.get() + 1); + } + } + + WalkAction::Continue + }); + + assert_eq!(count.get(), 2); + } +} diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs new file mode 100644 index 000000000..389dd3264 --- /dev/null +++ b/crates/core/src/lib.rs @@ -0,0 +1 @@ +mod css;