diff --git a/.editorconfig b/.editorconfig index 9a38f230..d9b0a84d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,7 @@ root = true [*] +max_line_length = 120 end_of_line = lf insert_final_newline = true charset = utf-8 diff --git a/Cargo.lock b/Cargo.lock index 02e0b69c..ad8ec497 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,31 +2,11 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -39,51 +19,50 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -100,9 +79,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitmask-enum" @@ -116,9 +95,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata", @@ -127,15 +106,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytecount" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "cast" @@ -143,12 +116,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - [[package]] name = "cfg-if" version = "1.0.0" @@ -157,9 +124,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -168,15 +135,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -184,33 +151,31 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", "clap_lex", - "once_cell", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -220,9 +185,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "closestmatch" @@ -241,15 +206,15 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -279,7 +244,7 @@ dependencies = [ "once_cell", "oorandom", "plotters", - "rayon 1.7.0", + "rayon 1.8.1", "regex", "serde", "serde_derive", @@ -298,86 +263,36 @@ dependencies = [ "itertools", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] -name = "cssparser" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "dtoa" -version = "1.0.9" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" - -[[package]] -name = "dtoa-short" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" -dependencies = [ - "dtoa", -] +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "either" @@ -393,9 +308,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -411,36 +326,25 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -455,63 +359,56 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grep-matcher" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3902ca28f26945fe35cad349d776f163981d777fee382ccd6ef451126f51b319" +checksum = "47a3141a10a43acfedc7c98a60a834d7ba00dfe7bec9071cbfc19b55b292ac02" dependencies = [ "memchr", ] [[package]] name = "grep-regex" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "997598b41d53a37a2e3fc5300d5c11d825368c054420a9c65125b8fe1078463f" +checksum = "f748bb135ca835da5cbc67ca0e6955f968db9c5df74ca4f56b18e1ddbc68230d" dependencies = [ - "aho-corasick 0.7.20", "bstr", "grep-matcher", "log", - "regex", - "regex-syntax 0.6.29", - "thread_local", + "regex-automata", + "regex-syntax", ] [[package]] name = "grep-searcher" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5601c4b9f480f0c9ebb40b1f6cbf447b8a50c5369223937a6c5214368c58779f" +checksum = "ba536ae4f69bec62d8839584dd3153d3028ef31bb229f04e09fb5a9e5a193c54" dependencies = [ "bstr", - "bytecount", "encoding_rs", "encoding_rs_io", "grep-matcher", "log", + "memchr", "memmap2", ] [[package]] name = "half" -version = "1.8.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" dependencies = [ - "ahash", + "cfg-if", + "crunchy", ] [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hdx" @@ -519,8 +416,9 @@ version = "0.0.1" dependencies = [ "bumpalo", "clap", + "hdx_ast", "hdx_atom", - "hdx_atomizable_derive", + "hdx_derive", "hdx_lexer", "hdx_parser", "hdx_syntax", @@ -534,12 +432,15 @@ dependencies = [ name = "hdx_ast" version = "0.0.0" dependencies = [ + "bitmask-enum", "bumpalo", "glob", "hdx_atom", - "hdx_atomizable_derive", + "hdx_derive", "hdx_lexer", + "hdx_parser", "hdx_syntax", + "hdx_writer", "miette", "oxc_allocator", "serde", @@ -561,15 +462,6 @@ dependencies = [ "string_cache_codegen", ] -[[package]] -name = "hdx_atomizable_derive" -version = "0.0.0" -dependencies = [ - "hdx_atom", - "quote", - "syn", -] - [[package]] name = "hdx_benchmark" version = "0.0.0" @@ -579,6 +471,7 @@ dependencies = [ "encoding_rs", "encoding_rs_io", "glob", + "hdx_ast", "hdx_lexer", "hdx_parser", "hdx_writer", @@ -597,10 +490,11 @@ name = "hdx_coverage" version = "0.0.0" dependencies = [ "console", - "cssparser", "encoding_rs", "encoding_rs_io", "glob", + "hdx_ast", + "hdx_atom", "hdx_lexer", "hdx_parser", "miette", @@ -613,6 +507,17 @@ dependencies = [ "similar", ] +[[package]] +name = "hdx_derive" +version = "0.0.0" +dependencies = [ + "hdx_atom", + "hdx_lexer", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "hdx_lexer" version = "0.0.1" @@ -631,10 +536,10 @@ dependencies = [ name = "hdx_parser" version = "0.0.1" dependencies = [ + "bitmask-enum", "bumpalo", "closestmatch", "glob", - "hdx_ast", "hdx_atom", "hdx_lexer", "hdx_syntax", @@ -670,7 +575,6 @@ dependencies = [ name = "hdx_writer" version = "0.0.0" dependencies = [ - "hdx_ast", "hdx_atom", "hdx_lexer", "hdx_parser", @@ -686,36 +590,36 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown", ] [[package]] name = "is-terminal" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "is_ci" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "itertools" @@ -728,15 +632,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0aa48fab2893d8a49caa94082ae8488f4e1050d73b367881dcd2198f4199fd8" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -749,21 +653,21 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -771,43 +675,32 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "miette" -version = "5.9.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a236ff270093b0b67451bc50a509bd1bad302cb1d3c7d37d5efe931238581fa9" +checksum = "337e1043bbc086dac9d9674983bef52ac991ce150e09b5b8e35c5a73dd83f66c" dependencies = [ - "is-terminal", "miette-derive", - "once_cell", "owo-colors", "supports-color", "supports-hyperlinks", @@ -820,9 +713,9 @@ dependencies = [ [[package]] name = "miette-derive" -version = "5.9.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4901771e1d44ddb37964565c654a3223ba41a594d02b8da471cc4464912b5cfa" +checksum = "71e622f2a0dd84cbca79bc6c3c33f4fd7dc69faf992216516aacc1d136102800" dependencies = [ "proc-macro2", "quote", @@ -837,28 +730,18 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -874,9 +757,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "oxc_allocator" -version = "0.0.7" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3bf539e213999faf9aa21e9dbd4fbd241467cc86b542d1e54739a0078c29a88" +checksum = "13747d4dc2ed0f6102d0372fc186351cec62531fe07ec327756f9176b7ae3435" dependencies = [ "bumpalo", "serde", @@ -894,25 +777,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.1", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", + "windows-targets 0.48.5", ] [[package]] @@ -921,33 +794,10 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ - "phf_shared 0.10.0", - "rand", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", + "phf_shared", "rand", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "phf_shared" version = "0.10.0" @@ -957,15 +807,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "pico-args" version = "0.5.0" @@ -1014,9 +855,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1029,9 +870,9 @@ checksum = "8bccbff07d5ed689c4087d20d7307a52ab6141edeedf487c3876a55b86cf63df" [[package]] name = "quote" -version = "1.0.31" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1077,9 +918,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -1087,72 +928,70 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" - -[[package]] -name = "regex-syntax" -version = "0.6.29" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rustix" -version = "0.38.2" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "same-file" @@ -1171,15 +1010,15 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -1197,9 +1036,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -1208,9 +1047,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -1219,9 +1058,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.22" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452e67b9c20c37fa79df53201dc03839651086ed9bbe92b3ca585ca9fdaa7d85" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ "indexmap", "itoa", @@ -1232,27 +1071,27 @@ dependencies = [ [[package]] name = "similar" -version = "2.2.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smawk" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "string_cache" @@ -1263,7 +1102,7 @@ dependencies = [ "new_debug_unreachable", "once_cell", "parking_lot", - "phf_shared 0.10.0", + "phf_shared", "precomputed-hash", "serde", ] @@ -1274,8 +1113,8 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -1288,37 +1127,30 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "supports-color" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" +checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" dependencies = [ - "is-terminal", "is_ci", ] [[package]] name = "supports-hyperlinks" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" -dependencies = [ - "is-terminal", -] +checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee" [[package]] name = "supports-unicode" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" -dependencies = [ - "is-terminal", -] +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.26" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -1327,19 +1159,19 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.1.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "libc", - "winapi", + "rustix", + "windows-sys 0.48.0", ] [[package]] name = "textwrap" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" dependencies = [ "smawk", "unicode-linebreak", @@ -1348,34 +1180,24 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -1388,31 +1210,27 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-linebreak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" -dependencies = [ - "hashbrown 0.12.3", - "regex", -] +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "utf8parse" @@ -1420,17 +1238,11 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -1444,9 +1256,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1454,9 +1266,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -1469,9 +1281,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -1481,9 +1293,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1491,9 +1303,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -1504,15 +1316,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-bindgen-test" -version = "0.3.37" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c" dependencies = [ "console_error_panic_hook", "js-sys", @@ -1524,19 +1336,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.37" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" dependencies = [ "proc-macro2", "quote", + "syn", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -1560,9 +1373,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -1575,132 +1388,132 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.48.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.52.0", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" 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_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index 02847a17..f3f495ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ repository = "https://github.com/keithamus/hdx" [workspace.dependencies] hdx = { version = "0.0.1", path = "crates/hdx" } hdx_atom = { version = "0.0.0", path = "crates/hdx_atom" } -hdx_atomizable_derive = { version = "0.0.0", path = "crates/hdx_atomizable_derive" } +hdx_derive = { version = "0.0.0", path = "crates/hdx_derive" } hdx_parser = { version = "0.0.1", path = "crates/hdx_parser" } hdx_lexer = { version = "0.0.1", path = "crates/hdx_lexer" } hdx_syntax = { version = "0.0.0", path = "crates/hdx_syntax" } @@ -22,19 +22,20 @@ hdx_ast = { version = "0.0.0", path = "crates/hdx_ast" } hdx_writer = { version = "0.0.0", path = "crates/hdx_writer" } # Use OXC Allocator until https://github.com/fitzgen/bumpalo/pull/210 is resolved -oxc_allocator = { version = "0.0.7" } +oxc_allocator = { version = "0.6.0" } bumpalo = { version = "3.13.0" } clap = { version = "4.3.19" } closestmatch = { version = "0.1.2" } -miette = { version = "5.9.0" } +miette = { version = "6.0.1" } thiserror = { version = "1.0.43" } serde = { version = "1.0.171" } serde_json = { version = "1.0.102" } syn = { version = "2.0.26" } quote = { version = "1.0.31" } +proc-macro2 = { version = "1.0.66" } bitmask-enum = { version = "2.2.1" } glob = { version = "0.3.1" } diff --git a/crates/hdx/Cargo.toml b/crates/hdx/Cargo.toml index dcd02259..b2094c00 100644 --- a/crates/hdx/Cargo.toml +++ b/crates/hdx/Cargo.toml @@ -12,10 +12,11 @@ repository.workspace = true [dependencies] hdx_lexer = { workspace = true } hdx_syntax = { workspace = true } +hdx_ast = { workspace = true } hdx_parser = { workspace = true } hdx_writer = { workspace = true } hdx_atom = { workspace = true } -hdx_atomizable_derive = { workspace = true } +hdx_derive = { workspace = true } clap = { workspace = true, features = ["derive", "cargo"] } diff --git a/crates/hdx/src/main.rs b/crates/hdx/src/main.rs index 88034f15..08f4a9eb 100644 --- a/crates/hdx/src/main.rs +++ b/crates/hdx/src/main.rs @@ -1,6 +1,7 @@ use clap::Parser; -use hdx_parser::Allocator; +use hdx_ast::css::StyleSheet; use hdx_writer::{BaseCssWriter, WriteCss}; +use oxc_allocator::Allocator; #[derive(Debug, Parser)] #[clap(author, version, about, long_about = None)] @@ -29,9 +30,9 @@ fn main() { let result = hdx_parser::Parser::new( &allocator, source_text.as_str(), - hdx_parser::ParserOptions::default(), + hdx_parser::Features::default(), ) - .parse(); + .parse_with::(); { let start = std::time::Instant::now(); let mut str = String::new(); diff --git a/crates/hdx_ast/Cargo.toml b/crates/hdx_ast/Cargo.toml index f710d806..bc18c597 100644 --- a/crates/hdx_ast/Cargo.toml +++ b/crates/hdx_ast/Cargo.toml @@ -13,7 +13,9 @@ repository.workspace = true hdx_lexer = { workspace = true } hdx_syntax = { workspace = true } hdx_atom = { workspace = true } -hdx_atomizable_derive = { workspace = true } +hdx_parser = { workspace = true } +hdx_writer = { workspace = true } +hdx_derive = { workspace = true } # Use OXC Allocator until https://github.com/fitzgen/bumpalo/pull/210 is resolved oxc_allocator = { workspace = true } @@ -23,6 +25,8 @@ miette = { workspace = true } serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } +bitmask-enum = { workspace = true } + [dev-dependencies] glob = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/hdx_ast/src/css/component_values.rs b/crates/hdx_ast/src/css/component_values.rs index c21092ff..3c701772 100644 --- a/crates/hdx_ast/src/css/component_values.rs +++ b/crates/hdx_ast/src/css/component_values.rs @@ -1,10 +1,12 @@ +use hdx_atom::Atom; +use hdx_lexer::{PairWise, Token}; +use hdx_parser::{unexpected, Box, Parse, Parser, Result as ParserResult, Spanned, State, Vec}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; -use crate::{Atom, Box, PairWise, Span, Spanned, Token, Vec}; - // https://drafts.csswg.org/css-syntax-3/#consume-component-value -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] pub enum ComponentValue<'a> { SimpleBlock(Spanned>), @@ -12,18 +14,182 @@ pub enum ComponentValue<'a> { Token(Token), } -#[derive(Debug, PartialEq, Hash)] +// https://drafts.csswg.org/css-syntax-3/#consume-component-value +impl<'a> Parse<'a> for ComponentValue<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::LeftCurly | Token::LeftSquare | Token::LeftParen => { + Ok(Self::SimpleBlock(SimpleBlock::parse(parser)?).spanned(span.end(parser.pos()))) + } + Token::Function(_) => Ok(Self::Function(Function::parse(parser)?).spanned(span.end(parser.pos()))), + token => { + parser.advance(); + Ok(Self::Token(token).spanned(span)) + } + } + } +} + +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub struct ComponentValues<'a>(pub Vec<'a, Spanned>>); + +impl<'a> Parse<'a> for ComponentValues<'a> { + // https://drafts.csswg.org/css-syntax-3/#consume-list-of-components + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut values = parser.new_vec(); + loop { + match parser.cur() { + Token::Eof => break, + Token::RightCurly if parser.is(State::Nested) => break, + // ComponentValues can be passed a "stop token" which could be any token. + // In reality it is only ever called with a comma-token or semicolon-token. + Token::Semicolon if parser.is(State::StopOnSemicolon) => break, + Token::Comma if parser.is(State::StopOnComma) => break, + Token::RightCurly => { + parser.advance(); + } + c => values.push(ComponentValue::parse(parser)?), + } + } + Ok(Self(values).spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for ComponentValues<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + todo!(); + } +} + +impl<'a> WriteCss<'a> for ComponentValue<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self { + Self::SimpleBlock(b) => b.write_css(sink), + Self::Function(f) => f.write_css(sink), + Self::Token(token) => { + match token { + Token::Ident(name) => sink.write_str(name.as_ref())?, + Token::AtKeyword(name) => { + sink.write_char('@')?; + sink.write_str(name.as_ref())?; + } + Token::Hash(hash) | Token::HashId(hash) => { + sink.write_char('#')?; + sink.write_str(hash.as_ref())?; + } + Token::String(string) => { + sink.write_char('"')?; + sink.write_str(string.as_ref())?; + sink.write_char('"')?; + } + Token::Url(url) => { + sink.write_str("url(")?; + sink.write_str(url.as_ref())?; + sink.write_str("\")")?; + } + Token::Delim(ch) => { + sink.write_char(*ch)?; + } + Token::Number(n, _) => sink.write_str(&format!("{}", n))?, + Token::Dimension(n, unit, _) => { + sink.write_str(&format!("{}", n))?; + sink.write_str(unit.as_ref())?; + } + Token::Whitespace => sink.write_char(' ')?, + Token::Cdo => sink.write_str("")?, + Token::Colon => sink.write_char(':')?, + Token::Semicolon => sink.write_char(';')?, + Token::Comma => sink.write_char(',')?, + Token::LeftSquare => sink.write_char('[')?, + Token::RightSquare => sink.write_char(']')?, + Token::LeftParen => sink.write_char('(')?, + Token::RightParen => sink.write_char(')')?, + Token::LeftCurly => sink.write_char('{')?, + Token::RightCurly => sink.write_char('}')?, + Token::Undetermined => {} + Token::Comment(content) => sink.write_trivia_str(content.as_ref())?, + Token::Function(name) => { + sink.write_str(name.as_ref())?; + sink.write_char('(')?; + } + Token::Eof | Token::BadString | Token::BadUrl => {} + } + Ok(()) + } + } + } +} + +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct SimpleBlock<'a> { pub pairwise: PairWise, - pub value: Box<'a, Vec<'a, Spanned>>>, + pub value: Box<'a, Spanned>>, +} + +// https://drafts.csswg.org/css-syntax-3/#consume-a-simple-block +impl<'a> Parse<'a> for SimpleBlock<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + if let Some(pairwise) = parser.cur().to_pairwise() { + let ending_token = pairwise.end(); + let span = parser.span(); + let value = ComponentValues::parse(parser)?; + Ok(Self { value: parser.boxup(value), pairwise }.spanned(span.end(parser.pos()))) + } else { + unexpected!(parser) + } + } +} + +impl<'a> WriteCss<'a> for SimpleBlock<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self.pairwise { + PairWise::Square => sink.write_char('[')?, + PairWise::Curly => sink.write_char('{')?, + PairWise::Paren => sink.write_char('(')?, + } + self.value.write_css(sink)?; + match self.pairwise { + PairWise::Square => sink.write_char(']')?, + PairWise::Curly => sink.write_char('}')?, + PairWise::Paren => sink.write_char(')')?, + } + Ok(()) + } } -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct Function<'a> { pub name: Atom, - pub value: Box<'a, Vec<'a, Spanned>>>, + pub value: Box<'a, Spanned>>, +} + +// https://drafts.csswg.org/css-syntax-3/#consume-function +impl<'a> Parse<'a> for Function<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Function(name) => { + let value = ComponentValues::parse(parser)?; + Ok(Self { name, value: parser.boxup(value) }.spanned(span.end(parser.pos()))) + } + token => unexpected!(parser, token), + } + } +} + +impl<'a> WriteCss<'a> for Function<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_str(self.name.as_ref())?; + sink.write_char('(')?; + self.value.write_css(sink)?; + sink.write_char(')') + } } #[cfg(test)] diff --git a/crates/hdx_ast/src/css/mod.rs b/crates/hdx_ast/src/css/mod.rs index 14dbb3c5..0a1f6393 100644 --- a/crates/hdx_ast/src/css/mod.rs +++ b/crates/hdx_ast/src/css/mod.rs @@ -1,8 +1,10 @@ pub mod component_values; pub mod properties; -pub mod qualified_rule; pub mod rules; pub mod selector; pub mod stylesheet; +pub mod stylerule; pub mod unknown; pub mod values; + +pub use stylesheet::StyleSheet; diff --git a/crates/hdx_ast/src/css/properties.rs b/crates/hdx_ast/src/css/properties.rs index 5244dd68..1cd98f80 100644 --- a/crates/hdx_ast/src/css/properties.rs +++ b/crates/hdx_ast/src/css/properties.rs @@ -1,263 +1,276 @@ use std::{fmt::Debug, hash::Hash}; +use hdx_atom::{atom, Atom}; +use hdx_lexer::Token; +use hdx_parser::{diagnostics, expect, Parse, Parser, Result as ParserResult, Spanned, State, unexpected, discard}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; use crate::{ - atom, - css::{component_values::ComponentValue, unknown::UnknownDeclaration, values::*}, - Atom, Atomizable, Box, Span, Spanned, Vec, + css::{component_values::ComponentValues, values}, + Box, }; -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct Custom<'a> { - pub name: Atom, - pub value: Box<'a, Vec<'a, Spanned>>>, - pub value_like: Spanned>, - pub important: bool, + pub value: Box<'a, Spanned>>, + // pub value_like: Spanned>, } -pub trait Declaration: Debug + PartialEq + Hash { - type Value: Default + Debug + PartialEq + Hash; +impl<'a> WriteCss<'a> for Custom<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + self.value.write_css(sink) + } +} - fn initial() -> Self::Value; - fn name_as_atom() -> Atom; - fn is_inherits() -> bool; - fn is_standard() -> bool; - fn is_shorthand() -> bool; +impl<'a> Parse<'a> for Custom<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + parser.set(State::StopOnSemicolon); + let value = ComponentValues::parse(parser)?; + parser.unset(State::StopOnSemicolon); + Ok(Self { value: parser.boxup(value) }.spanned(span.end(parser.pos()))) + } } -macro_rules! property_initial { - ($value: ty,) => { - fn initial() -> $value { - <$value>::default() - } - }; - ($value: ty, $initial: expr) => { - fn initial() -> $value { - $initial - } - }; +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct Unknown<'a> { + pub value: Box<'a, Spanned>>, } -macro_rules! property_standard { - ($l:literal) => { - fn is_standard() -> bool { - $l - } - }; - () => { - fn is_standard() -> bool { - true - } - }; +impl<'a> Parse<'a> for Unknown<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + parser.set(State::StopOnSemicolon); + let value = ComponentValues::parse(parser)?; + parser.unset(State::StopOnSemicolon); + Ok(Self { value: parser.boxup(value) }.spanned(span.end(parser.pos()))) + } } -macro_rules! property_shorthand { - ($l:literal) => { - fn is_shorthand() -> bool { - $l - } - }; - () => { - fn is_shorthand() -> bool { - false - } - }; +impl<'a> WriteCss<'a> for Unknown<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + self.value.write_css(sink) + } } -macro_rules! property_inherits { - ($l:literal) => { - fn is_inherits() -> bool { - $l - } - }; - () => { - fn is_inherits() -> bool { - false - } - }; +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub struct StyleProperty<'a> { + name: Atom, + value: StyleValue<'a>, + important: bool, } -macro_rules! property { - ( - $atom: expr, $name: ident, $value: ty, $($standard:literal)?, $($shorthand:literal)?, $($inherits:literal)?, $($initial: expr)? - ) => { - #[derive(Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] - pub struct $name<'a> { - pub important: bool, - pub value: Box<'a, Spanned<$value>>, - } - - impl<'a> Declaration for $name<'a> { - type Value = $value; - - property_initial!($value, $($initial)?); - property_inherits!($($inherits)?); - property_standard!($($standard)?); - property_shorthand!($($shorthand)?); - - fn name_as_atom() -> Atom { - $atom - } - } - }; +impl<'a> WriteCss<'a> for StyleProperty<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_str(self.name.as_ref())?; + sink.write_char(':')?; + sink.write_trivia_char(' ')?; + self.value.write_css(sink)?; + if self.important { + sink.write_str("!important")?; + } + Ok(()) + } } macro_rules! properties { ( $( - $atom: expr => $name: ident<$value: ty> $(standard=$standard:literal)? $(shorthand=$shorthand:literal)? $(inherits=$inherits:literal)? $(initial=$initial: expr)?, + $name: ident$(<$a: lifetime>)?: $atom: pat, )+ ) => { - #[derive(Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] - pub enum Property<'a> { - $( - $name(Box<'a, Spanned<$name<'a>>>), - )+ - Custom(Box<'a, Spanned>>), - Unknown(Box<'a, Spanned>>), - } - #[derive(Debug, PartialEq, Hash)] - pub enum PropertyId { - $( - $name, - )+ - } - impl Atomizable for PropertyId { - fn from_atom(atom: Atom) -> Option { - match atom { - $( - c if c == $atom => Some(Self::$name), - )+ - _ => None - } - } - fn to_atom(&self) -> Atom { - match self { - $( - Self::$name => $atom, - )+ - } - } - } - - $( - property!($atom, $name, $value, $($standard)?, $($inherits)?, $($shorthand)?, $($initial)?); - )+ - - #[cfg(test)] - mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - $( - assert_eq!(size_of::<$name>(), 16); - )+ - } - } - }; -} + #[derive(Debug, Hash)] + #[cfg_attr(feature = "serde", derive(Serialize), serde())] + pub enum StyleValue<'a> { + Initial, + Inherit, + Unset, + Revert, + RevertLayer, + Custom(Box<'a, Spanned>>), + Unknown(Box<'a, Spanned>>), + $( + $name(Box<'a, Spanned)?>>), + )+ + } -// TODO! -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Todo { - #[default] - Todo, + impl<'a> WriteCss<'a> for StyleValue<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self { + Self::Initial => sink.write_str("initial")?, + Self::Inherit => sink.write_str("inherit")?, + Self::Unset => sink.write_str("unset")?, + Self::Revert => sink.write_str("revert")?, + Self::RevertLayer => sink.write_str("revert-layer")?, + Self::Custom(v) => v.write_css(sink)?, + Self::Unknown(v) => v.write_css(sink)?, + $( + Self::$name(v) => v.write_css(sink)?, + )+ + } + Ok(()) + } + } + + impl<'a> Parse<'a> for StyleProperty<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let (name, value) = match parser.cur() { + Token::Ident(atom) => { + let name = atom.to_ascii_lowercase(); + match name { + $( + $atom => { + expect!(parser, Token::Colon); + parser.advance(); + let value = match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + atom!("initial") => { + parser.advance(); + StyleValue::Initial + } + atom!("inherit") => { + parser.advance(); + StyleValue::Inherit + } + atom!("unset") => { + parser.advance(); + StyleValue::Unset + } + atom!("revert") => { + parser.advance(); + StyleValue::Revert + } + atom!("revert-layer") => { + parser.advance(); + StyleValue::RevertLayer + }, + _ => { + let parsed = values::$name::parse(parser)?; + StyleValue::$name(parser.boxup(parsed)) + } + }, + _ => { + let parsed = values::$name::parse(parser)?; + StyleValue::$name(parser.boxup(parsed)) + } + }; + (name, value) + }, + )* + _ => { + let value = Unknown::parse(parser)?; + parser.warn(diagnostics::UnknownDeclaration(value.span).into()); + (atom, StyleValue::Unknown(parser.boxup(value))) + } + } + }, + token => unexpected!(parser, token), + }; + let important = if matches!(parser.cur(), Token::Delim('!')) && matches!(parser.peek(), Token::Ident(atom!("important"))) { + parser.advance(); + parser.advance(); + true + } else { + false + }; + discard!(parser, Token::Semicolon); + Ok(Self { name, value, important }.spanned(span.end(parser.pos()))) + } + } + }; } properties! { // https://drafts.csswg.org/css-align-3/#property-index - atom!("align-content") => AlignContent>, - atom!("align-items") => AlignItems>, - atom!("align-self") => AlignSelf>, - atom!("column-gap") => ColumnGap>, - atom!("gap") => Gap>> shorthand=true, - atom!("justify-content") => JustifyContent>, - atom!("justify-items") => JustifyItems>, - atom!("justify-self") => JustifySelf>, - atom!("place-content") => PlaceContent>> shorthand=true, - atom!("place-items") => PlaceItems>> shorthand=true, - atom!("place-self") => PlaceSelf>> shorthand=true, - atom!("row-gap") => RowGap>, + AlignContent: atom!("align-content"), + AlignItems: atom!("align-items"), + AlignSelf: atom!("align-self"), + ColumnGap: atom!("column-gap"), + Gap: atom!("gap"), + JustifyContent: atom!("justify-content"), + JustifyItems: atom!("justify-items"), + JustifySelf: atom!("justify-self"), + PlaceContent: atom!("place-content"), + PlaceItems: atom!("place-items"), + PlaceSelf: atom!("place-self"), + RowGap: atom!("row-gap"), // https://drafts.csswg.org/css-anchor-position-1/#property-index - atom!("anchor-default") => AnchorDefault>, - atom!("anchor-position") => AnchorPosition>, - atom!("position-fallback") => PositionFallback>, - atom!("position-fallback-bounds") => PositionFallbackBounds>, + AnchorDefault: atom!("anchor-default"), + AnchorPosition: atom!("anchor-position"), + PositionFallback: atom!("position-fallback"), + PositionFallbackBounds: atom!("position-fallback-bounds"), // https://drafts.csswg.org/css-animations-1/#property-index - atom!("animation") => Animation> shorthand=true, - atom!("animation-delay") => AnimationDelay>, - atom!("animation-direction") => AnimationDirection>, + AnimationExpr: atom!("animation"), + AnimationDelay: atom!("animation-delay"), + AnimationDirection: atom!("animation-direction"), // ! animation-duration redefined in css-animations-2 - atom!("animation-fill-mode") => AnimationFillMode>, - atom!("animation-iteration-count") => AnimationIterationCount>, - atom!("animation-name") => AnimationName>, - atom!("animation-play-state") => AnimationPlayState>, - atom!("animation-timing-function") => AnimationTimingFunction>, + AnimationFillMode: atom!("animation-fill-mode"), + AnimationIterationCount: atom!("animation-iteration-count"), + AnimationName: atom!("animation-name"), + AnimationPlayState: atom!("animation-play-state"), + AnimationTimingFunction: atom!("animation-timing-function"), // https://drafts.csswg.org/css-animations-2/#property-index - atom!("animation-duration") => AnimationDuration>, - atom!("animation-composition") => AnimationComposition>, - atom!("animation-timeline") => AnimationTimeline>, + AnimationDuration: atom!("animation-duration"), + AnimationComposition: atom!("animation-composition"), + AnimationTimeline: atom!("animation-timeline"), // https://drafts.csswg.org/css-backgrounds-3/#property-index - atom!("background") => Background> shorthand=true, - atom!("background-attachment") => BackgroundAttachment>, + Background: atom!("background"), + BackgroundAttachment: atom!("background-attachment"), // ! background-clip redefined in css-backgrounds-4 - atom!("background-color") => BackgroundColor>>, - atom!("background-image") => BackgroundImage>, - atom!("background-origin") => BackgroundOrigin>, + BackgroundColor: atom!("background-color"), + BackgroundImage: atom!("background-image"), + BackgroundOrigin: atom!("background-origin"), // ! background-position redefined in css-backgrounds-4 - atom!("background-repeat") => BackgroundRepeat>, - atom!("background-size") => BackgroundSize>, - atom!("border") => Border> shorthand=true, - atom!("border-bottom") => BorderBottom> shorthand=true, - atom!("border-bottom-color") => BorderBottomColor>> initial=Expr::Literal(Spanned::dummy(ColorValue::CurrentColor)), - atom!("border-bottom-left-radius") => BorderBottomLeftRadius>>, - atom!("border-bottom-right-radius") => BorderBottomRightRadius>>, - atom!("border-bottom-style") => BorderBottomStyle>, - atom!("border-bottom-width") => BorderBottomWidth>, - atom!("border-color") => BorderColor>>> shorthand=true, - atom!("border-image") => BorderImage> shorthand=true, - atom!("border-image-outset") => BorderImageOutset>, - atom!("border-image-repeat") => BorderImageRepeat>, - atom!("border-image-slice") => BorderImageSlice>, - atom!("border-image-source") => BorderImageSource>, - atom!("border-image-width") => BorderImageWidth>, - atom!("border-left") => BorderLeft> shorthand=true, - atom!("border-left-color") => BorderLeftColor> initial=ColorValue::CurrentColor, - atom!("border-left-style") => BorderLeftStyle>, - atom!("border-left-width") => BorderLeftWidth>, - atom!("border-radius") => BorderRadius> shorthand=true, - atom!("border-right") => BorderRight> shorthand=true, - atom!("border-right-color") => BorderRightColor> initial=ColorValue::CurrentColor, - atom!("border-right-style") => BorderRightStyle>, - atom!("border-right-width") => BorderRightWidth>, - atom!("border-style") => BorderStyle>> shorthand=true, - atom!("border-top") => BorderTop> shorthand=true, - atom!("border-top-color") => BorderTopColor> initial=ColorValue::CurrentColor, - atom!("border-top-left-radius") => BorderTopLeftRadius>>, - atom!("border-top-right-radius") => BorderTopRightRadius>>, - atom!("border-top-style") => BorderTopStyle>, - atom!("border-top-width") => BorderTopWidth>, - atom!("border-width") => BorderWidth>> shorthand=true, - atom!("box-shadow") => BoxShadow>, + BackgroundRepeat: atom!("background-repeat"), + BackgroundSize: atom!("background-size"), + Border: atom!("border"), + BorderBottom: atom!("border-bottom"), + BorderBottomColor: atom!("border-bottom-color"), + BorderBottomLeftRadius: atom!("border-bottom-left-radius"), + BorderBottomRightRadius: atom!("border-bottom-right-radius"), + BorderBottomStyle: atom!("border-bottom-style"), + BorderBottomWidth: atom!("border-bottom-width"), + BorderColor: atom!("border-color"), + BorderImage: atom!("border-image"), + BorderImageOutset: atom!("border-image-outset"), + BorderImageRepeat: atom!("border-image-repeat"), + BorderImageSlice: atom!("border-image-slice"), + BorderImageSource: atom!("border-image-source"), + BorderImageWidth: atom!("border-image-width"), + BorderLeft: atom!("border-left"), + BorderLeftColor: atom!("border-left-color"), + BorderLeftStyle: atom!("border-left-style"), + BorderLeftWidth: atom!("border-left-width"), + BorderRadius: atom!("border-radius"), + BorderRight: atom!("border-right"), + BorderRightColor: atom!("border-right-color"), + BorderRightStyle: atom!("border-right-style"), + BorderRightWidth: atom!("border-right-width"), + BorderStyle: atom!("border-style"), + BorderTop: atom!("border-top"), + BorderTopColor: atom!("border-top-color"), + BorderTopLeftRadius: atom!("border-top-left-radius"), + BorderTopRightRadius: atom!("border-top-right-radius"), + BorderTopStyle: atom!("border-top-style"), + BorderTopWidth: atom!("border-top-width"), + BorderWidth: atom!("border-width"), + BoxShadow: atom!("box-shadow"), // https://drafts.csswg.org/css-backgrounds-4/#property-index - atom!("background-clip") => BackgroundClip>, - atom!("background-position") => BackgroundPosition>, - atom!("background-position-block") => BackgroundPositionBlock>, - atom!("background-position-inline") => BackgroundPositionInline>, - atom!("background-position-x") => BackgroundPositionX>, - atom!("background-position-y") => BackgroundPositionY>, + BackgroundClip: atom!("background-clip"), + BackgroundPosition: atom!("background-position"), + BackgroundPositionBlock: atom!("background-position-block"), + BackgroundPositionInline: atom!("background-position-inline"), + BackgroundPositionX: atom!("background-position-x"), + BackgroundPositionY: atom!("background-position-y"), // https://drafts.csswg.org/css-box-3/#property-index @@ -273,17 +286,17 @@ properties! { // ! padding-top redefined in css-box-4 // https://drafts.csswg.org/css-box-4/#property-index - atom!("margin") => Margin>> shorthand=true, - atom!("margin-bottom") => MarginBottom>, - atom!("margin-left") => MarginLeft>, - atom!("margin-right") => MarginRight>, - atom!("margin-top") => MarginTop>, - atom!("margin-trim") => MarginTrim>, - atom!("padding") => Padding>> shorthand=true, - atom!("padding-bottom") => PaddingBottom>, - atom!("padding-left") => PaddingLeft>, - atom!("padding-right") => PaddingRight>, - atom!("padding-top") => PaddingTop>, + Margin: atom!("margin"), + MarginBottom: atom!("margin-bottom"), + MarginLeft: atom!("margin-left"), + MarginRight: atom!("margin-right"), + MarginTop: atom!("margin-top"), + MarginTrim: atom!("margin-trim"), + Padding: atom!("padding"), + PaddingBottom: atom!("padding-bottom"), + PaddingLeft: atom!("padding-left"), + PaddingRight: atom!("padding-right"), + PaddingTop: atom!("padding-top"), // https://drafts.csswg.org/css-break-3/#property-index // ! box-decoration-break redefined in css-break-4 @@ -294,20 +307,20 @@ properties! { // ! widows redefined in css-break-4 // https://drafts.csswg.org/css-break-4/#property-index - atom!("box-decoration-break") => BoxDecorationBreak>, - atom!("break-after") => BreakAfter>, - atom!("break-before") => BreakBefore>, - atom!("break-inside") => BreakInside>, - atom!("margin-break") => BreakMargin>, + BoxDecorationBreak: atom!("box-decoration-break"), + BreakAfter: atom!("break-after"), + BreakBefore: atom!("break-before"), + BreakInside: atom!("break-inside"), + MarginBreak: atom!("margin-break"), // For compatibility with CSS Level 2, UAs that conform to [CSS2] must alias the // page-break-before, page-break-after, and page-break-inside properties to break-before, // break-after, and break-inside by treating the page-break-* properties as legacy // shorthands for the break-* properties with the following value mappings: - atom!("page-break-after") => PageBreakAfter>, - atom!("page-break-before") => PageBreakBefore>, - atom!("page-break-inside") => PageBreakInside>, - atom!("orphans") => Orphans> inherits=true, - atom!("widows") => Widows> inherits=true, + PageBreakAfter: atom!("page-break-after"), + PageBreakBefore: atom!("page-break-before"), + PageBreakInside: atom!("page-break-inside"), + Orphans: atom!("orphans"), + Widows: atom!("widows"), // https://drafts.csswg.org/css-cascade-3/#property-index // ! all redefined in css-cascade-4 @@ -316,7 +329,7 @@ properties! { // ! all redefined in css-cascade-5 // https://drafts.csswg.org/css-cascade-5/#property-index - atom!("all") => All, + All: atom!("all"), // https://drafts.csswg.org/css-cascade-6/#property-index // @@ -326,8 +339,8 @@ properties! { // ! opacity redefined in css-color-4 // https://drafts.csswg.org/css-color-4/#property-index - atom!("color") => Color> inherits=true, - atom!("opacity") => Opacity>, + Color: atom!("color"), + Opacity: atom!("opacity"), // https://drafts.csswg.org/css-color-5/#property-index // @@ -336,10 +349,10 @@ properties! { // // https://drafts.csswg.org/css-color-adjust-1/#property-index - atom!("color-adjust") => ColorAdjust> shorthand=true, - atom!("color-scheme") => ColorScheme> inherits=true, - atom!("forced-color-adjust") => ForcedColorAdjust> inherits=true, - atom!("print-color-adjust") => PrintColorAdjust> inherits=true, + ColorAdjust: atom!("color-adjust"), + ColorScheme: atom!("color-scheme"), + ForcedColorAdjust: atom!("forced-color-adjust"), + PrintColorAdjust: atom!("print-color-adjust"), // https://drafts.csswg.org/css-color-hdr/#property-index // @@ -357,23 +370,23 @@ properties! { // ! content-visibility redefined in css-contain-3 // https://drafts.csswg.org/css-contain-2/#property-index - atom!("contain") => Contain>, + Contain: atom!("contain"), // ! content-visibility redefined in css-contain-3 // https://drafts.csswg.org/css-contain-3/#property-index - atom!("container") => Container> shorthand=true, - atom!("container-name") => ContainerName>, - atom!("container-type") => ContainerType>, - atom!("content-visibility") => ContentVisibility>, + Container: atom!("container"), + ContainerName: atom!("container-name"), + ContainerType: atom!("container-type"), + ContentVisibility: atom!("content-visibility"), // https://drafts.csswg.org/css-content-3/#property-index - atom!("bookmark-label") => BookmarkLabel>, - atom!("bookmark-level") => BookmarkLevel>, - atom!("bookmark-state") => BookmarkState>, - atom!("content") => Content>, - atom!("quotes") => Quotes>> inherits=true, - atom!("string-set") => StringSet> inherits=true, + BookmarkLabel: atom!("bookmark-label"), + BookmarkLevel: atom!("bookmark-level"), + BookmarkState: atom!("bookmark-state"), + Content: atom!("content"), + Quotes: atom!("quotes"), + StringSet: atom!("string-set"), // https://drafts.csswg.org/css-counter-styles-3/#property-index // @@ -384,11 +397,11 @@ properties! { // ! visibility redefined in css-display-4 // https://drafts.csswg.org/css-display-4/#property-index - atom!("display") => Display, - atom!("layout-order") => LayoutOrder>, - atom!("order") => Order>, - atom!("reading-order") => ReadingOrder>, - atom!("visibility") => Visibility inherits=true, + Display: atom!("display"), + LayoutOrder: atom!("layout-order"), + Order: atom!("order"), + ReadingOrder: atom!("reading-order"), + Visibility: atom!("visibility"), // https://drafts.csswg.org/css-easing-1/#property-index // @@ -403,8 +416,8 @@ properties! { // // https://drafts.csswg.org/css-exclusions-1/#property-index - atom!("wrap-flow") => WrapFlow>, - atom!("wrap-through") => WrapThrough>, + WrapFlow: atom!("wrap-flow"), + WrapThrough: atom!("wrap-through"), // https://drafts.csswg.org/css-extensions-1/#property-index // @@ -413,13 +426,13 @@ properties! { // ! align-content redefined in css-align-3 // ! align-items redefined in css-align-3 // ! align-self redefined in css-align-3 - atom!("flex") => Flex> shorthand=true, - atom!("flex-basis") => FlexBasis>, - atom!("flex-direction") => FlexDirection>, - atom!("flex-flow") => FlexFlow> shorthand=true, - atom!("flex-grow") => FlexGrow>, - atom!("flex-shrink") => FlexShrink>, - atom!("flex-wrap") => FlexWrap>, + Flex: atom!("flex"), + FlexBasis: atom!("flex-basis"), + FlexDirection: atom!("flex-direction"), + FlexFlow: atom!("flex-flow"), + FlexGrow: atom!("flex-grow"), + FlexShrink: atom!("flex-shrink"), + FlexWrap: atom!("flex-wrap"), // ! justify-content redefined in css-align-3 // https://drafts.csswg.org/css-font-loading-3/#property-index @@ -444,46 +457,46 @@ properties! { // ! font-weight redefined in css-fonts-4 // https://drafts.csswg.org/css-fonts-4/#property-index - atom!("font") => Font> shorthand=true inherits=true, - atom!("font-family") => FontFamily> inherits=true, - atom!("font-feature-settings") => FontFeatureSettings> inherits=true, - atom!("font-kerning") => FontKerning> inherits=true, - atom!("font-language-override") => FontLanguageOverride> inherits=true, - atom!("font-optical-sizing") => FontOpticalSizing> inherits=true, - atom!("font-palette") => FontPalette> inherits=true, - atom!("font-size") => FontSize> inherits=true, + Font: atom!("font"), + FontFamily: atom!("font-family"), + FontFeatureSettings: atom!("font-feature-settings"), + FontKerning: atom!("font-kerning"), + FontLanguageOverride: atom!("font-language-override"), + FontOpticalSizing: atom!("font-optical-sizing"), + FontPalette: atom!("font-palette"), + FontSize: atom!("font-size"), // ! font-size-adjust redefined in css-fonts-5 - atom!("font-stretch") => FontStretch> inherits=true, - atom!("font-style") => FontStyle>> inherits=true, - atom!("font-synthesis") => FontSynthesis> inherits=true, - atom!("font-synthesis-small-caps") => FontSynthesisSmallCaps> inherits=true, - atom!("font-synthesis-style") => FontSynthesisStyle> inherits=true, - atom!("font-synthesis-weight") => FontSynthesisWeight> inherits=true, - atom!("font-variant") => FontVariant> inherits=true, - atom!("font-variant-alternates") => FontVariantAlternates> inherits=true, - atom!("font-variant-caps") => FontVariantCaps> inherits=true, - atom!("font-variant-east-asian") => FontVariantEastAsian> inherits=true, - atom!("font-variant-emoji") => FontVariantEmoji> inherits=true, - atom!("font-variant-ligatures") => FontVariantLigatures> inherits=true, - atom!("font-variant-numeric") => FontVariantNumeric> inherits=true, - atom!("font-variant-position") => FontVariantPosition> inherits=true, - atom!("font-variation-settings") => FontVariationSettings> inherits=true, - atom!("font-weight") => FontWeight> inherits=true, + FontStretch: atom!("font-stretch"), + FontStyle: atom!("font-style"), + FontSynthesis: atom!("font-synthesis"), + FontSynthesisSmallCaps: atom!("font-synthesis-small-caps"), + FontSynthesisStyle: atom!("font-synthesis-style"), + FontSynthesisWeight: atom!("font-synthesis-weight"), + FontVariant: atom!("font-variant"), + FontVariantAlternates: atom!("font-variant-alternates"), + FontVariantCaps: atom!("font-variant-caps"), + FontVariantEastAsian: atom!("font-variant-east-asian"), + FontVariantEmoji: atom!("font-variant-emoji"), + FontVariantLigatures: atom!("font-variant-ligatures"), + FontVariantNumeric: atom!("font-variant-numeric"), + FontVariantPosition: atom!("font-variant-position"), + FontVariationSettings: atom!("font-variation-settings"), + FontWeight: atom!("font-weight"), // https://drafts.csswg.org/css-fonts-5/#property-index - atom!("font-size-adjust") => FontSizeAdjust> inherits=true, + FontSizeAdjust: atom!("font-size-adjust"), // https://drafts.csswg.org/css-forms-1/#property-index // // https://drafts.csswg.org/css-gcpm-3/#property-index - atom!("footnote-display") => FootnoteDisplay>, - atom!("footnote-policy") => FootnotePolicy>, - atom!("running") => Running>, + FootnoteDisplay: atom!("footnote-display"), + FootnotePolicy: atom!("footnote-policy"), + Running: atom!("running"), // ! string-set redefined in css-content-3 // https://drafts.csswg.org/css-gcpm-4/#property-index - atom!("copy-into") => CopyInto>, + CopyInto: atom!("copy-into"), // https://drafts.csswg.org/css-grid-1/#property-index // ! grid redefined in css-grid-2 @@ -503,103 +516,103 @@ properties! { // ! grid-template-rows redefined in css-grid-2 // https://drafts.csswg.org/css-grid-2/#property-index - atom!("grid") => Grid> shorthand=true, - atom!("grid-area") => GridArea> shorthand=true, - atom!("grid-auto-columns") => GridAutoColumns>, - atom!("grid-auto-flow") => GridAutoFlow>, - atom!("grid-auto-rows") => GridAutoRows>, - atom!("grid-column") => GridColumn> shorthand=true, - atom!("grid-column-end") => GridColumnEnd>, - atom!("grid-column-start") => GridColumnStart>, - atom!("grid-row") => GridRow> shorthand=true, - atom!("grid-row-end") => GridRowEnd>, - atom!("grid-row-start") => GridRowStart>, - atom!("grid-template") => GridTemplate> shorthand=true, - atom!("grid-template-areas") => GridTemplateAreas>, - atom!("grid-template-columns") => GridTemplateColumns>, - atom!("grid-template-rows") => GridTemplateRows>, + Grid: atom!("grid"), + GridArea: atom!("grid-area"), + GridAutoColumns: atom!("grid-auto-columns"), + GridAutoFlow: atom!("grid-auto-flow"), + GridAutoRows: atom!("grid-auto-rows"), + GridColumn: atom!("grid-column"), + GridColumnEnd: atom!("grid-column-end"), + GridColumnStart: atom!("grid-column-start"), + GridRow: atom!("grid-row"), + GridRowEnd: atom!("grid-row-end"), + GridRowStart: atom!("grid-row-start"), + GridTemplate: atom!("grid-template"), + GridTemplateAreas: atom!("grid-template-areas"), + GridTemplateColumns: atom!("grid-template-columns"), + GridTemplateRows: atom!("grid-template-rows"), // https://drafts.csswg.org/css-grid-3/#property-index - atom!("align-tracks") => AlignTracks>, - atom!("justify-tracks") => JustifyTracks>, - atom!("masonry-auto-flow") => MasonryAutoFlow>, + AlignTracks: atom!("align-tracks"), + JustifyTracks: atom!("justify-tracks"), + MasonryAutoFlow: atom!("masonry-auto-flow"), // https://drafts.csswg.org/css-images-3/#property-index - atom!("image-orientation") => ImageOrientation>, - atom!("image-rendering") => ImageRendering>, + ImageOrientation: atom!("image-orientation"), + ImageRendering: atom!("image-rendering"), // ! object-fit redefined in css-images-4 - atom!("object-position") => ObjectPosition>, + ObjectPosition: atom!("object-position"), // https://drafts.csswg.org/css-images-4/#property-index - atom!("image-resolution") => ImageResolution>, - atom!("object-fit") => ObjectFit>, + ImageResolution: atom!("image-resolution"), + ObjectFit: atom!("object-fit"), // https://drafts.csswg.org/css-images-5/#property-index - atom!("object-view-box") => ObjectViewBox>, + ObjectViewBox: atom!("object-view-box"), // https://drafts.csswg.org/css-inline-3/#property-index - atom!("alignment-baseline") => AlignmentBaseline>, - atom!("baseline-source") => BaselineSource>, - atom!("baseline-shift") => BaselineShift>, - atom!("dominant-baseline") => DominantBaseline inherits=true, - atom!("initial-letter") => InitialLetter>, - atom!("initial-letter-align") => InitialLetterAlign>, - atom!("initial-letter-wrap") => InitialLetterWrap> inherits=true, - atom!("inline-sizing") => InlineSizing inherits=true, - atom!("line-height") => LineHeight> inherits=true, - atom!("text-box-edge") => TextBoxEdge> inherits=true, - atom!("text-box-trim") => TextBoxTrim>, - atom!("vertical-align") => VerticalAlign> shorthand=true, + AlignmentBaseline: atom!("alignment-baseline"), + BaselineSource: atom!("baseline-source"), + BaselineShift: atom!("baseline-shift"), + DominantBaseline: atom!("dominant-baseline"), + InitialLetter: atom!("initial-letter"), + InitialLetterAlign: atom!("initial-letter-align"), + InitialLetterWrap: atom!("initial-letter-wrap"), + InlineSizing: atom!("inline-sizing"), + LineHeight: atom!("line-height"), + TextBoxEdge: atom!("text-box-edge"), + TextBoxTrim: atom!("text-box-trim"), + VerticalAlign: atom!("vertical-align"), // https://drafts.csswg.org/css-line-grid-1/#property-index - atom!("box-snap") => BoxSnap>, - atom!("line-grid") => LineGrid>, - atom!("line-snap") => LineSnap>, + BoxSnap: atom!("box-snap"), + LineGrid: atom!("line-grid"), + LineSnap: atom!("line-snap"), // https://drafts.csswg.org/css-link-params-1/#property-index - atom!("link-parameters") => LinkParameters>, + LinkParameters: atom!("link-parameters"), // https://drafts.csswg.org/css-lists-3/#property-index - atom!("counter-increment") => CounterIncrement>, - atom!("counter-reset") => CounterReset>, - atom!("counter-set") => CounterSet>, - atom!("list-style") => ListStyle> shorthand=true, - atom!("list-style-image") => ListStyleImage>> inherits=true, - atom!("list-style-position") => ListStylePosition> inherits=true, - atom!("list-style-type") => ListStyleType>> inherits=true, - atom!("marker-side") => MarkerSide> inherits=true, + CounterIncrement: atom!("counter-increment"), + CounterReset: atom!("counter-reset"), + CounterSet: atom!("counter-set"), + ListStyle: atom!("list-style"), + ListStyleImage: atom!("list-style-image"), + ListStylePosition: atom!("list-style-position"), + ListStyleType: atom!("list-style-type"), + MarkerSide: atom!("marker-side"), // https://drafts.csswg.org/css-logical-1/#property-index - atom!("block-size") => BlockSize, - atom!("border-block") => BorderBlock> shorthand=true, - atom!("border-block-color") => BorderBlockColor> shorthand=true, - atom!("border-block-end") => BorderBlockEnd> shorthand=true, - atom!("border-block-end-color") => BorderBlockEndColor> initial=ColorValue::CurrentColor, - atom!("border-block-end-style") => BorderBlockEndStyle, - atom!("border-block-end-width") => BorderBlockEndWidth, - atom!("border-block-start") => BorderBlockStart> shorthand=true, - atom!("border-block-start-color") => BorderBlockStartColor> initial=ColorValue::CurrentColor, - atom!("border-block-start-style") => BorderBlockStartStyle, - atom!("border-block-start-width") => BorderBlockStartWidth, - atom!("border-block-style") => BorderBlockStyle> shorthand=true, - atom!("border-block-width") => BorderBlockWidth> shorthand=true, - atom!("border-end-end-radius") => BorderEndEndRadius>>, - atom!("border-end-start-radius") => BorderEndStartRadius>>, - atom!("border-inline") => BorderInline> shorthand=true, - atom!("border-inline-color") => BorderInlineColor> shorthand=true, - atom!("border-inline-end") => BorderInlineEnd> shorthand=true, - atom!("border-inline-end-color") => BorderInlineEndColor> initial=ColorValue::CurrentColor, - atom!("border-inline-end-style") => BorderInlineEndStyle, - atom!("border-inline-end-width") => BorderInlineEndWidth, - atom!("border-inline-start") => BorderInlineStart> shorthand=true, - atom!("border-inline-start-color") => BorderInlineStartColor> initial=ColorValue::CurrentColor, - atom!("border-inline-start-style") => BorderInlineStartStyle, - atom!("border-inline-start-width") => BorderInlineStartWidth, - atom!("border-inline-style") => BorderInlineStyle> shorthand=true, - atom!("border-inline-width") => BorderInlineWidth> shorthand=true, - atom!("border-start-end-radius") => BorderStartEndRadius>>, - atom!("border-start-start-radius") => BorderStartStartRadius>>, - atom!("inline-size") => InlineSize shorthand=true, + BlockSize: atom!("block-size"), + BorderBlock: atom!("border-block"), + BorderBlockColor: atom!("border-block-color"), + BorderBlockEnd: atom!("border-block-end"), + BorderBlockEndColor: atom!("border-block-end-color"), + BorderBlockEndStyle: atom!("border-block-end-style"), + BorderBlockEndWidth: atom!("border-block-end-width"), + BorderBlockStart: atom!("border-block-start"), + BorderBlockStartColor: atom!("border-block-start-color"), + BorderBlockStartStyle: atom!("border-block-start-style"), + BorderBlockStartWidth: atom!("border-block-start-width"), + BorderBlockStyle: atom!("border-block-style"), + BorderBlockWidth: atom!("border-block-width"), + BorderEndEndRadius: atom!("border-end-end-radius"), + BorderEndStartRadius: atom!("border-end-start-radius"), + BorderInline: atom!("border-inline"), + BorderInlineColor: atom!("border-inline-color"), + BorderInlineEnd: atom!("border-inline-end"), + BorderInlineEndColor: atom!("border-inline-end-color"), + BorderInlineEndStyle: atom!("border-inline-end-style"), + BorderInlineEndWidth: atom!("border-inline-end-width"), + BorderInlineStart: atom!("border-inline-start"), + BorderInlineStartColor: atom!("border-inline-start-color"), + BorderInlineStartStyle: atom!("border-inline-start-style"), + BorderInlineStartWidth: atom!("border-inline-start-width"), + BorderInlineStyle: atom!("border-inline-style"), + BorderInlineWidth: atom!("border-inline-width"), + BorderStartEndRadius: atom!("border-start-end-radius"), + BorderStartStartRadius: atom!("border-start-start-radius"), + InlineSize: atom!("inline-size"), // ! inset redefined in css-position-3 // ! inset-block redefined in css-position-3 // ! inset-inline redefined in css-position-3 @@ -607,118 +620,118 @@ properties! { // ! inset-inline redefined in css-position-3 // ! inset-inline-end redefined in css-position-3 // ! inset-inline-start redefined in css-position-3 - atom!("margin-block") => MarginBlock> shorthand=true, - atom!("margin-block-end") => MarginBlockEnd, - atom!("margin-block-start") => MarginBlockStart, - atom!("margin-inline") => MarginInline> shorthand=true, - atom!("margin-inline-end") => MarginInlineEnd, - atom!("margin-inline-start") => MarginInlineStart, - atom!("max-block-size") => MaxBlockSize, - atom!("max-inline-size") => MaxInlineSize, - atom!("min-block-size") => MinBlockSize, - atom!("min-inline-size") => MinInlineSize, - atom!("padding-block") => PaddingBlock> shorthand=true, - atom!("padding-block-end") => PaddingBlockEnd, - atom!("padding-block-start") => PaddingBlockStart, - atom!("padding-inline") => PaddingInline> shorthand=true, - atom!("padding-inline-end") => PaddingInlineEnd, - atom!("padding-inline-start") => PaddingInlineStart, + MarginBlock: atom!("margin-block"), + MarginBlockEnd: atom!("margin-block-end"), + MarginBlockStart: atom!("margin-block-start"), + MarginInline: atom!("margin-inline"), + MarginInlineEnd: atom!("margin-inline-end"), + MarginInlineStart: atom!("margin-inline-start"), + MaxBlockSize: atom!("max-block-size"), + MaxInlineSize: atom!("max-inline-size"), + MinBlockSize: atom!("min-block-size"), + MinInlineSize: atom!("min-inline-size"), + PaddingBlock: atom!("padding-block"), + PaddingBlockEnd: atom!("padding-block-end"), + PaddingBlockStart: atom!("padding-block-start"), + PaddingInline: atom!("padding-inline"), + PaddingInlineEnd: atom!("padding-inline-end"), + PaddingInlineStart: atom!("padding-inline-start"), // https://drafts.csswg.org/css-mobile/#property-index // // https://drafts.csswg.org/css-multicol-1/#property-index - atom!("column-count") => ColumnCount>, - atom!("column-fill") => ColumnFill>, - atom!("column-rule") => ColumnRule> shorthand=true, - atom!("column-rule-color") => ColumnRuleColor> initial=ColorValue::CurrentColor, - atom!("column-rule-style") => ColumnRuleStyle, - atom!("column-rule-width") => ColumnRuleWidth, + ColumnCount: atom!("column-count"), + ColumnFill: atom!("column-fill"), + ColumnRule: atom!("column-rule"), + ColumnRuleColor: atom!("column-rule-color"), + ColumnRuleStyle: atom!("column-rule-style"), + ColumnRuleWidth: atom!("column-rule-width"), // ! column-span redined in css-multicol-2 - atom!("column-width") => ColumnWidth>, - atom!("columns") => Columns> shorthand=true, + ColumnWidth: atom!("column-width"), + Columns: atom!("columns"), // https://drafts.csswg.org/css-multicol-2/#property-index - atom!("column-span") => ColumnSpan>, + ColumnSpan: atom!("column-span"), // https://drafts.csswg.org/css-namespaces-3/#property-index // // https://drafts.csswg.org/css-nav-1/#property-index - atom!("spatial-navigation-action") => SpatialNavigationAction>, - atom!("spatial-navigation-contain") => SpatialNavigationContain>, - atom!("spatial-navigation-function") => SpatialNavigationFunction>, + SpatialNavigationAction: atom!("spatial-navigation-action"), + SpatialNavigationContain: atom!("spatial-navigation-contain"), + SpatialNavigationFunction: atom!("spatial-navigation-function"), // https://drafts.csswg.org/css-nesting-1/#property-index // // https://drafts.csswg.org/css-overflow-3/#property-index - atom!("overflow") => Overflow>> shorthand=true, - atom!("overflow-block") => OverflowBlock>, + Overflow: atom!("overflow"), + OverflowBlock: atom!("overflow-block"), // ! overflow-clip-margin redined in css-overflow-4 - atom!("overflow-inline") => OverflowInline>, - atom!("overflow-x") => OverflowX>, - atom!("overflow-y") => OverflowY>, - atom!("scroll-behavior") => ScrollBehavior>, - atom!("scrollbar-gutter") => ScrollbarGutter>, + OverflowInline: atom!("overflow-inline"), + OverflowX: atom!("overflow-x"), + OverflowY: atom!("overflow-y"), + ScrollBehavior: atom!("scroll-behavior"), + ScrollbarGutter: atom!("scrollbar-gutter"), // ! text-overflow redined in css-overflow-4 // https://drafts.csswg.org/css-overflow-4/#property-index // (Yes this is really in the spec as -webkit-line-clamp) - atom!("-webkit-line-clamp") => WebkitLineClamp> shorthand=true, - atom!("block-ellipsis") => BlockEllipsis> inherits=true, - atom!("continue") => Continue>, - atom!("line-clamp") => LineClamp> shorthand=true, - atom!("max-lines") => MaxLines>, - atom!("overflow-clip-margin") => OverflowClipMargin>, - atom!("overflow-clip-margin-block") => OverflowClipMarginBlock>, - atom!("overflow-clip-margin-block-end") => OverflowClipMarginBlockEnd>, - atom!("overflow-clip-margin-block-start") => OverflowClipMarginBlockStart>, - atom!("overflow-clip-margin-bottom") => OverflowClipMarginBottom>, - atom!("overflow-clip-margin-inline") => OverflowClipMarginInline>, - atom!("overflow-clip-margin-inline-end") => OverflowClipMarginInlineEnd>, - atom!("overflow-clip-margin-inline-start") => OverflowClipMarginInlineStart>, - atom!("overflow-clip-margin-left") => OverflowClipMarginLeft>, - atom!("overflow-clip-margin-right") => OverflowClipMarginRight>, - atom!("overflow-clip-margin-top") => OverflowClipMarginTop>, - atom!("text-overflow") => TextOverflow>, + WebkitLineClamp: atom!("-webkit-line-clamp"), + BlockEllipsis: atom!("block-ellipsis"), + Continue: atom!("continue"), + LineClamp: atom!("line-clamp"), + MaxLines: atom!("max-lines"), + OverflowClipMargin: atom!("overflow-clip-margin"), + OverflowClipMarginBlock: atom!("overflow-clip-margin-block"), + OverflowClipMarginBlockEnd: atom!("overflow-clip-margin-block-end"), + OverflowClipMarginBlockStart: atom!("overflow-clip-margin-block-start"), + OverflowClipMarginBottom: atom!("overflow-clip-margin-bottom"), + OverflowClipMarginInline: atom!("overflow-clip-margin-inline"), + OverflowClipMarginInlineEnd: atom!("overflow-clip-margin-inline-end"), + OverflowClipMarginInlineStart: atom!("overflow-clip-margin-inline-start"), + OverflowClipMarginLeft: atom!("overflow-clip-margin-left"), + OverflowClipMarginRight: atom!("overflow-clip-margin-right"), + OverflowClipMarginTop: atom!("overflow-clip-margin-top"), + TextOverflow: atom!("text-overflow"), // https://drafts.csswg.org/css-overscroll-1/#property-index - atom!("overscroll-behavior") => OverscrollBehavior> shorthand=true, - atom!("overscroll-behavior-block") => OverscrollBehaviorBlock>, - atom!("overscroll-behavior-inline") => OverscrollBehaviorInline>, - atom!("overscroll-behavior-x") => OverscrollBehaviorX>, - atom!("overscroll-behavior-y") => OverscrollBehaviorY>, + OverscrollBehavior: atom!("overscroll-behavior"), + OverscrollBehaviorBlock: atom!("overscroll-behavior-block"), + OverscrollBehaviorInline: atom!("overscroll-behavior-inline"), + OverscrollBehaviorX: atom!("overscroll-behavior-x"), + OverscrollBehaviorY: atom!("overscroll-behavior-y"), // https://drafts.csswg.org/css-page-3/#property-index - atom!("page") => Page>, + Page: atom!("page"), // https://drafts.csswg.org/css-page-4/#property-index // // https://drafts.csswg.org/css-page-floats-3/#property-index - atom!("clear") => Clear, - atom!("float") => Float, - atom!("float-defer") => FloatDefer, - atom!("float-offset") => FloatOffset, - atom!("float-reference") => FloatReference, + Clear: atom!("clear"), + Float: atom!("float"), + FloatDefer: atom!("float-defer"), + FloatOffset: atom!("float-offset"), + FloatReference: atom!("float-reference"), // https://drafts.csswg.org/css-page-template-1/#property-index // // https://drafts.csswg.org/css-position-3/#property-index - atom!("bottom") => Bottom> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("inset") => Inset>> shorthand=true, - atom!("inset-block") => InsetBlock>> shorthand=true, - atom!("inset-block-end") => InsetBlockEnd> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("inset-block-start") => InsetBlockStart> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("inset-inline") => InsetInline>> shorthand=true, - atom!("inset-inline-end") => InsetInlineEnd> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("inset-inline-start") => InsetInlineStart> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("left") => Left> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("position") => Position>, - atom!("right") => Right> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), - atom!("top") => Top> initial=MathExpr::Literal(Spanned::dummy(LengthPercentageOrAuto::Auto)), + Bottom: atom!("bottom"), + Inset: atom!("inset"), + InsetBlock: atom!("inset-block"), + InsetBlockEnd: atom!("inset-block-end"), + InsetBlockStart: atom!("inset-block-start"), + InsetInline: atom!("inset-inline"), + InsetInlineEnd: atom!("inset-inline-end"), + InsetInlineStart: atom!("inset-inline-start"), + Left: atom!("left"), + Position: atom!("position"), + Right: atom!("right"), + Top: atom!("top"), // https://drafts.csswg.org/css-preslev-1/#property-index // @@ -730,130 +743,130 @@ properties! { // // https://drafts.csswg.org/css-regions-1/#property-index - atom!("flow-from") => FlowFrom>, - atom!("flow-into") => FlowInto>, - atom!("region-fragment") => RegionFragment>, + FlowFrom: atom!("flow-from"), + FlowInto: atom!("flow-into"), + RegionFragment: atom!("region-fragment"), // https://drafts.csswg.org/css-rhythm-1/#property-index - atom!("block-step") => BlockStep> shorthand=true, - atom!("block-step-align") => BlockStepAlign>, - atom!("block-step-insert") => BlockStepInsert>, - atom!("block-step-round") => BlockStepRound>, - atom!("block-step-size") => BlockStepSize>, - atom!("line-height-step") => LineHeightStep>, + BlockStep: atom!("block-step"), + BlockStepAlign: atom!("block-step-align"), + BlockStepInsert: atom!("block-step-insert"), + BlockStepRound: atom!("block-step-round"), + BlockStepSize: atom!("block-step-size"), + LineHeightStep: atom!("line-height-step"), // https://drafts.csswg.org/css-round-display-1/#property-index - atom!("border-boundary") => BorderBoundary>, - atom!("shape-inside") => ShapeInside>, + BorderBoundary: atom!("border-boundary"), + ShapeInside: atom!("shape-inside"), // https://drafts.csswg.org/css-ruby-1/#property-index - atom!("ruby-align") => RubyAlign>, - atom!("ruby-merge") => RubyMerge>, - atom!("ruby-overhang") => RubyOverhang>, - atom!("ruby-position") => RubyPosition>, + RubyAlign: atom!("ruby-align"), + RubyMerge: atom!("ruby-merge"), + RubyOverhang: atom!("ruby-overhang"), + RubyPosition: atom!("ruby-position"), // https://drafts.csswg.org/css-scoping-1/#property-index // // https://drafts.csswg.org/css-scroll-anchoring-1/#property-index - atom!("overflow-anchor") => OverflowAnchor>, + OverflowAnchor: atom!("overflow-anchor"), // https://drafts.csswg.org/css-scroll-snap-1/#property-index - atom!("scroll-margin") => ScrollMargin> shorthand=true, - atom!("scroll-margin-block") => ScrollMarginBlock> shorthand=true, - atom!("scroll-margin-block-end") => ScrollMarginBlockEnd, - atom!("scroll-margin-block-start") => ScrollMarginBlockStart, - atom!("scroll-margin-bottom") => ScrollMarginBottom, - atom!("scroll-margin-inline") => ScrollMarginInline> shorthand=true, - atom!("scroll-margin-inline-end") => ScrollMarginInlineEnd, - atom!("scroll-margin-inline-start") => ScrollMarginInlineStart, - atom!("scroll-margin-left") => ScrollMarginLeft, - atom!("scroll-margin-right") => ScrollMarginRight, - atom!("scroll-margin-top") => ScrollMarginTop, - atom!("scroll-padding") => ScrollPadding> shorthand=true, - atom!("scroll-padding-block") => ScrollPaddingBlock> shorthand=true, - atom!("scroll-padding-block-end") => ScrollPaddingBlockEnd initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-block-start") => ScrollPaddingBlockStart initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-bottom") => ScrollPaddingBottom initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-inline") => ScrollPaddingInline> shorthand=true, - atom!("scroll-padding-inline-end") => ScrollPaddingInlineEnd initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-inline-start") => ScrollPaddingInlineStart initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-left") => ScrollPaddingLeft initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-right") => ScrollPaddingRight initial=LengthPercentageOrAuto::Auto, - atom!("scroll-padding-top") => ScrollPaddingTop initial=LengthPercentageOrAuto::Auto, - atom!("scroll-snap-align") => ScrollSnapAlign>, - atom!("scroll-snap-stop") => ScrollSnapStop>, - atom!("scroll-snap-type") => ScrollSnapType>, + ScrollMargin: atom!("scroll-margin"), + ScrollMarginBlock: atom!("scroll-margin-block"), + ScrollMarginBlockEnd: atom!("scroll-margin-block-end"), + ScrollMarginBlockStart: atom!("scroll-margin-block-start"), + ScrollMarginBottom: atom!("scroll-margin-bottom"), + ScrollMarginInline: atom!("scroll-margin-inline"), + ScrollMarginInlineEnd: atom!("scroll-margin-inline-end"), + ScrollMarginInlineStart: atom!("scroll-margin-inline-start"), + ScrollMarginLeft: atom!("scroll-margin-left"), + ScrollMarginRight: atom!("scroll-margin-right"), + ScrollMarginTop: atom!("scroll-margin-top"), + ScrollPadding: atom!("scroll-padding"), + ScrollPaddingBlock: atom!("scroll-padding-block"), + ScrollPaddingBlockEnd: atom!("scroll-padding-block-end"), + ScrollPaddingBlockStart: atom!("scroll-padding-block-start"), + ScrollPaddingBottom: atom!("scroll-padding-bottom"), + ScrollPaddingInline: atom!("scroll-padding-inline"), + ScrollPaddingInlineEnd: atom!("scroll-padding-inline-end"), + ScrollPaddingInlineStart: atom!("scroll-padding-inline-start"), + ScrollPaddingLeft: atom!("scroll-padding-left"), + ScrollPaddingRight: atom!("scroll-padding-right"), + ScrollPaddingTop: atom!("scroll-padding-top"), + ScrollSnapAlign: atom!("scroll-snap-align"), + ScrollSnapStop: atom!("scroll-snap-stop"), + ScrollSnapType: atom!("scroll-snap-type"), // https://drafts.csswg.org/css-scroll-snap-2/#property-index - atom!("scroll-start") => ScrollStart>, - atom!("scroll-start-block") => ScrollStartBlock>, - atom!("scroll-start-inline") => ScrollStartInline>, - atom!("scroll-start-target") => ScrollStartTarget>, - atom!("scroll-start-target-block") => ScrollStartTargetBlock>, - atom!("scroll-start-target-inline") => ScrollStartTargetInline>, - atom!("scroll-start-target-x") => ScrollStartTargetX>, - atom!("scroll-start-target-y") => ScrollStartTargetY>, - atom!("scroll-start-x") => ScrollStartX>, - atom!("scroll-start-y") => ScrollStartY>, + ScrollStart: atom!("scroll-start"), + ScrollStartBlock: atom!("scroll-start-block"), + ScrollStartInline: atom!("scroll-start-inline"), + ScrollStartTarget: atom!("scroll-start-target"), + ScrollStartTargetBlock: atom!("scroll-start-target-block"), + ScrollStartTargetInline: atom!("scroll-start-target-inline"), + ScrollStartTargetX: atom!("scroll-start-target-x"), + ScrollStartTargetY: atom!("scroll-start-target-y"), + ScrollStartX: atom!("scroll-start-x"), + ScrollStartY: atom!("scroll-start-y"), // https://drafts.csswg.org/css-scrollbars-1/#property-index - atom!("scrollbar-color") => ScrollbarColor>, - atom!("scrollbar-width") => ScrollbarWidth>, + ScrollbarColor: atom!("scrollbar-color"), + ScrollbarWidth: atom!("scrollbar-width"), // https://drafts.csswg.org/css-shadow-parts-1/#property-index // // https://drafts.csswg.org/css-shapes-1/#property-index - atom!("shape-image-threshold") => ShapeImageThreshold>, - atom!("shape-margin") => ShapeMargin>, - atom!("shape-outside") => ShapeOutside>, + ShapeImageThreshold: atom!("shape-image-threshold"), + ShapeMargin: atom!("shape-margin"), + ShapeOutside: atom!("shape-outside"), // https://drafts.csswg.org/css-shapes-2/#property-index // ! shape-inside is redefined in css-round-display-1 - atom!("shape-padding") => ShapePadding>, + ShapePadding: atom!("shape-padding"), // https://drafts.csswg.org/css-size-adjust-1/#property-index - atom!("text-size-adust") => TextSizeAdjust>, + TextSizeAdjust: atom!("text-size-adust"), // https://drafts.csswg.org/css-sizing-3/#property-index - atom!("box-sizing") => BoxSizing>, - atom!("height") => Height>, - atom!("max-height") => MaxHeight>, - atom!("max-width") => MaxWidth>, - atom!("min-height") => MinHeight>, - atom!("min-width") => MinWidth>, - atom!("width") => Width>, + BoxSizing: atom!("box-sizing"), + Height: atom!("height"), + MaxHeight: atom!("max-height"), + MaxWidth: atom!("max-width"), + MinHeight: atom!("min-height"), + MinWidth: atom!("min-width"), + Width: atom!("width"), // https://drafts.csswg.org/css-sizing-4/#property-index - atom!("aspect-ratio") => AspecRatio, - atom!("contain-intrinsic-block-size") => ContainIntrinsicBlockSize>, - atom!("contain-intrinsic-height") => ContainIntrinsicHeight>, - atom!("contain-intrinsic-inline-size") => ContainIntrinsicInlineSize>, - atom!("contain-intrinsic-size") => ContainIntrinsicSize>, - atom!("contain-intrinsic-width") => ContainIntrinsicWidth>, - atom!("min-intrinsic-sizing") => MinIntrinsicSizing>, + AspecRatio: atom!("aspect-ratio"), + ContainIntrinsicBlockSize: atom!("contain-intrinsic-block-size"), + ContainIntrinsicHeight: atom!("contain-intrinsic-height"), + ContainIntrinsicInlineSize: atom!("contain-intrinsic-inline-size"), + ContainIntrinsicSize: atom!("contain-intrinsic-size"), + ContainIntrinsicWidth: atom!("contain-intrinsic-width"), + MinIntrinsicSizing: atom!("min-intrinsic-sizing"), // https://drafts.csswg.org/css-speech-1/#property-index - atom!("cue") => Cue>, - atom!("cue-after") => CueAfter>, - atom!("cue-before") => CueBefore>, - atom!("pause") => Pause>, - atom!("pause-after") => PauseAfter>, - atom!("pause-before") => PauseBefore>, - atom!("rest") => Rest>, - atom!("rest-after") => RestAfter>, - atom!("rest-before") => RestBefore>, - atom!("speak") => Speak>, - atom!("speak-as") => SpeakAs>, - atom!("voice-balance") => VoiceBalance>, - atom!("voice-duration") => VoiceDuration>, - atom!("voice-family") => VoiceFamily>, - atom!("voice-pitch") => VoicePitch>, - atom!("voice-range") => VoiceRange>, - atom!("voice-rate") => VoiceRate>, - atom!("voice-stress") => VoiceStress>, - atom!("voice-volume") => VoiceVolume>, + Cue: atom!("cue"), + CueAfter: atom!("cue-after"), + CueBefore: atom!("cue-before"), + Pause: atom!("pause"), + PauseAfter: atom!("pause-after"), + PauseBefore: atom!("pause-before"), + Rest: atom!("rest"), + RestAfter: atom!("rest-after"), + RestBefore: atom!("rest-before"), + Speak: atom!("speak"), + SpeakAs: atom!("speak-as"), + VoiceBalance: atom!("voice-balance"), + VoiceDuration: atom!("voice-duration"), + VoiceFamily: atom!("voice-family"), + VoicePitch: atom!("voice-pitch"), + VoiceRange: atom!("voice-range"), + VoiceRate: atom!("voice-rate"), + VoiceStress: atom!("voice-stress"), + VoiceVolume: atom!("voice-volume"), // https://drafts.csswg.org/css-style-attr-1/#property-index // @@ -862,11 +875,11 @@ properties! { // // https://drafts.csswg.org/css-tables-3/#property-index - atom!("border-collapse") => BorderCollapse>, - atom!("border-spacing") => BorderSpacing>>, - atom!("caption-side") => CaptionSide>, - atom!("empty-cells") => EmptyCells>, - atom!("table-layout") => TableLayout>, + BorderCollapse: atom!("border-collapse"), + BorderSpacing: atom!("border-spacing"), + CaptionSide: atom!("caption-side"), + EmptyCells: atom!("empty-cells"), + TableLayout: atom!("table-layout"), // https://drafts.csswg.org/css-template-1/#property-index // TODO: Is this even a thing? @@ -891,40 +904,40 @@ properties! { // ! word-wrap redefined in css-text-4 // https://drafts.csswg.org/css-text-4/#property-index - atom!("hanging-punctuation") => HangingPunctuation> inherits=true, - atom!("hyphenate-character") => HyphenateCharacter> inherits=true, - atom!("hyphenate-limit-chars") => HyphenateLimitChars> inherits=true, - atom!("hyphenate-limit-last") => HyphenateLimitLast> inherits=true, - atom!("hyphenate-limit-lines") => HyphenateLimitLines> inherits=true, - atom!("hyphenate-limit-zone") => HyphenateLimitZone> inherits=true, - atom!("hyphens") => Hyphens> inherits=true, - atom!("letter-spacing") => LetterSpacing> inherits=true, - atom!("line-break") => LineBreak> inherits=true, - atom!("line-padding") => LinePadding> inherits=true, - atom!("overflow-wrap") => OverflowWrap> inherits=true, - atom!("tab-size") => TabSize> inherits=true, - atom!("text-align") => TextAlign> inherits=true, - atom!("text-align-all") => TextAlignAll> inherits=true, - atom!("text-align-last") => TextAlignLast> inherits=true, - atom!("text-autospace") => TextAutospace> inherits=true, - atom!("text-group-align") => TextGroupAlign>, - atom!("text-indent") => TextIndent> inherits=true, - atom!("text-justify") => TextJustify> inherits=true, - atom!("text-spacing") => TextSpacing> inherits=true, - atom!("text-spacing-trim") => TextSpacingTrim> inherits=true, - atom!("text-transform") => TextTransform> inherits=true, - atom!("text-wrap") => TextWrap> inherits=true, - atom!("white-space") => WhiteSpace> inherits=true, - atom!("white-space-collapse") => WhiteSpaceCollapse> inherits=true, - atom!("white-space-trim") => WhiteSpaceTrim>, - atom!("word-boundary-detection") => WordBoundaryDetection> inherits=true, - atom!("word-boundary-expansion") => WordBoundaryExpansion> inherits=true, - atom!("word-break") => WordBreak> inherits=true, - atom!("word-spacing") => WordSpacing> inherits=true, - atom!("word-wrap") => WordWrap>, - atom!("wrap-after") => WrapAfter>, - atom!("wrap-before") => WrapBefore>, - atom!("wrap-inside") => WrapInside>, + HangingPunctuation: atom!("hanging-punctuation"), + HyphenateCharacter: atom!("hyphenate-character"), + HyphenateLimitChars: atom!("hyphenate-limit-chars"), + HyphenateLimitLast: atom!("hyphenate-limit-last"), + HyphenateLimitLines: atom!("hyphenate-limit-lines"), + HyphenateLimitZone: atom!("hyphenate-limit-zone"), + Hyphens: atom!("hyphens"), + LetterSpacing: atom!("letter-spacing"), + LineBreak: atom!("line-break"), + LinePadding: atom!("line-padding"), + OverflowWrap: atom!("overflow-wrap"), + TabSize: atom!("tab-size"), + TextAlign: atom!("text-align"), + TextAlignAll: atom!("text-align-all"), + TextAlignLast: atom!("text-align-last"), + TextAutospace: atom!("text-autospace"), + TextGroupAlign: atom!("text-group-align"), + TextIndent: atom!("text-indent"), + TextJustify: atom!("text-justify"), + TextSpacing: atom!("text-spacing"), + TextSpacingTrim: atom!("text-spacing-trim"), + TextTransform: atom!("text-transform"), + TextWrap: atom!("text-wrap"), + WhiteSpace: atom!("white-space"), + WhiteSpaceCollapse: atom!("white-space-collapse"), + WhiteSpaceTrim: atom!("white-space-trim"), + WordBoundaryDetection: atom!("word-boundary-detection"), + WordBoundaryExpansion: atom!("word-boundary-expansion"), + WordBreak: atom!("word-break"), + WordSpacing: atom!("word-spacing"), + WordWrap: atom!("word-wrap"), + WrapAfter: atom!("wrap-after"), + WrapBefore: atom!("wrap-before"), + WrapInside: atom!("wrap-inside"), // https://drafts.csswg.org/css-text-decor-3/#property-index // ! text-decoration redefined in css-text-decor-4 @@ -938,31 +951,31 @@ properties! { // ! text-underline-position redefined in css-text-decor-4 // https://drafts.csswg.org/css-text-decor-4/#property-index - atom!("text-decoration") => TextDecoration> shorthand=true, - atom!("text-decoration-color") => TextDecorationColor>> initial=Expr::Literal(Spanned::dummy(ColorValue::CurrentColor)), - atom!("text-decoration-line") => TextDecorationLine> inherits=true, - atom!("text-decoration-skip") => TextDecorationSkip> inherits=true, - atom!("text-decoration-skip-ink") => TextDecorationSkipInk> inherits=true, - atom!("text-decoration-skip-self") => TextDecorationSkipSelf>, - atom!("text-decoration-skip-spaces") => TextDecorationSkipSpaces> inherits=true, - atom!("text-decoration-style") => TextDecorationStyle>, - atom!("text-decoration-thickness") => TextDecorationThickness>, - atom!("text-decoration-trim") => TextDecorationTrim>, - atom!("text-emphasis") => TextEmphasis> shorthand=true, - atom!("text-emphasis-color") => TextEmphasisColor> inherits=true initial=ColorValue::CurrentColor, - atom!("text-emphasis-position") => TextEmphasisPosition> inherits=true, - atom!("text-emphasis-skip") => TextEmphasisSkip> inherits=true, - atom!("text-emphasis-style") => TextEmphasisStyle> inherits=true, - atom!("text-shadow") => TextShadow> inherits=true, - atom!("text-underline-offset") => TextUnderlineOffset> inherits=true, - atom!("text-underline-position") => TextUnderlinePosition> inherits=true, + TextDecoration: atom!("text-decoration"), + TextDecorationColor: atom!("text-decoration-color"), + TextDecorationLine: atom!("text-decoration-line"), + TextDecorationSkip: atom!("text-decoration-skip"), + TextDecorationSkipInk: atom!("text-decoration-skip-ink"), + TextDecorationSkipSelf: atom!("text-decoration-skip-self"), + TextDecorationSkipSpaces: atom!("text-decoration-skip-spaces"), + TextDecorationStyle: atom!("text-decoration-style"), + TextDecorationThickness: atom!("text-decoration-thickness"), + TextDecorationTrim: atom!("text-decoration-trim"), + TextEmphasis: atom!("text-emphasis"), + TextEmphasisColor: atom!("text-emphasis-color"), + TextEmphasisPosition: atom!("text-emphasis-position"), + TextEmphasisSkip: atom!("text-emphasis-skip"), + TextEmphasisStyle: atom!("text-emphasis-style"), + TextShadow: atom!("text-shadow"), + TextUnderlineOffset: atom!("text-underline-offset"), + TextUnderlinePosition: atom!("text-underline-position"), // https://drafts.csswg.org/css-transitions-1/#property-index - atom!("transition") => Transition> shorthand=true, - atom!("transition-delay") => TransitionDelay>, - atom!("transition-duration") => TransitionDuration>, - atom!("transition-property") => TransitionProperty>, - atom!("transition-timing-function") => TransitionTimingFunction>, + Transition: atom!("transition"), + TransitionDelay: atom!("transition-delay"), + TransitionDuration: atom!("transition-duration"), + TransitionProperty: atom!("transition-property"), + TransitionTimingFunction: atom!("transition-timing-function"), // https://drafts.csswg.org/css-transitions-2/#property-index // @@ -983,25 +996,25 @@ properties! { // ! text-overflow redefined in css-overflow-4 // https://drafts.csswg.org/css-ui-4/#property-index - atom!("accent-color") => AccentColor> inherits=true, - atom!("appearance") => Appearance>, - atom!("caret") => Caret> inherits=true, - atom!("caret-color") => CaretColor> inherits=true, - atom!("caret-shape") => CaretShape> inherits=true, - atom!("cursor") => Cursor>> inherits=true, - atom!("input-security") => InputSecurity, - atom!("nav-down") => NavDown>, - atom!("nav-left") => NavLeft>, - atom!("nav-right") => NavRight>, - atom!("nav-up") => NavUp>, - atom!("outline") => Outline> shorthand=true, - atom!("outline-color") => OutlineColor>, - atom!("outline-offset") => OutlineOffset>, - atom!("outline-style") => OutlineStyle>, - atom!("outline-width") => OutlineWidth>, - atom!("pointer-events") => PointerEvents inherits=true, - atom!("resize") => Resize>, - atom!("user-select") => UserSelect>, + AccentColor: atom!("accent-color"), + Appearance: atom!("appearance"), + Caret: atom!("caret"), + CaretColor: atom!("caret-color"), + CaretShape: atom!("caret-shape"), + Cursor: atom!("cursor"), + InputSecurity: atom!("input-security"), + NavDown: atom!("nav-down"), + NavLeft: atom!("nav-left"), + NavRight: atom!("nav-right"), + NavUp: atom!("nav-up"), + Outline: atom!("outline"), + OutlineColor: atom!("outline-color"), + OutlineOffset: atom!("outline-offset"), + OutlineStyle: atom!("outline-style"), + OutlineWidth: atom!("outline-width"), + PointerEvents: atom!("pointer-events"), + Resize: atom!("resize"), + UserSelect: atom!("user-select"), // https://drafts.csswg.org/css-values-3/#property-index // @@ -1019,13 +1032,13 @@ properties! { // This spec defines the properties. // https://drafts.csswg.org/css-view-transitions-1/#property-index - atom!("view-transition-name") => ViewTransitionName>, + ViewTransitionName: atom!("view-transition-name"), // https://drafts.csswg.org/css-viewport/#property-index // // https://drafts.csswg.org/css-will-change-1/#property-index - atom!("will-change") => WillChange>, + WillChange: atom!("will-change"), // https://drafts.csswg.org/css-writing-modes-3/#property-index // ! direction is redefined in css-text-decor-4 @@ -1036,12 +1049,12 @@ properties! { // ! writing-mode is redefined in css-text-decor-4 // https://drafts.csswg.org/css-writing-modes-4/#property-index - atom!("direction") => Direction>, - atom!("glyph-orientation-horizontal") => GlyphOrientationHorizontal>, - atom!("text-combine-upright") => TextCombineUpright>, - atom!("text-orientation") => TextOrientation>, - atom!("unicode-bidi") => UnicodeBidi>, - atom!("writing-mode") => WritingMode>, + Direction: atom!("direction"), + GlyphOrientationHorizontal: atom!("glyph-orientation-horizontal"), + TextCombineUpright: atom!("text-combine-upright"), + TextOrientation: atom!("text-orientation"), + UnicodeBidi: atom!("unicode-bidi"), + WritingMode: atom!("writing-mode"), // https://drafts.csswg.org/css2/#property-index // ! background is redefined in css-backgrounds-3 @@ -1137,7 +1150,7 @@ properties! { // ! white-space is redefined in css-text-3 // ! widows is redefined in css-page-3 // ! word-spacing is redefined in css-text-decor-4 - atom!("z-index") => ZIndex>, + ZIndex: atom!("z-index"), // https://drafts.csswg.org/cssom-1/#property-index // @@ -1158,17 +1171,17 @@ properties! { // // https://drafts.csswg.org/scroll-animations-1/#property-index - atom!("antimation-range") => AnimationRange>, - atom!("antimation-range-end") => AnimationRangeEnd>, - atom!("antimation-range-start") => AnimationRangeStart>, - atom!("scroll-timeline") => ScrollTimeline>, - atom!("scroll-timeline-axis") => ScrollTimelineAxis>, - atom!("scroll-timeline-name") => ScrollTimelineName>, - atom!("timeline-scope") => TimelineScope>, - atom!("view-timeline") => ViewTimeline>, - atom!("view-timeline-axis") => ViewTimelineAxis>, - atom!("view-timeline-inset") => ViewTimelineInset>, - atom!("view-timeline-name") => ViewTimelineName>, + AnimationRange: atom!("antimation-range"), + AnimationRangeEnd: atom!("antimation-range-end"), + AnimationRangeStart: atom!("antimation-range-start"), + ScrollTimeline: atom!("scroll-timeline"), + ScrollTimelineAxis: atom!("scroll-timeline-axis"), + ScrollTimelineName: atom!("scroll-timeline-name"), + TimelineScope: atom!("timeline-scope"), + ViewTimeline: atom!("view-timeline"), + ViewTimelineAxis: atom!("view-timeline-axis"), + ViewTimelineInset: atom!("view-timeline-inset"), + ViewTimelineName: atom!("view-timeline-name"), // https://drafts.csswg.org/selectors-3/#property-index // @@ -1185,14 +1198,100 @@ properties! { // https://drafts.csswg.org/web-animations-2/#property-index // + // https://drafts.fxtf.org/compositing-2/#property-index + BackgroundBlendMode: atom!("background-blend-mode"), + Isolation: atom!("isolation"), + MixBlendMode: atom!("mix-blend-mode"), + + // https://drafts.fxtf.org/css-masking-1/#property-index + Clip: atom!("clip"), + ClipPath: atom!("clip-path"), + ClipRule: atom!("clip-rule"), + Mask: atom!("mask"), + MaskBorder: atom!("mask-border"), + MaskBorderMode: atom!("mask-border-mode"), + MaskBorderOutset: atom!("mask-border-outset"), + MaskBorderRepeat: atom!("mask-border-repeat"), + MaskBorderSlice: atom!("mask-border-slice"), + MaskBorderSource: atom!("mask-border-source"), + MaskBorderWidth: atom!("mask-border-width"), + MaskClip: atom!("mask-clip"), + MaskImage: atom!("mask-image"), + MaskMode: atom!("mask-mode"), + MaskOrigin: atom!("mask-origin"), + MaskPosition: atom!("mask-position"), + MaskRepeat: atom!("mask-repeat"), + MaskSize: atom!("mask-size"), + MaskType: atom!("mask-type"), + + // https://drafts.fxtf.org/filter-effects/#property-index + ColorInterpolationFilters: atom!("color-interpolation-filters"), + Filter: atom!("filter"), + FloodColor: atom!("flood-color"), + FloodOpacity: atom!("flood-opacity"), + LightingColor: atom!("lighting-color"), + + // https://drafts.fxtf.org/filter-effects-2/ + BackdropFilter: atom!("backdrop-filter"), + + // https://drafts.fxtf.org/fill-stroke/#property-index + Fill: atom!("fill"), + FillBreak: atom!("fill-break"), + FillColor: atom!("fill-color"), + FillImage: atom!("fill-image"), + FillOpacity: atom!("fill-opacity"), + FillOrigin: atom!("fill-origin"), + FillPosition: atom!("fill-position"), + FillRepeat: atom!("fill-repeat"), + FillRule: atom!("fill-rule"), + FillSize: atom!("fill-size"), + Stroke: atom!("stroke"), + StrokeAlign: atom!("stroke-align"), + StrokeBreak: atom!("stroke-break"), + StrokeColor: atom!("stroke-color"), + StrokeDashCorner: atom!("stroke-dash-corner"), + StrokeDashJustify: atom!("stroke-dash-justify"), + StrokeDasharray: atom!("stroke-dasharray"), + StrokeDashoffset: atom!("stroke-dashoffset"), + StrokeImage: atom!("stroke-image"), + StrokeLinecap: atom!("stroke-linecap"), + StrokeLinejoin: atom!("stroke-linejoin"), + StrokeMiterlimit: atom!("stroke-miterlimit"), + StrokeOpacity: atom!("stroke-opacity"), + StrokeOrigin: atom!("stroke-origin"), + StrokePosition: atom!("stroke-position"), + StrokeRepeat: atom!("stroke-repeat"), + StrokeSize: atom!("stroke-size"), + StrokeWidth: atom!("stroke-width"), + + // https://drafts.fxtf.org/motion-1/#property-index + Offset: atom!("offset"), + OffsetAnchor: atom!("offset-anchor"), + OffsetDistance: atom!("offset-distance"), + OffsetPath: atom!("offset-path"), + OffsetPosition: atom!("offset-position"), + OffsetRotate: atom!("offset-rotate"), + + // Non Standard Properties - atom!("zoom") => NonStandardZoom standard=false, - // https://drafts.fxtf.org/css-masking/#clip-property - atom!("clip") => NonStandardClip> standard=false, + Zoom: atom!("zoom"), // Webkit NonStandards - atom!("-webkit-text-size-adjust") => WebkitTextSizeAdjust> standard=false, - atom!("-webkit-text-decoration") => WebkitTextDecoration> standard=false, - atom!("-webkit-tap-highlight-color") => WebkitTapHighlightColor>> standard=false, - atom!("-webkit-text-decoration-skip-ink") => WebkitTextDecorationSkipInk> standard=false, + WebkitTextSizeAdjust: atom!("-webkit-text-size-adjust"), + WebkitTextDecoration: atom!("-webkit-text-decoration"), + WebkitTapHighlightColor: atom!("-webkit-tap-highlight-color"), + WebkitTextDecorationSkipInk: atom!("-webkit-text-decoration-skip-ink"), +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + use std::mem::size_of; + assert_eq!(size_of::(), 32); + assert_eq!(size_of::(), 16); + } } diff --git a/crates/hdx_ast/src/css/qualified_rule.rs b/crates/hdx_ast/src/css/qualified_rule.rs deleted file mode 100644 index 56356a8e..00000000 --- a/crates/hdx_ast/src/css/qualified_rule.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::Span; - -#[derive(Debug, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] -pub struct QualifiedRule<'a> { - pub str: &'a str, -} diff --git a/crates/hdx_ast/src/css/rules/charset.rs b/crates/hdx_ast/src/css/rules/charset.rs index 8d1fc345..62bfc4cc 100644 --- a/crates/hdx_ast/src/css/rules/charset.rs +++ b/crates/hdx_ast/src/css/rules/charset.rs @@ -1,15 +1,43 @@ +use hdx_atom::{atom, Atom}; +use hdx_lexer::Token; +use hdx_parser::{Parse, Parser, Result as ParserResult, Spanned, unexpected, expect}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; -use crate::Atom; - #[derive(Debug, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] // TODO: maybe make this an enum? Can use: // https://www.iana.org/assignments/character-sets/character-sets.xhtml -pub struct CSSCharsetRule { +pub struct CharsetRule { // Common charsets // atom!("UTF-8") // atom!("utf-8") + // atom!("ISO-8859-1") pub encoding: Atom, } + +impl<'a> Parse<'a> for CharsetRule { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + expect!(parser, Token::AtKeyword(atom!("charset"))); + parser.advance(); + match parser.cur() { + Token::String(encoding) => { + expect!(parser, Token::AtKeyword(atom!("charset"))); + expect!(parser, Token::Semicolon); + Ok(Self { encoding }.spanned(span.end(parser.pos()))) + } + token => unexpected!(parser, token), + } + } +} + +impl<'a> WriteCss<'a> for CharsetRule { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_str("@charset \"")?; + sink.write_str(self.encoding.as_ref())?; + sink.write_str("\";")?; + Ok(()) + } +} diff --git a/crates/hdx_ast/src/css/rules/mod.rs b/crates/hdx_ast/src/css/rules/mod.rs index 2b417ec3..bf026e7c 100644 --- a/crates/hdx_ast/src/css/rules/mod.rs +++ b/crates/hdx_ast/src/css/rules/mod.rs @@ -2,4 +2,28 @@ pub mod charset; pub mod page; pub use charset::*; +use hdx_lexer::Token; +use hdx_parser::{unexpected, Parse, Result as ParserResult, Spanned, Parser}; pub use page::*; + +pub struct NoPreludeAllowed; +impl<'a> Parse<'a> for NoPreludeAllowed { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::LeftCurly | Token::Semicolon => Ok(Self {}.spanned(span.end(parser.pos()))), + token => unexpected!(parser, token) + } + } +} + +pub struct NoBlockAllowed; +impl<'a> Parse<'a> for NoBlockAllowed { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Semicolon | Token::Eof => Ok(Self {}.spanned(span.end(parser.pos()))), + token => unexpected!(parser, token) + } + } +} diff --git a/crates/hdx_ast/src/css/rules/page.rs b/crates/hdx_ast/src/css/rules/page.rs index 1f606ac6..9d4edb92 100644 --- a/crates/hdx_ast/src/css/rules/page.rs +++ b/crates/hdx_ast/src/css/rules/page.rs @@ -1,21 +1,51 @@ -use oxc_allocator::{Box, Vec}; +use hdx_lexer::Token; +use hdx_parser::{ + diagnostics, expect, unexpected, AtRule, Box, DeclarationRuleList, Parse, Parser, Result as ParserResult, Spanned, + Vec, +}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; -use crate::{ - atom, css::properties::Property, Atom, Atomizable, Span, Spanned, Specificity, ToSpecificity, -}; +use super::NoPreludeAllowed; +use crate::{atom, css::properties::StyleProperty, Atom, Atomizable, Specificity, ToSpecificity}; // https://drafts.csswg.org/cssom-1/#csspagerule -#[derive(Debug, PartialEq, Hash)] +// https://drafts.csswg.org/css-page-3/#at-page-rule +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct CSSPageRule<'a> { - #[cfg_attr(feature = "serde", serde(borrow))] - pub selectors: Box<'a, Spanned>>, - #[cfg_attr(feature = "serde", serde(borrow))] - pub declarations: Box<'a, Vec<'a, Spanned>>>, +pub struct PageRule<'a> { #[cfg_attr(feature = "serde", serde(borrow))] - pub rules: Box<'a, Vec<'a, Spanned>>>, + pub selectors: Box<'a, Option>>>, + pub style: Box<'a, Spanned>>, +} + +// https://drafts.csswg.org/css-page-3/#syntax-page-selector +impl<'a> Parse<'a> for PageRule<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + expect!(parser, Token::AtKeyword(atom!("page"))); + let span = parser.span(); + let (selectors, style) = Self::parse_at_rule(parser)?; + if let Some(style) = style { + Ok(Self { selectors: parser.boxup(selectors), style: parser.boxup(style) }.spanned(span.end(parser.pos()))) + } else { + Err(diagnostics::MissingAtRuleBlock(span.end(parser.pos())))? + } + } +} + +impl<'a> AtRule<'a> for PageRule<'a> { + type Block = PageDeclaration<'a>; + type Prelude = PageSelectorList<'a>; +} + +impl<'a> WriteCss<'a> for PageRule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_str("@page ")?; + self.selectors.write_css(sink)?; + self.style.write_css(sink)?; + Ok(()) + } } #[derive(Debug, PartialEq, Hash)] @@ -24,6 +54,28 @@ pub struct PageSelectorList<'a> { pub children: Vec<'a, Spanned>>, } +impl<'a> Parse<'a> for PageSelectorList<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let ok = Ok(Self { children: parser.parse_comma_list_of::()? }.spanned(span.end(parser.pos()))); + ok + } +} + +impl<'a> WriteCss<'a> for PageSelectorList<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + let mut iter = self.children.iter().peekable(); + while let Some(selector) = iter.next() { + selector.write_css(sink)?; + if iter.peek().is_some() { + sink.write_char(',')?; + sink.write_trivia_char(' ')?; + } + } + Ok(()) + } +} + #[derive(Debug, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct PageSelector<'a> { @@ -32,10 +84,50 @@ pub struct PageSelector<'a> { pub pseudos: Vec<'a, Spanned>, } +impl<'a> Parse<'a> for PageSelector<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut page_type = None; + let mut pseudos = parser.new_vec(); + match parser.cur() { + Token::Ident(atom) => { + page_type = Some(atom); + parser.advance(); + } + _ => {} + } + loop { + match parser.cur() { + Token::Colon => { + pseudos.push(PagePseudoClass::parse(parser)?); + } + _ => { + break; + } + } + } + Ok(Self { page_type, pseudos }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for PageSelector<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + if let Some(page_type) = &self.page_type { + sink.write_str(page_type.as_ref())?; + } + for pseudo in self.pseudos.iter() { + sink.write_char(':')?; + sink.write_str(pseudo.to_atom().as_ref())?; + } + Ok(()) + } +} + impl<'a> PageSelector<'a> { pub fn selector(&self) -> &str { todo!(); - // format!("{}{}", self.page_type.unwrap_or("").to_owned(), self.pseudos.into_iter().fold("", |p| p.as_str())join("")).as_str() + // format!("{}{}", self.page_type.unwrap_or("").to_owned(), + // self.pseudos.into_iter().fold("", |p| p.as_str())join("")).as_str() } pub fn specificity(&self) -> Specificity { @@ -56,6 +148,21 @@ pub enum PagePseudoClass { Blank, } +impl<'a> Parse<'a> for PagePseudoClass { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + expect!(parser, Token::Colon); + parser.advance_including_whitespace(); + match parser.cur() { + Token::Ident(name) => match Self::from_atom(name.clone()) { + Some(v) => Ok(v.spanned(span.end(parser.pos()))), + _ => Err(diagnostics::UnexpectedPseudo(name, span).into()), + }, + token => unexpected!(parser, token), + } + } +} + impl ToSpecificity for PagePseudoClass { fn specificity(&self) -> Specificity { match self { @@ -67,13 +174,101 @@ impl ToSpecificity for PagePseudoClass { } } +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct PageDeclaration<'a> { + #[cfg_attr(feature = "serde", serde(borrow))] + pub properties: Box<'a, Vec<'a, Spanned>>>, + #[cfg_attr(feature = "serde", serde(borrow))] + pub rules: Box<'a, Vec<'a, Spanned>>>, +} + +impl<'a> Parse<'a> for PageDeclaration<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let (properties, rules) = Self::parse_declaration_rule_list(parser)?; + Ok(Self { properties: parser.boxup(properties), rules: parser.boxup(rules) }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> DeclarationRuleList<'a> for PageDeclaration<'a> { + type AtRule = MarginRule<'a>; + type Declaration = StyleProperty<'a>; +} + +impl<'a> WriteCss<'a> for PageDeclaration<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_char('{')?; + sink.indent(); + sink.write_newline()?; + let mut iter = self.properties.iter().peekable(); + let mut rule_iter = self.rules.iter().peekable(); + while let Some(decl) = iter.next() { + decl.write_css(sink)?; + if iter.peek().is_none() && rule_iter.peek().is_none() { + sink.write_trivia_char(';')?; + } else { + sink.write_char(';')?; + } + sink.write_newline()?; + } + for rule in rule_iter { + sink.write_newline()?; + rule.write_css(sink)?; + sink.write_newline()?; + } + sink.dedent(); + sink.write_indent()?; + sink.write_char('}') + } +} + // https://drafts.csswg.org/cssom-1/#cssmarginrule -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct CSSMarginRule<'a> { +pub struct MarginRule<'a> { pub name: PageMarginBox, #[cfg_attr(feature = "serde", serde(borrow))] - pub declarations: Vec<'a, Spanned>>, + pub style: Box<'a, Spanned>>, +} + +impl<'a> Parse<'a> for MarginRule<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + match parser.cur() { + Token::AtKeyword(atom) => { + if let Some(name) = PageMarginBox::from_atom(atom.clone()) { + let span = parser.span(); + let (_, style) = Self::parse_at_rule(parser)?; + if let Some(style) = style { + Ok(Self { name, style: parser.boxup(style) }.spanned(span.end(parser.pos()))) + } else { + Err(diagnostics::MissingAtRuleBlock(span.end(parser.pos())))? + } + } else { + Err(diagnostics::UnexpectedAtRule(atom, parser.span()))? + } + } + token => unexpected!(parser, token), + } + } +} + +impl<'a> AtRule<'a> for MarginRule<'a> { + type Block = MarginDeclaration<'a>; + type Prelude = NoPreludeAllowed; + + fn parse_prelude(_parser: &mut Parser<'a>) -> ParserResult>> { + Ok(None) + } +} + +impl<'a> WriteCss<'a> for MarginRule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_char('@')?; + sink.write_str(self.name.to_atom().as_ref())?; + sink.write_trivia_char(' ')?; + self.style.write_css(sink) + } } #[derive(Atomizable, Debug, Clone, PartialEq, Hash)] @@ -97,6 +292,56 @@ pub enum PageMarginBox { LeftTop, // atom!("left-top") } +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct MarginDeclaration<'a> { + #[cfg_attr(feature = "serde", serde(borrow))] + pub properties: Box<'a, Vec<'a, Spanned>>>, + #[cfg_attr(feature = "serde", serde(borrow))] + pub rules: Box<'a, Vec<'a, Spanned>>>, +} + +impl<'a> Parse<'a> for MarginDeclaration<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let (properties, rules) = Self::parse_declaration_rule_list(parser)?; + Ok(Self { properties: parser.boxup(properties), rules: parser.boxup(rules) } + .spanned(span.end(parser.pos()))) + } +} + +impl<'a> DeclarationRuleList<'a> for MarginDeclaration<'a> { + type AtRule = MarginRule<'a>; + type Declaration = StyleProperty<'a>; +} + +impl<'a> WriteCss<'a> for MarginDeclaration<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_char('{')?; + sink.indent(); + sink.write_newline()?; + let mut iter = self.properties.iter().peekable(); + let mut rule_iter = self.rules.iter().peekable(); + while let Some(decl) = iter.next() { + decl.write_css(sink)?; + if iter.peek().is_none() && rule_iter.peek().is_none() { + sink.write_trivia_char(';')?; + } else { + sink.write_char(';')?; + } + sink.write_newline()?; + } + for rule in rule_iter { + sink.write_newline()?; + rule.write_css(sink)?; + sink.write_newline()?; + } + sink.dedent(); + sink.write_indent()?; + sink.write_char('}') + } +} + #[cfg(test)] mod tests { @@ -105,8 +350,8 @@ mod tests { #[test] fn size_test() { use std::mem::size_of; - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 40); + assert_eq!(size_of::(), 16); + assert_eq!(size_of::(), 16); assert_eq!(size_of::(), 1); assert_eq!(size_of::(), 1); assert_eq!(size_of::(), 1); diff --git a/crates/hdx_ast/src/css/selector/attribute.rs b/crates/hdx_ast/src/css/selector/attribute.rs new file mode 100644 index 00000000..b77d02b5 --- /dev/null +++ b/crates/hdx_ast/src/css/selector/attribute.rs @@ -0,0 +1,190 @@ +use hdx_atom::{atom, Atom}; +use hdx_lexer::Token; +use hdx_parser::{expect, unexpected, unexpected_ident, Parse, Parser, Result as ParserResult, Spanned}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::{parse_wq_name, NSPrefix}; + +#[derive(Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct Attribute { + pub ns_prefix: NSPrefix, + pub name: Atom, + pub value: Atom, + pub matcher: AttributeMatch, + pub modifier: AttributeModifier, +} + +impl<'a> Parse<'a> for Attribute { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::LeftSquare => { + parser.advance(); + let (ns_prefix, name) = parse_wq_name(parser)?; + let matcher = match parser.cur() { + Token::RightSquare => { + parser.advance_including_whitespace_and_comments(); + return Ok(Self { + ns_prefix, + name, + value: atom!(""), + modifier: AttributeModifier::None, + matcher: AttributeMatch::Any, + } + .spanned(span.end(parser.pos()))); + } + Token::Delim('=') => { + parser.advance(); + AttributeMatch::Exact + } + Token::Delim('~') => { + parser.advance_including_whitespace_and_comments(); + expect!(parser, Token::Delim('=')); + parser.advance(); + AttributeMatch::SpaceList + } + Token::Delim('|') => { + parser.advance_including_whitespace_and_comments(); + expect!(parser, Token::Delim('=')); + parser.advance(); + AttributeMatch::LangPrefix + } + Token::Delim('^') => { + parser.advance_including_whitespace_and_comments(); + expect!(parser, Token::Delim('=')); + parser.advance(); + AttributeMatch::Prefix + } + Token::Delim('$') => { + parser.advance_including_whitespace_and_comments(); + expect!(parser, Token::Delim('=')); + parser.advance(); + AttributeMatch::Suffix + } + Token::Delim('*') => { + parser.advance_including_whitespace_and_comments(); + expect!(parser, Token::Delim('=')); + parser.advance(); + AttributeMatch::Contains + } + token => unexpected!(parser, token), + }; + let value = match parser.cur() { + Token::Ident(value) | Token::String(value) => { + parser.advance(); + value + } + token => unexpected!(parser, token), + }; + match parser.cur() { + Token::RightSquare => { + parser.advance_including_whitespace_and_comments(); + Ok(Self { ns_prefix, name, value, modifier: AttributeModifier::None, matcher } + .spanned(span.end(parser.pos()))) + } + Token::Ident(ident) => { + let modifier = match ident.to_ascii_lowercase() { + atom!("i") => AttributeModifier::Insensitive, + atom!("s") => AttributeModifier::Sensitive, + atom => unexpected_ident!(parser, atom), + }; + parser.advance(); + expect!(parser, Token::RightSquare); + parser.advance_including_whitespace_and_comments(); + Ok(Self { ns_prefix, name, value, modifier, matcher }.spanned(span.end(parser.pos()))) + } + token => unexpected!(parser, token), + } + } + token => unexpected!(parser, token), + } + } +} + +impl<'a> WriteCss<'a> for Attribute { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_char('[')?; + match &self.ns_prefix { + NSPrefix::None => {} + NSPrefix::Named(ns) => { + sink.write_str(ns.as_ref())?; + sink.write_char('|')?; + } + NSPrefix::Wildcard => { + sink.write_char('*')?; + sink.write_char('|')?; + } + } + sink.write_str(self.name.as_ref())?; + match &self.matcher { + AttributeMatch::Any => {} + AttributeMatch::Exact => { + sink.write_char('=')?; + } + AttributeMatch::SpaceList => { + sink.write_char('~')?; + sink.write_char('=')?; + } + AttributeMatch::LangPrefix => { + sink.write_char('|')?; + sink.write_char('=')?; + } + AttributeMatch::Prefix => { + sink.write_char('^')?; + sink.write_char('=')?; + } + AttributeMatch::Suffix => { + sink.write_char('$')?; + sink.write_char('=')?; + } + AttributeMatch::Contains => { + sink.write_char('*')?; + sink.write_char('=')?; + } + } + if &self.matcher != &AttributeMatch::Any { + sink.write_char('"')?; + sink.write_str(self.value.as_ref())?; + sink.write_char('"')?; + } + + sink.write_char(']')?; + Ok(()) + } +} + +#[derive(Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] +pub enum AttributeMatch { + Any, // [attr] + Exact, // [attr=val] + SpaceList, // [attr~=val] + LangPrefix, // [attr|=val] + Prefix, // [attr^=val] + Suffix, // [attr$=val] + Contains, // [attr*=val] +} + +#[derive(Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub enum AttributeModifier { + None, + Sensitive, + Insensitive, +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 40); + assert_eq!(::std::mem::size_of::(), 1); + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/selector/mod.rs b/crates/hdx_ast/src/css/selector/mod.rs index 9057d3a9..8793b579 100644 --- a/crates/hdx_ast/src/css/selector/mod.rs +++ b/crates/hdx_ast/src/css/selector/mod.rs @@ -1,33 +1,103 @@ +use hdx_atom::Atom; +use hdx_lexer::Token; +use hdx_parser::{diagnostics, Parse, Parser, Result as ParserResult, Span, Spanned, unexpected_ident, unexpected}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; -use crate::{atom, Atom, Atomizable, Box, Spanned, Vec}; +use crate::{Atomizable, Box, Vec}; + +mod attribute; +mod pseudo_class; + +use attribute::Attribute; +use pseudo_class::PseudoClass; // This encapsulates both `simple-selector` and `compound-selector`. // As `simple-selector` is a `compound-selector` but with only one `Component`. -// Having `Selector` be both ` simple-selector` and `compound-selector` makes parsing and visiting -// more practical. -#[derive(Debug, PartialEq, Hash)] +// Having `Selector` be both ` simple-selector` and `compound-selector` makes +// parsing and visiting more practical. +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct Selector<'a> { pub components: Box<'a, Vec<'a, Spanned>>>, } -#[derive(Debug, PartialEq, Hash)] +impl<'a> Parse<'a> for Selector<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut components: Vec<'a, Spanned> = parser.new_vec(); + loop { + match parser.cur() { + Token::Eof | Token::Semicolon | Token::Comma | Token::LeftCurly => { + break; + } + Token::Whitespace => { + if matches!(parser.peek(), Token::Eof | Token::Semicolon | Token::Comma | Token::LeftCurly) { + break; + } + } + _ => {} + } + let component = Component::parse(parser)?; + if let Some(Spanned { node, span: component_span }) = components.last() { + match (node, &component.node) { + // A selector like `a /**/ b` would parse as // , , + // , . The CSS selector grammar implicitly swallows adjacent + // descendant combinators as whitespace, but due to simplifying AST nodes in our + // parser, it means we must explicitly check for, and elide adjacent descendant + // combinators. Adjacent Descendant Combinator Elision is the name of my metal + // band, btw. + (Component::Combinator(_), Component::Combinator(Combinator::Descendant)) + | (Component::Combinator(Combinator::Descendant), Component::Combinator(_)) => { + continue; + } + // Combinators cannot be next to eachother. + (Component::Combinator(_), Component::Combinator(_)) => { + Err(diagnostics::AdjacentSelectorCombinators( + *component_span, + Span::new(span.start, component_span.start), + ))? + } + // Types cannot be next to eachother. + (Component::Type(_), Component::Type(_)) => Err(diagnostics::AdjacentSelectorTypes( + *component_span, + Span::new(span.start, component_span.start), + ))?, + _ => {} + } + } + components.push(component); + } + Ok(Self { components: parser.boxup(components) }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for Selector<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + for component in &(*self.components) { + component.write_css(sink)?; + } + Ok(()) + } +} + +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct ForgivingSelector<'a> { pub components: Box<'a, Vec<'a, Spanned>>>, } -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct RelativeSelector<'a> { pub components: Box<'a, Vec<'a, Spanned>>>, } // This encapsulates all `simple-selector` subtypes (e.g. `wq-name`, -// `id-selector`) into one enum, as it makes parsing and visiting much more practical. -#[derive(Debug, PartialEq, Hash)] +// `id-selector`) into one enum, as it makes parsing and visiting much more +// practical. +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] pub enum Component<'a> { Id(Atom), @@ -44,6 +114,148 @@ pub enum Component<'a> { NSPrefixedWildcard(NSPrefix), } +impl<'a> Parse<'a> for Component<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Whitespace => { + parser.advance_including_whitespace_and_comments(); + Ok(Self::Combinator(Combinator::Descendant).spanned(span.end(parser.pos()))) + } + Token::Ident(name) => { + parser.advance_including_whitespace_and_comments(); + Ok(Self::Type(name.to_ascii_lowercase()).spanned(span)) + } + Token::Colon => { + parser.advance_including_whitespace_and_comments(); + match parser.cur(){ + Token::Colon => { + parser.advance_including_whitespace_and_comments(); + match parser.cur() { + Token::Ident(name) => { + if let Some(selector) = PseudoElement::from_atom(name.clone()) { + parser.advance_including_whitespace_and_comments(); + Ok(Self::PseudoElement(selector).spanned(span.end(parser.pos()))) + } else { + unexpected_ident!(parser, name) + } + } + token => unexpected!(parser, token) + } + } + Token::Ident(ident) => { + if let Some(selector) = PseudoClass::from_atom(ident.clone()) { + parser.advance_including_whitespace_and_comments(); + Ok(Self::PseudoClass(selector).spanned(span.end(parser.pos()))) + } else if let Some(e) = LegacyPseudoElement::from_atom(ident.clone()) { + parser.advance_including_whitespace_and_comments(); + Ok(Self::LegacyPseudoElement(e).spanned(span.end(parser.pos()))) + } else { + Err(diagnostics::UnexpectedIdent(ident, parser.span()))? + } + } + _ => Err(diagnostics::Unimplemented(parser.span()))?, + } + } + Token::Hash(name) => { + parser.advance_including_whitespace_and_comments(); + Ok(Self::Id(name).spanned(span.end(parser.pos()))) + } + Token::Delim(char) => match char { + '.' => { + parser.advance_including_whitespace_and_comments(); + match parser.cur() { + Token::Ident(ident) => { + parser.advance_including_whitespace_and_comments(); + Ok(Self::Class(ident).spanned(span.end(parser.pos()))) + } + _ => Err(diagnostics::Unimplemented(parser.span()))?, + } + } + '*' => { + match parser.peek() { + Token::Delim('|') => { + let (prefix, atom) = parse_wq_name(parser)?; + Ok(Self::NSPrefixedType(parser.boxup((prefix, atom))).spanned(span.end(parser.pos()))) + } + _ => { + parser.advance_including_whitespace_and_comments(); + Ok(Self::Wildcard.spanned(span.end(parser.pos()))) + } + } + } + _ => Err(diagnostics::Unimplemented(parser.span()))?, + }, + Token::LeftSquare => { + let attr = Attribute::parse(parser)?; + Ok(Component::Attribute(parser.boxup(attr)).spanned(span.end(parser.pos()))) + } + _ => Err(diagnostics::Unimplemented(parser.span()))?, + } + } +} + +impl<'a> WriteCss<'a> for Component<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self { + Self::Type(ty) => { + sink.write_str(ty)?; + } + Self::Id(id) => { + sink.write_char('#')?; + sink.write_str(id)?; + } + Self::Class(class) => { + sink.write_char('.')?; + sink.write_str(class)?; + } + Self::PseudoClass(pseudo) => { + sink.write_char(':')?; + sink.write_str(pseudo.to_atom().as_ref())?; + } + Self::LegacyPseudoElement(pseudo) => { + sink.write_char(':')?; + sink.write_str(pseudo.to_atom().as_ref())?; + } + Self::PseudoElement(pseudo) => { + sink.write_char(':')?; + sink.write_char(':')?; + sink.write_str(pseudo.to_atom().as_ref())?; + } + Self::Attribute(attr) => { + attr.write_css(sink)?; + } + Self::Combinator(combinator) => { + sink.write_trivia_char(' ')?; + match combinator { + Combinator::Descendant => { + sink.write_char(' ')?; + } + Combinator::Child => { + sink.write_char('>')?; + } + Combinator::NextSibling => { + sink.write_char('+')?; + } + Combinator::SubsequentSibling => { + sink.write_char('~')?; + } + Combinator::ColumnCombintor => { + sink.write_char('|')?; + sink.write_char('|')?; + } + } + sink.write_trivia_char(' ')?; + } + Self::Wildcard => { + sink.write_char('*')?; + } + _ => todo!(), + } + Ok(()) + } +} + // https://drafts.csswg.org/css-pseudo/#index-defined-here #[derive(Atomizable, Debug, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] @@ -73,92 +285,7 @@ pub enum LegacyPseudoElement { FirstLine, // atom!("first-line") } -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Attribute { - pub ns_prefix: NSPrefix, - pub name: Atom, - pub value: Atom, - pub matcher: AttributeMatch, - pub modifier: AttributeModifier, -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum AttributeMatch { - Any, // [attr] - Exact, // [attr=val] - SpaceList, // [attr~=val] - LangPrefix, // [attr|=val] - Prefix, // [attr^=val] - Suffix, // [attr$=val] - Contains, // [attr*=val] -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum AttributeModifier { - None, - Sensitive, - Insensitive, -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "kebab-case"))] -pub enum PseudoClass { - Active, // atom!("active") - AnyLink, // atom!("any-link") - Autofill, // atom!("autofill") - Blank, // atom!("blank") - Checked, // atom!("checked") - Current, // atom!("current") - Default, // atom!("default") - Defined, // atom!("defined") - Disabled, // atom!("disabled") - Empty, // atom!("empty") - Enabled, // atom!("enabled") - First, // atom!("first") - FirstChild, // atom!("first-child") - FirstOfType, // atom!("first-of-type") - Fullscreen, // atom!("fullscreen") - Future, // atom!("future") - Focus, // atom!("focus") - FocusVisible, // atom!("focus-visible") - FocusWithin, // atom!("focus-within") - Host, // atom!("host") - Hover, // atom!("hover") - Indeterminate, // atom!("indeterminate") - InRange, // atom!("in-range") - Invalid, // atom!("invalid") - LastChild, // atom!("last-child") - LastOfType, // atom!("last-of-type") - Left, // atom!("left") - Link, // atom!("link") - LocalLink, // atom!("local-link") - Modal, // atom!("modal") - OnlyChild, // atom!("only-child") - OnlyOfType, // atom!("only-of-type") - Optional, // atom!("optional") - OutOfRange, // atom!("out-of-range") - Past, // atom!("past") - PictureInPicture, // atom!("picture-in-picture") - PlaceholderShown, // atom!("placeholder-shown") - PopoverOpen, // atom!("popover-open") - Paused, // atom!("paused") - Playing, // atom!("playing") - ReadOnly, // atom!("read-only") - ReadWrite, // atom!("read-write") - Required, // atom!("required") - Right, // atom!("right") - Root, // atom!("root") - Scope, // atom!("scope") - Target, // atom!("target") - TargetWithin, // atom!("target-within") - Valid, // atom!("valid") - Visited, // atom!("visited") -} - -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub enum PseudoFunction<'a> { Dir(DirValue), // atom!("dir") @@ -215,14 +342,43 @@ pub struct ANBEvenOdd { string: Atom, } +pub(crate) fn parse_wq_name(parser: &mut Parser) -> ParserResult<(NSPrefix, Atom)> { + let nsprefix = match parser.cur() { + Token::Delim('|') => { + parser.advance_including_whitespace_and_comments(); + NSPrefix::None + }, + Token::Delim('*') => { + parser.advance_including_whitespace_and_comments(); + match parser.cur() { + Token::Delim('|') => { + parser.advance_including_whitespace_and_comments(); + NSPrefix::Wildcard + }, + token => unexpected!(parser, token), + } + } + Token::Ident(name) => { + parser.advance_including_whitespace_and_comments(); + match parser.cur() { + Token::Delim('|') => { + parser.advance_including_whitespace_and_comments(); + NSPrefix::Named(name) + } + _ => return Ok((NSPrefix::None, name)) + } + }, + token => unexpected!(parser, token), + }; + match parser.cur() { + Token::Ident(name) => Ok((nsprefix, name)), + token => unexpected!(parser, token) + } +} + #[cfg(test)] mod test { - use oxc_allocator::Allocator; - use serde_json::{from_str, json, to_string, Value}; - use super::*; - use crate::{atom, Box, Span, Vec}; - #[test] fn size_test() { assert_eq!(::std::mem::size_of::(), 8); @@ -231,9 +387,6 @@ mod test { assert_eq!(::std::mem::size_of::(), 24); assert_eq!(::std::mem::size_of::(), 1); assert_eq!(::std::mem::size_of::(), 1); - assert_eq!(::std::mem::size_of::(), 40); - assert_eq!(::std::mem::size_of::(), 1); - assert_eq!(::std::mem::size_of::(), 1); assert_eq!(::std::mem::size_of::(), 1); assert_eq!(::std::mem::size_of::(), 16); assert_eq!(::std::mem::size_of::(), 1); diff --git a/crates/hdx_ast/src/css/selector/pseudo_class.rs b/crates/hdx_ast/src/css/selector/pseudo_class.rs new file mode 100644 index 00000000..96818a35 --- /dev/null +++ b/crates/hdx_ast/src/css/selector/pseudo_class.rs @@ -0,0 +1,59 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::Atomizable; + +#[derive(Atomizable, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "kebab-case"))] +pub enum PseudoClass { + Active, // atom!("active") + AnyLink, // atom!("any-link") + Autofill, // atom!("autofill") + Blank, // atom!("blank") + Checked, // atom!("checked") + Current, // atom!("current") + Default, // atom!("default") + Defined, // atom!("defined") + Disabled, // atom!("disabled") + Empty, // atom!("empty") + Enabled, // atom!("enabled") + First, // atom!("first") + FirstChild, // atom!("first-child") + FirstOfType, // atom!("first-of-type") + Fullscreen, // atom!("fullscreen") + Future, // atom!("future") + Focus, // atom!("focus") + FocusVisible, // atom!("focus-visible") + FocusWithin, // atom!("focus-within") + Host, // atom!("host") + Hover, // atom!("hover") + Indeterminate, // atom!("indeterminate") + InRange, // atom!("in-range") + Invalid, // atom!("invalid") + LastChild, // atom!("last-child") + LastOfType, // atom!("last-of-type") + Left, // atom!("left") + Link, // atom!("link") + LocalLink, // atom!("local-link") + Modal, // atom!("modal") + OnlyChild, // atom!("only-child") + OnlyOfType, // atom!("only-of-type") + Optional, // atom!("optional") + OutOfRange, // atom!("out-of-range") + Past, // atom!("past") + PictureInPicture, // atom!("picture-in-picture") + PlaceholderShown, // atom!("placeholder-shown") + PopoverOpen, // atom!("popover-open") + Paused, // atom!("paused") + Playing, // atom!("playing") + ReadOnly, // atom!("read-only") + ReadWrite, // atom!("read-write") + Required, // atom!("required") + Right, // atom!("right") + Root, // atom!("root") + Scope, // atom!("scope") + Target, // atom!("target") + TargetWithin, // atom!("target-within") + Valid, // atom!("valid") + Visited, // atom!("visited") +} diff --git a/crates/hdx_ast/src/css/stylerule.rs b/crates/hdx_ast/src/css/stylerule.rs new file mode 100644 index 00000000..0d50a081 --- /dev/null +++ b/crates/hdx_ast/src/css/stylerule.rs @@ -0,0 +1,108 @@ +use hdx_lexer::Token; +use hdx_parser::{unexpected, Parse, Parser, QualifiedRule, Result as ParserResult, expect}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{ + css::{properties::StyleProperty, selector::Selector}, + Box, Spanned, Vec, +}; + +// https://drafts.csswg.org/cssom-1/#the-cssstylerule-interface +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct StyleRule<'a> { + pub selectors: Box<'a, Spanned>>, + pub style: Box<'a, Spanned>>, +} + +impl<'a> Parse<'a> for StyleRule<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let (selectors, style) = Self::parse_qualified_rule(parser)?; + Ok(Self { selectors: parser.boxup(selectors), style: parser.boxup(style) }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> QualifiedRule<'a> for StyleRule<'a> { + type Block = StyleDeclaration<'a>; + type Prelude = Selector<'a>; +} + +impl<'a> WriteCss<'a> for StyleRule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + self.selectors.write_css(sink)?; + sink.write_trivia_char(' ')?; + sink.write_char('{')?; + sink.indent(); + sink.write_newline()?; + self.style.write_css(sink)?; + sink.dedent(); + sink.write_indent()?; + sink.write_char('}')?; + Ok(()) + } +} + +// https://drafts.csswg.org/cssom-1/#the-cssstylerule-interface +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub struct StyleDeclaration<'a> { + pub declarations: Vec<'a, Spanned>>, + pub rules: Vec<'a, Spanned>>, +} + +impl<'a> Parse<'a> for StyleDeclaration<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + expect!(parser, Token::LeftCurly); + let mut declarations = parser.new_vec(); + let mut rules = parser.new_vec(); + loop { + match parser.cur() { + Token::RightCurly => break, + t @ Token::Eof => unexpected!(parser, t), + _ => { + let checkpoint = parser.checkpoint(); + if let Ok(decl) = StyleProperty::parse(parser) { + declarations.push(decl) + } else { + parser.rewind(checkpoint); + rules.push(StyleRule::parse(parser)?); + } + } + } + } + Ok(Self { declarations, rules }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for StyleDeclaration<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + let mut iter = self.declarations.iter().peekable(); + while let Some(decl) = iter.next() { + sink.write_indent()?; + decl.write_css(sink)?; + if iter.peek().is_none() { + sink.write_trivia_char(';')?; + } else { + sink.write_char(';')?; + } + sink.write_newline()?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + use std::mem::size_of; + assert_eq!(size_of::(), 16); + } +} diff --git a/crates/hdx_ast/src/css/stylesheet.rs b/crates/hdx_ast/src/css/stylesheet.rs index 356260e1..909b6d13 100644 --- a/crates/hdx_ast/src/css/stylesheet.rs +++ b/crates/hdx_ast/src/css/stylesheet.rs @@ -1,57 +1,125 @@ +use hdx_atom::atom; +use hdx_derive::Atomizable; +use hdx_lexer::Token; +use hdx_parser::{diagnostics, discard, Parse, Parser, Result as ParserResult}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; use crate::{ - atom, css::{ - properties::Property, - rules::{page::CSSPageRule, CSSCharsetRule}, - selector::Selector, + stylerule::StyleRule, + rules::{PageRule, CharsetRule}, unknown::{UnknownAtRule, UnknownRule}, }, - Atom, Atomizable, Box, Spanned, Vec, + Box, Spanned, Vec, }; // https://drafts.csswg.org/cssom-1/#the-cssstylesheet-interface -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct CSSStyleSheet<'a> { - pub rules: Vec<'a, CSSRule<'a>>, +pub struct StyleSheet<'a> { + pub rules: Vec<'a, Rule<'a>>, +} + +// A StyleSheet represents the root node of a CSS-like language. +// The StyleSheet trait represents an abstraction of this, which allows for +// alternate implementations such as SCSS. +// AtRules vs QualifiedRules are differentiated by two different functions. +impl<'a> Parse<'a> for StyleSheet<'a> { + // https://drafts.csswg.org/css-syntax-3/#consume-stylesheet-contents + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + // 5.5.1. Consume a stylesheet’s contents + // "To consume a stylesheet’s contents from a token stream input:" + + let span = parser.span(); + + // "Let rules be an initially empty list of rules." + let mut rules = parser.new_vec(); + loop { + discard!(parser, Token::Comment(_) | Token::Whitespace | Token::Cdc | Token::Cdo); + match parser.cur() { + // Eof is the end of a StyleSheet + Token::Eof => break, + // "Consume an at-rule from input. If anything is returned, append it to rules." + Token::AtKeyword(atom) => { + let rule = match atom.to_ascii_lowercase() { + atom!("charset") => { + let rule = CharsetRule::parse(parser)?; + Rule::Charset(parser.boxup(rule)) + } + atom!("page") => { + let rule = PageRule::parse(parser)?; + Rule::Page(parser.boxup(rule)) + } + _ => { + let rule = UnknownAtRule::parse(parser)?; + parser.warn(diagnostics::UnknownRule(rule.span).into()); + Rule::UnknownAt(parser.boxup(rule)) + } + }; + rules.push(rule); + } + // "Consume a qualified rule from input. If anything is returned, append it to rules." + _ => { + let checkpoint = parser.checkpoint(); + let rule = match StyleRule::parse(parser) { + Ok(rule) => Rule::Style(parser.boxup(rule)), + Err(err) => { + parser.rewind(checkpoint); + parser.warn(err); + let rule = UnknownRule::parse(parser)?; + Rule::Unknown(parser.boxup(rule)) + } + }; + rules.push(rule); + } + } + } + Ok(Self { rules }.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for StyleSheet<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + for rule in &self.rules { + rule.write_css(sink)?; + sink.write_newline()?; + } + Ok(()) + } } // https://drafts.csswg.org/cssom-1/#the-cssrule-interface -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] -pub enum CSSRule<'a> { - Charset(Box<'a, Spanned>), - Page(Box<'a, Spanned>>), - Style(Box<'a, Spanned>>), +pub enum Rule<'a> { + Charset(Box<'a, Spanned>), + Page(Box<'a, Spanned>>), + Style(Box<'a, Spanned>>), UnknownAt(Box<'a, Spanned>>), Unknown(Box<'a, Spanned>>), } -#[derive(Atomizable, Debug, PartialEq, Hash)] +impl<'a> WriteCss<'a> for Rule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self { + Self::Style(rule) => rule.write_css(sink), + Self::Charset(rule) => rule.write_css(sink), + Self::Page(rule) => rule.write_css(sink), + Self::UnknownAt(rule) => rule.write_css(sink), + Self::Unknown(rule) => rule.write_css(sink), + } + } +} + +#[derive(Atomizable, PartialEq, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] pub enum AtRuleId { Charset, // atom!("charset") Page, // atom!("page") } -// https://drafts.csswg.org/cssom-1/#the-cssstylerule-interface -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct CSSStyleRule<'a> { - pub selectors: Box<'a, Spanned>>, - pub declarations: Box<'a, Vec<'a, Spanned>>>, - pub rules: Box<'a, Vec<'a, Spanned>>>, -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct SelectorSet<'a> { - pub children: Vec<'a, Spanned>>, -} - #[cfg(test)] mod tests { @@ -60,10 +128,8 @@ mod tests { #[test] fn size_test() { use std::mem::size_of; - assert_eq!(size_of::(), 32); - assert_eq!(size_of::(), 16); + assert_eq!(size_of::(), 32); + assert_eq!(size_of::(), 16); assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 32); } } diff --git a/crates/hdx_ast/src/css/unknown.rs b/crates/hdx_ast/src/css/unknown.rs index fdfd10ca..f245ec3a 100644 --- a/crates/hdx_ast/src/css/unknown.rs +++ b/crates/hdx_ast/src/css/unknown.rs @@ -1,41 +1,77 @@ +use hdx_lexer::Token; +use hdx_parser::{unexpected, AtRule, Parse, Parser, QualifiedRule, Result as ParserResult}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; -use crate::{ - css::{component_values::ComponentValue, values::ValueLike}, - Atom, Box, Spanned, Vec, -}; +use super::component_values::{ComponentValues, SimpleBlock}; +use crate::{Atom, Box, Spanned}; -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct UnknownAtRule<'a> { pub name: Atom, - pub prelude: Box<'a, Option>>>, - pub rules: Box<'a, Vec<'a, Spanned>>>, - pub properties: Box<'a, Vec<'a, Spanned>>>, + pub prelude: Box<'a, Option>>>, + pub block: Box<'a, Option>>>, } -#[derive(Debug, PartialEq, Hash)] +impl<'a> Parse<'a> for UnknownAtRule<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::AtKeyword(name) => { + let (prelude, block) = Self::parse_at_rule(parser)?; + Ok(Self { name, prelude: parser.boxup(prelude), block: parser.boxup(block) }.spanned(span.end(parser.pos()))) + } + token => unexpected!(parser, token), + } + } +} + +impl<'a> AtRule<'a> for UnknownAtRule<'a> { + type Block = SimpleBlock<'a>; + type Prelude = ComponentValues<'a>; +} + +impl<'a> WriteCss<'a> for UnknownAtRule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + sink.write_str("@")?; + sink.write_str(self.name.as_ref())?; + if let Some(prelude) = &self.prelude.0 { + prelude.write_css(sink)?; + sink.write_trivia_char(' ')?; + } + self.block.write_css(sink)?; + Ok(()) + } +} +#[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct UnknownRule<'a> { - pub prelude: Box<'a, Option>>>, - pub rules: Box<'a, Vec<'a, Spanned>>>, - pub properties: Box<'a, Vec<'a, Spanned>>>, + pub prelude: Box<'a, Spanned>>, + pub block: Box<'a, Spanned>>, } -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct UnknownPrelude<'a> { - pub value: Box<'a, Vec<'a, Spanned>>>, +impl<'a> Parse<'a> for UnknownRule<'a> { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let (prelude, block) = Self::parse_qualified_rule(parser)?; + Ok(Self { prelude: parser.boxup(prelude), block: parser.boxup(block) }.spanned(span.end(parser.pos()))) + } } -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct UnknownDeclaration<'a> { - pub name: Atom, - pub important: bool, - pub value: Box<'a, Vec<'a, Spanned>>>, - pub value_like: Spanned>, +impl<'a> QualifiedRule<'a> for UnknownRule<'a> { + type Block = SimpleBlock<'a>; + type Prelude = ComponentValues<'a>; +} + +impl<'a> WriteCss<'a> for UnknownRule<'a> { + fn write_css(&self, sink: &mut W) -> WriterResult { + self.prelude.write_css(sink)?; + sink.write_trivia_char(' ')?; + self.block.write_css(sink)?; + Ok(()) + } } #[cfg(test)] @@ -46,9 +82,7 @@ mod tests { #[test] fn size_test() { use std::mem::size_of; - assert_eq!(size_of::(), 32); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 48); + assert_eq!(size_of::(), 24); + assert_eq!(size_of::(), 16); } } diff --git a/crates/hdx_ast/src/css/values/align/align_content.rs b/crates/hdx_ast/src/css/values/align/align_content.rs new file mode 100644 index 00000000..b2ed2c26 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/align_content.rs @@ -0,0 +1 @@ +pub type AlignContent = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/align_items.rs b/crates/hdx_ast/src/css/values/align/align_items.rs new file mode 100644 index 00000000..452af598 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/align_items.rs @@ -0,0 +1 @@ +pub type AlignItems = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/align_self.rs b/crates/hdx_ast/src/css/values/align/align_self.rs new file mode 100644 index 00000000..686d4e27 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/align_self.rs @@ -0,0 +1 @@ +pub type AlignSelf = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/column_gap.rs b/crates/hdx_ast/src/css/values/align/column_gap.rs new file mode 100644 index 00000000..0c7fa169 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/column_gap.rs @@ -0,0 +1 @@ +pub type ColumnGap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/gap.rs b/crates/hdx_ast/src/css/values/align/gap.rs new file mode 100644 index 00000000..41034dbb --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/gap.rs @@ -0,0 +1 @@ +pub type Gap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/justify_content.rs b/crates/hdx_ast/src/css/values/align/justify_content.rs new file mode 100644 index 00000000..df1ddd86 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/justify_content.rs @@ -0,0 +1 @@ +pub type JustifyContent = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/justify_items.rs b/crates/hdx_ast/src/css/values/align/justify_items.rs new file mode 100644 index 00000000..3dda2dbd --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/justify_items.rs @@ -0,0 +1 @@ +pub type JustifyItems = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/justify_self.rs b/crates/hdx_ast/src/css/values/align/justify_self.rs new file mode 100644 index 00000000..778de2d1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/justify_self.rs @@ -0,0 +1 @@ +pub type JustifySelf = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/mod.rs b/crates/hdx_ast/src/css/values/align/mod.rs new file mode 100644 index 00000000..3ee895ae --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/mod.rs @@ -0,0 +1,24 @@ +mod align_content; +mod align_items; +mod align_self; +mod column_gap; +mod gap; +mod justify_content; +mod justify_items; +mod justify_self; +mod place_content; +mod place_items; +mod place_self; +mod row_gap; +pub use align_content::*; +pub use align_items::*; +pub use align_self::*; +pub use column_gap::*; +pub use gap::*; +pub use justify_content::*; +pub use justify_items::*; +pub use justify_self::*; +pub use place_content::*; +pub use place_items::*; +pub use place_self::*; +pub use row_gap::*; diff --git a/crates/hdx_ast/src/css/values/align/place_content.rs b/crates/hdx_ast/src/css/values/align/place_content.rs new file mode 100644 index 00000000..2d703f9d --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/place_content.rs @@ -0,0 +1 @@ +pub type PlaceContent = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/place_items.rs b/crates/hdx_ast/src/css/values/align/place_items.rs new file mode 100644 index 00000000..2309cde2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/place_items.rs @@ -0,0 +1 @@ +pub type PlaceItems = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/place_self.rs b/crates/hdx_ast/src/css/values/align/place_self.rs new file mode 100644 index 00000000..eb389537 --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/place_self.rs @@ -0,0 +1 @@ +pub type PlaceSelf = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/align/row_gap.rs b/crates/hdx_ast/src/css/values/align/row_gap.rs new file mode 100644 index 00000000..937be33b --- /dev/null +++ b/crates/hdx_ast/src/css/values/align/row_gap.rs @@ -0,0 +1 @@ +pub type RowGap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/anchor_position/anchor_default.rs b/crates/hdx_ast/src/css/values/anchor_position/anchor_default.rs new file mode 100644 index 00000000..76487df7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/anchor_position/anchor_default.rs @@ -0,0 +1 @@ +pub type AnchorDefault = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/anchor_position/anchor_position.rs b/crates/hdx_ast/src/css/values/anchor_position/anchor_position.rs new file mode 100644 index 00000000..86eb8891 --- /dev/null +++ b/crates/hdx_ast/src/css/values/anchor_position/anchor_position.rs @@ -0,0 +1 @@ +pub type AnchorPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/anchor_position/mod.rs b/crates/hdx_ast/src/css/values/anchor_position/mod.rs new file mode 100644 index 00000000..a09ce649 --- /dev/null +++ b/crates/hdx_ast/src/css/values/anchor_position/mod.rs @@ -0,0 +1,8 @@ +mod anchor_default; +mod anchor_position; +mod position_fallback; +mod position_fallback_bounds; +pub use anchor_default::*; +pub use anchor_position::*; +pub use position_fallback::*; +pub use position_fallback_bounds::*; diff --git a/crates/hdx_ast/src/css/values/anchor_position/position_fallback.rs b/crates/hdx_ast/src/css/values/anchor_position/position_fallback.rs new file mode 100644 index 00000000..18a436a5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/anchor_position/position_fallback.rs @@ -0,0 +1 @@ +pub type PositionFallback = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/anchor_position/position_fallback_bounds.rs b/crates/hdx_ast/src/css/values/anchor_position/position_fallback_bounds.rs new file mode 100644 index 00000000..f0454d91 --- /dev/null +++ b/crates/hdx_ast/src/css/values/anchor_position/position_fallback_bounds.rs @@ -0,0 +1 @@ +pub type PositionFallbackBounds = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/angle.rs b/crates/hdx_ast/src/css/values/angle.rs deleted file mode 100644 index 6e0e9786..00000000 --- a/crates/hdx_ast/src/css/values/angle.rs +++ /dev/null @@ -1,140 +0,0 @@ -use std::{ - f32::consts::TAU, - hash::{Hash, Hasher}, -}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom}; - -// https://drafts.csswg.org/css-values/#angles -#[derive(Copy, Clone, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum Angle { - Zero, - Deg(f32), - Grad(f32), - Rad(f32), - Turn(f32), -} - -impl Default for Angle { - fn default() -> Self { - Self::Deg(0.0) - } -} - -impl Angle { - fn to_f32_and_atom(self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Deg(n) => (n, atom!("deg")), - Self::Grad(n) => (n, atom!("grad")), - Self::Rad(n) => (n, atom!("rad")), - Self::Turn(n) => (n, atom!("turn")), - } - } - - fn from_f32_and_atom(n: f32, unit: Atom) -> Option { - match unit { - atom!("deg") => Some(Self::Deg(n)), - atom!("grad") => Some(Self::Grad(n)), - atom!("rad") => Some(Self::Rad(n)), - atom!("turn") => Some(Self::Turn(n)), - _ => None, - } - } - - fn to_deg(self) -> Self { - match self { - Self::Zero => Self::Deg(0.0), - Self::Deg(_) => self, - Self::Grad(n) => Self::Deg(n * 0.9), - Self::Rad(n) => Self::Deg(n.to_degrees()), - Self::Turn(n) => Self::Deg(n / 360.0), - } - } - - fn to_grad(&self) -> Self { - match self { - Self::Zero => Self::Grad(0.0), - Self::Deg(n) => Self::Grad(n * 1.111_111_2), - Self::Grad(_) => *self, - Self::Rad(n) => Self::Grad(n * 63.661_976), - Self::Turn(n) => Self::Grad(n * 400.0), - } - } - - fn to_rad(&self) -> Self { - match self { - Self::Zero => Self::Rad(0.0), - Self::Deg(n) => Self::Rad(n.to_radians()), - Self::Grad(n) => Self::Rad(n * 0.015_707_963), - Self::Rad(_) => *self, - Self::Turn(n) => Self::Rad(n * TAU), - } - } - - fn to_turn(&self) -> Self { - match self { - Self::Zero => Self::Turn(0.0), - Self::Deg(n) => Self::Turn(n * 0.002_777_777_8), - Self::Grad(n) => Self::Turn(n * 0.0025), - Self::Rad(n) => Self::Turn(n * 0.159_154_94), - Self::Turn(_) => *self, - } - } -} - -impl Hash for Angle { - fn hash(&self, state: &mut H) { - match self { - Self::Zero => { - state.write_u8(0); - } - Self::Deg(n) => { - state.write_u8(1); - state.write_u32(n.to_bits()); - } - Self::Grad(n) => { - state.write_u8(2); - state.write_u32(n.to_bits()); - } - Self::Rad(n) => { - state.write_u8(3); - state.write_u32(n.to_bits()); - } - Self::Turn(n) => { - state.write_u8(4); - state.write_u32(n.to_bits()); - } - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 8); - } - - #[test] - fn test_degrees_to_radians() { - assert_eq!(Angle::Deg(14.0).to_rad(), Angle::Rad(0.244346095279)); - assert_eq!(Angle::Deg(0.0).to_rad(), Angle::Rad(0.0)); - assert_eq!(Angle::Deg(360.0).to_rad(), Angle::Rad(6.28318530718)); - } - - #[test] - fn test_radians_to_degrees() { - assert_eq!(Angle::Rad(0.244346095279).to_deg(), Angle::Deg(14.0)); - assert_eq!(Angle::Rad(0.0).to_deg(), Angle::Deg(0.0)); - assert_eq!(Angle::Rad(6.28318530718).to_deg(), Angle::Deg(360.0)); - } -} diff --git a/crates/hdx_ast/src/css/values/animations/animation_composition.rs b/crates/hdx_ast/src/css/values/animations/animation_composition.rs new file mode 100644 index 00000000..d72404cd --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_composition.rs @@ -0,0 +1 @@ +pub type AnimationComposition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_delay.rs b/crates/hdx_ast/src/css/values/animations/animation_delay.rs new file mode 100644 index 00000000..7ba98afd --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_delay.rs @@ -0,0 +1 @@ +pub type AnimationDelay = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_direction.rs b/crates/hdx_ast/src/css/values/animations/animation_direction.rs new file mode 100644 index 00000000..8dc3d44f --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_direction.rs @@ -0,0 +1 @@ +pub type AnimationDirection = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_duration.rs b/crates/hdx_ast/src/css/values/animations/animation_duration.rs new file mode 100644 index 00000000..7c9421b5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_duration.rs @@ -0,0 +1 @@ +pub type AnimationDuration = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_expr.rs b/crates/hdx_ast/src/css/values/animations/animation_expr.rs new file mode 100644 index 00000000..42488e35 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_expr.rs @@ -0,0 +1 @@ +pub type AnimationExpr = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_fill_mode.rs b/crates/hdx_ast/src/css/values/animations/animation_fill_mode.rs new file mode 100644 index 00000000..ae43d279 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_fill_mode.rs @@ -0,0 +1 @@ +pub type AnimationFillMode = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_iteration_count.rs b/crates/hdx_ast/src/css/values/animations/animation_iteration_count.rs new file mode 100644 index 00000000..83cf28d4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_iteration_count.rs @@ -0,0 +1 @@ +pub type AnimationIterationCount = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_name.rs b/crates/hdx_ast/src/css/values/animations/animation_name.rs new file mode 100644 index 00000000..c5254862 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_name.rs @@ -0,0 +1 @@ +pub type AnimationName = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_play_state.rs b/crates/hdx_ast/src/css/values/animations/animation_play_state.rs new file mode 100644 index 00000000..842bb06b --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_play_state.rs @@ -0,0 +1 @@ +pub type AnimationPlayState = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_timeline.rs b/crates/hdx_ast/src/css/values/animations/animation_timeline.rs new file mode 100644 index 00000000..caf852e5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_timeline.rs @@ -0,0 +1 @@ +pub type AnimationTimeline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/animation_timing_function.rs b/crates/hdx_ast/src/css/values/animations/animation_timing_function.rs new file mode 100644 index 00000000..fd86cfc8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/animation_timing_function.rs @@ -0,0 +1 @@ +pub type AnimationTimingFunction = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/animations/mod.rs b/crates/hdx_ast/src/css/values/animations/mod.rs new file mode 100644 index 00000000..48ca2d17 --- /dev/null +++ b/crates/hdx_ast/src/css/values/animations/mod.rs @@ -0,0 +1,22 @@ +mod animation_composition; +mod animation_delay; +mod animation_direction; +mod animation_duration; +mod animation_expr; +mod animation_fill_mode; +mod animation_iteration_count; +mod animation_name; +mod animation_play_state; +mod animation_timeline; +mod animation_timing_function; +pub use animation_composition::*; +pub use animation_delay::*; +pub use animation_direction::*; +pub use animation_duration::*; +pub use animation_expr::*; +pub use animation_fill_mode::*; +pub use animation_iteration_count::*; +pub use animation_name::*; +pub use animation_play_state::*; +pub use animation_timeline::*; +pub use animation_timing_function::*; diff --git a/crates/hdx_ast/src/css/values/backgrounds.rs b/crates/hdx_ast/src/css/values/backgrounds.rs deleted file mode 100644 index bd20893d..00000000 --- a/crates/hdx_ast/src/css/values/backgrounds.rs +++ /dev/null @@ -1,56 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{ColorValue, Expr, Length, MathExpr, Shorthand}; -use crate::{atom, Atom, Atomizable, Spanned}; - -// https://drafts.csswg.org/css-position-3/#inset-shorthands -#[derive(Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct BorderShorthand<'a> { - pub line_width: Shorthand<'a, MathExpr<'a, LineWidth>>, - pub line_style: Shorthand<'a, Expr<'a, LineStyle>>, - pub color: Shorthand<'a, MathExpr<'a, ColorValue<'a>>>, -} - -// https://drafts.csswg.org/css-backgrounds-3/#typedef-line-width -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum LineWidth { - Thin, // atom!("thin") - #[default] - Medium, // atom!("medium") - Thick, // atom!("thick") - Length(Spanned), -} - -// https://drafts.csswg.org/css-backgrounds-3/#typedef-line-style -#[derive(Atomizable, Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum LineStyle { - #[default] - None, // atom!("none") - Hidden, // atom!("hidden") - Dotted, // atom!("dotted") - Dashed, // atom!("dashed") - Solid, // atom!("solid") - Double, // atom!("double") - Groove, // atom!("groove") - Ridge, // atom!("ridge") - Inset, // atom!("inset") - Outset, // atom!("outset") -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/backgrounds/background.rs b/crates/hdx_ast/src/css/values/backgrounds/background.rs new file mode 100644 index 00000000..4acbadf4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background.rs @@ -0,0 +1 @@ +pub type Background = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_attachment.rs b/crates/hdx_ast/src/css/values/backgrounds/background_attachment.rs new file mode 100644 index 00000000..59cf0d2a --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_attachment.rs @@ -0,0 +1 @@ +pub type BackgroundAttachment = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_clip.rs b/crates/hdx_ast/src/css/values/backgrounds/background_clip.rs new file mode 100644 index 00000000..3edf3f7f --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_clip.rs @@ -0,0 +1 @@ +pub type BackgroundClip = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_color.rs b/crates/hdx_ast/src/css/values/backgrounds/background_color.rs new file mode 100644 index 00000000..ee4876dc --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_color.rs @@ -0,0 +1 @@ +pub type BackgroundColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_image.rs b/crates/hdx_ast/src/css/values/backgrounds/background_image.rs new file mode 100644 index 00000000..9e01c510 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_image.rs @@ -0,0 +1 @@ +pub type BackgroundImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_origin.rs b/crates/hdx_ast/src/css/values/backgrounds/background_origin.rs new file mode 100644 index 00000000..d6dcf2d4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_origin.rs @@ -0,0 +1 @@ +pub type BackgroundOrigin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_position.rs b/crates/hdx_ast/src/css/values/backgrounds/background_position.rs new file mode 100644 index 00000000..f21e6d17 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_position.rs @@ -0,0 +1 @@ +pub type BackgroundPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_position_block.rs b/crates/hdx_ast/src/css/values/backgrounds/background_position_block.rs new file mode 100644 index 00000000..aa9e3aec --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_position_block.rs @@ -0,0 +1 @@ +pub type BackgroundPositionBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_position_inline.rs b/crates/hdx_ast/src/css/values/backgrounds/background_position_inline.rs new file mode 100644 index 00000000..739a9886 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_position_inline.rs @@ -0,0 +1 @@ +pub type BackgroundPositionInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_position_x.rs b/crates/hdx_ast/src/css/values/backgrounds/background_position_x.rs new file mode 100644 index 00000000..9c6165b9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_position_x.rs @@ -0,0 +1 @@ +pub type BackgroundPositionX = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_position_y.rs b/crates/hdx_ast/src/css/values/backgrounds/background_position_y.rs new file mode 100644 index 00000000..e7be2903 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_position_y.rs @@ -0,0 +1 @@ +pub type BackgroundPositionY = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_repeat.rs b/crates/hdx_ast/src/css/values/backgrounds/background_repeat.rs new file mode 100644 index 00000000..5dba7aee --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_repeat.rs @@ -0,0 +1 @@ +pub type BackgroundRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/background_size.rs b/crates/hdx_ast/src/css/values/backgrounds/background_size.rs new file mode 100644 index 00000000..507481e7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/background_size.rs @@ -0,0 +1 @@ +pub type BackgroundSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border.rs b/crates/hdx_ast/src/css/values/backgrounds/border.rs new file mode 100644 index 00000000..20849055 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border.rs @@ -0,0 +1 @@ +pub type Border = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom.rs new file mode 100644 index 00000000..2bda119e --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom.rs @@ -0,0 +1 @@ +pub type BorderBottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom_color.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_color.rs new file mode 100644 index 00000000..30c33bd4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_color.rs @@ -0,0 +1 @@ +pub type BorderBottomColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom_left_radius.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_left_radius.rs new file mode 100644 index 00000000..4f5251b2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_left_radius.rs @@ -0,0 +1 @@ +pub type BorderBottomLeftRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom_right_radius.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_right_radius.rs new file mode 100644 index 00000000..e7c2f67d --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_right_radius.rs @@ -0,0 +1 @@ +pub type BorderBottomRightRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom_style.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_style.rs new file mode 100644 index 00000000..72732a37 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_style.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-style +pub type BorderBottomStyle = super::BorderTopStyle; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_bottom_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_width.rs new file mode 100644 index 00000000..f69087bd --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_bottom_width.rs @@ -0,0 +1 @@ +pub type BorderBottomWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_color.rs b/crates/hdx_ast/src/css/values/backgrounds/border_color.rs new file mode 100644 index 00000000..b4a3f8c1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_color.rs @@ -0,0 +1 @@ +pub type BorderColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image.rs new file mode 100644 index 00000000..bc028bd1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image.rs @@ -0,0 +1 @@ +pub type BorderImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image_outset.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image_outset.rs new file mode 100644 index 00000000..2a5b8cb2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image_outset.rs @@ -0,0 +1 @@ +pub type BorderImageOutset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image_repeat.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image_repeat.rs new file mode 100644 index 00000000..d6ee8644 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image_repeat.rs @@ -0,0 +1 @@ +pub type BorderImageRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image_slice.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image_slice.rs new file mode 100644 index 00000000..a5f9e295 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image_slice.rs @@ -0,0 +1 @@ +pub type BorderImageSlice = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image_source.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image_source.rs new file mode 100644 index 00000000..2c4f338c --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image_source.rs @@ -0,0 +1 @@ +pub type BorderImageSource = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_image_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_image_width.rs new file mode 100644 index 00000000..1b261773 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_image_width.rs @@ -0,0 +1 @@ +pub type BorderImageWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_left.rs b/crates/hdx_ast/src/css/values/backgrounds/border_left.rs new file mode 100644 index 00000000..5a7dc784 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_left.rs @@ -0,0 +1 @@ +pub type BorderLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_left_color.rs b/crates/hdx_ast/src/css/values/backgrounds/border_left_color.rs new file mode 100644 index 00000000..d49cdc1f --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_left_color.rs @@ -0,0 +1 @@ +pub type BorderLeftColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_left_style.rs b/crates/hdx_ast/src/css/values/backgrounds/border_left_style.rs new file mode 100644 index 00000000..54b019d4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_left_style.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-style +pub type BorderLeftStyle = super::BorderTopStyle; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_left_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_left_width.rs new file mode 100644 index 00000000..964119a7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_left_width.rs @@ -0,0 +1 @@ +pub type BorderLeftWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_radius.rs b/crates/hdx_ast/src/css/values/backgrounds/border_radius.rs new file mode 100644 index 00000000..5dc7a863 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_radius.rs @@ -0,0 +1 @@ +pub type BorderRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_right.rs b/crates/hdx_ast/src/css/values/backgrounds/border_right.rs new file mode 100644 index 00000000..f3c99abc --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_right.rs @@ -0,0 +1 @@ +pub type BorderRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_right_color.rs b/crates/hdx_ast/src/css/values/backgrounds/border_right_color.rs new file mode 100644 index 00000000..774c6823 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_right_color.rs @@ -0,0 +1 @@ +pub type BorderRightColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_right_style.rs b/crates/hdx_ast/src/css/values/backgrounds/border_right_style.rs new file mode 100644 index 00000000..bf28a018 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_right_style.rs @@ -0,0 +1,3 @@ +// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-style +pub type BorderRightStyle = super::BorderTopStyle; + diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_right_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_right_width.rs new file mode 100644 index 00000000..8ac8963a --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_right_width.rs @@ -0,0 +1 @@ +pub type BorderRightWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_style.rs b/crates/hdx_ast/src/css/values/backgrounds/border_style.rs new file mode 100644 index 00000000..4ca4e207 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_style.rs @@ -0,0 +1 @@ +pub type BorderStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top.rs new file mode 100644 index 00000000..3e88c1b6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top.rs @@ -0,0 +1 @@ +pub type BorderTop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top_color.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top_color.rs new file mode 100644 index 00000000..26eeae7d --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top_color.rs @@ -0,0 +1 @@ +pub type BorderTopColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top_left_radius.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top_left_radius.rs new file mode 100644 index 00000000..9101b3c3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top_left_radius.rs @@ -0,0 +1 @@ +pub type BorderTopLeftRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top_right_radius.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top_right_radius.rs new file mode 100644 index 00000000..3b180559 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top_right_radius.rs @@ -0,0 +1 @@ +pub type BorderTopRightRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top_style.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top_style.rs new file mode 100644 index 00000000..7d15f806 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top_style.rs @@ -0,0 +1,32 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-style +#[derive(Parsable, Writable, Atomizable, Debug, Default, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BorderTopStyle { + #[default] + None, // atom!("none") + Hidden, // atom!("hidden") + Dotted, // atom!("dotted") + Dashed, // atom!("dashed") + Solid, // atom!("solid") + Double, // atom!("double") + Groove, // atom!("groove") + Ridge, // atom!("ridge") + Inset, // atom!("inset") + Outset, // atom!("outset") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_top_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_top_width.rs new file mode 100644 index 00000000..b93e1b2e --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_top_width.rs @@ -0,0 +1 @@ +pub type BorderTopWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/border_width.rs b/crates/hdx_ast/src/css/values/backgrounds/border_width.rs new file mode 100644 index 00000000..ccfd1f9e --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/border_width.rs @@ -0,0 +1 @@ +pub type BorderWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/box_shadow.rs b/crates/hdx_ast/src/css/values/backgrounds/box_shadow.rs new file mode 100644 index 00000000..8b6e66d8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/box_shadow.rs @@ -0,0 +1 @@ +pub type BoxShadow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/backgrounds/mod.rs b/crates/hdx_ast/src/css/values/backgrounds/mod.rs new file mode 100644 index 00000000..be428c84 --- /dev/null +++ b/crates/hdx_ast/src/css/values/backgrounds/mod.rs @@ -0,0 +1,90 @@ +mod background; +mod background_attachment; +mod background_clip; +mod background_color; +mod background_image; +mod background_origin; +mod background_position; +mod background_position_block; +mod background_position_inline; +mod background_position_x; +mod background_position_y; +mod background_repeat; +mod background_size; +mod border; +mod border_bottom; +mod border_bottom_color; +mod border_bottom_left_radius; +mod border_bottom_right_radius; +mod border_bottom_style; +mod border_bottom_width; +mod border_color; +mod border_image; +mod border_image_outset; +mod border_image_repeat; +mod border_image_slice; +mod border_image_source; +mod border_image_width; +mod border_left; +mod border_left_color; +mod border_left_style; +mod border_left_width; +mod border_radius; +mod border_right; +mod border_right_color; +mod border_right_style; +mod border_right_width; +mod border_style; +mod border_top; +mod border_top_color; +mod border_top_left_radius; +mod border_top_right_radius; +mod border_top_style; +mod border_top_width; +mod border_width; +mod box_shadow; +pub use background::*; +pub use background_attachment::*; +pub use background_clip::*; +pub use background_color::*; +pub use background_image::*; +pub use background_origin::*; +pub use background_position::*; +pub use background_position_block::*; +pub use background_position_inline::*; +pub use background_position_x::*; +pub use background_position_y::*; +pub use background_repeat::*; +pub use background_size::*; +pub use border::*; +pub use border_bottom::*; +pub use border_bottom_color::*; +pub use border_bottom_left_radius::*; +pub use border_bottom_right_radius::*; +pub use border_bottom_style::*; +pub use border_bottom_width::*; +pub use border_color::*; +pub use border_image::*; +pub use border_image_outset::*; +pub use border_image_repeat::*; +pub use border_image_slice::*; +pub use border_image_source::*; +pub use border_image_width::*; +pub use border_left::*; +pub use border_left_color::*; +pub use border_left_style::*; +pub use border_left_width::*; +pub use border_radius::*; +pub use border_right::*; +pub use border_right_color::*; +pub use border_right_style::*; +pub use border_right_width::*; +pub use border_style::*; +pub use border_top::*; +pub use border_top_color::*; +pub use border_top_left_radius::*; +pub use border_top_right_radius::*; +pub use border_top_style::*; +pub use border_top_width::*; +pub use border_width::*; +pub use box_shadow::*; diff --git a/crates/hdx_ast/src/css/values/border_radius.rs b/crates/hdx_ast/src/css/values/border_radius.rs deleted file mode 100644 index f21714c5..00000000 --- a/crates/hdx_ast/src/css/values/border_radius.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::hash::Hash; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::LengthPercentage; -use crate::Box; - -// https://drafts.csswg.org/css-values/#angles -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct BorderRadiusValue<'a> { - pub top_left: Box<'a, (LengthPercentage, LengthPercentage)>, - pub top_right: Box<'a, (LengthPercentage, LengthPercentage)>, - pub bottom_left: Box<'a, (LengthPercentage, LengthPercentage)>, - pub bottom_right: Box<'a, (LengthPercentage, LengthPercentage)>, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 32); - } -} diff --git a/crates/hdx_ast/src/css/values/box.rs b/crates/hdx_ast/src/css/values/box.rs deleted file mode 100644 index d726445a..00000000 --- a/crates/hdx_ast/src/css/values/box.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -// https://drafts.csswg.org/css-box-4/#propdef-margin-trim -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct MarginTrimValue { - pub block_start: bool, - pub block_end: bool, - pub inline_start: bool, - pub inline_end: bool, -} diff --git a/crates/hdx_ast/src/css/values/box/margin.rs b/crates/hdx_ast/src/css/values/box/margin.rs new file mode 100644 index 00000000..58409505 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin.rs @@ -0,0 +1 @@ +pub type Margin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/margin_bottom.rs b/crates/hdx_ast/src/css/values/box/margin_bottom.rs new file mode 100644 index 00000000..91fb6567 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin_bottom.rs @@ -0,0 +1 @@ +pub type MarginBottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/margin_left.rs b/crates/hdx_ast/src/css/values/box/margin_left.rs new file mode 100644 index 00000000..1f08b68f --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin_left.rs @@ -0,0 +1 @@ +pub type MarginLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/margin_right.rs b/crates/hdx_ast/src/css/values/box/margin_right.rs new file mode 100644 index 00000000..3c880a50 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin_right.rs @@ -0,0 +1 @@ +pub type MarginRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/margin_top.rs b/crates/hdx_ast/src/css/values/box/margin_top.rs new file mode 100644 index 00000000..363780ec --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin_top.rs @@ -0,0 +1 @@ +pub type MarginTop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/margin_trim.rs b/crates/hdx_ast/src/css/values/box/margin_trim.rs new file mode 100644 index 00000000..a3ad5439 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/margin_trim.rs @@ -0,0 +1,92 @@ +use hdx_atom::atom; +use hdx_lexer::Token; +use hdx_parser::{unexpected, unexpected_ident, Parse, Parser, Result as ParserResult, Spanned}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{bitmask, Atomizable}; + +// https://drafts.csswg.org/css-box-4/#propdef-margin-trim +#[derive(Atomizable)] +#[bitmask(u8)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum MarginTrim { + None, + Block, + Inline, + BlockStart, + BlockEnd, + InlineStart, + InlineEnd, +} + +impl<'a> Parse<'a> for MarginTrim { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut value = Self::none(); + loop { + if value.is_all() { + break; + } + match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + atom!("block") => value |= MarginTrim::Block, + atom!("inline") => value |= MarginTrim::Inline, + atom!("block-start") => value |= MarginTrim::BlockStart, + atom!("block-end") => value |= MarginTrim::BlockEnd, + atom!("inline-start") => value |= MarginTrim::InlineStart, + atom!("inline-end") => value |= MarginTrim::InlineEnd, + atom => unexpected_ident!(parser, atom), + }, + token => unexpected!(parser, token), + } + parser.advance(); + if value == Self::None || value == Self::Block || value == Self::Inline { + break; + } + } + if value.is_none() { + unexpected!(parser); + } + Ok(value.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for MarginTrim { + fn write_css(&self, sink: &mut W) -> WriterResult { + if self.contains(Self::BlockStart) { + sink.write_str("block-start")?; + } + if self.contains(Self::BlockEnd) { + if self.intersects(Self::BlockStart) { + sink.write_char(' ')?; + } + sink.write_str("block-end")?; + } + if self.contains(Self::InlineStart) { + if self.intersects(Self::BlockStart | Self::BlockEnd) { + sink.write_char(' ')?; + } + sink.write_str("inline-start")?; + } + if self.contains(Self::InlineEnd) { + if self.intersects(Self::BlockStart | Self::BlockEnd | Self::InlineStart) { + sink.write_char(' ')?; + } + sink.write_str("inline-end")?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/box/mod.rs b/crates/hdx_ast/src/css/values/box/mod.rs new file mode 100644 index 00000000..fb9610b4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/mod.rs @@ -0,0 +1,22 @@ +mod margin_trim; + +pub use margin_trim::*; + +use super::Todo; +use crate::macros::{length_percentage_property, positive_length_percentage_property}; + +// https://drafts.csswg.org/css-box-4 + +// https://drafts.csswg.org/css-box-4/#padding-physical +pub type Padding = Todo; +positive_length_percentage_property!(PaddingTop); +positive_length_percentage_property!(PaddingRight); +positive_length_percentage_property!(PaddingBottom); +positive_length_percentage_property!(PaddingLeft); + +// https://drafts.csswg.org/css-box-4/#margin-physical +pub type Margin = Todo; +length_percentage_property!(MarginTop); +length_percentage_property!(MarginRight); +length_percentage_property!(MarginBottom); +length_percentage_property!(MarginLeft); diff --git a/crates/hdx_ast/src/css/values/box/padding.rs b/crates/hdx_ast/src/css/values/box/padding.rs new file mode 100644 index 00000000..07d0716f --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/padding.rs @@ -0,0 +1 @@ +pub type Padding = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/box/padding_bottom.rs b/crates/hdx_ast/src/css/values/box/padding_bottom.rs new file mode 100644 index 00000000..4faeb5ee --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/padding_bottom.rs @@ -0,0 +1,4 @@ +use crate::css::values::units::{LengthPercentage, Positive}; + +// https://drafts.csswg.org/css-box-4/#padding-physical +pub type PaddingBottom = Positive; diff --git a/crates/hdx_ast/src/css/values/box/padding_left.rs b/crates/hdx_ast/src/css/values/box/padding_left.rs new file mode 100644 index 00000000..ea41681e --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/padding_left.rs @@ -0,0 +1,4 @@ +use crate::css::values::units::{LengthPercentage, Positive}; + +// https://drafts.csswg.org/css-box-4/#padding-physical +pub type PaddingLeft = Positive; diff --git a/crates/hdx_ast/src/css/values/box/padding_right.rs b/crates/hdx_ast/src/css/values/box/padding_right.rs new file mode 100644 index 00000000..25f824ed --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/padding_right.rs @@ -0,0 +1,30 @@ +use hdx_lexer::Token; +use hdx_parser::{ + diagnostics::{NumberNotNegative, UnexpectedDimension}, + unexpected, Parse, +}; + +use crate::css::values::units::LengthPercentage; + +// https://drafts.csswg.org/css-box-4/#padding-physical +pub type PaddingRight = LengthPercentage; + +impl<'a> Parse<'a> for PaddingRight { + fn parse(parser: &mut hdx_parser::Parser<'a>) -> miette::Result> { + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => Ok(Self::Zero.spanned(span)), + Token::Dimension(n, unit, _) if n == 0.0 => { + if n < 0 { + Err(NumberNotNegative(n, span))? + } + if let Some(val) = Self::new(n.into(), unit) { + Ok(val.spanned(span)) + } else { + Err(UnexpectedDimension(unit, span))? + } + } + token => unexpected!(parser, token), + } + } +} diff --git a/crates/hdx_ast/src/css/values/box/padding_top.rs b/crates/hdx_ast/src/css/values/box/padding_top.rs new file mode 100644 index 00000000..2a242142 --- /dev/null +++ b/crates/hdx_ast/src/css/values/box/padding_top.rs @@ -0,0 +1,30 @@ +use hdx_lexer::Token; +use hdx_parser::{ + diagnostics::{NumberNotNegative, UnexpectedDimension}, + unexpected, Parse, +}; + +use crate::css::values::units::LengthPercentage; + +// https://drafts.csswg.org/css-box-4/#padding-physical +pub struct PaddingTop(pub LengthPercentage); + +impl<'a> Parse<'a> for PaddingTop { + fn parse(parser: &mut hdx_parser::Parser<'a>) -> miette::Result> { + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => Ok(Self::Zero.spanned(span)), + Token::Dimension(n, unit, _) if n == 0.0 => { + if n < 0 { + Err(NumberNotNegative(n, span))? + } + if let Some(val) = Self::new(n.into(), unit) { + Ok(val.spanned(span)) + } else { + Err(UnexpectedDimension(unit, span))? + } + } + token => unexpected!(parser, token), + } + } +} diff --git a/crates/hdx_ast/src/css/values/break.rs b/crates/hdx_ast/src/css/values/break.rs deleted file mode 100644 index e63c7167..00000000 --- a/crates/hdx_ast/src/css/values/break.rs +++ /dev/null @@ -1,56 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable}; - -// https://drafts.csswg.org/css-break-4/#propdef-box-decoration-break -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BoxDecorationBreakValue { - #[default] - Slice, // atom!("slice") - Clone, // atom!("clone") -} - -// https://drafts.csswg.org/css-break-4/#propdef-break-after -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BreakValue { - #[default] - Auto, // atom!("auto") - Avoid, // atom!("avoid") - Always, // atom!("always") - All, // atom!("all") - AvoidPage, // atom!("avoid-page") - Page, // atom!("page") - Left, // atom!("left") - Right, // atom!("right") - Recto, // atom!("recto") - Verso, // atom!("verso") - AvoidColumn, // atom!("avoid-column") - Column, // atom!("column") - AvoidRegion, // atom!("avoid-region") - Region, // atom!("region") -} - -// https://drafts.csswg.org/css-break-4/#propdef-break-inside -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BreakInsideValue { - #[default] - Auto, // atom!("auto") - Avoid, // atom!("avoid") - AvoidPage, // atom!("avoid-page") - AvoidColumn, // atom!("avoid-column") - AvoidRegion, // atom!("avoid-region") -} - -// https://drafts.csswg.org/css-break-4/#propdef-margin-break -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum MarginBreakValue { - #[default] - Auto, // atom!("auto") - Keep, // atom!("keep") - Discard, // atom!("discard") -} diff --git a/crates/hdx_ast/src/css/values/break/box_decoration_break.rs b/crates/hdx_ast/src/css/values/break/box_decoration_break.rs new file mode 100644 index 00000000..bc5e0491 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/box_decoration_break.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-box-4/#propdef-margin-trim +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BoxDecorationBreak { + #[default] + Slice, // atom!("slice") + Clone, // atom!("clone") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/break/break_after.rs b/crates/hdx_ast/src/css/values/break/break_after.rs new file mode 100644 index 00000000..cee1583d --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/break_after.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-break-4/#propdef-break-after +pub type BreakAfter = super::BreakBefore; diff --git a/crates/hdx_ast/src/css/values/break/break_before.rs b/crates/hdx_ast/src/css/values/break/break_before.rs new file mode 100644 index 00000000..11f54e8c --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/break_before.rs @@ -0,0 +1,36 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-break-4/#propdef-break-before +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BreakBefore { + #[default] + Auto, // atom!("auto") + Avoid, // atom!("avoid") + Always, // atom!("always") + All, // atom!("all") + AvoidPage, // atom!("avoid-page") + Page, // atom!("page") + Left, // atom!("left") + Right, // atom!("right") + Recto, // atom!("recto") + Verso, // atom!("verso") + AvoidColumn, // atom!("avoid-column") + Column, // atom!("column") + AvoidRegion, // atom!("avoid-region") + Region, // atom!("region") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/break/break_inside.rs b/crates/hdx_ast/src/css/values/break/break_inside.rs new file mode 100644 index 00000000..f6589e85 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/break_inside.rs @@ -0,0 +1,16 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-break-4/#propdef-break-inside +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BreakInside { + #[default] + Auto, // atom!("auto") + Avoid, // atom!("avoid") + AvoidPage, // atom!("avoid-page") + AvoidColumn, // atom!("avoid-column") + AvoidRegion, // atom!("avoid-region") +} diff --git a/crates/hdx_ast/src/css/values/break/margin_break.rs b/crates/hdx_ast/src/css/values/break/margin_break.rs new file mode 100644 index 00000000..464f5f93 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/margin_break.rs @@ -0,0 +1,14 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-break-4/#propdef-margin-break +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum MarginBreak { + #[default] + Auto, // atom!("auto") + Keep, // atom!("keep") + Discard, // atom!("discard") +} diff --git a/crates/hdx_ast/src/css/values/break/mod.rs b/crates/hdx_ast/src/css/values/break/mod.rs new file mode 100644 index 00000000..d5743ca1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/mod.rs @@ -0,0 +1,20 @@ +mod box_decoration_break; +mod break_after; +mod break_before; +mod break_inside; +mod margin_break; +mod orphans; +mod page_break_after; +mod page_break_before; +mod page_break_inside; +mod widows; +pub use box_decoration_break::*; +pub use break_after::*; +pub use break_before::*; +pub use break_inside::*; +pub use margin_break::*; +pub use orphans::*; +pub use page_break_after::*; +pub use page_break_before::*; +pub use page_break_inside::*; +pub use widows::*; diff --git a/crates/hdx_ast/src/css/values/break/orphans.rs b/crates/hdx_ast/src/css/values/break/orphans.rs new file mode 100644 index 00000000..e5557942 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/orphans.rs @@ -0,0 +1 @@ +pub type Orphans = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/break/page_break_after.rs b/crates/hdx_ast/src/css/values/break/page_break_after.rs new file mode 100644 index 00000000..fc293a98 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/page_break_after.rs @@ -0,0 +1 @@ +pub type PageBreakAfter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/break/page_break_before.rs b/crates/hdx_ast/src/css/values/break/page_break_before.rs new file mode 100644 index 00000000..6efdad98 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/page_break_before.rs @@ -0,0 +1 @@ +pub type PageBreakBefore = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/break/page_break_inside.rs b/crates/hdx_ast/src/css/values/break/page_break_inside.rs new file mode 100644 index 00000000..c93277a3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/page_break_inside.rs @@ -0,0 +1 @@ +pub type PageBreakInside = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/break/widows.rs b/crates/hdx_ast/src/css/values/break/widows.rs new file mode 100644 index 00000000..5877292a --- /dev/null +++ b/crates/hdx_ast/src/css/values/break/widows.rs @@ -0,0 +1 @@ +pub type Widows = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/cascade/all.rs b/crates/hdx_ast/src/css/values/cascade/all.rs new file mode 100644 index 00000000..faed3b53 --- /dev/null +++ b/crates/hdx_ast/src/css/values/cascade/all.rs @@ -0,0 +1 @@ +pub type All = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/cascade/mod.rs b/crates/hdx_ast/src/css/values/cascade/mod.rs new file mode 100644 index 00000000..389aaaa9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/cascade/mod.rs @@ -0,0 +1,2 @@ +mod all; +pub use all::*; diff --git a/crates/hdx_ast/src/css/values/color.rs b/crates/hdx_ast/src/css/values/color.rs deleted file mode 100644 index dec3849e..00000000 --- a/crates/hdx_ast/src/css/values/color.rs +++ /dev/null @@ -1,515 +0,0 @@ -use std::{ - hash::{Hash, Hasher}, - str::Chars, -}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Angle, MathExpr}; -use crate::{atom, Atom, Atomizable, Box, Spanned}; - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum ColorValue<'a> { - CurrentColor, - #[default] - Transparent, - Hex(u32), - Named(NamedColor), - RGB(Box<'a, Spanned>>), - HSL(Box<'a, Spanned>>), - HWB(Box<'a, Spanned>>), - LAB(Box<'a, Spanned>>), - LCH(Box<'a, Spanned>>), - OKLAB(Box<'a, Spanned>>), - OKLCH(Box<'a, Spanned>>), -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct RGB<'a> { - pub r: Spanned>, - pub g: Spanned>, - pub b: Spanned>, - pub alpha: Spanned>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct HSL<'a> { - pub h: MathExpr<'a, Hue>, - pub s: MathExpr<'a, PercentageOrNone>, - pub l: MathExpr<'a, PercentageOrNone>, - pub alpha: MathExpr<'a, NumberPercentageOrNone>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct HWB<'a> { - pub h: MathExpr<'a, Hue>, - pub w: MathExpr<'a, PercentageOrNone>, - pub b: MathExpr<'a, PercentageOrNone>, - pub alpha: MathExpr<'a, NumberPercentageOrNone>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct LAB<'a> { - pub l: MathExpr<'a, NumberPercentageOrNone>, - pub a: MathExpr<'a, NumberPercentageOrNone>, - pub b: MathExpr<'a, Hue>, - pub alpha: MathExpr<'a, NumberPercentageOrNone>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct LCH<'a> { - pub l: MathExpr<'a, NumberPercentageOrNone>, - pub c: MathExpr<'a, NumberPercentageOrNone>, - pub h: MathExpr<'a, Hue>, - pub alpha: MathExpr<'a, NumberPercentageOrNone>, -} - -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum NumberPercentageOrNone { - #[default] - None, - Number(f32), - Percentage(f32), -} - -impl Hash for NumberPercentageOrNone { - fn hash(&self, state: &mut H) { - match self { - Self::None => { - 0.hash(state); - } - Self::Number(n) => { - 1.hash(state); - n.to_bits().hash(state); - } - Self::Percentage(p) => { - 2.hash(state); - p.to_bits().hash(state); - } - } - } -} - -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum PercentageOrNone { - #[default] - None, - Percentage(f32), -} - -impl Hash for PercentageOrNone { - fn hash(&self, state: &mut H) { - match self { - Self::None => { - 0.hash(state); - } - Self::Percentage(p) => { - 1.hash(state); - p.to_bits().hash(state); - } - } - } -} - -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum Hue { - #[default] - None, - Number(f32), - Angle(Angle), -} - -impl Hash for Hue { - fn hash(&self, state: &mut H) { - match self { - Self::None => { - 0.hash(state); - } - Self::Number(n) => { - 1.hash(state); - n.to_bits().hash(state); - } - Self::Angle(a) => { - 2.hash(state); - a.hash(state); - } - } - } -} - -trait HexableChars { - fn next_as_hex(&mut self) -> Option; -} - -impl<'a> HexableChars for Chars<'a> { - fn next_as_hex(&mut self) -> Option { - match self.next() { - Some(ch) => { - let b = ch as u8; - match b { - b'A'..=b'F' => Some((b - b'A' + 10) as u32), - b'a'..=b'f' => Some((b - b'a' + 10) as u32), - b'0'..=b'9' => Some((b - b'0') as u32), - _ => None, - } - } - _ => None, - } - } -} - -pub enum ToHexStyle { - Compact, - ExpandedElideAlpha, - Expanded, -} - -impl<'a> ColorValue<'a> { - pub fn from_hex(str: &str) -> Option> { - let mut chars = str.chars(); - if str.starts_with('#') { - chars.next(); - } - let (r, g, b, a) = match str.len() { - // implied alpha - 3 => ( - chars.next_as_hex().unwrap() * 17, - chars.next_as_hex().unwrap() * 17, - chars.next_as_hex().unwrap() * 17, - 255, - ), - // - 4 => ( - chars.next_as_hex().unwrap() * 17, - chars.next_as_hex().unwrap() * 17, - chars.next_as_hex().unwrap() * 17, - chars.next_as_hex().unwrap() * 17, - ), - // implied alpha - 6 => ( - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - 255, - ), - // - 8 => ( - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - chars.next_as_hex().unwrap() << 4 | chars.next_as_hex().unwrap(), - ), - _ => { - return None; - } - }; - Some(ColorValue::Hex(r << 24 | g << 16 | b << 8 | a)) - } - - pub fn to_hex(&self, style: ToHexStyle) -> Option { - if let Self::Hex(d) = self { - let compacted = ((d & 0x0FF00000) >> 12) | ((d & 0x00000FF0) >> 4); - let expanded = ((compacted & 0xF000) << 16) - | ((compacted & 0xFF00) << 12) - | ((compacted & 0x0FF0) << 8) - | ((compacted & 0x00FF) << 4) - | (compacted & 0x000F); - // Shorthand can be used - if &expanded == d && d & 255 == 255 { - Some(format!("#{:03x}", compacted >> 4)) - } else if &expanded == d { - Some(format!("#{:04x}", compacted)) - } else if d & 255 == 255 { - Some(format!("#{:06x}", d >> 8)) - } else { - Some(format!("#{:08x}", d)) - } - } else { - None - } - } -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum NamedColor { - Aliceblue, // atom!("aliceblue") - Antiquewhite, // atom!("antiquewhite") - Aqua, // atom!("aqua") - Aquamarine, // atom!("aquamarine") - Azure, // atom!("azure") - Beige, // atom!("beige") - Bisque, // atom!("bisque") - Black, // atom!("black") - Blanchedalmond, // atom!("blanchedalmond") - Blue, // atom!("blue") - Blueviolet, // atom!("blueviolet") - Brown, // atom!("brown") - Burlywood, // atom!("burlywood") - Cadetblue, // atom!("cadetblue") - Chartreuse, // atom!("chartreuse") - Chocolate, // atom!("chocolate") - Coral, // atom!("coral") - Cornflowerblue, // atom!("cornflowerblue") - Cornsilk, // atom!("cornsilk") - Crimson, // atom!("crimson") - Cyan, // atom!("cyan") - Darkblue, // atom!("darkblue") - Darkcyan, // atom!("darkcyan") - Darkgoldenrod, // atom!("darkgoldenrod") - Darkgray, // atom!("darkgray") - Darkgreen, // atom!("darkgreen") - Darkgrey, // atom!("darkgrey") - Darkkhaki, // atom!("darkkhaki") - Darkmagenta, // atom!("darkmagenta") - Darkolivegreen, // atom!("darkolivegreen") - Darkorange, // atom!("darkorange") - Darkorchid, // atom!("darkorchid") - Darkred, // atom!("darkred") - Darksalmon, // atom!("darksalmon") - Darkseagreen, // atom!("darkseagreen") - Darkslateblue, // atom!("darkslateblue") - Darkslategray, // atom!("darkslategray") - Darkslategrey, // atom!("darkslategrey") - Darkturquoise, // atom!("darkturquoise") - Darkviolet, // atom!("darkviolet") - Deeppink, // atom!("deeppink") - Deepskyblue, // atom!("deepskyblue") - Dimgray, // atom!("dimgray") - Dimgrey, // atom!("dimgrey") - Dodgerblue, // atom!("dodgerblue") - Firebrick, // atom!("firebrick") - Floralwhite, // atom!("floralwhite") - Forestgreen, // atom!("forestgreen") - Fuchsia, // atom!("fuchsia") - Gainsboro, // atom!("gainsboro") - Ghostwhite, // atom!("ghostwhite") - Gold, // atom!("gold") - Goldenrod, // atom!("goldenrod") - Gray, // atom!("gray") - Green, // atom!("green") - Greenyellow, // atom!("greenyellow") - Grey, // atom!("grey") - Honeydew, // atom!("honeydew") - Hotpink, // atom!("hotpink") - Indianred, // atom!("indianred") - Indigo, // atom!("indigo") - Ivory, // atom!("ivory") - Khaki, // atom!("khaki") - Lavender, // atom!("lavender") - Lavenderblush, // atom!("lavenderblush") - Lawngreen, // atom!("lawngreen") - Lemonchiffon, // atom!("lemonchiffon") - Lightblue, // atom!("lightblue") - Lightcoral, // atom!("lightcoral") - Lightcyan, // atom!("lightcyan") - Lightgoldenrodyellow, // atom!("lightgoldenrodyellow") - Lightgray, // atom!("lightgray") - Lightgreen, // atom!("lightgreen") - Lightgrey, // atom!("lightgrey") - Lightpink, // atom!("lightpink") - Lightsalmon, // atom!("lightsalmon") - Lightseagreen, // atom!("lightseagreen") - Lightskyblue, // atom!("lightskyblue") - Lightslategray, // atom!("lightslategray") - Lightslategrey, // atom!("lightslategrey") - Lightsteelblue, // atom!("lightsteelblue") - Lightyellow, // atom!("lightyellow") - Lime, // atom!("lime") - Limegreen, // atom!("limegreen") - Linen, // atom!("linen") - Magenta, // atom!("magenta") - Maroon, // atom!("maroon") - Mediumaquamarine, // atom!("mediumaquamarine") - Mediumblue, // atom!("mediumblue") - Mediumorchid, // atom!("mediumorchid") - Mediumpurple, // atom!("mediumpurple") - Mediumseagreen, // atom!("mediumseagreen") - Mediumslateblue, // atom!("mediumslateblue") - Mediumspringgreen, // atom!("mediumspringgreen") - Mediumturquoise, // atom!("mediumturquoise") - Mediumvioletred, // atom!("mediumvioletred") - Midnightblue, // atom!("midnightblue") - Mintcream, // atom!("mintcream") - Mistyrose, // atom!("mistyrose") - Moccasin, // atom!("moccasin") - Navajowhite, // atom!("navajowhite") - Navy, // atom!("navy") - Oldlace, // atom!("oldlace") - Olive, // atom!("olive") - Olivedrab, // atom!("olivedrab") - Orange, // atom!("orange") - Orangered, // atom!("orangered") - Orchid, // atom!("orchid") - Palegoldenrod, // atom!("palegoldenrod") - Palegreen, // atom!("palegreen") - Paleturquoise, // atom!("paleturquoise") - Palevioletred, // atom!("palevioletred") - Papayawhip, // atom!("papayawhip") - Peachpuff, // atom!("peachpuff") - Peru, // atom!("peru") - Pink, // atom!("pink") - Plum, // atom!("plum") - Powderblue, // atom!("powderblue") - Purple, // atom!("purple") - Rebeccapurple, // atom!("rebeccapurple") - Red, // atom!("red") - Rosybrown, // atom!("rosybrown") - Royalblue, // atom!("royalblue") - Saddlebrown, // atom!("saddlebrown") - Salmon, // atom!("salmon") - Sandybrown, // atom!("sandybrown") - Seagreen, // atom!("seagreen") - Seashell, // atom!("seashell") - Sienna, // atom!("sienna") - Silver, // atom!("silver") - Skyblue, // atom!("skyblue") - Slateblue, // atom!("slateblue") - Slategray, // atom!("slategray") - Slategrey, // atom!("slategrey") - Snow, // atom!("snow") - Springgreen, // atom!("springgreen") - Steelblue, // atom!("steelblue") - Tan, // atom!("tan") - Teal, // atom!("teal") - Thistle, // atom!("thistle") - Tomato, // atom!("tomato") - Turquoise, // atom!("turquoise") - Violet, // atom!("violet") - Wheat, // atom!("wheat") - White, // atom!("white") - Whitesmoke, // atom!("whitesmoke") - Yellow, // atom!("yellow") - Yellowgreen, // atom!("yellowgreen") -} - -// https://drafts.csswg.org/css-color/#typedef-alpha-value -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum AlphaValue { - Number(f32), - Percentage(f32), -} - -impl Hash for AlphaValue { - fn hash(&self, state: &mut H) { - let (i, f) = match self { - Self::Number(f) => (0, f), - Self::Percentage(f) => (1, f), - }; - i.hash(state); - f.to_bits().hash(state); - } -} - -// https://drafts.csswg.org/css-color/#interpolation-space -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum ColorSpace { - Rectangular(RectangularColorSpace), - Polar(PolarColorSpace), -} - -// https://drafts.csswg.org/css-color/#interpolation-space -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum PolarColorSpace { - Hsl, - Hwb, - Lch, - OkLch, -} - -// https://drafts.csswg.org/css-color/#interpolation-space -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum RectangularColorSpace { - Srgb, - SrgbLinear, - DisplayP3, - A98Rgb, - ProphotoRgb, - Rec2020, - Lab, - OkLab, - Xyz, - XyzD50, - XyzD65, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 2); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 1); - } - - #[test] - fn color_from_hex_3() { - assert_eq!(ColorValue::from_hex("abc"), Some(ColorValue::Hex(2864434431))); - assert_eq!(ColorValue::from_hex("fff"), Some(ColorValue::Hex(4294967295))); - assert_eq!(ColorValue::from_hex("000"), Some(ColorValue::Hex(255))); - } - - #[test] - fn color_from_hex_4() { - assert_eq!(ColorValue::from_hex("abcd"), Some(ColorValue::Hex(2864434397))); - assert_eq!(ColorValue::from_hex("ffff"), Some(ColorValue::Hex(4294967295))); - assert_eq!(ColorValue::from_hex("fff0"), Some(ColorValue::Hex(4294967040))); - } - - #[test] - fn color_from_hex_5() { - assert_eq!(ColorValue::from_hex("abcde"), None); - assert_eq!(ColorValue::from_hex("fffff"), None); - assert_eq!(ColorValue::from_hex("fff00"), None); - } - - #[test] - fn color_from_hex_6() { - assert_eq!(ColorValue::from_hex("bbccdd"), Some(ColorValue::Hex(3150765567))); - assert_eq!(ColorValue::from_hex("ffffff"), Some(ColorValue::Hex(4294967295))); - } - - #[test] - fn color_from_hex_8() { - assert_eq!(ColorValue::from_hex("bbccddee"), Some(ColorValue::Hex(3150765550))); - assert_eq!(ColorValue::from_hex("ffffffff"), Some(ColorValue::Hex(4294967295))); - assert_eq!(ColorValue::from_hex("ffffff00"), Some(ColorValue::Hex(4294967040))); - } - - #[test] - fn color_to_hex() { - assert_eq!(ColorValue::Hex(255).to_hex(ToHexStyle::Compact), Some("#000".into())); - assert_eq!(ColorValue::Hex(2864434431).to_hex(ToHexStyle::Compact), Some("#abc".into())); - assert_eq!(ColorValue::Hex(4294967295).to_hex(ToHexStyle::Compact), Some("#fff".into())); - assert_eq!(ColorValue::Hex(4294967040).to_hex(ToHexStyle::Compact), Some("#fff0".into())); - assert_eq!( - ColorValue::Hex(4210752000).to_hex(ToHexStyle::Compact), - Some("#fafafa00".into()) - ); - // assert_eq!( - // ColorValue::Hex(255).to_hex(ToHexStyle::ExpandedElideAlpha), - // Some("#000000".into()) - // ); - } -} diff --git a/crates/hdx_ast/src/css/values/color/color.rs b/crates/hdx_ast/src/css/values/color/color.rs new file mode 100644 index 00000000..62d57993 --- /dev/null +++ b/crates/hdx_ast/src/css/values/color/color.rs @@ -0,0 +1 @@ +pub type Color = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/color/mod.rs b/crates/hdx_ast/src/css/values/color/mod.rs new file mode 100644 index 00000000..b2f50487 --- /dev/null +++ b/crates/hdx_ast/src/css/values/color/mod.rs @@ -0,0 +1,4 @@ +mod color; +mod opacity; +pub use color::*; +pub use opacity::*; diff --git a/crates/hdx_ast/src/css/values/color/opacity.rs b/crates/hdx_ast/src/css/values/color/opacity.rs new file mode 100644 index 00000000..61e826ab --- /dev/null +++ b/crates/hdx_ast/src/css/values/color/opacity.rs @@ -0,0 +1 @@ +pub type Opacity = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/color_adjust/color_adjust.rs b/crates/hdx_ast/src/css/values/color_adjust/color_adjust.rs new file mode 100644 index 00000000..482111af --- /dev/null +++ b/crates/hdx_ast/src/css/values/color_adjust/color_adjust.rs @@ -0,0 +1 @@ +pub type ColorAdjust = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/color_adjust/color_scheme.rs b/crates/hdx_ast/src/css/values/color_adjust/color_scheme.rs new file mode 100644 index 00000000..9abfcc5e --- /dev/null +++ b/crates/hdx_ast/src/css/values/color_adjust/color_scheme.rs @@ -0,0 +1 @@ +pub type ColorScheme = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/color_adjust/forced_color_adjust.rs b/crates/hdx_ast/src/css/values/color_adjust/forced_color_adjust.rs new file mode 100644 index 00000000..3381e343 --- /dev/null +++ b/crates/hdx_ast/src/css/values/color_adjust/forced_color_adjust.rs @@ -0,0 +1 @@ +pub type ForcedColorAdjust = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/color_adjust/mod.rs b/crates/hdx_ast/src/css/values/color_adjust/mod.rs new file mode 100644 index 00000000..2a2b9446 --- /dev/null +++ b/crates/hdx_ast/src/css/values/color_adjust/mod.rs @@ -0,0 +1,8 @@ +mod color_adjust; +mod color_scheme; +mod forced_color_adjust; +mod print_color_adjust; +pub use color_adjust::*; +pub use color_scheme::*; +pub use forced_color_adjust::*; +pub use print_color_adjust::*; diff --git a/crates/hdx_ast/src/css/values/color_adjust/print_color_adjust.rs b/crates/hdx_ast/src/css/values/color_adjust/print_color_adjust.rs new file mode 100644 index 00000000..b14eba73 --- /dev/null +++ b/crates/hdx_ast/src/css/values/color_adjust/print_color_adjust.rs @@ -0,0 +1 @@ +pub type PrintColorAdjust = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/compositing.rs b/crates/hdx_ast/src/css/values/compositing.rs deleted file mode 100644 index 9e1081da..00000000 --- a/crates/hdx_ast/src/css/values/compositing.rs +++ /dev/null @@ -1,36 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -// https://drafts.fxtf.org/compositing/#ltblendmodegt -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum BlendMode { - Normal, - Multiply, - Screen, - Overlay, - Darken, - Lighten, - ColorDoge, - ColorBurn, - HardLight, - SoftLight, - Difference, - Exclusion, - Hue, - Saturation, - Color, - Luminosity, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/compositing/background_blend_mode.rs b/crates/hdx_ast/src/css/values/compositing/background_blend_mode.rs new file mode 100644 index 00000000..3af1c48f --- /dev/null +++ b/crates/hdx_ast/src/css/values/compositing/background_blend_mode.rs @@ -0,0 +1 @@ +pub type BackgroundBlendMode = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/compositing/isolation.rs b/crates/hdx_ast/src/css/values/compositing/isolation.rs new file mode 100644 index 00000000..4b3d0366 --- /dev/null +++ b/crates/hdx_ast/src/css/values/compositing/isolation.rs @@ -0,0 +1 @@ +pub type Isolation = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/compositing/mix_blend_mode.rs b/crates/hdx_ast/src/css/values/compositing/mix_blend_mode.rs new file mode 100644 index 00000000..bdb32e46 --- /dev/null +++ b/crates/hdx_ast/src/css/values/compositing/mix_blend_mode.rs @@ -0,0 +1,40 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode +#[derive(Parsable, Writable, Atomizable, Debug, Default, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum MixBlendMode { + #[default] + Normal, // atom!("normal") + Multiply, // atom!("multiply") + Screen, // atom!("screen") + Overlay, // atom!("overlay") + Darken, // atom!("darken") + Lighten, // atom!("lighten") + ColorDodge, // atom!("color-dodge") + ColorBurn, // atom!("color-burn") + HardLight, // atom!("hard-light") + SoftLight, // atom!("soft-light") + Difference, // atom!("difference") + Exclusion, // atom!("exclusion") + Hue, // atom!("hue") + Saturation, // atom!("saturation") + Color, // atom!("color") + Luminosity, // atom!("luminosity") + PlusDarker, // atom!("plus-darker") + PlusLighter, // atom!("plus-lighter") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/compositing/mod.rs b/crates/hdx_ast/src/css/values/compositing/mod.rs new file mode 100644 index 00000000..93077198 --- /dev/null +++ b/crates/hdx_ast/src/css/values/compositing/mod.rs @@ -0,0 +1,6 @@ +mod background_blend_mode; +mod isolation; +mod mix_blend_mode; +pub use background_blend_mode::*; +pub use isolation::*; +pub use mix_blend_mode::*; diff --git a/crates/hdx_ast/src/css/values/contain/contain.rs b/crates/hdx_ast/src/css/values/contain/contain.rs new file mode 100644 index 00000000..6edef5eb --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/contain.rs @@ -0,0 +1 @@ +pub type Contain = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/contain/container.rs b/crates/hdx_ast/src/css/values/contain/container.rs new file mode 100644 index 00000000..09d4fcd6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/container.rs @@ -0,0 +1 @@ +pub type Container = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/contain/container_name.rs b/crates/hdx_ast/src/css/values/contain/container_name.rs new file mode 100644 index 00000000..de2bfb3b --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/container_name.rs @@ -0,0 +1 @@ +pub type ContainerName = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/contain/container_type.rs b/crates/hdx_ast/src/css/values/contain/container_type.rs new file mode 100644 index 00000000..8fccec92 --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/container_type.rs @@ -0,0 +1 @@ +pub type ContainerType = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/contain/content_visibility.rs b/crates/hdx_ast/src/css/values/contain/content_visibility.rs new file mode 100644 index 00000000..3439f776 --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/content_visibility.rs @@ -0,0 +1 @@ +pub type ContentVisibility = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/contain/mod.rs b/crates/hdx_ast/src/css/values/contain/mod.rs new file mode 100644 index 00000000..ecf6e95f --- /dev/null +++ b/crates/hdx_ast/src/css/values/contain/mod.rs @@ -0,0 +1,10 @@ +mod contain; +mod container; +mod container_name; +mod container_type; +mod content_visibility; +pub use contain::*; +pub use container::*; +pub use container_name::*; +pub use container_type::*; +pub use content_visibility::*; diff --git a/crates/hdx_ast/src/css/values/content.rs b/crates/hdx_ast/src/css/values/content.rs deleted file mode 100644 index eef349fc..00000000 --- a/crates/hdx_ast/src/css/values/content.rs +++ /dev/null @@ -1,101 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{CounterOrCounters, Image}; -use crate::{atom, Atom, Atomizable, Spanned, Vec}; - -// -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ContentsValue<'a> { - #[default] - Normal, - None, - Replacement(Spanned>), - List(Spanned>), -} - -// -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ContentAlt<'a> { - #[default] - None, - String(Atom), - Counter(Spanned>), -} - -// -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct ContentReplacement<'a> { - pub image: Image<'a>, - pub alt: ContentAlt<'a>, -} - -// -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct ContentList<'a> { - pub values: Vec<'a, ContentElement<'a>>, - pub alt: Vec<'a, ContentAlt<'a>>, -} -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ContentElement<'a> { - String(Atom), - Contents, - Image(Spanned>), - Counter(Spanned>), - Quote(Quote), - Leader(Leader), -} - -// https://drafts.csswg.org/css-content-3/#typedef-quote -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum Quote { - OpenQuote, // atom!("open-quote") - CloseQuote, // atom!("close-quote") - NoOpenQuote, // atom!("no-open-quote") - NoCloseQuote, // atom!("no-close-quote") -} - -// https://drafts.csswg.org/css-content-3/#leader-function -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Leader { - Dotted, - Solid, - Space, - String(Atom), -} - -// https://drafts.csswg.org/css-content-3/#leader-function -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum QuotesValue<'a> { - #[default] - Auto, - None, - Custom(Vec<'a, (Atom, Atom)>), -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 80); - assert_eq!(size_of::(), 40); - assert_eq!(size_of::(), 56); - assert_eq!(size_of::(), 64); - assert_eq!(size_of::(), 40); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 40); - } -} diff --git a/crates/hdx_ast/src/css/values/content/bookmark_label.rs b/crates/hdx_ast/src/css/values/content/bookmark_label.rs new file mode 100644 index 00000000..7b7a4b7f --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/bookmark_label.rs @@ -0,0 +1 @@ +pub type BookmarkLabel = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/content/bookmark_level.rs b/crates/hdx_ast/src/css/values/content/bookmark_level.rs new file mode 100644 index 00000000..d8dd16f4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/bookmark_level.rs @@ -0,0 +1 @@ +pub type BookmarkLevel = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/content/bookmark_state.rs b/crates/hdx_ast/src/css/values/content/bookmark_state.rs new file mode 100644 index 00000000..aa462620 --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/bookmark_state.rs @@ -0,0 +1 @@ +pub type BookmarkState = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/content/content.rs b/crates/hdx_ast/src/css/values/content/content.rs new file mode 100644 index 00000000..7bc4c42c --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/content.rs @@ -0,0 +1 @@ +pub type Content = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/content/mod.rs b/crates/hdx_ast/src/css/values/content/mod.rs new file mode 100644 index 00000000..46c4b19a --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/mod.rs @@ -0,0 +1,12 @@ +mod bookmark_label; +mod bookmark_level; +mod bookmark_state; +mod content; +mod quotes; +mod string_set; +pub use bookmark_label::*; +pub use bookmark_level::*; +pub use bookmark_state::*; +pub use content::*; +pub use quotes::*; +pub use string_set::*; diff --git a/crates/hdx_ast/src/css/values/content/quotes.rs b/crates/hdx_ast/src/css/values/content/quotes.rs new file mode 100644 index 00000000..303e4e1b --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/quotes.rs @@ -0,0 +1 @@ +pub type Quotes = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/content/string_set.rs b/crates/hdx_ast/src/css/values/content/string_set.rs new file mode 100644 index 00000000..ff4c62c9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/content/string_set.rs @@ -0,0 +1 @@ +pub type StringSet = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/counter_styles.rs b/crates/hdx_ast/src/css/values/counter_styles.rs deleted file mode 100644 index 349d3494..00000000 --- a/crates/hdx_ast/src/css/values/counter_styles.rs +++ /dev/null @@ -1,105 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::Image; -use crate::{atom, Atom, Atomizable, Box, Spanned, Vec}; - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum CounterStyle<'a> { - Named(Atom), - Symbols(Spanned>), - Predefined(PredefinedCounterStyle), -} - -// https://drafts.csswg.org/css-counter-styles-3/#predefined-counters -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum PredefinedCounterStyle { - Decimal, // atom!("decimal"), - DecimalLeadingZero, // atom!("decimal-leading-zero"), - ArabicIndic, // atom!("arabic-indic"), - Armenian, // atom!("armenian"), - UpperArmenian, // atom!("upper-armenian"), - LowerArmenian, // atom!("lower-armenian"), - Bengali, // atom!("bengali"), - Cambodian, // atom!("cambodian"), - Khmer, // atom!("khmer"), - CjkDecimal, // atom!("cjk-decimal"), - Devanagari, // atom!("devanagari"), - Georgian, // atom!("georgian"), - Gujarati, // atom!("gujarati"), - Gurmukhi, // atom!("gurmukhi"), - Hebrew, // atom!("hebrew"), - Kannada, // atom!("kannada"), - Lao, // atom!("lao"), - Malayalam, // atom!("malayalam"), - Mongolian, // atom!("mongolian"), - Myanmar, // atom!("myanmar"), - Oriya, // atom!("oriya"), - Persian, // atom!("persian"), - LowerRoman, // atom!("lower-roman"), - UpperRoman, // atom!("upper-roman"), - Tamil, // atom!("tamil"), - Telugu, // atom!("telugu"), - Thai, // atom!("thai"), - Tibetan, // atom!("tibetan"), - LowerAlpha, // atom!("lower-alpha"), - UpperAlpha, // atom!("upper-alpha"), - UpperLatin, // atom!("upper-latin"), - LowerGreek, // atom!("lower-greek"), - Hiragana, // atom!("hiragana"), - HiraganaIroha, // atom!("hiragana-iroha"), - Katakana, // atom!("katakana"), - KatakanaIroha, // atom!("katakana-iroha"), - #[default] - Disc, // atom!("disc"), - Square, // atom!("square"), - DisclousureOpen, // atom!("disclousure-open"), - DisclousureClosed, // atom!("disclousure-closed"), - CjkEarthlyBranch, // atom!("cjk-earthly-branch"), - CjkHeavenlyStem, // atom!("cjk-heavenly-stem"), -} - -// https://drafts.csswg.org/css-counter-styles-3/#funcdef-symbols -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Symbols<'a> { - kind: SymbolsType, - symbols: Box<'a, Vec<'a, Symbol<'a>>>, -} - -// https://drafts.csswg.org/css-counter-styles-3/#funcdef-symbols -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Symbol<'a> { - String(Atom), - Image(Box<'a, Image<'a>>), -} - -// https://drafts.csswg.org/css-counter-styles-3/#typedef-symbols-type -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum SymbolsType { - Cyclic, // atom!("cyclic") - Numeric, // atom!("numeric") - Alphabetic, // atom!("alphabetic") - #[default] - Symbolic, // atom!("symbolic") - Fixed, // atom!("fixed") -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/css2/mod.rs b/crates/hdx_ast/src/css/values/css2/mod.rs new file mode 100644 index 00000000..b7751349 --- /dev/null +++ b/crates/hdx_ast/src/css/values/css2/mod.rs @@ -0,0 +1,2 @@ +mod z_index; +pub use z_index::*; diff --git a/crates/hdx_ast/src/css/values/css2/z_index.rs b/crates/hdx_ast/src/css/values/css2/z_index.rs new file mode 100644 index 00000000..8407b6b6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/css2/z_index.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Parsable, Writable, css::values::units::CSSFloat}; + +#[derive(Parsable, Writable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] +pub enum ZIndex { + #[default] + Auto, + #[parsable(Number, Check::Int)] + Integer(CSSFloat), +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + } +} diff --git a/crates/hdx_ast/src/css/values/display.rs b/crates/hdx_ast/src/css/values/display.rs deleted file mode 100644 index 50611400..00000000 --- a/crates/hdx_ast/src/css/values/display.rs +++ /dev/null @@ -1,227 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable}; - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum DisplayValue { - None, // atom!("none") - Contents, // atom!("contents") - TableRowGroup, // atom!("table-row-group") - TableHeaderGroup, // atom!("table-header-group") - TableFooterGroup, // atom!("table-footer-group") - TableRow, // atom!("table-row") - TableCell, // atom!("table-cell") - TableColumnGroup, // atom!("table-column-group") - TableColumn, // atom!("table-column") - TableCaption, // atom!("table-caption") - RubyBase, // atom!("ruby-base") - RubyText, // atom!("ruby-text") - RubyBaseContainer, // atom!("ruby-base-container") - RubyTextContainer, // atom!("ruby-text-container") - // Legacy - InlineBlock, // atom!("inline-block") - InlineTable, // atom!("inline-flex") - InlineFlex, // atom!("inline-flex") - InlineGrid, // atom!("inline-flex") - Pair(DisplayOutside, DisplayInside), - PairAndMarker(DisplayOutside, DisplayInside, DisplayMarker), -} - -impl Default for DisplayValue { - fn default() -> Self { - Self::Pair(DisplayOutside::default(), DisplayInside::default()) - } -} - -// https://drafts.csswg.org/css-display-4/#propdef-display -impl DisplayValue { - pub fn from_atom(atom: Atom) -> Option { - match atom { - atom!("none") => Some(Self::None), - atom!("contents") => Some(Self::Contents), - atom!("table-row-group") => Some(Self::TableRowGroup), - atom!("table-header-group") => Some(Self::TableHeaderGroup), - atom!("table-footer-group") => Some(Self::TableFooterGroup), - atom!("table-row") => Some(Self::TableRow), - atom!("table-cell") => Some(Self::TableCell), - atom!("table-column-group") => Some(Self::TableColumnGroup), - atom!("table-column") => Some(Self::TableColumn), - atom!("table-caption") => Some(Self::TableCaption), - atom!("ruby-base") => Some(Self::RubyBase), - atom!("ruby-text") => Some(Self::RubyText), - atom!("ruby-base-container") => Some(Self::RubyBaseContainer), - atom!("ruby-text-container") => Some(Self::RubyTextContainer), - atom!("flow-root") => Some(Self::Pair(DisplayOutside::Block, DisplayInside::FlowRoot)), - atom!("list-item") => Some(Self::PairAndMarker( - DisplayOutside::Implicit, - DisplayInside::Implicit, - DisplayMarker::ListItem, - )), - // Legacy - atom!("inline-block") => Some(Self::InlineBlock), - atom!("inline-table") => Some(Self::InlineTable), - atom!("inline-flex") => Some(Self::InlineFlex), - atom!("inline-grid") => Some(Self::InlineGrid), - _ => { - if let Some(display) = DisplayInside::from_atom(atom.clone()) { - Some(Self::Pair(DisplayOutside::Implicit, display)) - } else if let Some(display) = DisplayOutside::from_atom(atom) { - Some(Self::Pair(display, DisplayInside::Implicit)) - } else { - None - } - } - } - } - - pub fn from_atom_pair(atom1: Atom, atom2: Atom) -> Option { - let outside = DisplayOutside::from_atom(atom1.clone()); - let inside = DisplayInside::from_atom(atom2.clone()); - match (outside, inside) { - (Some(o), Some(i)) => Some(DisplayValue::Pair(o, i)), - _ => { - let outside = DisplayOutside::from_atom(atom2); - let inside = DisplayInside::from_atom(atom1); - match (outside, inside) { - (Some(o), Some(i)) => Some(DisplayValue::Pair(o, i)), - _ => None, - } - } - } - } - - pub fn to_atom(&self) -> Option { - match self { - Self::None => Some(atom!("none")), - Self::Contents => Some(atom!("contents")), - Self::TableRowGroup => Some(atom!("table-row-group")), - Self::TableHeaderGroup => Some(atom!("table-header-group")), - Self::TableFooterGroup => Some(atom!("table-footer-group")), - Self::TableRow => Some(atom!("table-row")), - Self::TableCell => Some(atom!("table-cell")), - Self::TableColumnGroup => Some(atom!("table-column-group")), - Self::TableColumn => Some(atom!("table-column")), - Self::TableCaption => Some(atom!("table-caption")), - Self::RubyBase => Some(atom!("ruby-base")), - Self::RubyText => Some(atom!("ruby-text")), - Self::RubyBaseContainer => Some(atom!("ruby-base-container")), - Self::RubyTextContainer => Some(atom!("ruby-text-container")), - Self::InlineBlock => Some(atom!("inline-block")), - Self::InlineTable => Some(atom!("inline-table")), - Self::InlineFlex => Some(atom!("inline-flex")), - Self::InlineGrid => Some(atom!("inline-grid")), - Self::Pair(DisplayOutside::Implicit, i) => i.to_atom(), - Self::Pair(o, DisplayInside::Implicit) => o.to_atom(), - Self::Pair(_, _) => None, - Self::PairAndMarker(DisplayOutside::Implicit, DisplayInside::Implicit, m) => { - m.to_atom() - } - Self::PairAndMarker(_o, _i, _m) => None, - } - } -} - -// https://drafts.csswg.org/css-display-4/#typedef-display-outside -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum DisplayOutside { - Implicit, - Block, // atom!("block") - #[default] - Inline, // atom!("inline") - RunIn, // atom!("run-in") -} - -impl DisplayOutside { - pub fn from_atom(atom: Atom) -> Option { - match atom { - atom!("block") => Some(Self::Block), - atom!("inline") => Some(Self::Inline), - atom!("run-in") => Some(Self::RunIn), - _ => None, - } - } - - pub fn to_atom(&self) -> Option { - match self { - Self::Implicit => None, - Self::Block => Some(atom!("block")), - Self::Inline => Some(atom!("inline")), - Self::RunIn => Some(atom!("run-in")), - } - } -} - -// https://drafts.csswg.org/css-display-4/#typedef-display-inside -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum DisplayInside { - Implicit, - #[default] - Flow, // atom!("flow") - FlowRoot, // atom!("flow-root") - Table, // atom!("table") - Flex, // atom!("flex") - Grid, // atom!("grid") - Ruby, // atom!("ruby") -} - -impl DisplayInside { - pub fn from_atom(atom: Atom) -> Option { - match atom { - atom!("flow") => Some(Self::Flow), - atom!("flow-root") => Some(Self::FlowRoot), - atom!("table") => Some(Self::Table), - atom!("flex") => Some(Self::Flex), - atom!("grid") => Some(Self::Grid), - atom!("ruby") => Some(Self::Ruby), - _ => None, - } - } - - pub fn to_atom(&self) -> Option { - match self { - Self::Implicit => None, - Self::Flow => Some(atom!("flow")), - Self::FlowRoot => Some(atom!("flow-root")), - Self::Table => Some(atom!("table")), - Self::Flex => Some(atom!("flex")), - Self::Grid => Some(atom!("grid")), - Self::Ruby => Some(atom!("ruby")), - } - } -} - -// https://drafts.csswg.org/css-display-4/#typedef-display-listitem -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum DisplayMarker { - ListItem, // atom!("list-item") -} - -impl DisplayMarker { - pub fn from_atom(atom: Atom) -> Option { - match atom { - atom!("list-item") => Some(Self::ListItem), - _ => None, - } - } - - pub fn to_atom(&self) -> Option { - match self { - Self::ListItem => Some(atom!("list-item")), - } - } -} - -// https://drafts.csswg.org/css-display-4/#propdef-visibility -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum VisibilityValue { - #[default] - Visible, // atom!("visible") - Hidden, // atom!("hidden") - Collapse, // atom!("collapse") -} diff --git a/crates/hdx_ast/src/css/values/display/display.rs b/crates/hdx_ast/src/css/values/display/display.rs new file mode 100644 index 00000000..a51b443b --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/display.rs @@ -0,0 +1,326 @@ +use hdx_atom::{atom, Atom}; +use hdx_lexer::Token; +use hdx_parser::{diagnostics, unexpected_ident, Parse, Parser, Result as ParserResult, Spanned}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::bitmask; + +// https://drafts.csswg.org/css-display-4/#propdef-display +#[derive(Default)] +#[bitmask(u8)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum Display { + // The anatomy of the u8 for Display values is: + // + // |--------- First two bits are special flags + // | |------ Next two bits are Outside values + // | | |--- Next four bits are Inside/Internal values + // v v v + // 0b 00 00 0000 + // ^ ^ ^ + // | | |--- Inside: 0001 = Flow + // | | | 0010 = Flow-Root + // | | | 0011 = Flex + // | | | 0100 = Grid + // | | | 0101 = Ruby + // | | | 1000 = Table + // | | | + // | | |--- Internal: 0100 = ruby-base + // | | 0101 = ruby-text + // | | 0110 = ruby-base-container + // | | 0111 = ruby-text-container + // | | 1000 = table-row-group + // | | 1001 = table-header-group + // | | 1010 = table-footer-group + // | | 1011 = table-row + // | | 1100 = table-cell + // | | 1101 = table-column-group + // | | 1110 = table-column + // | | 1111 = table-caption + // | | + // | | + // | |------ Outside: 01 = Block + // | 10 = Inline + // | 11 = Run-in + // | + // |--------- Special: 00 = N/A + // 01 = list-item + // 10 = + // 11 = + // Special sentinel values also exist: + // + // 0b11_11_1111 -> Contents + // 0b00_00_0000 -> None + + // + InlineBlock = 0b1010_0010, // Legacy "inline flow-root" + InlineTable = 0b1010_1000, // Legacy "inline table" + InlineFlex = 0b1010_0011, // Legacy "inline flex" + InlineGrid = 0b1010_0100, // Legacy "inline grid" + // + None = 0b0000_0000, + Contents = 0b1111_1111, + // + TableRowGroup = 0b1100_1000, + TableHeaderGroup = 0b1100_1001, + TableFooterGroup = 0b1100_1010, + TableRow = 0b1100_1011, + TableCell = 0b1100_1100, + TableColumnGroup = 0b1100_1101, + TableColumn = 0b1100_1110, + TableCaption = 0b1100_1111, + RubyBase = 0b1100_0100, + RubyText = 0b1100_0101, + RubyBaseContainer = 0b1100_0110, + RubyTextContainer = 0b1100_0111, + // + ListItem = 0b0100_0000, + // + Block = 0b0001_0000, + #[default] + Inline = 0b0010_0000, + RunIn = 0b0011_0000, + // + Flow = 0b0000_0001, + FlowRoot = 0b0000_0010, + Flex = 0b0000_0011, + Grid = 0b0000_0100, + Ruby = 0b0000_0101, + Table = 0b0000_0110, +} + +impl Display { + #[inline] + fn outside_bits(&self) -> Self { + Self { bits: self.bits & 0b0011_0000 } + } + + #[inline] + fn inside_bits(&self) -> Self { + Self { bits: self.bits & 0b0000_1111 } + } + + #[inline] + fn has_inside(&self) -> bool { + self.bits & 0b0000_1111 > 0 && self.bits & 0b1000_0000 == 0 + } + + #[inline] + fn has_outside(&self) -> bool { + self.bits & 0b0011_0000 > 0 + } + + #[inline] + fn has_list_item(&self) -> bool { + self.bits & 0b1100_0000 == 0b0100_0000 + } + + #[inline] + fn valid_list_item(&self) -> bool { + self.bits & 0b0000_1100 == 0 && self.bits & 0b0000_0011 > 0 && self.bits & 0b0000_0011 != 0b0000_0011 + } + + #[inline] + fn is_legacy(&self) -> bool { + self.bits & 0b1100_0000 == 0b1000_0000 + } + + #[inline] + fn is_internal(&self) -> bool { + self.bits & 0b1100_0000 == 0b1100_0000 + } + + #[inline] + fn is_table(&self) -> bool { + self.bits & 0b1100_1000 == 0b1100_1000 || self.bits & 0b0000_1000 == 0b0000_1000 + } + + #[inline] + fn is_ruby(&self) -> bool { + self.bits & 0b1100_0100 == 0b1100_0100 || self.bits & 0b0000_0101 == 0b0000_0101 + } + + #[inline] + fn outside_to_atom(&self) -> Option { + match self.outside_bits() { + Display::RunIn => Some(atom!("run-in")), + Display::Block => Some(atom!("block")), + Display::Inline => Some(atom!("inline")), + _ => None, + } + } + + #[inline] + fn inside_to_atom(&self) -> Option { + match self.inside_bits() { + Display::Flow => Some(atom!("flow")), + Display::FlowRoot => Some(atom!("flow-root")), + Display::Flex => Some(atom!("flex")), + Display::Grid => Some(atom!("grid")), + Display::Ruby => Some(atom!("ruby")), + Display::Table => Some(atom!("table")), + _ => None, + } + } +} + +impl<'a> Parse<'a> for Display { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + // Certain values can only be used in a "standalone way" and so complete the + // value: + let single_value = match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + // + atom!("none") => Some(Display::None), + atom!("contents") => Some(Display::Contents), + // + atom!("inline-block") => Some(Display::InlineBlock), + atom!("inline-table") => Some(Display::InlineTable), + atom!("inline-flex") => Some(Display::InlineFlex), + atom!("inline-grid") => Some(Display::InlineGrid), + // + atom!("table-row-group") => Some(Display::TableRowGroup), + atom!("table-header-group") => Some(Display::TableHeaderGroup), + atom!("table-footer-group") => Some(Display::TableFooterGroup), + atom!("table-row") => Some(Display::TableRow), + atom!("table-cell") => Some(Display::TableCell), + atom!("table-column-group") => Some(Display::TableColumnGroup), + atom!("table-column") => Some(Display::TableColumn), + atom!("table-caption") => Some(Display::TableCaption), + atom!("ruby-base") => Some(Display::RubyBase), + atom!("ruby-text") => Some(Display::RubyText), + atom!("ruby-base-container") => Some(Display::RubyBaseContainer), + atom!("ruby-text-container") => Some(Display::RubyTextContainer), + _ => None, + }, + _ => None, + }; + if let Some(value) = single_value { + parser.advance(); + return Ok(value.spanned(span.end(parser.pos()))); + } + + // If a legacy/internal/box value is not applied then it must be a pair/triplet + let mut value = Display::None; + loop { + match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + // + atom!("block") if !value.has_outside() => value |= Display::Block, + atom!("inline") if !value.has_outside() => value |= Display::Inline, + atom!("run-in") if !value.has_outside() => value |= Display::RunIn, + // + atom!("flow") if !value.has_inside() => value |= Display::Flow, + atom!("flow-root") if !value.has_inside() => value |= Display::FlowRoot, + atom!("flex") if !value.has_inside() => value |= Display::Flex, + atom!("grid") if !value.has_inside() => value |= Display::Grid, + atom!("ruby") if !value.has_inside() => value |= Display::Ruby, + atom!("table") if !value.has_inside() => value |= Display::Table, + // + atom!("list-item") if !value.has_list_item() => value |= Display::ListItem, + + atom => unexpected_ident!(parser, atom), + }, + _ => break, + } + parser.advance(); + } + if value.has_list_item() && !value.valid_list_item() { + Err(diagnostics::DisplayHasInvalidListItemCombo(value.inside_to_atom().unwrap(), span.end(parser.pos())))?; + } + Ok(value.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for Display { + fn write_css(&self, sink: &mut W) -> WriterResult { + match self { + &Self::None => sink.write_str("none"), + &Self::Contents => sink.write_str("contents"), + &Self::InlineBlock if self.is_legacy() => sink.write_str("inline-block"), + &Self::InlineTable if self.is_legacy() => sink.write_str("inline-table"), + &Self::InlineFlex if self.is_legacy() => sink.write_str("inline-flex"), + &Self::InlineGrid if self.is_legacy() => sink.write_str("inline-grid"), + &Self::TableRowGroup if self.is_internal() => sink.write_str("table-row-group"), + &Self::TableHeaderGroup if self.is_internal() => sink.write_str("table-header-group"), + &Self::TableFooterGroup if self.is_internal() => sink.write_str("table-footer-group"), + &Self::TableRow if self.is_internal() => sink.write_str("table-row"), + &Self::TableCell if self.is_internal() => sink.write_str("table-cell"), + &Self::TableColumnGroup if self.is_internal() => sink.write_str("table-column-group"), + &Self::TableColumn if self.is_internal() => sink.write_str("table-column"), + &Self::TableCaption if self.is_internal() => sink.write_str("table-caption"), + &Self::RubyBase if self.is_internal() => sink.write_str("ruby-base"), + &Self::RubyText if self.is_internal() => sink.write_str("ruby-text"), + &Self::RubyBaseContainer if self.is_internal() => sink.write_str("ruby-base-container"), + &Self::RubyTextContainer if self.is_internal() => sink.write_str("ruby-text-container"), + + _ => { + if let Some(outside) = self.outside_to_atom() { + outside.write_css(sink)?; + if self.has_inside() || self.has_list_item() { + sink.write_char(' ')?; + } + } + if let Some(inside) = self.inside_to_atom() { + inside.write_css(sink)?; + if self.has_list_item() { + sink.write_char(' ')?; + } + } + if self.has_list_item() { + sink.write_str("list-item")?; + } + Ok(()) + } + } + } +} + +#[cfg(test)] +mod tests { + + use hdx_writer::{BaseCssWriter, WriteCss}; + use oxc_allocator::Allocator; + + use super::*; + use crate::test_helpers::test_write; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } + + #[test] + fn test_to_atoms() { + assert_eq!(Display::FlowRoot.inside_to_atom(), Some(atom!("flow-root"))); + assert_eq!(Display::Flex.inside_to_atom(), Some(atom!("flex"))); + assert_eq!((Display::Block | Display::Flex).inside_to_atom(), Some(atom!("flex"))); + assert_eq!((Display::RunIn | Display::Flow).inside_to_atom(), Some(atom!("flow"))); + } + + #[test] + fn test_variants() { + let allocator = Allocator::default(); + // Parsing a display value should be written identically + test_write::(&allocator, "none", "none"); + test_write::(&allocator, "contents", "contents"); + test_write::(&allocator, "block flow", "block flow"); + test_write::(&allocator, "block flow-root", "block flow-root"); + test_write::(&allocator, "inline flow", "inline flow"); + test_write::(&allocator, "inline flow-root", "inline flow-root"); + test_write::(&allocator, "run-in flow", "run-in flow"); + test_write::(&allocator, "block flow list-item", "block flow list-item"); + test_write::(&allocator, "inline flow list-item", "inline flow list-item"); + test_write::(&allocator, "block flex", "block flex"); + test_write::(&allocator, "inline flex", "inline flex"); + test_write::(&allocator, "block grid", "block grid"); + test_write::(&allocator, "inline grid", "inline grid"); + test_write::(&allocator, "inline ruby", "inline ruby"); + test_write::(&allocator, "block ruby", "block ruby"); + test_write::(&allocator, "block table", "block table"); + test_write::(&allocator, "inline table", "inline table"); + } +} diff --git a/crates/hdx_ast/src/css/values/display/layout_order.rs b/crates/hdx_ast/src/css/values/display/layout_order.rs new file mode 100644 index 00000000..201c619d --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/layout_order.rs @@ -0,0 +1 @@ +pub type LayoutOrder = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/display/mod.rs b/crates/hdx_ast/src/css/values/display/mod.rs new file mode 100644 index 00000000..e41dd1d2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/mod.rs @@ -0,0 +1,10 @@ +mod display; +mod layout_order; +mod order; +mod reading_order; +mod visibility; +pub use display::*; +pub use layout_order::*; +pub use order::*; +pub use reading_order::*; +pub use visibility::*; diff --git a/crates/hdx_ast/src/css/values/display/order.rs b/crates/hdx_ast/src/css/values/display/order.rs new file mode 100644 index 00000000..7ed34493 --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/order.rs @@ -0,0 +1 @@ +pub type Order = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/display/reading_order.rs b/crates/hdx_ast/src/css/values/display/reading_order.rs new file mode 100644 index 00000000..3126cce6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/reading_order.rs @@ -0,0 +1 @@ +pub type ReadingOrder = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/display/visibility.rs b/crates/hdx_ast/src/css/values/display/visibility.rs new file mode 100644 index 00000000..0a4e5508 --- /dev/null +++ b/crates/hdx_ast/src/css/values/display/visibility.rs @@ -0,0 +1 @@ +pub type Visibility = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/exclusions/mod.rs b/crates/hdx_ast/src/css/values/exclusions/mod.rs new file mode 100644 index 00000000..7140ae98 --- /dev/null +++ b/crates/hdx_ast/src/css/values/exclusions/mod.rs @@ -0,0 +1,4 @@ +mod wrap_flow; +mod wrap_through; +pub use wrap_flow::*; +pub use wrap_through::*; diff --git a/crates/hdx_ast/src/css/values/exclusions/wrap_flow.rs b/crates/hdx_ast/src/css/values/exclusions/wrap_flow.rs new file mode 100644 index 00000000..b364ec9c --- /dev/null +++ b/crates/hdx_ast/src/css/values/exclusions/wrap_flow.rs @@ -0,0 +1 @@ +pub type WrapFlow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/exclusions/wrap_through.rs b/crates/hdx_ast/src/css/values/exclusions/wrap_through.rs new file mode 100644 index 00000000..25950074 --- /dev/null +++ b/crates/hdx_ast/src/css/values/exclusions/wrap_through.rs @@ -0,0 +1 @@ +pub type WrapThrough = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/expr.rs b/crates/hdx_ast/src/css/values/expr.rs deleted file mode 100644 index 7316c95c..00000000 --- a/crates/hdx_ast/src/css/values/expr.rs +++ /dev/null @@ -1,220 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable, Box, Spanned, Vec}; - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Expr<'a, T> { - GlobalValue(GlobalValue), - Literal(Spanned), - Reference(Spanned>>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum MathExpr<'a, T> { - GlobalValue(GlobalValue), - Literal(Spanned), - Reference(Spanned>>), - Math(Spanned>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ExprList<'a, T> { - GlobalValue(GlobalValue), - Values(Vec<'a, Spanned>>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum MathExprList<'a, T> { - GlobalValue(GlobalValue), - Values(Vec<'a, Spanned>>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ExprListItem<'a, T> { - Literal(Spanned), - Reference(Spanned>>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum MathExprListItem<'a, T> { - Literal(Spanned), - Reference(Spanned>>), - Math(Spanned>), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Reference<'a, T> { - Var(Atom, Box<'a, Option>>), - Env(Atom, Box<'a, Option>>), -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum GlobalValue { - Inherit, // atom!("inherit") - Initial, // atom!("initial") - Unset, // atom!("unset") - Revert, // atom!("revert") - RevertLayer, // atom!("revert-layer") -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum MathFunc<'a> { - Calc(Box<'a, CalcSum<'a>>), - Min(Box<'a, Vec<'a, CalcSum<'a>>>), - Max(Box<'a, Vec<'a, CalcSum<'a>>>), - Clamp(Box<'a, (CalcSum<'a>, CalcSum<'a>, CalcSum<'a>)>), - Round(Box<'a, (RoundStrategy, CalcSum<'a>, CalcSum<'a>)>), - Mod(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Rem(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Sin(Box<'a, CalcSum<'a>>), - Cos(Box<'a, CalcSum<'a>>), - Tan(Box<'a, CalcSum<'a>>), - ASin(Box<'a, CalcSum<'a>>), - ACos(Box<'a, CalcSum<'a>>), - ATan(Box<'a, CalcSum<'a>>), - ATan2(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Pow(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Sqrt(Box<'a, CalcSum<'a>>), - Hypot(Box<'a, Vec<'a, CalcSum<'a>>>), - Log(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Exp(Box<'a, CalcSum<'a>>), - Abs(Box<'a, CalcSum<'a>>), - Sign(Box<'a, CalcSum<'a>>), -} - -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum CalcSum<'a> { - Number(f32), - Dimension(f32, Atom), - Percentage(f32), - E, - Pi, - Infinity, - NegInfinity, - NaN, - Div(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Mul(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Add(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), - Sub(Box<'a, (CalcSum<'a>, CalcSum<'a>)>), -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum RoundStrategy { - Nearest, // atom!("nearest") - Up, // atom!("up") - Down, // atom!("down") - ToZero, // atom!("to-zero") -} - -impl<'a, T> Default for Expr<'a, T> -where - T: Default, -{ - fn default() -> Self { - Self::Literal(Spanned::dummy(T::default())) - } -} - -impl<'a, T> Default for MathExpr<'a, T> -where - T: Default, -{ - fn default() -> Self { - Self::Literal(Spanned::dummy(T::default())) - } -} - -impl<'a, T> Default for ExprList<'a, T> -where - T: Default, -{ - fn default() -> Self { - Self::GlobalValue(GlobalValue::Initial) - } -} - -impl<'a, T> Default for MathExprList<'a, T> -where - T: Default, -{ - fn default() -> Self { - Self::GlobalValue(GlobalValue::Initial) - } -} -impl Hash for CalcSum<'_> { - fn hash(&self, state: &mut H) { - match self { - CalcSum::Number(n) => { - state.write_u8(0); - n.to_bits().hash(state); - } - CalcSum::Dimension(n, u) => { - state.write_u8(1); - n.to_bits().hash(state); - u.hash(state); - } - CalcSum::Percentage(n) => { - state.write_u8(2); - n.to_bits().hash(state); - } - CalcSum::E => state.write_u8(3), - CalcSum::Pi => state.write_u8(4), - CalcSum::Infinity => state.write_u8(5), - CalcSum::NegInfinity => state.write_u8(6), - CalcSum::NaN => state.write_u8(7), - CalcSum::Div(a) => { - state.write_u8(8); - a.hash(state); - } - CalcSum::Mul(a) => { - state.write_u8(9); - a.hash(state); - } - CalcSum::Add(a) => { - state.write_u8(10); - a.hash(state); - } - CalcSum::Sub(a) => { - state.write_u8(11); - a.hash(state); - } - } - } -} - -#[cfg(test)] -mod tests { - - use super::super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 32); - assert_eq!(size_of::>(), 24); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill.rs new file mode 100644 index 00000000..c0fa733c --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill.rs @@ -0,0 +1 @@ +pub type Fill = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_break.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_break.rs new file mode 100644 index 00000000..56876194 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_break.rs @@ -0,0 +1 @@ +pub type FillBreak = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_color.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_color.rs new file mode 100644 index 00000000..2c52ae55 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_color.rs @@ -0,0 +1 @@ +pub type FillColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_image.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_image.rs new file mode 100644 index 00000000..b2f06be0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_image.rs @@ -0,0 +1 @@ +pub type FillImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_opacity.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_opacity.rs new file mode 100644 index 00000000..5103fca9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_opacity.rs @@ -0,0 +1 @@ +pub type FillOpacity = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_origin.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_origin.rs new file mode 100644 index 00000000..51853510 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_origin.rs @@ -0,0 +1 @@ +pub type FillOrigin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_position.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_position.rs new file mode 100644 index 00000000..c7fac579 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_position.rs @@ -0,0 +1 @@ +pub type FillPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_repeat.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_repeat.rs new file mode 100644 index 00000000..9a9f83c7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_repeat.rs @@ -0,0 +1 @@ +pub type FillRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_rule.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_rule.rs new file mode 100644 index 00000000..5247c24f --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_rule.rs @@ -0,0 +1 @@ +pub type FillRule = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/fill_size.rs b/crates/hdx_ast/src/css/values/fill_stroke/fill_size.rs new file mode 100644 index 00000000..e6e38e8f --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/fill_size.rs @@ -0,0 +1 @@ +pub type FillSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/mod.rs b/crates/hdx_ast/src/css/values/fill_stroke/mod.rs new file mode 100644 index 00000000..01498c20 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/mod.rs @@ -0,0 +1,57 @@ +mod fill; +mod fill_break; +mod fill_color; +mod fill_image; +mod fill_opacity; +mod fill_origin; +mod fill_position; +mod fill_repeat; +mod fill_rule; +mod fill_size; +mod stroke; +mod stroke_align; +mod stroke_break; +mod stroke_color; +mod stroke_dash_corner; +mod stroke_dash_justify; +mod stroke_dasharray; +mod stroke_dashoffset; +mod stroke_image; +mod stroke_linecap; +mod stroke_linejoin; +mod stroke_miterlimit; +mod stroke_opacity; +mod stroke_origin; +mod stroke_position; +mod stroke_repeat; +mod stroke_size; +mod stroke_width; + +pub use fill::*; +pub use fill_break::*; +pub use fill_color::*; +pub use fill_image::*; +pub use fill_opacity::*; +pub use fill_origin::*; +pub use fill_position::*; +pub use fill_repeat::*; +pub use fill_rule::*; +pub use fill_size::*; +pub use stroke::*; +pub use stroke_align::*; +pub use stroke_break::*; +pub use stroke_color::*; +pub use stroke_dash_corner::*; +pub use stroke_dash_justify::*; +pub use stroke_dasharray::*; +pub use stroke_dashoffset::*; +pub use stroke_image::*; +pub use stroke_linecap::*; +pub use stroke_linejoin::*; +pub use stroke_miterlimit::*; +pub use stroke_opacity::*; +pub use stroke_origin::*; +pub use stroke_position::*; +pub use stroke_repeat::*; +pub use stroke_size::*; +pub use stroke_width::*; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke.rs new file mode 100644 index 00000000..b0e9c1af --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke.rs @@ -0,0 +1 @@ +pub type Stroke = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_align.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_align.rs new file mode 100644 index 00000000..664f1f5d --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_align.rs @@ -0,0 +1 @@ +pub type StrokeAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_break.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_break.rs new file mode 100644 index 00000000..82215fdf --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_break.rs @@ -0,0 +1 @@ +pub type StrokeBreak = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_color.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_color.rs new file mode 100644 index 00000000..a70f21d1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_color.rs @@ -0,0 +1 @@ +pub type StrokeColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_corner.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_corner.rs new file mode 100644 index 00000000..8e653787 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_corner.rs @@ -0,0 +1 @@ +pub type StrokeDashCorner = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_justify.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_justify.rs new file mode 100644 index 00000000..ef08b1d4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dash_justify.rs @@ -0,0 +1 @@ +pub type StrokeDashJustify = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_dasharray.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dasharray.rs new file mode 100644 index 00000000..d9e36ad6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dasharray.rs @@ -0,0 +1 @@ +pub type StrokeDasharray = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_dashoffset.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dashoffset.rs new file mode 100644 index 00000000..c6dc57ec --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_dashoffset.rs @@ -0,0 +1 @@ +pub type StrokeDashoffset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_image.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_image.rs new file mode 100644 index 00000000..e8471be7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_image.rs @@ -0,0 +1 @@ +pub type StrokeImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_linecap.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_linecap.rs new file mode 100644 index 00000000..4051dc8b --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_linecap.rs @@ -0,0 +1 @@ +pub type StrokeLinecap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_linejoin.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_linejoin.rs new file mode 100644 index 00000000..7f775a87 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_linejoin.rs @@ -0,0 +1 @@ +pub type StrokeLinejoin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_miterlimit.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_miterlimit.rs new file mode 100644 index 00000000..cd1e3195 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_miterlimit.rs @@ -0,0 +1 @@ +pub type StrokeMiterlimit = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_opacity.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_opacity.rs new file mode 100644 index 00000000..d02489cd --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_opacity.rs @@ -0,0 +1 @@ +pub type StrokeOpacity = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_origin.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_origin.rs new file mode 100644 index 00000000..e8722ca9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_origin.rs @@ -0,0 +1 @@ +pub type StrokeOrigin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_position.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_position.rs new file mode 100644 index 00000000..a7df1be9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_position.rs @@ -0,0 +1 @@ +pub type StrokePosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_repeat.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_repeat.rs new file mode 100644 index 00000000..a75aacb9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_repeat.rs @@ -0,0 +1 @@ +pub type StrokeRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_size.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_size.rs new file mode 100644 index 00000000..bad1893b --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_size.rs @@ -0,0 +1 @@ +pub type StrokeSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fill_stroke/stroke_width.rs b/crates/hdx_ast/src/css/values/fill_stroke/stroke_width.rs new file mode 100644 index 00000000..d06384fa --- /dev/null +++ b/crates/hdx_ast/src/css/values/fill_stroke/stroke_width.rs @@ -0,0 +1 @@ +pub type StrokeWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/backdrop_filter.rs b/crates/hdx_ast/src/css/values/filter_effects/backdrop_filter.rs new file mode 100644 index 00000000..bf5f705c --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/backdrop_filter.rs @@ -0,0 +1 @@ +pub type BackdropFilter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/color_interpolation_filters.rs b/crates/hdx_ast/src/css/values/filter_effects/color_interpolation_filters.rs new file mode 100644 index 00000000..8fa4c540 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/color_interpolation_filters.rs @@ -0,0 +1 @@ +pub type ColorInterpolationFilters = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/filter.rs b/crates/hdx_ast/src/css/values/filter_effects/filter.rs new file mode 100644 index 00000000..b2f3c074 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/filter.rs @@ -0,0 +1 @@ +pub type Filter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/flood_color.rs b/crates/hdx_ast/src/css/values/filter_effects/flood_color.rs new file mode 100644 index 00000000..626ebbd5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/flood_color.rs @@ -0,0 +1 @@ +pub type FloodColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/flood_opacity.rs b/crates/hdx_ast/src/css/values/filter_effects/flood_opacity.rs new file mode 100644 index 00000000..1677d664 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/flood_opacity.rs @@ -0,0 +1 @@ +pub type FloodOpacity = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/lighting_color.rs b/crates/hdx_ast/src/css/values/filter_effects/lighting_color.rs new file mode 100644 index 00000000..ec9562e8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/lighting_color.rs @@ -0,0 +1 @@ +pub type LightingColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/filter_effects/mod.rs b/crates/hdx_ast/src/css/values/filter_effects/mod.rs new file mode 100644 index 00000000..72e76779 --- /dev/null +++ b/crates/hdx_ast/src/css/values/filter_effects/mod.rs @@ -0,0 +1,13 @@ +mod backdrop_filter; +mod color_interpolation_filters; +mod filter; +mod flood_color; +mod flood_opacity; +mod lighting_color; + +pub use backdrop_filter::*; +pub use color_interpolation_filters::*; +pub use filter::*; +pub use flood_color::*; +pub use flood_opacity::*; +pub use lighting_color::*; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex.rs b/crates/hdx_ast/src/css/values/flexbox/flex.rs new file mode 100644 index 00000000..9de6dcbf --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex.rs @@ -0,0 +1 @@ +pub type Flex = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_basis.rs b/crates/hdx_ast/src/css/values/flexbox/flex_basis.rs new file mode 100644 index 00000000..91c5b05f --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_basis.rs @@ -0,0 +1 @@ +pub type FlexBasis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_direction.rs b/crates/hdx_ast/src/css/values/flexbox/flex_direction.rs new file mode 100644 index 00000000..f6e68ecf --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_direction.rs @@ -0,0 +1 @@ +pub type FlexDirection = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_flow.rs b/crates/hdx_ast/src/css/values/flexbox/flex_flow.rs new file mode 100644 index 00000000..b7735216 --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_flow.rs @@ -0,0 +1 @@ +pub type FlexFlow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_grow.rs b/crates/hdx_ast/src/css/values/flexbox/flex_grow.rs new file mode 100644 index 00000000..8d0d4bff --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_grow.rs @@ -0,0 +1 @@ +pub type FlexGrow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_shrink.rs b/crates/hdx_ast/src/css/values/flexbox/flex_shrink.rs new file mode 100644 index 00000000..6b786a39 --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_shrink.rs @@ -0,0 +1 @@ +pub type FlexShrink = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/flex_wrap.rs b/crates/hdx_ast/src/css/values/flexbox/flex_wrap.rs new file mode 100644 index 00000000..4b3a6809 --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/flex_wrap.rs @@ -0,0 +1 @@ +pub type FlexWrap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/flexbox/mod.rs b/crates/hdx_ast/src/css/values/flexbox/mod.rs new file mode 100644 index 00000000..9f32fdaa --- /dev/null +++ b/crates/hdx_ast/src/css/values/flexbox/mod.rs @@ -0,0 +1,14 @@ +mod flex; +mod flex_basis; +mod flex_direction; +mod flex_flow; +mod flex_grow; +mod flex_shrink; +mod flex_wrap; +pub use flex::*; +pub use flex_basis::*; +pub use flex_direction::*; +pub use flex_flow::*; +pub use flex_grow::*; +pub use flex_shrink::*; +pub use flex_wrap::*; diff --git a/crates/hdx_ast/src/css/values/fonts.rs b/crates/hdx_ast/src/css/values/fonts.rs deleted file mode 100644 index 202f010d..00000000 --- a/crates/hdx_ast/src/css/values/fonts.rs +++ /dev/null @@ -1,87 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Angle, MathExpr, PositiveLengthPercentage}; -use crate::{atom, Atom, Atomizable, Spanned}; - -// https://drafts.csswg.org/css2/#value-def-absolute-size -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum AbsoluteSize { - XxSmall, // atom!("xx-small") - XSmall, // atom!("x-small") - Small, // atom!("small") - #[default] - Medium, // atom!("medium") - Large, // atom!("large") - XLarge, // atom!("x-large") - XxLarge, // atom!("xx-large") -} - -// https://drafts.csswg.org/css2/#value-def-relative-size -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum RelativeSize { - Larger, // atom!("larger") - Smaller, // atom!("smaller") -} - -// https://drafts.csswg.org/css-fonts/#font-weight-prop -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FontWeightValue { - #[default] - Normal, - Bold, - Bolder, - Lighter, - Number(u16), -} - -// https://drafts.csswg.org/css-fonts-4/#propdef-font-size -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FontSizeValue { - Absolute(AbsoluteSize), - Relative(RelativeSize), - LengthPercentage(Spanned), - Math, -} - -impl Default for FontSizeValue { - fn default() -> Self { - Self::Absolute(AbsoluteSize::Medium) - } -} - -// https://drafts.csswg.org/css-fonts-4/#propdef-font-size -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FontFamilyValue { - Named(Atom), - // https://drafts.csswg.org/css-fonts-4/#generic-font-families - #[default] - Serif, - SansSerif, - Cursive, - Fantasy, - Monospace, - SystemUi, - Emoji, - Math, - Fangsong, - UiSerif, - UiSansSerif, - UiMonospace, - UiRounded, -} - -// https://drafts.csswg.org/css-fonts/#propdef-font-style -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FontStyleValue<'a> { - #[default] - Normal, - Italic, - Oblique(Spanned>), -} diff --git a/crates/hdx_ast/src/css/values/fonts/font.rs b/crates/hdx_ast/src/css/values/fonts/font.rs new file mode 100644 index 00000000..0e06f387 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font.rs @@ -0,0 +1 @@ +pub type Font = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_family.rs b/crates/hdx_ast/src/css/values/fonts/font_family.rs new file mode 100644 index 00000000..05370f82 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_family.rs @@ -0,0 +1 @@ +pub type FontFamily = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_feature_settings.rs b/crates/hdx_ast/src/css/values/fonts/font_feature_settings.rs new file mode 100644 index 00000000..de15a083 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_feature_settings.rs @@ -0,0 +1 @@ +pub type FontFeatureSettings = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_kerning.rs b/crates/hdx_ast/src/css/values/fonts/font_kerning.rs new file mode 100644 index 00000000..22033370 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_kerning.rs @@ -0,0 +1 @@ +pub type FontKerning = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_language_override.rs b/crates/hdx_ast/src/css/values/fonts/font_language_override.rs new file mode 100644 index 00000000..6a54aa7e --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_language_override.rs @@ -0,0 +1 @@ +pub type FontLanguageOverride = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_optical_sizing.rs b/crates/hdx_ast/src/css/values/fonts/font_optical_sizing.rs new file mode 100644 index 00000000..03b6beab --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_optical_sizing.rs @@ -0,0 +1 @@ +pub type FontOpticalSizing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_palette.rs b/crates/hdx_ast/src/css/values/fonts/font_palette.rs new file mode 100644 index 00000000..20a34e84 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_palette.rs @@ -0,0 +1 @@ +pub type FontPalette = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_size.rs b/crates/hdx_ast/src/css/values/fonts/font_size.rs new file mode 100644 index 00000000..784d5a3d --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_size.rs @@ -0,0 +1 @@ +pub type FontSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_size_adjust.rs b/crates/hdx_ast/src/css/values/fonts/font_size_adjust.rs new file mode 100644 index 00000000..b9e9ea57 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_size_adjust.rs @@ -0,0 +1 @@ +pub type FontSizeAdjust = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_stretch.rs b/crates/hdx_ast/src/css/values/fonts/font_stretch.rs new file mode 100644 index 00000000..ea8ca47c --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_stretch.rs @@ -0,0 +1 @@ +pub type FontStretch = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_style.rs b/crates/hdx_ast/src/css/values/fonts/font_style.rs new file mode 100644 index 00000000..bfa8b929 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_style.rs @@ -0,0 +1 @@ +pub type FontStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_synthesis.rs b/crates/hdx_ast/src/css/values/fonts/font_synthesis.rs new file mode 100644 index 00000000..3855c519 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_synthesis.rs @@ -0,0 +1 @@ +pub type FontSynthesis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_synthesis_small_caps.rs b/crates/hdx_ast/src/css/values/fonts/font_synthesis_small_caps.rs new file mode 100644 index 00000000..78f37fea --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_synthesis_small_caps.rs @@ -0,0 +1 @@ +pub type FontSynthesisSmallCaps = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_synthesis_style.rs b/crates/hdx_ast/src/css/values/fonts/font_synthesis_style.rs new file mode 100644 index 00000000..dd92737d --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_synthesis_style.rs @@ -0,0 +1 @@ +pub type FontSynthesisStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_synthesis_weight.rs b/crates/hdx_ast/src/css/values/fonts/font_synthesis_weight.rs new file mode 100644 index 00000000..f5528a6b --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_synthesis_weight.rs @@ -0,0 +1 @@ +pub type FontSynthesisWeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant.rs b/crates/hdx_ast/src/css/values/fonts/font_variant.rs new file mode 100644 index 00000000..fdda6ea6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant.rs @@ -0,0 +1 @@ +pub type FontVariant = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_alternates.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_alternates.rs new file mode 100644 index 00000000..0573112a --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_alternates.rs @@ -0,0 +1 @@ +pub type FontVariantAlternates = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_caps.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_caps.rs new file mode 100644 index 00000000..21a050eb --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_caps.rs @@ -0,0 +1 @@ +pub type FontVariantCaps = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_east_asian.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_east_asian.rs new file mode 100644 index 00000000..66435f4c --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_east_asian.rs @@ -0,0 +1 @@ +pub type FontVariantEastAsian = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_emoji.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_emoji.rs new file mode 100644 index 00000000..e41828c4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_emoji.rs @@ -0,0 +1 @@ +pub type FontVariantEmoji = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_ligatures.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_ligatures.rs new file mode 100644 index 00000000..bd910184 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_ligatures.rs @@ -0,0 +1 @@ +pub type FontVariantLigatures = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_numeric.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_numeric.rs new file mode 100644 index 00000000..6d647edb --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_numeric.rs @@ -0,0 +1 @@ +pub type FontVariantNumeric = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variant_position.rs b/crates/hdx_ast/src/css/values/fonts/font_variant_position.rs new file mode 100644 index 00000000..bc481688 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variant_position.rs @@ -0,0 +1 @@ +pub type FontVariantPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_variation_settings.rs b/crates/hdx_ast/src/css/values/fonts/font_variation_settings.rs new file mode 100644 index 00000000..1830eb9e --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_variation_settings.rs @@ -0,0 +1 @@ +pub type FontVariationSettings = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/font_weight.rs b/crates/hdx_ast/src/css/values/fonts/font_weight.rs new file mode 100644 index 00000000..466d0b6b --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/font_weight.rs @@ -0,0 +1 @@ +pub type FontWeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/fonts/mod.rs b/crates/hdx_ast/src/css/values/fonts/mod.rs new file mode 100644 index 00000000..33687a57 --- /dev/null +++ b/crates/hdx_ast/src/css/values/fonts/mod.rs @@ -0,0 +1,50 @@ +mod font; +mod font_family; +mod font_feature_settings; +mod font_kerning; +mod font_language_override; +mod font_optical_sizing; +mod font_palette; +mod font_size; +mod font_size_adjust; +mod font_stretch; +mod font_style; +mod font_synthesis; +mod font_synthesis_small_caps; +mod font_synthesis_style; +mod font_synthesis_weight; +mod font_variant; +mod font_variant_alternates; +mod font_variant_caps; +mod font_variant_east_asian; +mod font_variant_emoji; +mod font_variant_ligatures; +mod font_variant_numeric; +mod font_variant_position; +mod font_variation_settings; +mod font_weight; +pub use font::*; +pub use font_family::*; +pub use font_feature_settings::*; +pub use font_kerning::*; +pub use font_language_override::*; +pub use font_optical_sizing::*; +pub use font_palette::*; +pub use font_size::*; +pub use font_size_adjust::*; +pub use font_stretch::*; +pub use font_style::*; +pub use font_synthesis::*; +pub use font_synthesis_small_caps::*; +pub use font_synthesis_style::*; +pub use font_synthesis_weight::*; +pub use font_variant::*; +pub use font_variant_alternates::*; +pub use font_variant_caps::*; +pub use font_variant_east_asian::*; +pub use font_variant_emoji::*; +pub use font_variant_ligatures::*; +pub use font_variant_numeric::*; +pub use font_variant_position::*; +pub use font_variation_settings::*; +pub use font_weight::*; diff --git a/crates/hdx_ast/src/css/values/frequency.rs b/crates/hdx_ast/src/css/values/frequency.rs deleted file mode 100644 index f402f7e6..00000000 --- a/crates/hdx_ast/src/css/values/frequency.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable}; - -// https://drafts.csswg.org/css-values/#frequency-value -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Frequency { - value: f32, - unit: FrequencyUnit, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum FrequencyUnit { - #[default] - Hertz, - KiloHertz, -} - -impl Atomizable for FrequencyUnit { - fn to_atom(&self) -> Atom { - match self { - Self::Hertz => atom!("hz"), - Self::KiloHertz => atom!("khz"), - } - } - - fn from_atom(unit: Atom) -> Option { - match unit { - atom!("hz") => Some(Self::Hertz), - atom!("khz") => Some(Self::KiloHertz), - _ => None, - } - } -} - -impl Hash for Frequency { - fn hash(&self, state: &mut H) { - self.value.to_bits().hash(state); - self.unit.hash(state); - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 8); - } -} diff --git a/crates/hdx_ast/src/css/values/gcpm/copy_into.rs b/crates/hdx_ast/src/css/values/gcpm/copy_into.rs new file mode 100644 index 00000000..a7c2b60a --- /dev/null +++ b/crates/hdx_ast/src/css/values/gcpm/copy_into.rs @@ -0,0 +1 @@ +pub type CopyInto = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/gcpm/footnote_display.rs b/crates/hdx_ast/src/css/values/gcpm/footnote_display.rs new file mode 100644 index 00000000..23606aff --- /dev/null +++ b/crates/hdx_ast/src/css/values/gcpm/footnote_display.rs @@ -0,0 +1 @@ +pub type FootnoteDisplay = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/gcpm/footnote_policy.rs b/crates/hdx_ast/src/css/values/gcpm/footnote_policy.rs new file mode 100644 index 00000000..f2a46a94 --- /dev/null +++ b/crates/hdx_ast/src/css/values/gcpm/footnote_policy.rs @@ -0,0 +1 @@ +pub type FootnotePolicy = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/gcpm/mod.rs b/crates/hdx_ast/src/css/values/gcpm/mod.rs new file mode 100644 index 00000000..d3d6e160 --- /dev/null +++ b/crates/hdx_ast/src/css/values/gcpm/mod.rs @@ -0,0 +1,8 @@ +mod copy_into; +mod footnote_display; +mod footnote_policy; +mod running; +pub use copy_into::*; +pub use footnote_display::*; +pub use footnote_policy::*; +pub use running::*; diff --git a/crates/hdx_ast/src/css/values/gcpm/running.rs b/crates/hdx_ast/src/css/values/gcpm/running.rs new file mode 100644 index 00000000..574a9457 --- /dev/null +++ b/crates/hdx_ast/src/css/values/gcpm/running.rs @@ -0,0 +1 @@ +pub type Running = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/align_tracks.rs b/crates/hdx_ast/src/css/values/grid/align_tracks.rs new file mode 100644 index 00000000..707f6638 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/align_tracks.rs @@ -0,0 +1 @@ +pub type AlignTracks = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid.rs b/crates/hdx_ast/src/css/values/grid/grid.rs new file mode 100644 index 00000000..b2bddb1f --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid.rs @@ -0,0 +1 @@ +pub type Grid = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_area.rs b/crates/hdx_ast/src/css/values/grid/grid_area.rs new file mode 100644 index 00000000..9804312b --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_area.rs @@ -0,0 +1 @@ +pub type GridArea = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_auto_columns.rs b/crates/hdx_ast/src/css/values/grid/grid_auto_columns.rs new file mode 100644 index 00000000..211bf91f --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_auto_columns.rs @@ -0,0 +1 @@ +pub type GridAutoColumns = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_auto_flow.rs b/crates/hdx_ast/src/css/values/grid/grid_auto_flow.rs new file mode 100644 index 00000000..08eec58a --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_auto_flow.rs @@ -0,0 +1 @@ +pub type GridAutoFlow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_auto_rows.rs b/crates/hdx_ast/src/css/values/grid/grid_auto_rows.rs new file mode 100644 index 00000000..712f6e57 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_auto_rows.rs @@ -0,0 +1 @@ +pub type GridAutoRows = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_column.rs b/crates/hdx_ast/src/css/values/grid/grid_column.rs new file mode 100644 index 00000000..5f62263b --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_column.rs @@ -0,0 +1 @@ +pub type GridColumn = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_column_end.rs b/crates/hdx_ast/src/css/values/grid/grid_column_end.rs new file mode 100644 index 00000000..24458e7a --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_column_end.rs @@ -0,0 +1 @@ +pub type GridColumnEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_column_start.rs b/crates/hdx_ast/src/css/values/grid/grid_column_start.rs new file mode 100644 index 00000000..f2e60e63 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_column_start.rs @@ -0,0 +1 @@ +pub type GridColumnStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_row.rs b/crates/hdx_ast/src/css/values/grid/grid_row.rs new file mode 100644 index 00000000..fc419efc --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_row.rs @@ -0,0 +1 @@ +pub type GridRow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_row_end.rs b/crates/hdx_ast/src/css/values/grid/grid_row_end.rs new file mode 100644 index 00000000..88227ff8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_row_end.rs @@ -0,0 +1 @@ +pub type GridRowEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_row_start.rs b/crates/hdx_ast/src/css/values/grid/grid_row_start.rs new file mode 100644 index 00000000..31baf689 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_row_start.rs @@ -0,0 +1 @@ +pub type GridRowStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_template.rs b/crates/hdx_ast/src/css/values/grid/grid_template.rs new file mode 100644 index 00000000..c56adcf0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_template.rs @@ -0,0 +1 @@ +pub type GridTemplate = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_template_areas.rs b/crates/hdx_ast/src/css/values/grid/grid_template_areas.rs new file mode 100644 index 00000000..dc75eb10 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_template_areas.rs @@ -0,0 +1 @@ +pub type GridTemplateAreas = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_template_columns.rs b/crates/hdx_ast/src/css/values/grid/grid_template_columns.rs new file mode 100644 index 00000000..d342b3bd --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_template_columns.rs @@ -0,0 +1 @@ +pub type GridTemplateColumns = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/grid_template_rows.rs b/crates/hdx_ast/src/css/values/grid/grid_template_rows.rs new file mode 100644 index 00000000..fec251cf --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/grid_template_rows.rs @@ -0,0 +1 @@ +pub type GridTemplateRows = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/justify_tracks.rs b/crates/hdx_ast/src/css/values/grid/justify_tracks.rs new file mode 100644 index 00000000..4860ab8d --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/justify_tracks.rs @@ -0,0 +1 @@ +pub type JustifyTracks = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/masonry_auto_flow.rs b/crates/hdx_ast/src/css/values/grid/masonry_auto_flow.rs new file mode 100644 index 00000000..d1eec8ec --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/masonry_auto_flow.rs @@ -0,0 +1 @@ +pub type MasonryAutoFlow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/grid/mod.rs b/crates/hdx_ast/src/css/values/grid/mod.rs new file mode 100644 index 00000000..0be08ec7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/grid/mod.rs @@ -0,0 +1,36 @@ +mod align_tracks; +mod grid; +mod grid_area; +mod grid_auto_columns; +mod grid_auto_flow; +mod grid_auto_rows; +mod grid_column; +mod grid_column_end; +mod grid_column_start; +mod grid_row; +mod grid_row_end; +mod grid_row_start; +mod grid_template; +mod grid_template_areas; +mod grid_template_columns; +mod grid_template_rows; +mod justify_tracks; +mod masonry_auto_flow; +pub use align_tracks::*; +pub use grid::*; +pub use grid_area::*; +pub use grid_auto_columns::*; +pub use grid_auto_flow::*; +pub use grid_auto_rows::*; +pub use grid_column::*; +pub use grid_column_end::*; +pub use grid_column_start::*; +pub use grid_row::*; +pub use grid_row_end::*; +pub use grid_row_start::*; +pub use grid_template::*; +pub use grid_template_areas::*; +pub use grid_template_columns::*; +pub use grid_template_rows::*; +pub use justify_tracks::*; +pub use masonry_auto_flow::*; diff --git a/crates/hdx_ast/src/css/values/images.rs b/crates/hdx_ast/src/css/values/images.rs deleted file mode 100644 index 15990f20..00000000 --- a/crates/hdx_ast/src/css/values/images.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{ColorValue, Length, LengthPercentage}; -use crate::{atom, Atom, Atomizable, Box}; - -// https://drafts.csswg.org/css2/#value-def-absolute-size -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Image<'a> { - Url(Atom), - Gradient(Box<'a, Gradient<'a>>), -} - -// https://drafts.csswg.org/css-images-3/#typedef-gradient -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Gradient<'a> { - LinearGradient(LinearGradientDirection, Vec>), - RepeatingLinearGradient(LinearGradientDirection, Vec>), - RadialGradient(RadialGradientSize, RadialGradientEndingShape, Vec>), - RepeatingRadialGradient( - RadialGradientSize, - RadialGradientEndingShape, - Vec>, - ), -} - -// https://drafts.csswg.org/css-images-3/#typedef-rg-size -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum RadialGradientSize { - #[default] - ClosestCorner, - ClosestSide, - FarthestCorner, - FarthestSide, - Length(Length), - LengthPercentage(LengthPercentage), -} - -// https://drafts.csswg.org/css-images-3/#typedef-rg-ending-shape -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum RadialGradientEndingShape { - #[default] - Circle, // atom!("circle") - Ellipse, // atom!("ellipse") -} - -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum LinearGradientDirection { - Angle(f32), - ToLeft, - ToRight, - ToTop, - ToBottom, -} - -impl Hash for LinearGradientDirection { - fn hash(&self, state: &mut H) { - match self { - Self::Angle(f) => { - 0.hash(state); - f.to_bits().hash(state); - } - Self::ToLeft => 1.hash(state), - Self::ToRight => 2.hash(state), - Self::ToTop => 3.hash(state), - Self::ToBottom => 4.hash(state), - } - } -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ColorStopOrHint<'a> { - ColorStop(Box<'a, ColorValue<'a>>, Option), - ColorHint(LengthPercentage), -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 40); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 12); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 16); - } -} diff --git a/crates/hdx_ast/src/css/values/images/image_orientation.rs b/crates/hdx_ast/src/css/values/images/image_orientation.rs new file mode 100644 index 00000000..e6b1ce7b --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/image_orientation.rs @@ -0,0 +1 @@ +pub type ImageOrientation = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/images/image_rendering.rs b/crates/hdx_ast/src/css/values/images/image_rendering.rs new file mode 100644 index 00000000..656213e4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/image_rendering.rs @@ -0,0 +1 @@ +pub type ImageRendering = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/images/image_resolution.rs b/crates/hdx_ast/src/css/values/images/image_resolution.rs new file mode 100644 index 00000000..8ccd65e9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/image_resolution.rs @@ -0,0 +1 @@ +pub type ImageResolution = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/images/mod.rs b/crates/hdx_ast/src/css/values/images/mod.rs new file mode 100644 index 00000000..f8525e75 --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/mod.rs @@ -0,0 +1,12 @@ +mod image_orientation; +mod image_rendering; +mod image_resolution; +mod object_fit; +mod object_position; +mod object_view_box; +pub use image_orientation::*; +pub use image_rendering::*; +pub use image_resolution::*; +pub use object_fit::*; +pub use object_position::*; +pub use object_view_box::*; diff --git a/crates/hdx_ast/src/css/values/images/object_fit.rs b/crates/hdx_ast/src/css/values/images/object_fit.rs new file mode 100644 index 00000000..aed8e5dd --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/object_fit.rs @@ -0,0 +1 @@ +pub type ObjectFit = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/images/object_position.rs b/crates/hdx_ast/src/css/values/images/object_position.rs new file mode 100644 index 00000000..baeaeb2a --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/object_position.rs @@ -0,0 +1 @@ +pub type ObjectPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/images/object_view_box.rs b/crates/hdx_ast/src/css/values/images/object_view_box.rs new file mode 100644 index 00000000..6ae15899 --- /dev/null +++ b/crates/hdx_ast/src/css/values/images/object_view_box.rs @@ -0,0 +1 @@ +pub type ObjectViewBox = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline.rs b/crates/hdx_ast/src/css/values/inline.rs deleted file mode 100644 index b4c00f16..00000000 --- a/crates/hdx_ast/src/css/values/inline.rs +++ /dev/null @@ -1,110 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Expr, LengthPercentage, MathExpr, Shorthand}; -use crate::{atom, Atom, Atomizable, Spanned}; - -// https://drafts.csswg.org/css-inline/#propdef-alignment-baseline -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum AlignmentBaselineValue { - #[default] - Baseline, // atom!("baseline") - TextBottom, // atom!("text-bottom") - Alphabetic, // atom!("alphabetic") - Ideographic, // atom!("ideograpic") - Middle, // atom!("middle") - Central, // atom!("central") - Mathematical, // atom!("mathematical") - TextTop, // atom!("text-top") -} - -// https://drafts.csswg.org/css-inline/#propdef-baseline-source -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BaselineSourceValue { - #[default] - Auto, // atom!("auto") - First, // atom!("first") - Last, // atom!("last") -} - -// https://drafts.csswg.org/css-inline-3/#propdef-baseline-shift -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum BaselineShiftValue { - LengthPercentage(Spanned), - Sub, // atom!("sub"), - Super, // atom!("super") - Top, // atom!("top") - Center, // atom!("center") - Bottom, // atom!("bottom") -} - -impl Default for BaselineShiftValue { - fn default() -> Self { - Self::LengthPercentage(Spanned::dummy(LengthPercentage::default())) - } -} - -// https://drafts.csswg.org/css-inline/#propdef-dominant-baseline -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum DominantBaselineValue { - #[default] - Auto, // atom!("auto") - TextBottom, // atom!("text-bottom") - Alphabetic, // atom!("alphabetic") - Ideographic, // atom!("ideographic") - Middle, // atom!("middle") - Central, // atom!("central") - Mathematical, // atom!("mathematical") - Hanging, // atom!("hanging") - TextTop, // atom!("text-top") -} - -// https://drafts.csswg.org/css-inline/#propdef-inline-sizing -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum InlineSizingValue { - #[default] - Normal, // atom!("normal") - Stretch, // atom!("stetch") -} - -// https://drafts.csswg.org/css-inline/#line-height-property -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum LineHeightValue { - #[default] - Normal, // atom!("normal") - Number(f32), - LengthPercentage(Spanned), -} - -impl Hash for LineHeightValue { - fn hash(&self, state: &mut H) { - match self { - Self::Normal => 0.hash(state), - Self::Number(n) => { - 1.hash(state); - n.to_bits().hash(state); - } - Self::LengthPercentage(lp) => { - 2.hash(state); - lp.hash(state); - } - } - } -} - -// https://drafts.csswg.org/css-inline-3/#propdef-vertical-align -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct VerticalAlignShorthand<'a> { - pub baseline_source: Shorthand<'a, Expr<'a, BaselineSourceValue>>, - pub alignment_baseline: Shorthand<'a, Expr<'a, AlignmentBaselineValue>>, - pub baseline_shift: Shorthand<'a, MathExpr<'a, BaselineShiftValue>>, -} diff --git a/crates/hdx_ast/src/css/values/inline/alignment_baseline.rs b/crates/hdx_ast/src/css/values/inline/alignment_baseline.rs new file mode 100644 index 00000000..3afae93b --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/alignment_baseline.rs @@ -0,0 +1,30 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-inline/#propdef-alignment-baseline +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum AlignmentBaseline { + #[default] + Baseline, // atom!("baseline") + TextBottom, // atom!("text-bottom") + Alphabetic, // atom!("alphabetic") + Ideographic, // atom!("ideographic") + Middle, // atom!("middle") + Central, // atom!("central") + Mathematical, // atom!("mathematical") + TextTop, // atom!("text-top") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/inline/baseline_shift.rs b/crates/hdx_ast/src/css/values/inline/baseline_shift.rs new file mode 100644 index 00000000..b176502e --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/baseline_shift.rs @@ -0,0 +1 @@ +pub type BaselineShift = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/baseline_source.rs b/crates/hdx_ast/src/css/values/inline/baseline_source.rs new file mode 100644 index 00000000..421201eb --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/baseline_source.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-inline/#propdef-baseline-source +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BaselineSource { + #[default] + Auto, // atom!("auto") + First, // atom!("first") + Last, // atom!("last") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/inline/dominant_baseline.rs b/crates/hdx_ast/src/css/values/inline/dominant_baseline.rs new file mode 100644 index 00000000..49e6a288 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/dominant_baseline.rs @@ -0,0 +1,31 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-inline/#propdef-dominant-baseline +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum DominantBaseline { + #[default] + Auto, // atom!("auto") + TextBottom, // atom!("text-bottom") + Alphabetic, // atom!("alphabetic") + Ideographic, // atom!("ideographic") + Middle, // atom!("middle") + Central, // atom!("central") + Mathematical, // atom!("mathematical") + Hanging, // atom!("hanging") + TextTop, // atom!("text-top") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/inline/initial_letter.rs b/crates/hdx_ast/src/css/values/inline/initial_letter.rs new file mode 100644 index 00000000..43377479 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/initial_letter.rs @@ -0,0 +1 @@ +pub type InitialLetter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/initial_letter_align.rs b/crates/hdx_ast/src/css/values/inline/initial_letter_align.rs new file mode 100644 index 00000000..9fd2e526 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/initial_letter_align.rs @@ -0,0 +1 @@ +pub type InitialLetterAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/initial_letter_wrap.rs b/crates/hdx_ast/src/css/values/inline/initial_letter_wrap.rs new file mode 100644 index 00000000..d013edf9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/initial_letter_wrap.rs @@ -0,0 +1 @@ +pub type InitialLetterWrap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/inline_sizing.rs b/crates/hdx_ast/src/css/values/inline/inline_sizing.rs new file mode 100644 index 00000000..8ecb1eb7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/inline_sizing.rs @@ -0,0 +1 @@ +pub type InlineSizing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/line_height.rs b/crates/hdx_ast/src/css/values/inline/line_height.rs new file mode 100644 index 00000000..350755d8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/line_height.rs @@ -0,0 +1 @@ +pub type LineHeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/mod.rs b/crates/hdx_ast/src/css/values/inline/mod.rs new file mode 100644 index 00000000..d099bf7d --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/mod.rs @@ -0,0 +1,24 @@ +mod alignment_baseline; +mod baseline_shift; +mod baseline_source; +mod dominant_baseline; +mod initial_letter; +mod initial_letter_align; +mod initial_letter_wrap; +mod inline_sizing; +mod line_height; +mod text_box_edge; +mod text_box_trim; +mod vertical_align; +pub use alignment_baseline::*; +pub use baseline_shift::*; +pub use baseline_source::*; +pub use dominant_baseline::*; +pub use initial_letter::*; +pub use initial_letter_align::*; +pub use initial_letter_wrap::*; +pub use inline_sizing::*; +pub use line_height::*; +pub use text_box_edge::*; +pub use text_box_trim::*; +pub use vertical_align::*; diff --git a/crates/hdx_ast/src/css/values/inline/text_box_edge.rs b/crates/hdx_ast/src/css/values/inline/text_box_edge.rs new file mode 100644 index 00000000..48bee726 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/text_box_edge.rs @@ -0,0 +1 @@ +pub type TextBoxEdge = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/text_box_trim.rs b/crates/hdx_ast/src/css/values/inline/text_box_trim.rs new file mode 100644 index 00000000..5cd68bdd --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/text_box_trim.rs @@ -0,0 +1 @@ +pub type TextBoxTrim = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/inline/vertical_align.rs b/crates/hdx_ast/src/css/values/inline/vertical_align.rs new file mode 100644 index 00000000..f5f98d64 --- /dev/null +++ b/crates/hdx_ast/src/css/values/inline/vertical_align.rs @@ -0,0 +1 @@ +pub type VerticalAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/line_grid/box_snap.rs b/crates/hdx_ast/src/css/values/line_grid/box_snap.rs new file mode 100644 index 00000000..3b4d55a6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/line_grid/box_snap.rs @@ -0,0 +1 @@ +pub type BoxSnap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/line_grid/line_grid.rs b/crates/hdx_ast/src/css/values/line_grid/line_grid.rs new file mode 100644 index 00000000..a17d2937 --- /dev/null +++ b/crates/hdx_ast/src/css/values/line_grid/line_grid.rs @@ -0,0 +1 @@ +pub type LineGrid = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/line_grid/line_snap.rs b/crates/hdx_ast/src/css/values/line_grid/line_snap.rs new file mode 100644 index 00000000..b184be95 --- /dev/null +++ b/crates/hdx_ast/src/css/values/line_grid/line_snap.rs @@ -0,0 +1 @@ +pub type LineSnap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/line_grid/mod.rs b/crates/hdx_ast/src/css/values/line_grid/mod.rs new file mode 100644 index 00000000..6049c7fc --- /dev/null +++ b/crates/hdx_ast/src/css/values/line_grid/mod.rs @@ -0,0 +1,6 @@ +mod box_snap; +mod line_grid; +mod line_snap; +pub use box_snap::*; +pub use line_grid::*; +pub use line_snap::*; diff --git a/crates/hdx_ast/src/css/values/link_params/link_parameters.rs b/crates/hdx_ast/src/css/values/link_params/link_parameters.rs new file mode 100644 index 00000000..6be4507c --- /dev/null +++ b/crates/hdx_ast/src/css/values/link_params/link_parameters.rs @@ -0,0 +1 @@ +pub type LinkParameters = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/link_params/mod.rs b/crates/hdx_ast/src/css/values/link_params/mod.rs new file mode 100644 index 00000000..f09b95fa --- /dev/null +++ b/crates/hdx_ast/src/css/values/link_params/mod.rs @@ -0,0 +1,2 @@ +mod link_parameters; +pub use link_parameters::*; diff --git a/crates/hdx_ast/src/css/values/lists.rs b/crates/hdx_ast/src/css/values/lists.rs deleted file mode 100644 index cffd68a0..00000000 --- a/crates/hdx_ast/src/css/values/lists.rs +++ /dev/null @@ -1,89 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{CounterStyle, Expr, Image, PredefinedCounterStyle, Shorthand}; -use crate::{atom, Atom, Atomizable, Box, Spanned}; - -// https://drafts.csswg.org/css-lists-3/#counter-functions -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum CounterOrCounters<'a> { - Counter(Counter<'a>), - Counters(Counters<'a>), -} - -// https://drafts.csswg.org/css-lists-3/#funcdef-counter -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Counter<'a> { - pub name: Atom, - pub style: Box<'a, CounterStyle<'a>>, -} - -// https://drafts.csswg.org/css-lists-3/#funcdef-counters -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Counters<'a> { - pub name: Atom, - pub concatenator: Atom, - pub style: Box<'a, CounterStyle<'a>>, -} - -// https://drafts.csswg.org/css-lists-3/#funcdef-counters -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum ListStylePositionValue { - #[default] - Outside, // atom!("outside") - Inside, // atom!("inside") -} - -// https://drafts.csswg.org/css-lists-3/#funcdef-counters -#[derive(Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ListStyleImageValue<'a> { - #[default] - None, - Image(Spanned>), -} -// -// https://drafts.csswg.org/css-lists-3/#funcdef-counters -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum ListStyleTypeValue<'a> { - CounterStyle(Spanned>), - String(Atom), - None, -} - -impl<'a> Default for ListStyleTypeValue<'a> { - fn default() -> Self { - Self::CounterStyle(Spanned::dummy(CounterStyle::Predefined(PredefinedCounterStyle::Disc))) - } -} - -// https://drafts.csswg.org/css-lists/#propdef-list-style -#[derive(Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct ListStyleShorthand<'a> { - pub position: Shorthand<'a, Expr<'a, ListStylePositionValue>>, - pub image: Shorthand<'a, Expr<'a, ListStyleImageValue<'a>>>, - pub marker: Shorthand<'a, Expr<'a, ListStyleTypeValue<'a>>>, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 32); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/lists/counter_increment.rs b/crates/hdx_ast/src/css/values/lists/counter_increment.rs new file mode 100644 index 00000000..e9828b1f --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/counter_increment.rs @@ -0,0 +1 @@ +pub type CounterIncrement = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/counter_reset.rs b/crates/hdx_ast/src/css/values/lists/counter_reset.rs new file mode 100644 index 00000000..a8b15b5e --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/counter_reset.rs @@ -0,0 +1 @@ +pub type CounterReset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/counter_set.rs b/crates/hdx_ast/src/css/values/lists/counter_set.rs new file mode 100644 index 00000000..5fe899f8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/counter_set.rs @@ -0,0 +1 @@ +pub type CounterSet = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/list_style.rs b/crates/hdx_ast/src/css/values/lists/list_style.rs new file mode 100644 index 00000000..94cfc59a --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/list_style.rs @@ -0,0 +1 @@ +pub type ListStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/list_style_image.rs b/crates/hdx_ast/src/css/values/lists/list_style_image.rs new file mode 100644 index 00000000..9a7f85cf --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/list_style_image.rs @@ -0,0 +1 @@ +pub type ListStyleImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/list_style_position.rs b/crates/hdx_ast/src/css/values/lists/list_style_position.rs new file mode 100644 index 00000000..e93dc106 --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/list_style_position.rs @@ -0,0 +1 @@ +pub type ListStylePosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/list_style_type.rs b/crates/hdx_ast/src/css/values/lists/list_style_type.rs new file mode 100644 index 00000000..b66c5c1c --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/list_style_type.rs @@ -0,0 +1 @@ +pub type ListStyleType = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/marker_side.rs b/crates/hdx_ast/src/css/values/lists/marker_side.rs new file mode 100644 index 00000000..218df212 --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/marker_side.rs @@ -0,0 +1 @@ +pub type MarkerSide = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/lists/mod.rs b/crates/hdx_ast/src/css/values/lists/mod.rs new file mode 100644 index 00000000..5e6e2b15 --- /dev/null +++ b/crates/hdx_ast/src/css/values/lists/mod.rs @@ -0,0 +1,16 @@ +mod counter_increment; +mod counter_reset; +mod counter_set; +mod list_style; +mod list_style_image; +mod list_style_position; +mod list_style_type; +mod marker_side; +pub use counter_increment::*; +pub use counter_reset::*; +pub use counter_set::*; +pub use list_style::*; +pub use list_style_image::*; +pub use list_style_position::*; +pub use list_style_type::*; +pub use marker_side::*; diff --git a/crates/hdx_ast/src/css/values/logical/block_size.rs b/crates/hdx_ast/src/css/values/logical/block_size.rs new file mode 100644 index 00000000..7444c5ae --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/block_size.rs @@ -0,0 +1 @@ +pub type BlockSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block.rs b/crates/hdx_ast/src/css/values/logical/border_block.rs new file mode 100644 index 00000000..b82e6931 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block.rs @@ -0,0 +1 @@ +pub type BorderBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_color.rs b/crates/hdx_ast/src/css/values/logical/border_block_color.rs new file mode 100644 index 00000000..0bc79917 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_color.rs @@ -0,0 +1 @@ +pub type BorderBlockColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_end.rs b/crates/hdx_ast/src/css/values/logical/border_block_end.rs new file mode 100644 index 00000000..bf354b70 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_end.rs @@ -0,0 +1 @@ +pub type BorderBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_end_color.rs b/crates/hdx_ast/src/css/values/logical/border_block_end_color.rs new file mode 100644 index 00000000..857dba95 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_end_color.rs @@ -0,0 +1 @@ +pub type BorderBlockEndColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_end_style.rs b/crates/hdx_ast/src/css/values/logical/border_block_end_style.rs new file mode 100644 index 00000000..06615ccd --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_end_style.rs @@ -0,0 +1 @@ +pub type BorderBlockEndStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_end_width.rs b/crates/hdx_ast/src/css/values/logical/border_block_end_width.rs new file mode 100644 index 00000000..066b88ae --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_end_width.rs @@ -0,0 +1 @@ +pub type BorderBlockEndWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_start.rs b/crates/hdx_ast/src/css/values/logical/border_block_start.rs new file mode 100644 index 00000000..bb2c9495 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_start.rs @@ -0,0 +1 @@ +pub type BorderBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_start_color.rs b/crates/hdx_ast/src/css/values/logical/border_block_start_color.rs new file mode 100644 index 00000000..4ca5012a --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_start_color.rs @@ -0,0 +1 @@ +pub type BorderBlockStartColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_start_style.rs b/crates/hdx_ast/src/css/values/logical/border_block_start_style.rs new file mode 100644 index 00000000..9393e805 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_start_style.rs @@ -0,0 +1 @@ +pub type BorderBlockStartStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_start_width.rs b/crates/hdx_ast/src/css/values/logical/border_block_start_width.rs new file mode 100644 index 00000000..1cc39ef8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_start_width.rs @@ -0,0 +1 @@ +pub type BorderBlockStartWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_style.rs b/crates/hdx_ast/src/css/values/logical/border_block_style.rs new file mode 100644 index 00000000..383abfc0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_style.rs @@ -0,0 +1 @@ +pub type BorderBlockStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_block_width.rs b/crates/hdx_ast/src/css/values/logical/border_block_width.rs new file mode 100644 index 00000000..7bf8012f --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_block_width.rs @@ -0,0 +1 @@ +pub type BorderBlockWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_end_end_radius.rs b/crates/hdx_ast/src/css/values/logical/border_end_end_radius.rs new file mode 100644 index 00000000..08caf1d6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_end_end_radius.rs @@ -0,0 +1 @@ +pub type BorderEndEndRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_end_start_radius.rs b/crates/hdx_ast/src/css/values/logical/border_end_start_radius.rs new file mode 100644 index 00000000..c44682dc --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_end_start_radius.rs @@ -0,0 +1 @@ +pub type BorderEndStartRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline.rs b/crates/hdx_ast/src/css/values/logical/border_inline.rs new file mode 100644 index 00000000..a5657545 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline.rs @@ -0,0 +1 @@ +pub type BorderInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_color.rs b/crates/hdx_ast/src/css/values/logical/border_inline_color.rs new file mode 100644 index 00000000..98c285fb --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_color.rs @@ -0,0 +1 @@ +pub type BorderInlineColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_end.rs b/crates/hdx_ast/src/css/values/logical/border_inline_end.rs new file mode 100644 index 00000000..bf5e136f --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_end.rs @@ -0,0 +1 @@ +pub type BorderInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_end_color.rs b/crates/hdx_ast/src/css/values/logical/border_inline_end_color.rs new file mode 100644 index 00000000..8decc360 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_end_color.rs @@ -0,0 +1 @@ +pub type BorderInlineEndColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_end_style.rs b/crates/hdx_ast/src/css/values/logical/border_inline_end_style.rs new file mode 100644 index 00000000..06bfb031 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_end_style.rs @@ -0,0 +1 @@ +pub type BorderInlineEndStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_end_width.rs b/crates/hdx_ast/src/css/values/logical/border_inline_end_width.rs new file mode 100644 index 00000000..871df4b8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_end_width.rs @@ -0,0 +1 @@ +pub type BorderInlineEndWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_start.rs b/crates/hdx_ast/src/css/values/logical/border_inline_start.rs new file mode 100644 index 00000000..e87cdd48 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_start.rs @@ -0,0 +1 @@ +pub type BorderInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_start_color.rs b/crates/hdx_ast/src/css/values/logical/border_inline_start_color.rs new file mode 100644 index 00000000..ebfe2ccf --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_start_color.rs @@ -0,0 +1 @@ +pub type BorderInlineStartColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_start_style.rs b/crates/hdx_ast/src/css/values/logical/border_inline_start_style.rs new file mode 100644 index 00000000..91615ae3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_start_style.rs @@ -0,0 +1 @@ +pub type BorderInlineStartStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_start_width.rs b/crates/hdx_ast/src/css/values/logical/border_inline_start_width.rs new file mode 100644 index 00000000..b0b97db2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_start_width.rs @@ -0,0 +1 @@ +pub type BorderInlineStartWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_style.rs b/crates/hdx_ast/src/css/values/logical/border_inline_style.rs new file mode 100644 index 00000000..d79dc74f --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_style.rs @@ -0,0 +1 @@ +pub type BorderInlineStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_inline_width.rs b/crates/hdx_ast/src/css/values/logical/border_inline_width.rs new file mode 100644 index 00000000..0744c9a2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_inline_width.rs @@ -0,0 +1 @@ +pub type BorderInlineWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_start_end_radius.rs b/crates/hdx_ast/src/css/values/logical/border_start_end_radius.rs new file mode 100644 index 00000000..96eac8ae --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_start_end_radius.rs @@ -0,0 +1 @@ +pub type BorderStartEndRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/border_start_start_radius.rs b/crates/hdx_ast/src/css/values/logical/border_start_start_radius.rs new file mode 100644 index 00000000..c9179848 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/border_start_start_radius.rs @@ -0,0 +1 @@ +pub type BorderStartStartRadius = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/inline_size.rs b/crates/hdx_ast/src/css/values/logical/inline_size.rs new file mode 100644 index 00000000..63e91d0f --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/inline_size.rs @@ -0,0 +1 @@ +pub type InlineSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_block.rs b/crates/hdx_ast/src/css/values/logical/margin_block.rs new file mode 100644 index 00000000..763302cd --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_block.rs @@ -0,0 +1 @@ +pub type MarginBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_block_end.rs b/crates/hdx_ast/src/css/values/logical/margin_block_end.rs new file mode 100644 index 00000000..0ab53547 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_block_end.rs @@ -0,0 +1 @@ +pub type MarginBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_block_start.rs b/crates/hdx_ast/src/css/values/logical/margin_block_start.rs new file mode 100644 index 00000000..315ef759 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_block_start.rs @@ -0,0 +1 @@ +pub type MarginBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_inline.rs b/crates/hdx_ast/src/css/values/logical/margin_inline.rs new file mode 100644 index 00000000..126a4d59 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_inline.rs @@ -0,0 +1 @@ +pub type MarginInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_inline_end.rs b/crates/hdx_ast/src/css/values/logical/margin_inline_end.rs new file mode 100644 index 00000000..bf549a2c --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_inline_end.rs @@ -0,0 +1 @@ +pub type MarginInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/margin_inline_start.rs b/crates/hdx_ast/src/css/values/logical/margin_inline_start.rs new file mode 100644 index 00000000..8f273ef0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/margin_inline_start.rs @@ -0,0 +1 @@ +pub type MarginInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/max_block_size.rs b/crates/hdx_ast/src/css/values/logical/max_block_size.rs new file mode 100644 index 00000000..d936db13 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/max_block_size.rs @@ -0,0 +1 @@ +pub type MaxBlockSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/max_inline_size.rs b/crates/hdx_ast/src/css/values/logical/max_inline_size.rs new file mode 100644 index 00000000..8374cbc8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/max_inline_size.rs @@ -0,0 +1 @@ +pub type MaxInlineSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/min_block_size.rs b/crates/hdx_ast/src/css/values/logical/min_block_size.rs new file mode 100644 index 00000000..5fa4505a --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/min_block_size.rs @@ -0,0 +1 @@ +pub type MinBlockSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/min_inline_size.rs b/crates/hdx_ast/src/css/values/logical/min_inline_size.rs new file mode 100644 index 00000000..87066cca --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/min_inline_size.rs @@ -0,0 +1 @@ +pub type MinInlineSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/mod.rs b/crates/hdx_ast/src/css/values/logical/mod.rs new file mode 100644 index 00000000..9de3a911 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/mod.rs @@ -0,0 +1,92 @@ +mod block_size; +mod border_block; +mod border_block_color; +mod border_block_end; +mod border_block_end_color; +mod border_block_end_style; +mod border_block_end_width; +mod border_block_start; +mod border_block_start_color; +mod border_block_start_style; +mod border_block_start_width; +mod border_block_style; +mod border_block_width; +mod border_end_end_radius; +mod border_end_start_radius; +mod border_inline; +mod border_inline_color; +mod border_inline_end; +mod border_inline_end_color; +mod border_inline_end_style; +mod border_inline_end_width; +mod border_inline_start; +mod border_inline_start_color; +mod border_inline_start_style; +mod border_inline_start_width; +mod border_inline_style; +mod border_inline_width; +mod border_start_end_radius; +mod border_start_start_radius; +mod inline_size; +mod margin_block; +mod margin_block_end; +mod margin_block_start; +mod margin_inline; +mod margin_inline_end; +mod margin_inline_start; +mod max_block_size; +mod max_inline_size; +mod min_block_size; +mod min_inline_size; +mod padding_block; +mod padding_block_end; +mod padding_block_start; +mod padding_inline; +mod padding_inline_end; +mod padding_inline_start; +pub use block_size::*; +pub use border_block::*; +pub use border_block_color::*; +pub use border_block_end::*; +pub use border_block_end_color::*; +pub use border_block_end_style::*; +pub use border_block_end_width::*; +pub use border_block_start::*; +pub use border_block_start_color::*; +pub use border_block_start_style::*; +pub use border_block_start_width::*; +pub use border_block_style::*; +pub use border_block_width::*; +pub use border_end_end_radius::*; +pub use border_end_start_radius::*; +pub use border_inline::*; +pub use border_inline_color::*; +pub use border_inline_end::*; +pub use border_inline_end_color::*; +pub use border_inline_end_style::*; +pub use border_inline_end_width::*; +pub use border_inline_start::*; +pub use border_inline_start_color::*; +pub use border_inline_start_style::*; +pub use border_inline_start_width::*; +pub use border_inline_style::*; +pub use border_inline_width::*; +pub use border_start_end_radius::*; +pub use border_start_start_radius::*; +pub use inline_size::*; +pub use margin_block::*; +pub use margin_block_end::*; +pub use margin_block_start::*; +pub use margin_inline::*; +pub use margin_inline_end::*; +pub use margin_inline_start::*; +pub use max_block_size::*; +pub use max_inline_size::*; +pub use min_block_size::*; +pub use min_inline_size::*; +pub use padding_block::*; +pub use padding_block_end::*; +pub use padding_block_start::*; +pub use padding_inline::*; +pub use padding_inline_end::*; +pub use padding_inline_start::*; diff --git a/crates/hdx_ast/src/css/values/logical/padding_block.rs b/crates/hdx_ast/src/css/values/logical/padding_block.rs new file mode 100644 index 00000000..f3ce4196 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_block.rs @@ -0,0 +1 @@ +pub type PaddingBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/padding_block_end.rs b/crates/hdx_ast/src/css/values/logical/padding_block_end.rs new file mode 100644 index 00000000..6adf03c8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_block_end.rs @@ -0,0 +1 @@ +pub type PaddingBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/padding_block_start.rs b/crates/hdx_ast/src/css/values/logical/padding_block_start.rs new file mode 100644 index 00000000..9cab5ffb --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_block_start.rs @@ -0,0 +1 @@ +pub type PaddingBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/padding_inline.rs b/crates/hdx_ast/src/css/values/logical/padding_inline.rs new file mode 100644 index 00000000..234a2dcb --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_inline.rs @@ -0,0 +1 @@ +pub type PaddingInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/padding_inline_end.rs b/crates/hdx_ast/src/css/values/logical/padding_inline_end.rs new file mode 100644 index 00000000..58a3b7a5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_inline_end.rs @@ -0,0 +1 @@ +pub type PaddingInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/logical/padding_inline_start.rs b/crates/hdx_ast/src/css/values/logical/padding_inline_start.rs new file mode 100644 index 00000000..24a35495 --- /dev/null +++ b/crates/hdx_ast/src/css/values/logical/padding_inline_start.rs @@ -0,0 +1 @@ +pub type PaddingInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/clip.rs b/crates/hdx_ast/src/css/values/masking/clip.rs new file mode 100644 index 00000000..6198bc6c --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/clip.rs @@ -0,0 +1 @@ +pub type Clip = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/clip_path.rs b/crates/hdx_ast/src/css/values/masking/clip_path.rs new file mode 100644 index 00000000..0f1c468b --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/clip_path.rs @@ -0,0 +1 @@ +pub type ClipPath = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/clip_rule.rs b/crates/hdx_ast/src/css/values/masking/clip_rule.rs new file mode 100644 index 00000000..7a0c5b17 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/clip_rule.rs @@ -0,0 +1 @@ +pub type ClipRule = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask.rs b/crates/hdx_ast/src/css/values/masking/mask.rs new file mode 100644 index 00000000..f0ff9711 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask.rs @@ -0,0 +1 @@ +pub type Mask = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border.rs b/crates/hdx_ast/src/css/values/masking/mask_border.rs new file mode 100644 index 00000000..011eab14 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border.rs @@ -0,0 +1 @@ +pub type MaskBorder = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_mode.rs b/crates/hdx_ast/src/css/values/masking/mask_border_mode.rs new file mode 100644 index 00000000..704adefd --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_mode.rs @@ -0,0 +1 @@ +pub type MaskBorderMode = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_outset.rs b/crates/hdx_ast/src/css/values/masking/mask_border_outset.rs new file mode 100644 index 00000000..f163baad --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_outset.rs @@ -0,0 +1 @@ +pub type MaskBorderOutset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_repeat.rs b/crates/hdx_ast/src/css/values/masking/mask_border_repeat.rs new file mode 100644 index 00000000..2eaa33b2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_repeat.rs @@ -0,0 +1 @@ +pub type MaskBorderRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_slice.rs b/crates/hdx_ast/src/css/values/masking/mask_border_slice.rs new file mode 100644 index 00000000..75ac1896 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_slice.rs @@ -0,0 +1 @@ +pub type MaskBorderSlice = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_source.rs b/crates/hdx_ast/src/css/values/masking/mask_border_source.rs new file mode 100644 index 00000000..9809c2ea --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_source.rs @@ -0,0 +1 @@ +pub type MaskBorderSource = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_border_width.rs b/crates/hdx_ast/src/css/values/masking/mask_border_width.rs new file mode 100644 index 00000000..8ce3aa4a --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_border_width.rs @@ -0,0 +1 @@ +pub type MaskBorderWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_clip.rs b/crates/hdx_ast/src/css/values/masking/mask_clip.rs new file mode 100644 index 00000000..18626214 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_clip.rs @@ -0,0 +1 @@ +pub type MaskClip = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_image.rs b/crates/hdx_ast/src/css/values/masking/mask_image.rs new file mode 100644 index 00000000..2e8ab891 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_image.rs @@ -0,0 +1 @@ +pub type MaskImage = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_mode.rs b/crates/hdx_ast/src/css/values/masking/mask_mode.rs new file mode 100644 index 00000000..413f334c --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_mode.rs @@ -0,0 +1 @@ +pub type MaskMode = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_origin.rs b/crates/hdx_ast/src/css/values/masking/mask_origin.rs new file mode 100644 index 00000000..9d64cbd0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_origin.rs @@ -0,0 +1 @@ +pub type MaskOrigin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_position.rs b/crates/hdx_ast/src/css/values/masking/mask_position.rs new file mode 100644 index 00000000..ff73ca75 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_position.rs @@ -0,0 +1 @@ +pub type MaskPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_repeat.rs b/crates/hdx_ast/src/css/values/masking/mask_repeat.rs new file mode 100644 index 00000000..65e361e0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_repeat.rs @@ -0,0 +1 @@ +pub type MaskRepeat = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_size.rs b/crates/hdx_ast/src/css/values/masking/mask_size.rs new file mode 100644 index 00000000..bfe60568 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_size.rs @@ -0,0 +1 @@ +pub type MaskSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mask_type.rs b/crates/hdx_ast/src/css/values/masking/mask_type.rs new file mode 100644 index 00000000..274491f0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mask_type.rs @@ -0,0 +1 @@ +pub type MaskType = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/masking/mod.rs b/crates/hdx_ast/src/css/values/masking/mod.rs new file mode 100644 index 00000000..454a684a --- /dev/null +++ b/crates/hdx_ast/src/css/values/masking/mod.rs @@ -0,0 +1,39 @@ +mod clip; +mod clip_path; +mod clip_rule; +mod mask; +mod mask_border; +mod mask_border_mode; +mod mask_border_outset; +mod mask_border_repeat; +mod mask_border_slice; +mod mask_border_source; +mod mask_border_width; +mod mask_clip; +mod mask_image; +mod mask_mode; +mod mask_origin; +mod mask_position; +mod mask_repeat; +mod mask_size; +mod mask_type; + +pub use clip::*; +pub use clip_path::*; +pub use clip_rule::*; +pub use mask::*; +pub use mask_border::*; +pub use mask_border_mode::*; +pub use mask_border_outset::*; +pub use mask_border_repeat::*; +pub use mask_border_slice::*; +pub use mask_border_source::*; +pub use mask_border_width::*; +pub use mask_clip::*; +pub use mask_image::*; +pub use mask_mode::*; +pub use mask_origin::*; +pub use mask_position::*; +pub use mask_repeat::*; +pub use mask_size::*; +pub use mask_type::*; diff --git a/crates/hdx_ast/src/css/values/mod.rs b/crates/hdx_ast/src/css/values/mod.rs index 77a514fc..198e1a14 100644 --- a/crates/hdx_ast/src/css/values/mod.rs +++ b/crates/hdx_ast/src/css/values/mod.rs @@ -1,204 +1,279 @@ -use std::hash::{Hash, Hasher}; - +use hdx_parser::{diagnostics, Parse, Parser, Result as ParserResult}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; #[cfg(feature = "serde")] use serde::Serialize; +use crate::Spanned; + /// Values -pub mod color; // https://drafts.csswg.org/css-color-5/#typedef-color -// TODO! pub mod image; // https://drafts.csswg.org/css-images-3/#typedef-image -pub mod angle; -pub mod backgrounds; -pub mod border_radius; -pub mod r#box; -pub mod r#break; -pub mod compositing; -pub mod content; -pub mod counter_styles; -pub mod display; -pub mod expr; -pub mod fonts; -pub mod frequency; -pub mod images; -pub mod inline; -pub mod lists; -pub mod non_standard; -pub mod overflow; -pub mod page_floats; -pub mod position; -pub mod resolution; -pub mod shapes; -pub mod shorthand; -pub mod size_adjust; -pub mod sizing; -pub mod tables; -pub mod text; -pub mod text_decor; -pub mod time; -pub mod ui; -pub mod units; +mod align; +mod anchor_position; +mod animations; +mod backgrounds; +mod r#box; +mod r#break; +mod cascade; +mod color; +mod color_adjust; +mod compositing; +mod contain; +mod content; +mod css2; +mod display; +mod exclusions; +mod fill_stroke; +mod filter_effects; +mod flexbox; +mod fonts; +mod gcpm; +mod grid; +mod images; +mod inline; +mod line_grid; +mod link_params; +mod lists; +mod logical; +mod masking; +mod motion; +mod multicol; +mod nav; +mod non_standard; +mod overflow; +mod overscroll; +mod page; +mod page_floats; +mod position; +mod regions; +mod rhythm; +mod round_display; +mod ruby; +mod scroll_anchoring; +mod scroll_animations; +mod scroll_snap; +mod scrollbars; +mod shapes; +mod size_adjust; +mod sizing; +mod speech; +mod tables; +mod text; +mod text_decor; +mod transitions; +mod ui; +mod view_transitions; +mod webkit; +mod will_change; +mod writing_modes; -pub use angle::*; +pub use align::*; +pub use anchor_position::*; +pub use animations::*; pub use backgrounds::*; -pub use border_radius::*; pub use r#box::*; pub use r#break::*; +pub use cascade::*; pub use color::*; +pub use color_adjust::*; pub use compositing::*; +pub use contain::*; pub use content::*; -pub use counter_styles::*; +pub use css2::*; pub use display::*; -pub use expr::*; +pub use exclusions::*; +pub use fill_stroke::*; +pub use filter_effects::*; +pub use flexbox::*; pub use fonts::*; -pub use frequency::*; +pub use gcpm::*; +pub use grid::*; pub use images::*; pub use inline::*; +pub use line_grid::*; +pub use link_params::*; pub use lists::*; +pub use logical::*; +pub use masking::*; +pub use motion::*; +pub use multicol::*; +pub use nav::*; pub use non_standard::*; pub use overflow::*; +pub use overscroll::*; +pub use page::*; pub use page_floats::*; pub use position::*; -pub use resolution::*; +pub use regions::*; +pub use rhythm::*; +pub use round_display::*; +pub use ruby::*; +pub use scroll_anchoring::*; +pub use scroll_animations::*; +pub use scroll_snap::*; +pub use scrollbars::*; pub use shapes::*; -pub use shorthand::*; pub use size_adjust::*; pub use sizing::*; +pub use speech::*; pub use tables::*; pub use text::*; pub use text_decor::*; -pub use time::*; +pub use transitions::*; pub use ui::*; -pub use units::*; - -use crate::{atom, Atom, Atomizable, Box, Spanned}; - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] -pub enum ValueLike<'a> { - Color(Box<'a, Spanned>>>), - Length(Box<'a, Spanned>>), - LengthPercentage(Box<'a, Spanned>>), - FontFamily(Box<'a, Spanned>>), - Unknown, -} - -// https://drafts.csswg.org/css-values-4/#typedef-position -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct PositionXY { - pub x: HorizontalPosition, - pub y: VerticalPosition, -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum HorizontalPosition { - Center, - Length(LengthPercentage), - Left(Option), - Right(Option), -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum VerticalPosition { - Center, - Length(LengthPercentage), - Top(Option), - Bottom(Option), -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct NoNonGlobalValuesAllowed; - -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum AutoOrNone { - #[default] - Auto, - None, -} +pub use view_transitions::*; +pub use webkit::*; +pub use will_change::*; +pub use writing_modes::*; -// https://drafts.csswg.org/css-values-4/#ratio-value -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Ratio(u8, u8); +mod units; +// TODO! #[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum TimeOrAuto { +#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] +pub enum Todo { #[default] - Auto, - Time(Time), -} - -// https://drafts.csswg.org/css-values/#typedef-length-percentage -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum FrequencyPercentage { - Frequency(Frequency), - Percentage(f32), - // TODO: Calc(Box<'a, Calc>) -} - -impl Hash for FrequencyPercentage { - fn hash(&self, state: &mut H) { - match self { - Self::Frequency(f) => f.hash(state), - Self::Percentage(f) => f.to_bits().hash(state), - } - } + Todo, } -// https://drafts.csswg.org/css-values/#typedef-length-percentage -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum AnglePercentage { - Angle(Angle), - Percentage(f32), - // TODO: Calc(Box<'a, Calc>) -} - -impl Hash for AnglePercentage { - fn hash(&self, state: &mut H) { - match self { - Self::Angle(a) => a.hash(state), - Self::Percentage(f) => f.to_bits().hash(state), - } +impl<'a> Parse<'a> for Todo { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + Err(diagnostics::Unimplemented(parser.span()))? } } -// https://drafts.csswg.org/css-values/#typedef-length-percentage -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum TimePercentage { - Time(Time), - Percentage(f32), - // TODO: Calc(Box<'a, Calc>) -} - -impl Hash for TimePercentage { - fn hash(&self, state: &mut H) { - match self { - Self::Time(t) => t.hash(state), - Self::Percentage(f) => f.to_bits().hash(state), - } +impl<'a> WriteCss<'a> for Todo { + fn write_css(&self, _sink: &mut W) -> WriterResult { + todo!("Cannot write out Todo values") } } -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 12); - assert_eq!(size_of::(), 12); - } -} +// #[derive(Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] +// pub enum ValueLike<'a> { +// Color(Box<'a, Spanned>>>), +// Length(Box<'a, Spanned>>), +// LengthPercentage(Box<'a, Spanned>>), +// FontFamily(Box<'a, Spanned>>), +// Unknown, +// } +// +// // https://drafts.csswg.org/css-values-4/#typedef-position +// #[derive(Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub struct PositionXY { +// pub x: HorizontalPosition, +// pub y: VerticalPosition, +// } +// +// #[derive(Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub enum HorizontalPosition { +// Center, +// Length(LengthPercentage), +// Left(Option), +// Right(Option), +// } +// +// #[derive(Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub enum VerticalPosition { +// Center, +// Length(LengthPercentage), +// Top(Option), +// Bottom(Option), +// } +// +// #[derive(Default, Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde())] +// pub struct NoNonGlobalValuesAllowed; +// +// #[derive(Atomizable, Default, Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde())] +// pub enum AutoOrNone { +// #[default] +// Auto, +// None, +// } +// +// // https://drafts.csswg.org/css-values-4/#ratio-value +// #[derive(Default, Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde())] +// pub struct Ratio(u8, u8); +// +// #[derive(Default, Debug, PartialEq, Hash)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde())] +// pub enum TimeOrAuto { +// #[default] +// Auto, +// Time(Time), +// } +// +// // https://drafts.csswg.org/css-values/#typedef-length-percentage +// #[derive(Debug, PartialEq)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub enum FrequencyPercentage { +// Frequency(Frequency), +// Percentage(f32), +// // TODO: Calc(Box<'a, Calc>) +// } +// +// impl Hash for FrequencyPercentage { +// fn hash(&self, state: &mut H) { +// match self { +// Self::Frequency(f) => f.hash(state), +// Self::Percentage(f) => f.to_bits().hash(state), +// } +// } +// } +// +// // https://drafts.csswg.org/css-values/#typedef-length-percentage +// #[derive(Debug, PartialEq)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub enum AnglePercentage { +// Angle(Angle), +// Percentage(f32), +// // TODO: Calc(Box<'a, Calc>) +// } +// +// impl Hash for AnglePercentage { +// fn hash(&self, state: &mut H) { +// match self { +// Self::Angle(a) => a.hash(state), +// Self::Percentage(f) => f.to_bits().hash(state), +// } +// } +// } +// +// // https://drafts.csswg.org/css-values/#typedef-length-percentage +// #[derive(Debug, PartialEq)] +// #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +// pub enum TimePercentage { +// Time(Time), +// Percentage(f32), +// // TODO: Calc(Box<'a, Calc>) +// } +// +// impl Hash for TimePercentage { +// fn hash(&self, state: &mut H) { +// match self { +// Self::Time(t) => t.hash(state), +// Self::Percentage(f) => f.to_bits().hash(state), +// } +// } +// } +// +// #[cfg(test)] +// mod tests { +// +// use super::*; +// +// #[test] +// fn size_test() { +// use std::mem::size_of; +// assert_eq!(size_of::(), 8); +// assert_eq!(size_of::(), 8); +// assert_eq!(size_of::(), 8); +// assert_eq!(size_of::(), 24); +// assert_eq!(size_of::(), 12); +// assert_eq!(size_of::(), 12); +// } +// } diff --git a/crates/hdx_ast/src/css/values/motion/mod.rs b/crates/hdx_ast/src/css/values/motion/mod.rs new file mode 100644 index 00000000..123793bf --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/mod.rs @@ -0,0 +1,13 @@ +mod offset; +mod offset_anchor; +mod offset_distance; +mod offset_path; +mod offset_position; +mod offset_rotate; + +pub use offset::*; +pub use offset_anchor::*; +pub use offset_distance::*; +pub use offset_path::*; +pub use offset_position::*; +pub use offset_rotate::*; diff --git a/crates/hdx_ast/src/css/values/motion/offset.rs b/crates/hdx_ast/src/css/values/motion/offset.rs new file mode 100644 index 00000000..45e698cc --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset.rs @@ -0,0 +1 @@ +pub type Offset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/motion/offset_anchor.rs b/crates/hdx_ast/src/css/values/motion/offset_anchor.rs new file mode 100644 index 00000000..4bbe2f73 --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset_anchor.rs @@ -0,0 +1 @@ +pub type OffsetAnchor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/motion/offset_distance.rs b/crates/hdx_ast/src/css/values/motion/offset_distance.rs new file mode 100644 index 00000000..af76dd67 --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset_distance.rs @@ -0,0 +1 @@ +pub type OffsetDistance = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/motion/offset_path.rs b/crates/hdx_ast/src/css/values/motion/offset_path.rs new file mode 100644 index 00000000..543cc35e --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset_path.rs @@ -0,0 +1 @@ +pub type OffsetPath = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/motion/offset_position.rs b/crates/hdx_ast/src/css/values/motion/offset_position.rs new file mode 100644 index 00000000..a8b0e3ca --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset_position.rs @@ -0,0 +1 @@ +pub type OffsetPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/motion/offset_rotate.rs b/crates/hdx_ast/src/css/values/motion/offset_rotate.rs new file mode 100644 index 00000000..139382b2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/motion/offset_rotate.rs @@ -0,0 +1 @@ +pub type OffsetRotate = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_count.rs b/crates/hdx_ast/src/css/values/multicol/column_count.rs new file mode 100644 index 00000000..f9b709ed --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_count.rs @@ -0,0 +1 @@ +pub type ColumnCount = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_fill.rs b/crates/hdx_ast/src/css/values/multicol/column_fill.rs new file mode 100644 index 00000000..1be79001 --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_fill.rs @@ -0,0 +1 @@ +pub type ColumnFill = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_rule.rs b/crates/hdx_ast/src/css/values/multicol/column_rule.rs new file mode 100644 index 00000000..396c5bcb --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_rule.rs @@ -0,0 +1 @@ +pub type ColumnRule = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_rule_color.rs b/crates/hdx_ast/src/css/values/multicol/column_rule_color.rs new file mode 100644 index 00000000..8bdd223e --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_rule_color.rs @@ -0,0 +1 @@ +pub type ColumnRuleColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_rule_style.rs b/crates/hdx_ast/src/css/values/multicol/column_rule_style.rs new file mode 100644 index 00000000..e2dc9d10 --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_rule_style.rs @@ -0,0 +1 @@ +pub type ColumnRuleStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_rule_width.rs b/crates/hdx_ast/src/css/values/multicol/column_rule_width.rs new file mode 100644 index 00000000..101cafc7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_rule_width.rs @@ -0,0 +1 @@ +pub type ColumnRuleWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_span.rs b/crates/hdx_ast/src/css/values/multicol/column_span.rs new file mode 100644 index 00000000..6a2a15e2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_span.rs @@ -0,0 +1 @@ +pub type ColumnSpan = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/column_width.rs b/crates/hdx_ast/src/css/values/multicol/column_width.rs new file mode 100644 index 00000000..6080f0fa --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/column_width.rs @@ -0,0 +1 @@ +pub type ColumnWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/columns.rs b/crates/hdx_ast/src/css/values/multicol/columns.rs new file mode 100644 index 00000000..b8ef10f9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/columns.rs @@ -0,0 +1 @@ +pub type Columns = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/multicol/mod.rs b/crates/hdx_ast/src/css/values/multicol/mod.rs new file mode 100644 index 00000000..9128239f --- /dev/null +++ b/crates/hdx_ast/src/css/values/multicol/mod.rs @@ -0,0 +1,18 @@ +mod column_count; +mod column_fill; +mod column_rule; +mod column_rule_color; +mod column_rule_style; +mod column_rule_width; +mod column_span; +mod column_width; +mod columns; +pub use column_count::*; +pub use column_fill::*; +pub use column_rule::*; +pub use column_rule_color::*; +pub use column_rule_style::*; +pub use column_rule_width::*; +pub use column_span::*; +pub use column_width::*; +pub use columns::*; diff --git a/crates/hdx_ast/src/css/values/nav/mod.rs b/crates/hdx_ast/src/css/values/nav/mod.rs new file mode 100644 index 00000000..d8a0a81c --- /dev/null +++ b/crates/hdx_ast/src/css/values/nav/mod.rs @@ -0,0 +1,6 @@ +mod spatial_navigation_action; +mod spatial_navigation_contain; +mod spatial_navigation_function; +pub use spatial_navigation_action::*; +pub use spatial_navigation_contain::*; +pub use spatial_navigation_function::*; diff --git a/crates/hdx_ast/src/css/values/nav/spatial_navigation_action.rs b/crates/hdx_ast/src/css/values/nav/spatial_navigation_action.rs new file mode 100644 index 00000000..dce0e1a7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/nav/spatial_navigation_action.rs @@ -0,0 +1 @@ +pub type SpatialNavigationAction = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/nav/spatial_navigation_contain.rs b/crates/hdx_ast/src/css/values/nav/spatial_navigation_contain.rs new file mode 100644 index 00000000..44f0f2ae --- /dev/null +++ b/crates/hdx_ast/src/css/values/nav/spatial_navigation_contain.rs @@ -0,0 +1 @@ +pub type SpatialNavigationContain = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/nav/spatial_navigation_function.rs b/crates/hdx_ast/src/css/values/nav/spatial_navigation_function.rs new file mode 100644 index 00000000..ac24784f --- /dev/null +++ b/crates/hdx_ast/src/css/values/nav/spatial_navigation_function.rs @@ -0,0 +1 @@ +pub type SpatialNavigationFunction = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/non_standard.rs b/crates/hdx_ast/src/css/values/non_standard.rs deleted file mode 100644 index 2491aed6..00000000 --- a/crates/hdx_ast/src/css/values/non_standard.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -// https://drafts.csswg.org/css-values/#typedef-length-percentage -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] -pub enum ZoomValue { - #[default] - Normal, - Reset, - Number(f32), - Percentage(f32), -} - -impl Hash for ZoomValue { - fn hash(&self, state: &mut H) { - match self { - Self::Normal => 0.hash(state), - Self::Reset => 1.hash(state), - Self::Number(f) => { - 2.hash(state); - f.to_bits().hash(state); - } - Self::Percentage(f) => { - 3.hash(state); - f.to_bits().hash(state); - } - } - } -} diff --git a/crates/hdx_ast/src/css/values/non_standard/mod.rs b/crates/hdx_ast/src/css/values/non_standard/mod.rs new file mode 100644 index 00000000..5730b9e5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/non_standard/mod.rs @@ -0,0 +1,2 @@ +mod zoom; +pub use zoom::*; diff --git a/crates/hdx_ast/src/css/values/non_standard/zoom.rs b/crates/hdx_ast/src/css/values/non_standard/zoom.rs new file mode 100644 index 00000000..261c3e36 --- /dev/null +++ b/crates/hdx_ast/src/css/values/non_standard/zoom.rs @@ -0,0 +1,31 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{ + css::values::units::{CSSFloat}, + Parsable, Writable, +}; + +#[derive(Parsable, Writable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", content = "value"))] +pub enum Zoom { + #[default] + Normal, // atom!("normal") + Reset, // atom!("reset") + #[parsable(Number)] + Number(CSSFloat), + #[parsable(Dimension, atom = "%")] + #[writable(suffix = "%")] + Percent(CSSFloat), +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + } +} diff --git a/crates/hdx_ast/src/css/values/overflow/block_ellipsis.rs b/crates/hdx_ast/src/css/values/overflow/block_ellipsis.rs new file mode 100644 index 00000000..aea18e8f --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/block_ellipsis.rs @@ -0,0 +1 @@ +pub type BlockEllipsis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/continue.rs b/crates/hdx_ast/src/css/values/overflow/continue.rs new file mode 100644 index 00000000..49be74b0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/continue.rs @@ -0,0 +1 @@ +pub type Continue = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/line_clamp.rs b/crates/hdx_ast/src/css/values/overflow/line_clamp.rs new file mode 100644 index 00000000..d7565858 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/line_clamp.rs @@ -0,0 +1 @@ +pub type LineClamp = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/max_lines.rs b/crates/hdx_ast/src/css/values/overflow/max_lines.rs new file mode 100644 index 00000000..babedefc --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/max_lines.rs @@ -0,0 +1 @@ +pub type MaxLines = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/mod.rs b/crates/hdx_ast/src/css/values/overflow/mod.rs new file mode 100644 index 00000000..094d0bd3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/mod.rs @@ -0,0 +1,48 @@ +mod block_ellipsis; +mod r#continue; +mod line_clamp; +mod max_lines; +mod overflow; +mod overflow_block; +mod overflow_clip_margin; +mod overflow_clip_margin_block; +mod overflow_clip_margin_block_end; +mod overflow_clip_margin_block_start; +mod overflow_clip_margin_bottom; +mod overflow_clip_margin_inline; +mod overflow_clip_margin_inline_end; +mod overflow_clip_margin_inline_start; +mod overflow_clip_margin_left; +mod overflow_clip_margin_right; +mod overflow_clip_margin_top; +mod overflow_inline; +mod overflow_x; +mod overflow_y; +mod scroll_behavior; +mod scrollbar_gutter; +mod text_overflow; +mod webkit_line_clamp; +pub use block_ellipsis::*; +pub use r#continue::*; +pub use line_clamp::*; +pub use max_lines::*; +pub use overflow::*; +pub use overflow_block::*; +pub use overflow_clip_margin::*; +pub use overflow_clip_margin_block::*; +pub use overflow_clip_margin_block_end::*; +pub use overflow_clip_margin_block_start::*; +pub use overflow_clip_margin_bottom::*; +pub use overflow_clip_margin_inline::*; +pub use overflow_clip_margin_inline_end::*; +pub use overflow_clip_margin_inline_start::*; +pub use overflow_clip_margin_left::*; +pub use overflow_clip_margin_right::*; +pub use overflow_clip_margin_top::*; +pub use overflow_inline::*; +pub use overflow_x::*; +pub use overflow_y::*; +pub use scroll_behavior::*; +pub use scrollbar_gutter::*; +pub use text_overflow::*; +pub use webkit_line_clamp::*; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow.rs b/crates/hdx_ast/src/css/values/overflow/overflow.rs new file mode 100644 index 00000000..9e166d73 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow.rs @@ -0,0 +1 @@ +pub type Overflow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow.rs b/crates/hdx_ast/src/css/values/overflow/overflow_block.rs similarity index 56% rename from crates/hdx_ast/src/css/values/overflow.rs rename to crates/hdx_ast/src/css/values/overflow/overflow_block.rs index e983566d..69964be0 100644 --- a/crates/hdx_ast/src/css/values/overflow.rs +++ b/crates/hdx_ast/src/css/values/overflow/overflow_block.rs @@ -1,12 +1,12 @@ #[cfg(feature = "serde")] use serde::Serialize; -use crate::{atom, Atom, Atomizable}; +use crate::{Atomizable, Parsable, Writable}; // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-block -#[derive(Atomizable, Copy, Clone, Default, Debug, PartialEq, Hash)] +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum OverflowKeyword { +pub enum OverflowBlock { #[default] Visible, // atom!("visible") Hidden, // atom!("hidden") @@ -14,3 +14,14 @@ pub enum OverflowKeyword { Scroll, // atom!("scroll") Auto, // atom!("auto") } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin.rs new file mode 100644 index 00000000..e34820b2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin.rs @@ -0,0 +1 @@ +pub type OverflowClipMargin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block.rs new file mode 100644 index 00000000..57d499e5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_end.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_end.rs new file mode 100644 index 00000000..ab081962 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_end.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_start.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_start.rs new file mode 100644 index 00000000..953b0039 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_block_start.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_bottom.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_bottom.rs new file mode 100644 index 00000000..6ec96bb9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_bottom.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginBottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline.rs new file mode 100644 index 00000000..8dfe8d6d --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_end.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_end.rs new file mode 100644 index 00000000..e6e1ec2c --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_end.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_start.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_start.rs new file mode 100644 index 00000000..7f152fac --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_inline_start.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_left.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_left.rs new file mode 100644 index 00000000..44e2f40b --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_left.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_right.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_right.rs new file mode 100644 index 00000000..9a6455f9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_right.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_top.rs b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_top.rs new file mode 100644 index 00000000..d9592067 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_clip_margin_top.rs @@ -0,0 +1 @@ +pub type OverflowClipMarginTop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_inline.rs b/crates/hdx_ast/src/css/values/overflow/overflow_inline.rs new file mode 100644 index 00000000..8987362b --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_inline.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-overflow-3/#propdef-overflow-block +pub type OverflowInline = super::OverflowBlock; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_x.rs b/crates/hdx_ast/src/css/values/overflow/overflow_x.rs new file mode 100644 index 00000000..26def5e7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_x.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-overflow-3/#propdef-overflow-block +pub type OverflowX = super::OverflowBlock; diff --git a/crates/hdx_ast/src/css/values/overflow/overflow_y.rs b/crates/hdx_ast/src/css/values/overflow/overflow_y.rs new file mode 100644 index 00000000..25a466fb --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/overflow_y.rs @@ -0,0 +1,2 @@ +// https://drafts.csswg.org/css-overflow-3/#propdef-overflow-block +pub type OverflowY = super::OverflowBlock; diff --git a/crates/hdx_ast/src/css/values/overflow/scroll_behavior.rs b/crates/hdx_ast/src/css/values/overflow/scroll_behavior.rs new file mode 100644 index 00000000..63e3f130 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/scroll_behavior.rs @@ -0,0 +1 @@ +pub type ScrollBehavior = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/scrollbar_gutter.rs b/crates/hdx_ast/src/css/values/overflow/scrollbar_gutter.rs new file mode 100644 index 00000000..69db61c3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/scrollbar_gutter.rs @@ -0,0 +1 @@ +pub type ScrollbarGutter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/text_overflow.rs b/crates/hdx_ast/src/css/values/overflow/text_overflow.rs new file mode 100644 index 00000000..c3e9e3bc --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/text_overflow.rs @@ -0,0 +1 @@ +pub type TextOverflow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overflow/webkit_line_clamp.rs b/crates/hdx_ast/src/css/values/overflow/webkit_line_clamp.rs new file mode 100644 index 00000000..74469243 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overflow/webkit_line_clamp.rs @@ -0,0 +1 @@ +pub type WebkitLineClamp = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overscroll/mod.rs b/crates/hdx_ast/src/css/values/overscroll/mod.rs new file mode 100644 index 00000000..462c3f9a --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/mod.rs @@ -0,0 +1,10 @@ +mod overscroll_behavior; +mod overscroll_behavior_block; +mod overscroll_behavior_inline; +mod overscroll_behavior_x; +mod overscroll_behavior_y; +pub use overscroll_behavior::*; +pub use overscroll_behavior_block::*; +pub use overscroll_behavior_inline::*; +pub use overscroll_behavior_x::*; +pub use overscroll_behavior_y::*; diff --git a/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior.rs b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior.rs new file mode 100644 index 00000000..9616ea35 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior.rs @@ -0,0 +1 @@ +pub type OverscrollBehavior = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_block.rs b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_block.rs new file mode 100644 index 00000000..558ce7d6 --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_block.rs @@ -0,0 +1 @@ +pub type OverscrollBehaviorBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_inline.rs b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_inline.rs new file mode 100644 index 00000000..760c8a7a --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_inline.rs @@ -0,0 +1 @@ +pub type OverscrollBehaviorInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_x.rs b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_x.rs new file mode 100644 index 00000000..b44bac0f --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_x.rs @@ -0,0 +1 @@ +pub type OverscrollBehaviorX = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_y.rs b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_y.rs new file mode 100644 index 00000000..37db6d6b --- /dev/null +++ b/crates/hdx_ast/src/css/values/overscroll/overscroll_behavior_y.rs @@ -0,0 +1 @@ +pub type OverscrollBehaviorY = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/page/mod.rs b/crates/hdx_ast/src/css/values/page/mod.rs new file mode 100644 index 00000000..f5f67f8c --- /dev/null +++ b/crates/hdx_ast/src/css/values/page/mod.rs @@ -0,0 +1,2 @@ +mod page; +pub use page::*; diff --git a/crates/hdx_ast/src/css/values/page/page.rs b/crates/hdx_ast/src/css/values/page/page.rs new file mode 100644 index 00000000..e82bf2d0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page/page.rs @@ -0,0 +1 @@ +pub type Page = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/page_floats.rs b/crates/hdx_ast/src/css/values/page_floats.rs deleted file mode 100644 index 75dca0c8..00000000 --- a/crates/hdx_ast/src/css/values/page_floats.rs +++ /dev/null @@ -1,148 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::Length; -use crate::{atom, Atom, Atomizable, Spanned}; - -// https://drafts.csswg.org/css-page-floats-3/#propdef-float -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FloatValue { - BlockStart, - BlockEnd, - InlineStart, - InlineEnd, - SnapBlock, - SnapBlockFunction(Spanned, SnapBlockFloat), - SnapInline, - SnapInlineFunction(Spanned, SnapInlineFloat), - Left, - Right, - Top, - Bottom, - #[default] - None, -} - -impl FloatValue { - pub fn from_atom(atom: Atom) -> Option { - match atom { - atom!("block-start") => Some(Self::BlockStart), - atom!("block-end") => Some(Self::BlockEnd), - atom!("inline-start") => Some(Self::InlineStart), - atom!("inline-end") => Some(Self::InlineEnd), - atom!("snap-block") => Some(Self::SnapBlock), - atom!("snap-inline") => Some(Self::SnapInline), - atom!("left") => Some(Self::Left), - atom!("right") => Some(Self::Right), - atom!("top") => Some(Self::Top), - atom!("bottom") => Some(Self::Bottom), - atom!("none") => Some(Self::None), - _ => None, - } - } - - pub fn to_atom(&self) -> Option { - match self { - Self::BlockStart => Some(atom!("block-start")), - Self::BlockEnd => Some(atom!("block-end")), - Self::InlineStart => Some(atom!("inline-start")), - Self::InlineEnd => Some(atom!("inline-end")), - Self::SnapBlock => Some(atom!("snap-block")), - Self::SnapBlockFunction(_, _) => None, - Self::SnapInline => Some(atom!("snap-inline")), - Self::SnapInlineFunction(_, _) => None, - Self::Left => Some(atom!("left")), - Self::Right => Some(atom!("right")), - Self::Top => Some(atom!("top")), - Self::Bottom => Some(atom!("bottom")), - Self::None => Some(atom!("none")), - } - } -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum SnapBlockFloat { - Start, // atom!("start") - End, // atom!("end") - Near, // atom!("near") -} - -#[derive(Atomizable, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum SnapInlineFloat { - Right, // atom!("right") - Left, // atom!("left") - Near, // atom!("near") -} - -// https://drafts.csswg.org/css-page-floats-3/#propdef-clear -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum ClearValue { - InlineStart, // atom!("inline-start") - InlineEnd, // atom!("inline-end") - BlockStart, // atom!("block-start") - BlockEnd, // atom!("block-end") - Left, // atom!("left") - Right, // atom!("right") - Top, // atom!("top") - Bottom, // atom!("bottom") - BothInline, // atom!("both-inline") - BothBlock, // atom!("both-block") - Both, // atom!("both") - #[default] - None, // atom!("none") -} - -// https://drafts.csswg.org/css-page-floats-3/#propdef-float-defer -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum FloatDeferValue { - #[default] - Last, - None, - Integer(i32), -} - -impl Atomizable for FloatDeferValue { - fn to_atom(&self) -> Atom { - match self { - Self::Last => atom!("last"), - Self::None => atom!("none"), - Self::Integer(_) => atom!(""), - } - } - - fn from_atom(atom: Atom) -> Option { - match atom { - atom!("last") => Some(Self::Last), - atom!("none") => Some(Self::None), - _ => None, - } - } -} - -impl From for FloatDeferValue { - fn from(float: f32) -> Self { - Self::Integer(float as i32) - } -} - -impl From for FloatDeferValue { - fn from(int: i32) -> Self { - Self::Integer(int) - } -} - -// https://drafts.csswg.org/css-page-floats-3/#propdef-float-reference -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum FloatReferenceValue { - #[default] - Inline, // atom!("inline") - Column, // atom!("column") - Region, // atom!("region") - Page, // atom!("page") -} diff --git a/crates/hdx_ast/src/css/values/page_floats/clear.rs b/crates/hdx_ast/src/css/values/page_floats/clear.rs new file mode 100644 index 00000000..ebf7d1e4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/clear.rs @@ -0,0 +1,34 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-page-floats-3/#propdef-clear +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum Clear { + InlineStart, // atom!("inline-start") + InlineEnd, // atom!("inline-end") + BlockStart, // atom!("block-start") + BlockEnd, // atom!("block-end") + Left, // atom!("left") + Right, // atom!("right") + Top, // atom!("top") + Bottom, // atom!("bottom") + BothInline, // atom!("both-inline") + BothBlock, // atom!("both-block") + Both, // atom!("both") + #[default] + None, // atom!("none") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/page_floats/float.rs b/crates/hdx_ast/src/css/values/page_floats/float.rs new file mode 100644 index 00000000..b50e615a --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/float.rs @@ -0,0 +1 @@ +pub type Float = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/page_floats/float_defer.rs b/crates/hdx_ast/src/css/values/page_floats/float_defer.rs new file mode 100644 index 00000000..e53c46b1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/float_defer.rs @@ -0,0 +1,26 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Parsable, Writable, css::values::units::CSSFloat}; + +// https://drafts.csswg.org/css-page-floats-3/#propdef-float-defer +#[derive(Parsable, Writable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum FloatDefer { + #[default] + Last, + None, + #[parsable(Number, Check::Int)] + Integer(CSSFloat), +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + } +} diff --git a/crates/hdx_ast/src/css/values/page_floats/float_offset.rs b/crates/hdx_ast/src/css/values/page_floats/float_offset.rs new file mode 100644 index 00000000..5a736148 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/float_offset.rs @@ -0,0 +1 @@ +pub type FloatOffset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/page_floats/float_reference.rs b/crates/hdx_ast/src/css/values/page_floats/float_reference.rs new file mode 100644 index 00000000..c0f406b0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/float_reference.rs @@ -0,0 +1,26 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-page-floats-3/#propdef-float-reference +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum FloatReference { + #[default] + Inline, // atom!("inline") + Column, // atom!("column") + Region, // atom!("region") + Page, // atom!("page") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/page_floats/mod.rs b/crates/hdx_ast/src/css/values/page_floats/mod.rs new file mode 100644 index 00000000..6668a0e9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/page_floats/mod.rs @@ -0,0 +1,10 @@ +mod clear; +mod float; +mod float_defer; +mod float_offset; +mod float_reference; +pub use clear::*; +pub use float::*; +pub use float_defer::*; +pub use float_offset::*; +pub use float_reference::*; diff --git a/crates/hdx_ast/src/css/values/position.rs b/crates/hdx_ast/src/css/values/position.rs deleted file mode 100644 index 100064f0..00000000 --- a/crates/hdx_ast/src/css/values/position.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{LengthPercentageOrAuto, MathExpr, Shorthand}; -use crate::{atom, Atom, Atomizable}; - -// https://drafts.csswg.org/css-position-3/#propdef-position -#[derive(Atomizable, Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum PositionValue { - #[default] - Static, // atom!("static") - Relative, // atom!("relative") - Absolute, // atom!("absolute") - Sticky, // atom!("sticky") - Fixed, // atom!("fixed") -} - -// https://drafts.csswg.org/css-position-3/#inset-shorthands -#[derive(Debug, Default, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub struct InsetShorthand<'a> { - pub top: Shorthand<'a, MathExpr<'a, LengthPercentageOrAuto>>, - pub right: Shorthand<'a, MathExpr<'a, LengthPercentageOrAuto>>, - pub bottom: Shorthand<'a, MathExpr<'a, LengthPercentageOrAuto>>, - pub left: Shorthand<'a, MathExpr<'a, LengthPercentageOrAuto>>, -} diff --git a/crates/hdx_ast/src/css/values/position/bottom.rs b/crates/hdx_ast/src/css/values/position/bottom.rs new file mode 100644 index 00000000..4d0fe56d --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/bottom.rs @@ -0,0 +1 @@ +pub type Bottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset.rs b/crates/hdx_ast/src/css/values/position/inset.rs new file mode 100644 index 00000000..1e6dbf1a --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset.rs @@ -0,0 +1 @@ +pub type Inset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_block.rs b/crates/hdx_ast/src/css/values/position/inset_block.rs new file mode 100644 index 00000000..e18e2d40 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_block.rs @@ -0,0 +1 @@ +pub type InsetBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_block_end.rs b/crates/hdx_ast/src/css/values/position/inset_block_end.rs new file mode 100644 index 00000000..39520260 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_block_end.rs @@ -0,0 +1 @@ +pub type InsetBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_block_start.rs b/crates/hdx_ast/src/css/values/position/inset_block_start.rs new file mode 100644 index 00000000..e6804de4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_block_start.rs @@ -0,0 +1 @@ +pub type InsetBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_inline.rs b/crates/hdx_ast/src/css/values/position/inset_inline.rs new file mode 100644 index 00000000..b18641fd --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_inline.rs @@ -0,0 +1 @@ +pub type InsetInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_inline_end.rs b/crates/hdx_ast/src/css/values/position/inset_inline_end.rs new file mode 100644 index 00000000..e0d61360 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_inline_end.rs @@ -0,0 +1 @@ +pub type InsetInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/inset_inline_start.rs b/crates/hdx_ast/src/css/values/position/inset_inline_start.rs new file mode 100644 index 00000000..c4ecb0a7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/inset_inline_start.rs @@ -0,0 +1 @@ +pub type InsetInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/left.rs b/crates/hdx_ast/src/css/values/position/left.rs new file mode 100644 index 00000000..0453fb4b --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/left.rs @@ -0,0 +1 @@ +pub type Left = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/mod.rs b/crates/hdx_ast/src/css/values/position/mod.rs new file mode 100644 index 00000000..665d95fa --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/mod.rs @@ -0,0 +1,24 @@ +mod bottom; +mod inset; +mod inset_block; +mod inset_block_end; +mod inset_block_start; +mod inset_inline; +mod inset_inline_end; +mod inset_inline_start; +mod left; +mod position; +mod right; +mod top; +pub use bottom::*; +pub use inset::*; +pub use inset_block::*; +pub use inset_block_end::*; +pub use inset_block_start::*; +pub use inset_inline::*; +pub use inset_inline_end::*; +pub use inset_inline_start::*; +pub use left::*; +pub use position::*; +pub use right::*; +pub use top::*; diff --git a/crates/hdx_ast/src/css/values/position/position.rs b/crates/hdx_ast/src/css/values/position/position.rs new file mode 100644 index 00000000..5cbc350a --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/position.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-position-3/#propdef-position +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum Position { + #[default] + Static, // atom!("static") + Relative, // atom!("relative") + Absolute, // atom!("absolute") + Sticky, // atom!("sticky") + Fixed, // atom!("fixed") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/position/right.rs b/crates/hdx_ast/src/css/values/position/right.rs new file mode 100644 index 00000000..c583db70 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/right.rs @@ -0,0 +1 @@ +pub type Right = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/position/top.rs b/crates/hdx_ast/src/css/values/position/top.rs new file mode 100644 index 00000000..7fb4ef72 --- /dev/null +++ b/crates/hdx_ast/src/css/values/position/top.rs @@ -0,0 +1 @@ +pub type Top = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/regions/flow_from.rs b/crates/hdx_ast/src/css/values/regions/flow_from.rs new file mode 100644 index 00000000..eada9c0a --- /dev/null +++ b/crates/hdx_ast/src/css/values/regions/flow_from.rs @@ -0,0 +1 @@ +pub type FlowFrom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/regions/flow_into.rs b/crates/hdx_ast/src/css/values/regions/flow_into.rs new file mode 100644 index 00000000..4a8c1df4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/regions/flow_into.rs @@ -0,0 +1 @@ +pub type FlowInto = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/regions/mod.rs b/crates/hdx_ast/src/css/values/regions/mod.rs new file mode 100644 index 00000000..f54758c5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/regions/mod.rs @@ -0,0 +1,6 @@ +mod flow_from; +mod flow_into; +mod region_fragment; +pub use flow_from::*; +pub use flow_into::*; +pub use region_fragment::*; diff --git a/crates/hdx_ast/src/css/values/regions/region_fragment.rs b/crates/hdx_ast/src/css/values/regions/region_fragment.rs new file mode 100644 index 00000000..41779b7c --- /dev/null +++ b/crates/hdx_ast/src/css/values/regions/region_fragment.rs @@ -0,0 +1 @@ +pub type RegionFragment = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/resolution.rs b/crates/hdx_ast/src/css/values/resolution.rs deleted file mode 100644 index 4114d931..00000000 --- a/crates/hdx_ast/src/css/values/resolution.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable}; - -// https://drafts.csswg.org/css-values/#resolution-value -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Resolution { - value: f32, - unit: ResolutionUnit, -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum ResolutionUnit { - Dpi, - Dpcm, - Dppx, - X, -} -impl Atomizable for ResolutionUnit { - fn to_atom(&self) -> Atom { - match self { - Self::Dpi => atom!("dpi"), - Self::Dpcm => atom!("dpcm"), - Self::Dppx => atom!("dppx"), - Self::X => atom!("x"), - } - } - - fn from_atom(unit: Atom) -> Option { - match unit { - atom!("dpi") => Some(Self::Dpi), - atom!("dpcm") => Some(Self::Dpcm), - atom!("dppx") => Some(Self::Dppx), - atom!("x") => Some(Self::X), - _ => None, - } - } -} - -impl Hash for Resolution { - fn hash(&self, state: &mut H) { - self.value.to_bits().hash(state); - self.unit.hash(state); - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 8); - } -} diff --git a/crates/hdx_ast/src/css/values/rhythm/block_step.rs b/crates/hdx_ast/src/css/values/rhythm/block_step.rs new file mode 100644 index 00000000..8ef9fdeb --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/block_step.rs @@ -0,0 +1 @@ +pub type BlockStep = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/block_step_align.rs b/crates/hdx_ast/src/css/values/rhythm/block_step_align.rs new file mode 100644 index 00000000..84ce31ce --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/block_step_align.rs @@ -0,0 +1 @@ +pub type BlockStepAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/block_step_insert.rs b/crates/hdx_ast/src/css/values/rhythm/block_step_insert.rs new file mode 100644 index 00000000..14cd4c7f --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/block_step_insert.rs @@ -0,0 +1 @@ +pub type BlockStepInsert = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/block_step_round.rs b/crates/hdx_ast/src/css/values/rhythm/block_step_round.rs new file mode 100644 index 00000000..6baca820 --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/block_step_round.rs @@ -0,0 +1 @@ +pub type BlockStepRound = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/block_step_size.rs b/crates/hdx_ast/src/css/values/rhythm/block_step_size.rs new file mode 100644 index 00000000..e43bf89f --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/block_step_size.rs @@ -0,0 +1 @@ +pub type BlockStepSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/line_height_step.rs b/crates/hdx_ast/src/css/values/rhythm/line_height_step.rs new file mode 100644 index 00000000..572552aa --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/line_height_step.rs @@ -0,0 +1 @@ +pub type LineHeightStep = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/rhythm/mod.rs b/crates/hdx_ast/src/css/values/rhythm/mod.rs new file mode 100644 index 00000000..817c944f --- /dev/null +++ b/crates/hdx_ast/src/css/values/rhythm/mod.rs @@ -0,0 +1,12 @@ +mod block_step; +mod block_step_align; +mod block_step_insert; +mod block_step_round; +mod block_step_size; +mod line_height_step; +pub use block_step::*; +pub use block_step_align::*; +pub use block_step_insert::*; +pub use block_step_round::*; +pub use block_step_size::*; +pub use line_height_step::*; diff --git a/crates/hdx_ast/src/css/values/round_display/border_boundary.rs b/crates/hdx_ast/src/css/values/round_display/border_boundary.rs new file mode 100644 index 00000000..ae7c237e --- /dev/null +++ b/crates/hdx_ast/src/css/values/round_display/border_boundary.rs @@ -0,0 +1 @@ +pub type BorderBoundary = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/round_display/mod.rs b/crates/hdx_ast/src/css/values/round_display/mod.rs new file mode 100644 index 00000000..4594ecf5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/round_display/mod.rs @@ -0,0 +1,4 @@ +mod border_boundary; +mod shape_inside; +pub use border_boundary::*; +pub use shape_inside::*; diff --git a/crates/hdx_ast/src/css/values/round_display/shape_inside.rs b/crates/hdx_ast/src/css/values/round_display/shape_inside.rs new file mode 100644 index 00000000..122a2c80 --- /dev/null +++ b/crates/hdx_ast/src/css/values/round_display/shape_inside.rs @@ -0,0 +1 @@ +pub type ShapeInside = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ruby/mod.rs b/crates/hdx_ast/src/css/values/ruby/mod.rs new file mode 100644 index 00000000..e6b0a801 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ruby/mod.rs @@ -0,0 +1,8 @@ +mod ruby_align; +mod ruby_merge; +mod ruby_overhang; +mod ruby_position; +pub use ruby_align::*; +pub use ruby_merge::*; +pub use ruby_overhang::*; +pub use ruby_position::*; diff --git a/crates/hdx_ast/src/css/values/ruby/ruby_align.rs b/crates/hdx_ast/src/css/values/ruby/ruby_align.rs new file mode 100644 index 00000000..c8f69d51 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ruby/ruby_align.rs @@ -0,0 +1 @@ +pub type RubyAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ruby/ruby_merge.rs b/crates/hdx_ast/src/css/values/ruby/ruby_merge.rs new file mode 100644 index 00000000..4e6b7401 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ruby/ruby_merge.rs @@ -0,0 +1 @@ +pub type RubyMerge = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ruby/ruby_overhang.rs b/crates/hdx_ast/src/css/values/ruby/ruby_overhang.rs new file mode 100644 index 00000000..962b9ed8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ruby/ruby_overhang.rs @@ -0,0 +1 @@ +pub type RubyOverhang = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ruby/ruby_position.rs b/crates/hdx_ast/src/css/values/ruby/ruby_position.rs new file mode 100644 index 00000000..f3a4d89d --- /dev/null +++ b/crates/hdx_ast/src/css/values/ruby/ruby_position.rs @@ -0,0 +1 @@ +pub type RubyPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_anchoring/mod.rs b/crates/hdx_ast/src/css/values/scroll_anchoring/mod.rs new file mode 100644 index 00000000..16d33719 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_anchoring/mod.rs @@ -0,0 +1,2 @@ +mod overflow_anchor; +pub use overflow_anchor::*; diff --git a/crates/hdx_ast/src/css/values/scroll_anchoring/overflow_anchor.rs b/crates/hdx_ast/src/css/values/scroll_anchoring/overflow_anchor.rs new file mode 100644 index 00000000..72f830ac --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_anchoring/overflow_anchor.rs @@ -0,0 +1 @@ +pub type OverflowAnchor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/animation_range.rs b/crates/hdx_ast/src/css/values/scroll_animations/animation_range.rs new file mode 100644 index 00000000..5f00e300 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/animation_range.rs @@ -0,0 +1 @@ +pub type AnimationRange = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/animation_range_end.rs b/crates/hdx_ast/src/css/values/scroll_animations/animation_range_end.rs new file mode 100644 index 00000000..1793e7df --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/animation_range_end.rs @@ -0,0 +1 @@ +pub type AnimationRangeEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/animation_range_start.rs b/crates/hdx_ast/src/css/values/scroll_animations/animation_range_start.rs new file mode 100644 index 00000000..16c82e36 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/animation_range_start.rs @@ -0,0 +1 @@ +pub type AnimationRangeStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/mod.rs b/crates/hdx_ast/src/css/values/scroll_animations/mod.rs new file mode 100644 index 00000000..f6d5f632 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/mod.rs @@ -0,0 +1,22 @@ +mod animation_range; +mod animation_range_end; +mod animation_range_start; +mod scroll_timeline; +mod scroll_timeline_axis; +mod scroll_timeline_name; +mod timeline_scope; +mod view_timeline; +mod view_timeline_axis; +mod view_timeline_inset; +mod view_timeline_name; +pub use animation_range::*; +pub use animation_range_end::*; +pub use animation_range_start::*; +pub use scroll_timeline::*; +pub use scroll_timeline_axis::*; +pub use scroll_timeline_name::*; +pub use timeline_scope::*; +pub use view_timeline::*; +pub use view_timeline_axis::*; +pub use view_timeline_inset::*; +pub use view_timeline_name::*; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline.rs b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline.rs new file mode 100644 index 00000000..b2ea717a --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline.rs @@ -0,0 +1 @@ +pub type ScrollTimeline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_axis.rs b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_axis.rs new file mode 100644 index 00000000..e6331d8a --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_axis.rs @@ -0,0 +1 @@ +pub type ScrollTimelineAxis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_name.rs b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_name.rs new file mode 100644 index 00000000..915fa41d --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/scroll_timeline_name.rs @@ -0,0 +1 @@ +pub type ScrollTimelineName = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/timeline_scope.rs b/crates/hdx_ast/src/css/values/scroll_animations/timeline_scope.rs new file mode 100644 index 00000000..f2ed9e7b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/timeline_scope.rs @@ -0,0 +1 @@ +pub type TimelineScope = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/view_timeline.rs b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline.rs new file mode 100644 index 00000000..7694e938 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline.rs @@ -0,0 +1 @@ +pub type ViewTimeline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_axis.rs b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_axis.rs new file mode 100644 index 00000000..90ae68ed --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_axis.rs @@ -0,0 +1 @@ +pub type ViewTimelineAxis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_inset.rs b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_inset.rs new file mode 100644 index 00000000..58e4a45a --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_inset.rs @@ -0,0 +1 @@ +pub type ViewTimelineInset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_name.rs b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_name.rs new file mode 100644 index 00000000..b07fdf49 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_animations/view_timeline_name.rs @@ -0,0 +1 @@ +pub type ViewTimelineName = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/mod.rs b/crates/hdx_ast/src/css/values/scroll_snap/mod.rs new file mode 100644 index 00000000..dcf753e3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/mod.rs @@ -0,0 +1,70 @@ +mod scroll_margin; +mod scroll_margin_block; +mod scroll_margin_block_end; +mod scroll_margin_block_start; +mod scroll_margin_bottom; +mod scroll_margin_inline; +mod scroll_margin_inline_end; +mod scroll_margin_inline_start; +mod scroll_margin_left; +mod scroll_margin_right; +mod scroll_margin_top; +mod scroll_padding; +mod scroll_padding_block; +mod scroll_padding_block_end; +mod scroll_padding_block_start; +mod scroll_padding_bottom; +mod scroll_padding_inline; +mod scroll_padding_inline_end; +mod scroll_padding_inline_start; +mod scroll_padding_left; +mod scroll_padding_right; +mod scroll_padding_top; +mod scroll_snap_align; +mod scroll_snap_stop; +mod scroll_snap_type; +mod scroll_start; +mod scroll_start_block; +mod scroll_start_inline; +mod scroll_start_target; +mod scroll_start_target_block; +mod scroll_start_target_inline; +mod scroll_start_target_x; +mod scroll_start_target_y; +mod scroll_start_x; +mod scroll_start_y; +pub use scroll_margin::*; +pub use scroll_margin_block::*; +pub use scroll_margin_block_end::*; +pub use scroll_margin_block_start::*; +pub use scroll_margin_bottom::*; +pub use scroll_margin_inline::*; +pub use scroll_margin_inline_end::*; +pub use scroll_margin_inline_start::*; +pub use scroll_margin_left::*; +pub use scroll_margin_right::*; +pub use scroll_margin_top::*; +pub use scroll_padding::*; +pub use scroll_padding_block::*; +pub use scroll_padding_block_end::*; +pub use scroll_padding_block_start::*; +pub use scroll_padding_bottom::*; +pub use scroll_padding_inline::*; +pub use scroll_padding_inline_end::*; +pub use scroll_padding_inline_start::*; +pub use scroll_padding_left::*; +pub use scroll_padding_right::*; +pub use scroll_padding_top::*; +pub use scroll_snap_align::*; +pub use scroll_snap_stop::*; +pub use scroll_snap_type::*; +pub use scroll_start::*; +pub use scroll_start_block::*; +pub use scroll_start_inline::*; +pub use scroll_start_target::*; +pub use scroll_start_target_block::*; +pub use scroll_start_target_inline::*; +pub use scroll_start_target_x::*; +pub use scroll_start_target_y::*; +pub use scroll_start_x::*; +pub use scroll_start_y::*; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin.rs new file mode 100644 index 00000000..00233e6b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin.rs @@ -0,0 +1 @@ +pub type ScrollMargin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block.rs new file mode 100644 index 00000000..a503997b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block.rs @@ -0,0 +1 @@ +pub type ScrollMarginBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_end.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_end.rs new file mode 100644 index 00000000..12f16f9f --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_end.rs @@ -0,0 +1 @@ +pub type ScrollMarginBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_start.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_start.rs new file mode 100644 index 00000000..a191b595 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_block_start.rs @@ -0,0 +1 @@ +pub type ScrollMarginBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_bottom.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_bottom.rs new file mode 100644 index 00000000..2ce5285c --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_bottom.rs @@ -0,0 +1 @@ +pub type ScrollMarginBottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline.rs new file mode 100644 index 00000000..e18ed143 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline.rs @@ -0,0 +1 @@ +pub type ScrollMarginInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_end.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_end.rs new file mode 100644 index 00000000..fb271d19 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_end.rs @@ -0,0 +1 @@ +pub type ScrollMarginInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_start.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_start.rs new file mode 100644 index 00000000..9b8dc733 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_inline_start.rs @@ -0,0 +1 @@ +pub type ScrollMarginInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_left.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_left.rs new file mode 100644 index 00000000..7fbc85a4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_left.rs @@ -0,0 +1 @@ +pub type ScrollMarginLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_right.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_right.rs new file mode 100644 index 00000000..5b1d3564 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_right.rs @@ -0,0 +1 @@ +pub type ScrollMarginRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_top.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_top.rs new file mode 100644 index 00000000..88b85962 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_margin_top.rs @@ -0,0 +1 @@ +pub type ScrollMarginTop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding.rs new file mode 100644 index 00000000..cff81111 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding.rs @@ -0,0 +1 @@ +pub type ScrollPadding = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block.rs new file mode 100644 index 00000000..b554380e --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block.rs @@ -0,0 +1 @@ +pub type ScrollPaddingBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_end.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_end.rs new file mode 100644 index 00000000..2ca030d8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_end.rs @@ -0,0 +1 @@ +pub type ScrollPaddingBlockEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_start.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_start.rs new file mode 100644 index 00000000..741a0223 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_block_start.rs @@ -0,0 +1 @@ +pub type ScrollPaddingBlockStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_bottom.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_bottom.rs new file mode 100644 index 00000000..6facc975 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_bottom.rs @@ -0,0 +1 @@ +pub type ScrollPaddingBottom = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline.rs new file mode 100644 index 00000000..0270319d --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline.rs @@ -0,0 +1 @@ +pub type ScrollPaddingInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_end.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_end.rs new file mode 100644 index 00000000..0d932f5a --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_end.rs @@ -0,0 +1 @@ +pub type ScrollPaddingInlineEnd = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_start.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_start.rs new file mode 100644 index 00000000..bcad7927 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_inline_start.rs @@ -0,0 +1 @@ +pub type ScrollPaddingInlineStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_left.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_left.rs new file mode 100644 index 00000000..3c54952c --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_left.rs @@ -0,0 +1 @@ +pub type ScrollPaddingLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_right.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_right.rs new file mode 100644 index 00000000..9e6da3a7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_right.rs @@ -0,0 +1 @@ +pub type ScrollPaddingRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_top.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_top.rs new file mode 100644 index 00000000..132ce984 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_padding_top.rs @@ -0,0 +1 @@ +pub type ScrollPaddingTop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_align.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_align.rs new file mode 100644 index 00000000..2a6ac4a1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_align.rs @@ -0,0 +1 @@ +pub type ScrollSnapAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_stop.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_stop.rs new file mode 100644 index 00000000..16c3719b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_stop.rs @@ -0,0 +1 @@ +pub type ScrollSnapStop = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_type.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_type.rs new file mode 100644 index 00000000..872b519b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_snap_type.rs @@ -0,0 +1 @@ +pub type ScrollSnapType = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start.rs new file mode 100644 index 00000000..e6eb9db5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start.rs @@ -0,0 +1 @@ +pub type ScrollStart = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_block.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_block.rs new file mode 100644 index 00000000..e7f10b4e --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_block.rs @@ -0,0 +1 @@ +pub type ScrollStartBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_inline.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_inline.rs new file mode 100644 index 00000000..083b89ac --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_inline.rs @@ -0,0 +1 @@ +pub type ScrollStartInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target.rs new file mode 100644 index 00000000..7e44dba9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target.rs @@ -0,0 +1 @@ +pub type ScrollStartTarget = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_block.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_block.rs new file mode 100644 index 00000000..ea1bb278 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_block.rs @@ -0,0 +1 @@ +pub type ScrollStartTargetBlock = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_inline.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_inline.rs new file mode 100644 index 00000000..c4c743b5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_inline.rs @@ -0,0 +1 @@ +pub type ScrollStartTargetInline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_x.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_x.rs new file mode 100644 index 00000000..be46f07c --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_x.rs @@ -0,0 +1 @@ +pub type ScrollStartTargetX = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_y.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_y.rs new file mode 100644 index 00000000..6f5aae2b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_target_y.rs @@ -0,0 +1 @@ +pub type ScrollStartTargetY = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_x.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_x.rs new file mode 100644 index 00000000..33b7ec30 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_x.rs @@ -0,0 +1 @@ +pub type ScrollStartX = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_y.rs b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_y.rs new file mode 100644 index 00000000..2d6a148b --- /dev/null +++ b/crates/hdx_ast/src/css/values/scroll_snap/scroll_start_y.rs @@ -0,0 +1 @@ +pub type ScrollStartY = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scrollbars/mod.rs b/crates/hdx_ast/src/css/values/scrollbars/mod.rs new file mode 100644 index 00000000..985f9ad2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scrollbars/mod.rs @@ -0,0 +1,4 @@ +mod scrollbar_color; +mod scrollbar_width; +pub use scrollbar_color::*; +pub use scrollbar_width::*; diff --git a/crates/hdx_ast/src/css/values/scrollbars/scrollbar_color.rs b/crates/hdx_ast/src/css/values/scrollbars/scrollbar_color.rs new file mode 100644 index 00000000..890073d7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/scrollbars/scrollbar_color.rs @@ -0,0 +1 @@ +pub type ScrollbarColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/scrollbars/scrollbar_width.rs b/crates/hdx_ast/src/css/values/scrollbars/scrollbar_width.rs new file mode 100644 index 00000000..f6d1c1cb --- /dev/null +++ b/crates/hdx_ast/src/css/values/scrollbars/scrollbar_width.rs @@ -0,0 +1 @@ +pub type ScrollbarWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/shapes.rs b/crates/hdx_ast/src/css/values/shapes.rs deleted file mode 100644 index a77acf39..00000000 --- a/crates/hdx_ast/src/css/values/shapes.rs +++ /dev/null @@ -1,122 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{BorderRadiusValue, LengthPercentage, PositionXY}; -use crate::{Box, Vec}; - -// https://drafts.csswg.org/css-shapes/#basic-shape-functions -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum BasicShape<'a> { - Inset(ShapeInset<'a>), - Xywh(ShapeXywh<'a>), - Rect(ShapeRect<'a>), - Circle(ShapeCircle<'a>), - Ellipse(ShapeEllipse<'a>), - Polygon(ShapePolygon<'a>), - Path(ShapePath<'a>), -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-inset -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapeInset<'a> { - rect: Box<'a, ShapeRect<'a>>, - radius: Box<'a, BorderRadiusValue<'a>>, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-xywh -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapeXywh<'a> { - rect: Box<'a, ShapeRect<'a>>, - radius: Box<'a, BorderRadiusValue<'a>>, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-rect -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapeRect<'a> { - top: Box<'a, LengthPercentage>, - right: Box<'a, LengthPercentage>, - bottom: Box<'a, LengthPercentage>, - left: Box<'a, LengthPercentage>, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-circle -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapeCircle<'a> { - radius: Box<'a, ShapeRadius>, - position: Box<'a, PositionXY>, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-ellipse -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapeEllipse<'a> { - rx: Box<'a, ShapeRadius>, - ry: Box<'a, ShapeRadius>, - position: Box<'a, PositionXY>, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-polygon -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapePolygon<'a> { - fill_rule: FillRule, - points: Vec<'a, Point>, -} - -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Point { - x: LengthPercentage, - y: LengthPercentage, -} - -// https://drafts.csswg.org/css-shapes/#funcdef-basic-shape-path -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct ShapePath<'a> { - fill_rule: FillRule, - path: Box<'a, &'a str>, -} - -// https://svgwg.org/svg2-draft/painting.html#FillRuleProperty -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum FillRule { - NonZero, - EvenOdd, -} - -// https://drafts.csswg.org/css-shapes/#typedef-shape-radius -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum ShapeRadius { - LengthPercentage(LengthPercentage), - ClosestSide, - FarthestSide, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 40); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 32); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 40); - assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 8); - } -} diff --git a/crates/hdx_ast/src/css/values/shapes/mod.rs b/crates/hdx_ast/src/css/values/shapes/mod.rs new file mode 100644 index 00000000..dbf82314 --- /dev/null +++ b/crates/hdx_ast/src/css/values/shapes/mod.rs @@ -0,0 +1,8 @@ +mod shape_image_threshold; +mod shape_margin; +mod shape_outside; +mod shape_padding; +pub use shape_image_threshold::*; +pub use shape_margin::*; +pub use shape_outside::*; +pub use shape_padding::*; diff --git a/crates/hdx_ast/src/css/values/shapes/shape_image_threshold.rs b/crates/hdx_ast/src/css/values/shapes/shape_image_threshold.rs new file mode 100644 index 00000000..5af39788 --- /dev/null +++ b/crates/hdx_ast/src/css/values/shapes/shape_image_threshold.rs @@ -0,0 +1 @@ +pub type ShapeImageThreshold = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/shapes/shape_margin.rs b/crates/hdx_ast/src/css/values/shapes/shape_margin.rs new file mode 100644 index 00000000..cd82d3b3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/shapes/shape_margin.rs @@ -0,0 +1 @@ +pub type ShapeMargin = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/shapes/shape_outside.rs b/crates/hdx_ast/src/css/values/shapes/shape_outside.rs new file mode 100644 index 00000000..00906154 --- /dev/null +++ b/crates/hdx_ast/src/css/values/shapes/shape_outside.rs @@ -0,0 +1 @@ +pub type ShapeOutside = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/shapes/shape_padding.rs b/crates/hdx_ast/src/css/values/shapes/shape_padding.rs new file mode 100644 index 00000000..d1495a98 --- /dev/null +++ b/crates/hdx_ast/src/css/values/shapes/shape_padding.rs @@ -0,0 +1 @@ +pub type ShapePadding = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/shorthand.rs b/crates/hdx_ast/src/css/values/shorthand.rs deleted file mode 100644 index 0f4e85c9..00000000 --- a/crates/hdx_ast/src/css/values/shorthand.rs +++ /dev/null @@ -1,44 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{Box, Spanned}; - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum Shorthand<'a, T> { - #[default] - Implicit, - Explicit(Box<'a, Spanned>), -} - -impl<'a, T> Shorthand<'a, T> { - #[inline] - pub fn is_implicit(&self) -> bool { - matches!(self, Self::Implicit) - } - - #[inline] - pub fn is_explicit(&self) -> bool { - !self.is_implicit() - } -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct BoxShorthand<'a, T> { - pub top: Shorthand<'a, T>, - pub right: Shorthand<'a, T>, - pub bottom: Shorthand<'a, T>, - pub left: Shorthand<'a, T>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct XYShorthand<'a, T> { - pub x: Shorthand<'a, T>, - pub y: Shorthand<'a, T>, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct DoubleShorthand<'a, T>(pub Shorthand<'a, T>, pub Shorthand<'a, T>); diff --git a/crates/hdx_ast/src/css/values/size_adjust.rs b/crates/hdx_ast/src/css/values/size_adjust.rs deleted file mode 100644 index 10272615..00000000 --- a/crates/hdx_ast/src/css/values/size_adjust.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -// https://drafts.csswg.org/css-size-adjust-1/#propdef-text-size-adjust -#[derive(Default, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum TextSizeAdjustValue { - None, - #[default] - Auto, - Percentage(f32), -} - -impl Hash for TextSizeAdjustValue { - fn hash(&self, state: &mut H) { - match self { - TextSizeAdjustValue::None => state.write_u8(0), - TextSizeAdjustValue::Auto => state.write_u8(1), - TextSizeAdjustValue::Percentage(v) => { - state.write_u8(2); - v.to_bits().hash(state); - } - } - } -} diff --git a/crates/hdx_ast/src/css/values/size_adjust/mod.rs b/crates/hdx_ast/src/css/values/size_adjust/mod.rs new file mode 100644 index 00000000..4ed0ef94 --- /dev/null +++ b/crates/hdx_ast/src/css/values/size_adjust/mod.rs @@ -0,0 +1,2 @@ +mod text_size_adjust; +pub use text_size_adjust::*; diff --git a/crates/hdx_ast/src/css/values/size_adjust/text_size_adjust.rs b/crates/hdx_ast/src/css/values/size_adjust/text_size_adjust.rs new file mode 100644 index 00000000..8f59c190 --- /dev/null +++ b/crates/hdx_ast/src/css/values/size_adjust/text_size_adjust.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{css::values::units::CSSFloat, Parsable, Writable}; + +// https://drafts.csswg.org/css-size-adjust-1/#propdef-text-size-adjust +#[derive(Parsable, Writable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum TextSizeAdjust { + None, + #[default] + Auto, + #[writable(suffix = "%")] + #[parsable(Dimension, atom = "%")] + Percentage(CSSFloat), +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + } +} diff --git a/crates/hdx_ast/src/css/values/sizing.rs b/crates/hdx_ast/src/css/values/sizing.rs deleted file mode 100644 index 8cd3f8d3..00000000 --- a/crates/hdx_ast/src/css/values/sizing.rs +++ /dev/null @@ -1,77 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::LengthPercentage; -use crate::{atom, Atom, Atomizable, Spanned}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-box-sizing -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BoxSizingValue { - #[default] - ContentBox, // atom!("content-box") - BorderBox, // atom!("border-box") -} - -// https://drafts.csswg.org/css-sizing-4/#sizing-values -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum Sizing { - #[default] - Auto, - LengthPercentage(Spanned), - MinContent, - MaxContent, // TODO: `intrinsic` non standard - FitContentFunction(Spanned), - // https://drafts.csswg.org/css-sizing-4/#sizing-values - Stretch, // TODO: -webkit-fill-available, -moz-available - FitContent, - Contain, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum MaxSizing { - #[default] - None, - LengthPercentage(Spanned), - MinContent, - MaxContent, - FitContentFunction(Spanned), - // https://drafts.csswg.org/css-sizing-4/#sizing-values - Stretch, - FitContent, - Contain, -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum RatioOrAuto { - #[default] - Auto, - Ratio((u32, u32)), -} - -// https://drafts.csswg.org/css-sizing-4/#intrinsic-contribution-override -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum MinIntrinsicSizingValue { - #[default] - Legacy, // atom!("legacy") - ZeroIfScroll, // atom!("zero-if-scroll") - ZeroIfExtrinsic, // atom!("zero-if-extrinsic") -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 20); - assert_eq!(size_of::(), 20); - assert_eq!(size_of::(), 12); - } -} diff --git a/crates/hdx_ast/src/css/values/sizing/aspec_ratio.rs b/crates/hdx_ast/src/css/values/sizing/aspec_ratio.rs new file mode 100644 index 00000000..6a991f1c --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/aspec_ratio.rs @@ -0,0 +1 @@ +pub type AspecRatio = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/box_sizing.rs b/crates/hdx_ast/src/css/values/sizing/box_sizing.rs new file mode 100644 index 00000000..bcc75688 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/box_sizing.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-sizing/#propdef-box-sizing +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BoxSizing { + #[default] + ContentBox, // atom!("content-box") + BorderBox, // atom!("border-box") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_block_size.rs b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_block_size.rs new file mode 100644 index 00000000..15d41c7c --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_block_size.rs @@ -0,0 +1 @@ +pub type ContainIntrinsicBlockSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_height.rs b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_height.rs new file mode 100644 index 00000000..c5787753 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_height.rs @@ -0,0 +1 @@ +pub type ContainIntrinsicHeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_inline_size.rs b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_inline_size.rs new file mode 100644 index 00000000..04892f19 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_inline_size.rs @@ -0,0 +1 @@ +pub type ContainIntrinsicInlineSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_size.rs b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_size.rs new file mode 100644 index 00000000..271d1e07 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_size.rs @@ -0,0 +1 @@ +pub type ContainIntrinsicSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_width.rs b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_width.rs new file mode 100644 index 00000000..2355e5c1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/contain_intrinsic_width.rs @@ -0,0 +1 @@ +pub type ContainIntrinsicWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/height.rs b/crates/hdx_ast/src/css/values/sizing/height.rs new file mode 100644 index 00000000..f1e4dc26 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/height.rs @@ -0,0 +1 @@ +pub type Height = super::Width; diff --git a/crates/hdx_ast/src/css/values/sizing/max_height.rs b/crates/hdx_ast/src/css/values/sizing/max_height.rs new file mode 100644 index 00000000..f34792a9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/max_height.rs @@ -0,0 +1 @@ +pub type MaxHeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/max_width.rs b/crates/hdx_ast/src/css/values/sizing/max_width.rs new file mode 100644 index 00000000..2f21f2be --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/max_width.rs @@ -0,0 +1 @@ +pub type MaxWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/min_height.rs b/crates/hdx_ast/src/css/values/sizing/min_height.rs new file mode 100644 index 00000000..799d61c9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/min_height.rs @@ -0,0 +1 @@ +pub type MinHeight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/min_intrinsic_sizing.rs b/crates/hdx_ast/src/css/values/sizing/min_intrinsic_sizing.rs new file mode 100644 index 00000000..03487e7a --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/min_intrinsic_sizing.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-sizing-4/#propdef-min-intrinsic-sizing +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum MinIntrinsicSizing { + #[default] + Legacy, // atom!("legacy") + ZeroIfScroll, // atom!("zero-if-scroll") + ZeroIfExtrinsic, // atom!("zero-if-extrinsic") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/sizing/min_width.rs b/crates/hdx_ast/src/css/values/sizing/min_width.rs new file mode 100644 index 00000000..2ec1c1aa --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/min_width.rs @@ -0,0 +1 @@ +pub type MinWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/sizing/mod.rs b/crates/hdx_ast/src/css/values/sizing/mod.rs new file mode 100644 index 00000000..52aa8cc0 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/mod.rs @@ -0,0 +1,28 @@ +mod aspec_ratio; +mod box_sizing; +mod contain_intrinsic_block_size; +mod contain_intrinsic_height; +mod contain_intrinsic_inline_size; +mod contain_intrinsic_size; +mod contain_intrinsic_width; +mod height; +mod max_height; +mod max_width; +mod min_height; +mod min_intrinsic_sizing; +mod min_width; +mod width; +pub use aspec_ratio::*; +pub use box_sizing::*; +pub use contain_intrinsic_block_size::*; +pub use contain_intrinsic_height::*; +pub use contain_intrinsic_inline_size::*; +pub use contain_intrinsic_size::*; +pub use contain_intrinsic_width::*; +pub use height::*; +pub use max_height::*; +pub use max_width::*; +pub use min_height::*; +pub use min_intrinsic_sizing::*; +pub use min_width::*; +pub use width::*; diff --git a/crates/hdx_ast/src/css/values/sizing/width.rs b/crates/hdx_ast/src/css/values/sizing/width.rs new file mode 100644 index 00000000..765af082 --- /dev/null +++ b/crates/hdx_ast/src/css/values/sizing/width.rs @@ -0,0 +1,98 @@ +use hdx_atom::atom; +use hdx_lexer::Token; +use hdx_parser::{diagnostics, expect, unexpected, Parse, Parser, Result as ParserResult, Spanned}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::super::units::LengthPercentage; +use crate::Writable; + +// https://drafts.csswg.org/css-sizing-4/#sizing-values +#[derive(Writable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum Width { + #[default] + Auto, // atom!("auto") + MinContent, // atom!("min-content") + MaxContent, // atom!("max-content") TODO: `intrinsic` non standard + // https://drafts.csswg.org/css-sizing-4/#sizing-values + Stretch, // atom!("stretch") TODO: -webkit-fill-available, -moz-available + FitContent, // atom!("fit-content") + Contain, // atom!("contain") + + LengthPercentage(LengthPercentage), + #[writable(as_function = "fit-content")] + FitContentFunction(LengthPercentage), +} + +impl<'a> Parse<'a> for Width { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Ident(atom!("auto")) => { + parser.advance(); + Ok(Self::Auto.spanned(span)) + } + Token::Ident(atom!("min-content")) => { + parser.advance(); + Ok(Self::MinContent.spanned(span)) + } + Token::Ident(atom!("max-content")) => { + parser.advance(); + Ok(Self::MaxContent.spanned(span)) + } + Token::Ident(atom!("stretch")) => { + parser.advance(); + Ok(Self::Stretch.spanned(span)) + } + Token::Ident(atom!("fit-content")) => { + parser.advance(); + Ok(Self::FitContent.spanned(span)) + } + Token::Ident(atom!("contain")) => { + parser.advance(); + Ok(Self::Contain.spanned(span)) + } + Token::Dimension(val, unit, _) => { + if val < 0.0 { + Err(diagnostics::NumberNotNegative(val, span))? + } + if let Some(val) = LengthPercentage::new(val.into(), unit.clone()) { + Ok(Self::LengthPercentage(val).spanned(span)) + } else { + Err(diagnostics::UnexpectedDimension(unit, span))? + } + } + Token::Number(val, _) if val == 0.0 => { + parser.advance(); + Ok(Self::LengthPercentage(LengthPercentage::Zero).spanned(span)) + } + Token::Function(atom!("fit-content")) => { + parser.advance(); + match parser.cur() { + Token::Dimension(val, unit, _) => { + if val < 0.0 { + Err(diagnostics::NumberNotNegative(val, span))? + } + if let Some(val) = LengthPercentage::new(val.into(), unit.clone()) { + parser.advance(); + expect!(parser, Token::RightParen); + parser.advance(); + Ok(Self::LengthPercentage(val).spanned(span)) + } else { + Err(diagnostics::UnexpectedDimension(unit, span))? + } + } + Token::Number(val, _) if val == 0.0 => { + parser.advance(); + expect!(parser, Token::RightParen); + parser.advance(); + Ok(Self::LengthPercentage(LengthPercentage::Zero).spanned(span)) + } + token => unexpected!(parser, token), + } + } + token => unexpected!(parser, token), + } + } +} diff --git a/crates/hdx_ast/src/css/values/speech/cue.rs b/crates/hdx_ast/src/css/values/speech/cue.rs new file mode 100644 index 00000000..5ce05044 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/cue.rs @@ -0,0 +1 @@ +pub type Cue = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/cue_after.rs b/crates/hdx_ast/src/css/values/speech/cue_after.rs new file mode 100644 index 00000000..a4752ad2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/cue_after.rs @@ -0,0 +1 @@ +pub type CueAfter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/cue_before.rs b/crates/hdx_ast/src/css/values/speech/cue_before.rs new file mode 100644 index 00000000..fb00dcf8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/cue_before.rs @@ -0,0 +1 @@ +pub type CueBefore = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/mod.rs b/crates/hdx_ast/src/css/values/speech/mod.rs new file mode 100644 index 00000000..6484aaf8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/mod.rs @@ -0,0 +1,38 @@ +mod cue; +mod cue_after; +mod cue_before; +mod pause; +mod pause_after; +mod pause_before; +mod rest; +mod rest_after; +mod rest_before; +mod speak; +mod speak_as; +mod voice_balance; +mod voice_duration; +mod voice_family; +mod voice_pitch; +mod voice_range; +mod voice_rate; +mod voice_stress; +mod voice_volume; +pub use cue::*; +pub use cue_after::*; +pub use cue_before::*; +pub use pause::*; +pub use pause_after::*; +pub use pause_before::*; +pub use rest::*; +pub use rest_after::*; +pub use rest_before::*; +pub use speak::*; +pub use speak_as::*; +pub use voice_balance::*; +pub use voice_duration::*; +pub use voice_family::*; +pub use voice_pitch::*; +pub use voice_range::*; +pub use voice_rate::*; +pub use voice_stress::*; +pub use voice_volume::*; diff --git a/crates/hdx_ast/src/css/values/speech/pause.rs b/crates/hdx_ast/src/css/values/speech/pause.rs new file mode 100644 index 00000000..adc29040 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/pause.rs @@ -0,0 +1 @@ +pub type Pause = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/pause_after.rs b/crates/hdx_ast/src/css/values/speech/pause_after.rs new file mode 100644 index 00000000..10354ea3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/pause_after.rs @@ -0,0 +1 @@ +pub type PauseAfter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/pause_before.rs b/crates/hdx_ast/src/css/values/speech/pause_before.rs new file mode 100644 index 00000000..9eb6fb26 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/pause_before.rs @@ -0,0 +1 @@ +pub type PauseBefore = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/rest.rs b/crates/hdx_ast/src/css/values/speech/rest.rs new file mode 100644 index 00000000..a2405f53 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/rest.rs @@ -0,0 +1 @@ +pub type Rest = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/rest_after.rs b/crates/hdx_ast/src/css/values/speech/rest_after.rs new file mode 100644 index 00000000..8b2288ea --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/rest_after.rs @@ -0,0 +1 @@ +pub type RestAfter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/rest_before.rs b/crates/hdx_ast/src/css/values/speech/rest_before.rs new file mode 100644 index 00000000..60b12715 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/rest_before.rs @@ -0,0 +1 @@ +pub type RestBefore = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/speak.rs b/crates/hdx_ast/src/css/values/speech/speak.rs new file mode 100644 index 00000000..13e11736 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/speak.rs @@ -0,0 +1 @@ +pub type Speak = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/speak_as.rs b/crates/hdx_ast/src/css/values/speech/speak_as.rs new file mode 100644 index 00000000..b4784614 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/speak_as.rs @@ -0,0 +1 @@ +pub type SpeakAs = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_balance.rs b/crates/hdx_ast/src/css/values/speech/voice_balance.rs new file mode 100644 index 00000000..09f3153d --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_balance.rs @@ -0,0 +1 @@ +pub type VoiceBalance = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_duration.rs b/crates/hdx_ast/src/css/values/speech/voice_duration.rs new file mode 100644 index 00000000..cc82db79 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_duration.rs @@ -0,0 +1 @@ +pub type VoiceDuration = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_family.rs b/crates/hdx_ast/src/css/values/speech/voice_family.rs new file mode 100644 index 00000000..e1798e34 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_family.rs @@ -0,0 +1 @@ +pub type VoiceFamily = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_pitch.rs b/crates/hdx_ast/src/css/values/speech/voice_pitch.rs new file mode 100644 index 00000000..ec5f28d7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_pitch.rs @@ -0,0 +1 @@ +pub type VoicePitch = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_range.rs b/crates/hdx_ast/src/css/values/speech/voice_range.rs new file mode 100644 index 00000000..87addb5c --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_range.rs @@ -0,0 +1 @@ +pub type VoiceRange = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_rate.rs b/crates/hdx_ast/src/css/values/speech/voice_rate.rs new file mode 100644 index 00000000..9979146a --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_rate.rs @@ -0,0 +1 @@ +pub type VoiceRate = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_stress.rs b/crates/hdx_ast/src/css/values/speech/voice_stress.rs new file mode 100644 index 00000000..d9168381 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_stress.rs @@ -0,0 +1 @@ +pub type VoiceStress = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/speech/voice_volume.rs b/crates/hdx_ast/src/css/values/speech/voice_volume.rs new file mode 100644 index 00000000..882c8c24 --- /dev/null +++ b/crates/hdx_ast/src/css/values/speech/voice_volume.rs @@ -0,0 +1 @@ +pub type VoiceVolume = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/tables.rs b/crates/hdx_ast/src/css/values/tables.rs deleted file mode 100644 index 7a4a5ec6..00000000 --- a/crates/hdx_ast/src/css/values/tables.rs +++ /dev/null @@ -1,47 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{ColorValue, Expr, MathExpr, PositiveLength, Shorthand}; -use crate::{atom, Atom, Atomizable, Span}; - -// https://drafts.csswg.org/css-tables-3/#propdef-border-collapse -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum BorderCollapseValue { - #[default] - Separate, // atom!("separate") - Collapse, // atom!("collapse") -} - -// https://drafts.csswg.org/css-tables-3/#propdef-caption-side -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum CaptionSideValue { - #[default] - Top, // atom!("top") - Bottom, // atom!("bottom") -} - -// https://drafts.csswg.org/css-tables-3/#propdef-caption-side -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum EmptyCellsValue { - #[default] - Show, // atom!("show") - Hide, // atom!("hide") -} - -// https://drafts.csswg.org/css-tables-3/#propdef-caption-side -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TableLayoutValue { - #[default] - Auto, // atom!("auto") - Fixed, // atom!("fixed") -} - -// atom!("border-collapse") => BorderCollapse>, -// atom!("border-spacing") => BorderSpacing>, -// atom!("caption-side") => CaptionSide>, -// atom!("empty-cells") => EmptyCells>, -// atom!("table-layout") => TableLayout>, diff --git a/crates/hdx_ast/src/css/values/tables/border_collapse.rs b/crates/hdx_ast/src/css/values/tables/border_collapse.rs new file mode 100644 index 00000000..ba8dfe44 --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/border_collapse.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-tables-3/#propdef-border-collapse +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum BorderCollapse { + #[default] + Separate, // atom!("separate") + Collapse, // atom!("collapse") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/tables/border_spacing.rs b/crates/hdx_ast/src/css/values/tables/border_spacing.rs new file mode 100644 index 00000000..6315edaa --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/border_spacing.rs @@ -0,0 +1 @@ +pub type BorderSpacing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/tables/caption_side.rs b/crates/hdx_ast/src/css/values/tables/caption_side.rs new file mode 100644 index 00000000..170d2f9b --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/caption_side.rs @@ -0,0 +1 @@ +pub type CaptionSide = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/tables/empty_cells.rs b/crates/hdx_ast/src/css/values/tables/empty_cells.rs new file mode 100644 index 00000000..d9ffba75 --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/empty_cells.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-tables-3/#propdef-empty-cells +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum EmptyCells { + #[default] + Show, // atom!("show") + Hide, // atom!("hide") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/tables/mod.rs b/crates/hdx_ast/src/css/values/tables/mod.rs new file mode 100644 index 00000000..20cddf71 --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/mod.rs @@ -0,0 +1,10 @@ +mod border_collapse; +mod border_spacing; +mod caption_side; +mod empty_cells; +mod table_layout; +pub use border_collapse::*; +pub use border_spacing::*; +pub use caption_side::*; +pub use empty_cells::*; +pub use table_layout::*; diff --git a/crates/hdx_ast/src/css/values/tables/table_layout.rs b/crates/hdx_ast/src/css/values/tables/table_layout.rs new file mode 100644 index 00000000..c836d827 --- /dev/null +++ b/crates/hdx_ast/src/css/values/tables/table_layout.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-tables-3/#propdef-table-layout +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TableLayout { + #[default] + Auto, // atom!("auto") + Fixed, // atom!("fixed") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text.rs b/crates/hdx_ast/src/css/values/text.rs deleted file mode 100644 index 38df4f8e..00000000 --- a/crates/hdx_ast/src/css/values/text.rs +++ /dev/null @@ -1,122 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Expr, Shorthand}; -use crate::{atom, Atom, Atomizable}; - -// https://drafts.csswg.org/css-text-4/#propdef-text-align -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextAlignValue { - #[default] - Start, // atom!("start") - End, // atom!("end") - Left, // atom!("left") - Right, // atom!("right") - Center, // atom!("center") - Justify, // atom!("justify") - MatchParent, // atom!("match-parent") - JustifyAll, // atom!("justify-all") - // TODO: Custom? -} - -// https://drafts.csswg.org/css-text-4/#propdef-text-align-all -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextAlignAllValue { - #[default] - Start, // atom!("start") - End, // atom!("end") - Left, // atom!("left") - Right, // atom!("right") - Center, // atom!("center") - Justify, // atom!("justify") - MatchParent, // atom!("match-parent") -} - -// https://drafts.csswg.org/css-text-4/#propdef-text-align-last -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextAlignLastValue { - #[default] - Auto, // atom!("auto") - Start, // atom!("start") - End, // atom!("end") - Left, // atom!("left") - Right, // atom!("right") - Center, // atom!("center") - Justify, // atom!("justify") - MatchParent, // atom!("match-parent") -} - -// https://drafts.csswg.org/css-text-4/#propdef-text-wrap -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextWrapValue { - #[default] - Wrap, // atom!("wrap") - Nowrap, // atom!("nowrap") - Balance, // atom!("balance") - Stable, // atom!("stable") - Pretty, // atom!("pretty") -} - -// https://drafts.csswg.org/css-text-4/#propdef-white-space-collapse -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum WhiteSpaceCollapseValue { - #[default] - Collapse, // atom!("collapse") - Discard, // atom!("discard") - Preserve, // atom!("preserve") - PreserveBreaks, // atom!("preserve-breaks") - PreserveSpaces, // atom!("preserve-spaces") - BreakSpaces, // atom!("break-spaces") -} - -// https://drafts.csswg.org/css-text-4/#propdef-white-space-trim -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum WhiteSpaceTrimValue { - #[default] - None, - Discard { - before: bool, - after: bool, - inner: bool, - }, -} - -// https://drafts.csswg.org/css-text-4/#propdef-white-space -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum WhiteSpaceShorthand<'a> { - #[default] - Normal, - Pre, - Nowrap, - PreWrap, - PreLine, - Expanded { - collapse: Shorthand<'a, Expr<'a, WhiteSpaceCollapseValue>>, - wrap: Shorthand<'a, Expr<'a, TextWrapValue>>, - trim: Shorthand<'a, Expr<'a, WhiteSpaceTrimValue>>, - }, -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 3); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 32); - } -} diff --git a/crates/hdx_ast/src/css/values/text/hanging_punctuation.rs b/crates/hdx_ast/src/css/values/text/hanging_punctuation.rs new file mode 100644 index 00000000..69be7498 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hanging_punctuation.rs @@ -0,0 +1 @@ +pub type HangingPunctuation = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphenate_character.rs b/crates/hdx_ast/src/css/values/text/hyphenate_character.rs new file mode 100644 index 00000000..8737d067 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphenate_character.rs @@ -0,0 +1 @@ +pub type HyphenateCharacter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphenate_limit_chars.rs b/crates/hdx_ast/src/css/values/text/hyphenate_limit_chars.rs new file mode 100644 index 00000000..7ee15e01 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphenate_limit_chars.rs @@ -0,0 +1 @@ +pub type HyphenateLimitChars = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphenate_limit_last.rs b/crates/hdx_ast/src/css/values/text/hyphenate_limit_last.rs new file mode 100644 index 00000000..9427a028 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphenate_limit_last.rs @@ -0,0 +1 @@ +pub type HyphenateLimitLast = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphenate_limit_lines.rs b/crates/hdx_ast/src/css/values/text/hyphenate_limit_lines.rs new file mode 100644 index 00000000..b379bc76 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphenate_limit_lines.rs @@ -0,0 +1 @@ +pub type HyphenateLimitLines = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphenate_limit_zone.rs b/crates/hdx_ast/src/css/values/text/hyphenate_limit_zone.rs new file mode 100644 index 00000000..4e616337 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphenate_limit_zone.rs @@ -0,0 +1 @@ +pub type HyphenateLimitZone = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/hyphens.rs b/crates/hdx_ast/src/css/values/text/hyphens.rs new file mode 100644 index 00000000..fdc0fafe --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/hyphens.rs @@ -0,0 +1 @@ +pub type Hyphens = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/letter_spacing.rs b/crates/hdx_ast/src/css/values/text/letter_spacing.rs new file mode 100644 index 00000000..ae92db9b --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/letter_spacing.rs @@ -0,0 +1 @@ +pub type LetterSpacing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/line_break.rs b/crates/hdx_ast/src/css/values/text/line_break.rs new file mode 100644 index 00000000..b5bc3439 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/line_break.rs @@ -0,0 +1 @@ +pub type LineBreak = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/line_padding.rs b/crates/hdx_ast/src/css/values/text/line_padding.rs new file mode 100644 index 00000000..69d66f30 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/line_padding.rs @@ -0,0 +1 @@ +pub type LinePadding = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/mod.rs b/crates/hdx_ast/src/css/values/text/mod.rs new file mode 100644 index 00000000..93fd614b --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/mod.rs @@ -0,0 +1,68 @@ +mod hanging_punctuation; +mod hyphenate_character; +mod hyphenate_limit_chars; +mod hyphenate_limit_last; +mod hyphenate_limit_lines; +mod hyphenate_limit_zone; +mod hyphens; +mod letter_spacing; +mod line_break; +mod line_padding; +mod overflow_wrap; +mod tab_size; +mod text_align; +mod text_align_all; +mod text_align_last; +mod text_autospace; +mod text_group_align; +mod text_indent; +mod text_justify; +mod text_spacing; +mod text_spacing_trim; +mod text_transform; +mod text_wrap; +mod white_space; +mod white_space_collapse; +mod white_space_trim; +mod word_boundary_detection; +mod word_boundary_expansion; +mod word_break; +mod word_spacing; +mod word_wrap; +mod wrap_after; +mod wrap_before; +mod wrap_inside; +pub use hanging_punctuation::*; +pub use hyphenate_character::*; +pub use hyphenate_limit_chars::*; +pub use hyphenate_limit_last::*; +pub use hyphenate_limit_lines::*; +pub use hyphenate_limit_zone::*; +pub use hyphens::*; +pub use letter_spacing::*; +pub use line_break::*; +pub use line_padding::*; +pub use overflow_wrap::*; +pub use tab_size::*; +pub use text_align::*; +pub use text_align_all::*; +pub use text_align_last::*; +pub use text_autospace::*; +pub use text_group_align::*; +pub use text_indent::*; +pub use text_justify::*; +pub use text_spacing::*; +pub use text_spacing_trim::*; +pub use text_transform::*; +pub use text_wrap::*; +pub use white_space::*; +pub use white_space_collapse::*; +pub use white_space_trim::*; +pub use word_boundary_detection::*; +pub use word_boundary_expansion::*; +pub use word_break::*; +pub use word_spacing::*; +pub use word_wrap::*; +pub use wrap_after::*; +pub use wrap_before::*; +pub use wrap_inside::*; diff --git a/crates/hdx_ast/src/css/values/text/overflow_wrap.rs b/crates/hdx_ast/src/css/values/text/overflow_wrap.rs new file mode 100644 index 00000000..15567d0c --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/overflow_wrap.rs @@ -0,0 +1 @@ +pub type OverflowWrap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/tab_size.rs b/crates/hdx_ast/src/css/values/text/tab_size.rs new file mode 100644 index 00000000..128e311a --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/tab_size.rs @@ -0,0 +1 @@ +pub type TabSize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_align.rs b/crates/hdx_ast/src/css/values/text/text_align.rs new file mode 100644 index 00000000..37d8b065 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_align.rs @@ -0,0 +1,31 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text-4/#propdef-text-align +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextAlign { + #[default] + Start, // atom!("start") + End, // atom!("end") + Left, // atom!("left") + Right, // atom!("right") + Center, // atom!("center") + Justify, // atom!("justify") + MatchParent, // atom!("match-parent") + JustifyAll, /* atom!("justify-all") + * TODO: Custom? */ +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/text_align_all.rs b/crates/hdx_ast/src/css/values/text/text_align_all.rs new file mode 100644 index 00000000..c995511a --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_align_all.rs @@ -0,0 +1,29 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text-4/#propdef-text-align-all +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextAlignAll { + #[default] + Start, // atom!("start") + End, // atom!("end") + Left, // atom!("left") + Right, // atom!("right") + Center, // atom!("center") + Justify, // atom!("justify") + MatchParent, // atom!("match-parent") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/text_align_last.rs b/crates/hdx_ast/src/css/values/text/text_align_last.rs new file mode 100644 index 00000000..c42c7a7f --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_align_last.rs @@ -0,0 +1,30 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text-4/#propdef-text-align-last +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextAlignLast { + #[default] + Auto, // atom!("auto") + Start, // atom!("start") + End, // atom!("end") + Left, // atom!("left") + Right, // atom!("right") + Center, // atom!("center") + Justify, // atom!("justify") + MatchParent, // atom!("match-parent") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/text_autospace.rs b/crates/hdx_ast/src/css/values/text/text_autospace.rs new file mode 100644 index 00000000..06d3d672 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_autospace.rs @@ -0,0 +1 @@ +pub type TextAutospace = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_group_align.rs b/crates/hdx_ast/src/css/values/text/text_group_align.rs new file mode 100644 index 00000000..9dde1ede --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_group_align.rs @@ -0,0 +1 @@ +pub type TextGroupAlign = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_indent.rs b/crates/hdx_ast/src/css/values/text/text_indent.rs new file mode 100644 index 00000000..eedb6428 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_indent.rs @@ -0,0 +1 @@ +pub type TextIndent = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_justify.rs b/crates/hdx_ast/src/css/values/text/text_justify.rs new file mode 100644 index 00000000..28437dcb --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_justify.rs @@ -0,0 +1 @@ +pub type TextJustify = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_spacing.rs b/crates/hdx_ast/src/css/values/text/text_spacing.rs new file mode 100644 index 00000000..ba06472d --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_spacing.rs @@ -0,0 +1 @@ +pub type TextSpacing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_spacing_trim.rs b/crates/hdx_ast/src/css/values/text/text_spacing_trim.rs new file mode 100644 index 00000000..6d727d28 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_spacing_trim.rs @@ -0,0 +1 @@ +pub type TextSpacingTrim = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_transform.rs b/crates/hdx_ast/src/css/values/text/text_transform.rs new file mode 100644 index 00000000..3ee78107 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_transform.rs @@ -0,0 +1 @@ +pub type TextTransform = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/text_wrap.rs b/crates/hdx_ast/src/css/values/text/text_wrap.rs new file mode 100644 index 00000000..a30cc73b --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/text_wrap.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text-4/#propdef-text-wrap +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextWrap { + #[default] + Wrap, // atom!("wrap") + Nowrap, // atom!("nowrap") + Balance, // atom!("balance") + Stable, // atom!("stable") + Pretty, // atom!("pretty") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/white_space.rs b/crates/hdx_ast/src/css/values/text/white_space.rs new file mode 100644 index 00000000..1d8a3941 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/white_space.rs @@ -0,0 +1 @@ +pub type WhiteSpace = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/white_space_collapse.rs b/crates/hdx_ast/src/css/values/text/white_space_collapse.rs new file mode 100644 index 00000000..4b3ef718 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/white_space_collapse.rs @@ -0,0 +1,28 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text-4/#propdef-white-space-collapse +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum WhiteSpaceCollapse { + #[default] + Collapse, // atom!("collapse") + Discard, // atom!("discard") + Preserve, // atom!("preserve") + PreserveBreaks, // atom!("preserve-breaks") + PreserveSpaces, // atom!("preserve-spaces") + BreakSpaces, // atom!("break-spaces") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/white_space_trim.rs b/crates/hdx_ast/src/css/values/text/white_space_trim.rs new file mode 100644 index 00000000..049f2802 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/white_space_trim.rs @@ -0,0 +1,88 @@ +use hdx_atom::atom; +use hdx_lexer::Token; +use hdx_parser::{Parse, Parser, Result as ParserResult, unexpected, Spanned}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{bitmask, Atomizable}; + +// https://drafts.csswg.org/css-text-4/#propdef-white-space-trim +#[derive(Default, Atomizable)] +#[bitmask(u8)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum WhiteSpaceTrim { + #[default] + None = 0b0000, // atom!("none") + DiscardBefore = 0b0001, // atom!("discard-before") + DiscardAfter = 0b0010, // atom!("discard-after") + DiscardInner = 0b0100, // atom!("discard-inner") +} + +impl<'a> Parse<'a> for WhiteSpaceTrim { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut value = Self::none(); + loop { + if value.is_all() { + break; + } + match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + atom!("none") if value.is_none() => { + return Ok(Self::None.spanned(span.end(parser.pos()))); + } + atom!("discard-before") if !value.contains(Self::DiscardBefore) => { + value |= Self::DiscardBefore + } + atom!("discard-after") if !value.contains(Self::DiscardAfter) => { + value |= Self::DiscardAfter + } + atom!("discard-inner") if !value.contains(Self::DiscardInner) => { + value |= Self::DiscardInner + }, + _ => break + }, + token => unexpected!(parser, token) + } + parser.advance(); + } + Ok(value.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for WhiteSpaceTrim { + fn write_css(&self, sink: &mut W) -> WriterResult { + if self.is_none() { + sink.write_str("none")?; + } else { + if self.contains(Self::DiscardBefore) { + sink.write_str("discard-before")?; + } + if self.contains(Self::DiscardAfter) { + if self.intersects(Self::DiscardBefore) { + sink.write_char(' ')?; + } + sink.write_str("discard-after")?; + } + if self.contains(Self::DiscardInner) { + if self.intersects(Self::DiscardBefore | Self::DiscardAfter) { + sink.write_char(' ')?; + } + sink.write_str("discard-inner")?; + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text/word_boundary_detection.rs b/crates/hdx_ast/src/css/values/text/word_boundary_detection.rs new file mode 100644 index 00000000..97e1fcd3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/word_boundary_detection.rs @@ -0,0 +1 @@ +pub type WordBoundaryDetection = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/word_boundary_expansion.rs b/crates/hdx_ast/src/css/values/text/word_boundary_expansion.rs new file mode 100644 index 00000000..995e988d --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/word_boundary_expansion.rs @@ -0,0 +1 @@ +pub type WordBoundaryExpansion = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/word_break.rs b/crates/hdx_ast/src/css/values/text/word_break.rs new file mode 100644 index 00000000..a4813c57 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/word_break.rs @@ -0,0 +1 @@ +pub type WordBreak = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/word_spacing.rs b/crates/hdx_ast/src/css/values/text/word_spacing.rs new file mode 100644 index 00000000..55fc0985 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/word_spacing.rs @@ -0,0 +1 @@ +pub type WordSpacing = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/word_wrap.rs b/crates/hdx_ast/src/css/values/text/word_wrap.rs new file mode 100644 index 00000000..5e91aaa5 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/word_wrap.rs @@ -0,0 +1 @@ +pub type WordWrap = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/wrap_after.rs b/crates/hdx_ast/src/css/values/text/wrap_after.rs new file mode 100644 index 00000000..69b5183e --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/wrap_after.rs @@ -0,0 +1 @@ +pub type WrapAfter = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/wrap_before.rs b/crates/hdx_ast/src/css/values/text/wrap_before.rs new file mode 100644 index 00000000..65533d27 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/wrap_before.rs @@ -0,0 +1 @@ +pub type WrapBefore = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text/wrap_inside.rs b/crates/hdx_ast/src/css/values/text/wrap_inside.rs new file mode 100644 index 00000000..93fe14ad --- /dev/null +++ b/crates/hdx_ast/src/css/values/text/wrap_inside.rs @@ -0,0 +1 @@ +pub type WrapInside = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor.rs b/crates/hdx_ast/src/css/values/text_decor.rs deleted file mode 100644 index 7b57d91a..00000000 --- a/crates/hdx_ast/src/css/values/text_decor.rs +++ /dev/null @@ -1,64 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{ColorValue, Expr, MathExpr, Shorthand}; -use crate::{atom, Atom, Atomizable, Box}; - -// https://drafts.csswg.org/css-text/#text-align-property -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct TextDecorationShorthand<'a> { - pub line: Shorthand<'a, Expr<'a, TextDecorationLineValue>>, - pub style: Shorthand<'a, Expr<'a, TextDecorationStyleValue>>, - pub color: Shorthand<'a, MathExpr<'a, ColorValue<'a>>>, -} - -// https://drafts.csswg.org/css-text/#text-align-property -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum TextDecorationLineValue { - #[default] - None, - Style { - underline: bool, - overline: bool, - line_through: bool, - blink: bool, - }, -} - -// https://drafts.csswg.org/css-text/#text-align-property -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextDecorationSkipInkValue { - #[default] - Auto, // atom!("auto") - None, // atom!("none") - All, // atom!("all") -} - -// https://drafts.csswg.org/css-text/#text-align-property -#[derive(Atomizable, Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] -pub enum TextDecorationStyleValue { - #[default] - Solid, // atom!("solid"), - Double, // atom!("double") - Dotted, // atom!("dotted") - Dashed, // atom!("dashed") - Wavy, // atom!("wavy") -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 24); - assert_eq!(size_of::(), 1); - assert_eq!(size_of::(), 1); - } -} diff --git a/crates/hdx_ast/src/css/values/text_decor/mod.rs b/crates/hdx_ast/src/css/values/text_decor/mod.rs new file mode 100644 index 00000000..dccff203 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/mod.rs @@ -0,0 +1,36 @@ +mod text_decoration; +mod text_decoration_color; +mod text_decoration_line; +mod text_decoration_skip; +mod text_decoration_skip_ink; +mod text_decoration_skip_self; +mod text_decoration_skip_spaces; +mod text_decoration_style; +mod text_decoration_thickness; +mod text_decoration_trim; +mod text_emphasis; +mod text_emphasis_color; +mod text_emphasis_position; +mod text_emphasis_skip; +mod text_emphasis_style; +mod text_shadow; +mod text_underline_offset; +mod text_underline_position; +pub use text_decoration::*; +pub use text_decoration_color::*; +pub use text_decoration_line::*; +pub use text_decoration_skip::*; +pub use text_decoration_skip_ink::*; +pub use text_decoration_skip_self::*; +pub use text_decoration_skip_spaces::*; +pub use text_decoration_style::*; +pub use text_decoration_thickness::*; +pub use text_decoration_trim::*; +pub use text_emphasis::*; +pub use text_emphasis_color::*; +pub use text_emphasis_position::*; +pub use text_emphasis_skip::*; +pub use text_emphasis_style::*; +pub use text_shadow::*; +pub use text_underline_offset::*; +pub use text_underline_position::*; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration.rs new file mode 100644 index 00000000..819424e4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration.rs @@ -0,0 +1 @@ +pub type TextDecoration = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_color.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_color.rs new file mode 100644 index 00000000..129ae4af --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_color.rs @@ -0,0 +1 @@ +pub type TextDecorationColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_line.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_line.rs new file mode 100644 index 00000000..f2f8129d --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_line.rs @@ -0,0 +1,90 @@ +use hdx_atom::atom; +use hdx_lexer::Token; +use hdx_parser::{unexpected, Parse, Parser, Result as ParserResult, Spanned}; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::bitmask; + +// https://drafts.csswg.org/css-text/#text-align-property +#[derive(Default)] +#[bitmask(u8)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum TextDecorationLine { + #[default] + None = 0b0000, + Underline = 0b0001, + Overline = 0b0010, + LineThrough = 0b0100, + Blink = 0b1000, +} + +impl<'a> Parse<'a> for TextDecorationLine { + fn parse(parser: &mut Parser<'a>) -> ParserResult> { + let span = parser.span(); + let mut value = Self::none(); + loop { + if value.is_all() { + break; + } + match parser.cur() { + Token::Ident(atom) => match atom.to_ascii_lowercase() { + atom!("none") if value.is_none() => { + return Ok(Self::None.spanned(span.end(parser.pos()))); + } + atom!("underline") if !value.contains(Self::Underline) => value |= Self::Underline, + atom!("overline") if !value.contains(Self::Overline) => value |= Self::Overline, + atom!("line-through") if !value.contains(Self::LineThrough) => value |= Self::LineThrough, + atom!("blink") if !value.contains(Self::Blink) => value |= Self::Blink, + _ => break, + }, + token => unexpected!(parser, token), + } + parser.advance(); + } + Ok(value.spanned(span.end(parser.pos()))) + } +} + +impl<'a> WriteCss<'a> for TextDecorationLine { + fn write_css(&self, sink: &mut W) -> WriterResult { + if self.is_none() { + sink.write_str("none")?; + } else { + if self.contains(Self::Underline) { + sink.write_str("underline")?; + } + if self.contains(Self::Overline) { + if self.intersects(Self::Overline) { + sink.write_char(' ')?; + } + sink.write_str("overline")?; + } + if self.contains(Self::LineThrough) { + if self.intersects(Self::Underline | Self::Overline) { + sink.write_char(' ')?; + } + sink.write_str("line-through")?; + } + if self.contains(Self::Blink) { + if self.intersects(Self::Underline | Self::Overline | Self::LineThrough) { + sink.write_char(' ')?; + } + sink.write_str("blink")?; + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip.rs new file mode 100644 index 00000000..129a0036 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip.rs @@ -0,0 +1 @@ +pub type TextDecorationSkip = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_ink.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_ink.rs new file mode 100644 index 00000000..d81fef02 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_ink.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text/#text-align-property +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextDecorationSkipInk { + #[default] + Auto, // atom!("auto") + None, // atom!("none") + All, // atom!("all") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_self.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_self.rs new file mode 100644 index 00000000..5e28dd81 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_self.rs @@ -0,0 +1 @@ +pub type TextDecorationSkipSelf = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_spaces.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_spaces.rs new file mode 100644 index 00000000..0a686b4d --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_skip_spaces.rs @@ -0,0 +1 @@ +pub type TextDecorationSkipSpaces = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_style.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_style.rs new file mode 100644 index 00000000..c77493eb --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_style.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-text/#text-align-property +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum TextDecorationStyle { + #[default] + Solid, // atom!("solid"), + Double, // atom!("double") + Dotted, // atom!("dotted") + Dashed, // atom!("dashed") + Wavy, // atom!("wavy") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_thickness.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_thickness.rs new file mode 100644 index 00000000..1ea3eb73 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_thickness.rs @@ -0,0 +1 @@ +pub type TextDecorationThickness = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_decoration_trim.rs b/crates/hdx_ast/src/css/values/text_decor/text_decoration_trim.rs new file mode 100644 index 00000000..fbd992ce --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_decoration_trim.rs @@ -0,0 +1 @@ +pub type TextDecorationTrim = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_emphasis.rs b/crates/hdx_ast/src/css/values/text_decor/text_emphasis.rs new file mode 100644 index 00000000..72512449 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_emphasis.rs @@ -0,0 +1 @@ +pub type TextEmphasis = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_emphasis_color.rs b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_color.rs new file mode 100644 index 00000000..44499477 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_color.rs @@ -0,0 +1 @@ +pub type TextEmphasisColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_emphasis_position.rs b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_position.rs new file mode 100644 index 00000000..97dac294 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_position.rs @@ -0,0 +1 @@ +pub type TextEmphasisPosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_emphasis_skip.rs b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_skip.rs new file mode 100644 index 00000000..47f20800 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_skip.rs @@ -0,0 +1 @@ +pub type TextEmphasisSkip = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_emphasis_style.rs b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_style.rs new file mode 100644 index 00000000..dae3dc9a --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_emphasis_style.rs @@ -0,0 +1 @@ +pub type TextEmphasisStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_shadow.rs b/crates/hdx_ast/src/css/values/text_decor/text_shadow.rs new file mode 100644 index 00000000..338f8faa --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_shadow.rs @@ -0,0 +1 @@ +pub type TextShadow = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_underline_offset.rs b/crates/hdx_ast/src/css/values/text_decor/text_underline_offset.rs new file mode 100644 index 00000000..303adee2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_underline_offset.rs @@ -0,0 +1 @@ +pub type TextUnderlineOffset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/text_decor/text_underline_position.rs b/crates/hdx_ast/src/css/values/text_decor/text_underline_position.rs new file mode 100644 index 00000000..94108d98 --- /dev/null +++ b/crates/hdx_ast/src/css/values/text_decor/text_underline_position.rs @@ -0,0 +1 @@ +pub type TextUnderlinePosition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/time.rs b/crates/hdx_ast/src/css/values/time.rs deleted file mode 100644 index 290496a7..00000000 --- a/crates/hdx_ast/src/css/values/time.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use crate::{atom, Atom, Atomizable, Unit}; - -// https://drafts.csswg.org/css-values/#time-value -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Time { - value: f32, - unit: TimeUnit, -} - -impl Unit for Time { - type Unit = TimeUnit; - - fn new(value: f32, unit: Self::Unit) -> Self { - Self { value, unit } - } -} - -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub enum TimeUnit { - #[default] - None, - - Seconds, - Milliseconds, -} - -impl Atomizable for TimeUnit { - fn to_atom(&self) -> Atom { - match self { - Self::None => atom!(""), - Self::Seconds => atom!("s"), - Self::Milliseconds => atom!("ms"), - } - } - - fn from_atom(unit: Atom) -> Option { - match unit { - atom!("s") => Some(Self::Seconds), - atom!("ms") => Some(Self::Milliseconds), - _ => None, - } - } -} - -impl Hash for Time { - fn hash(&self, state: &mut H) { - self.value.to_bits().hash(state); - self.unit.hash(state); - } -} diff --git a/crates/hdx_ast/src/css/values/transitions/mod.rs b/crates/hdx_ast/src/css/values/transitions/mod.rs new file mode 100644 index 00000000..ad8b0050 --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/mod.rs @@ -0,0 +1,10 @@ +mod transition; +mod transition_delay; +mod transition_duration; +mod transition_property; +mod transition_timing_function; +pub use transition::*; +pub use transition_delay::*; +pub use transition_duration::*; +pub use transition_property::*; +pub use transition_timing_function::*; diff --git a/crates/hdx_ast/src/css/values/transitions/transition.rs b/crates/hdx_ast/src/css/values/transitions/transition.rs new file mode 100644 index 00000000..21f4251e --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/transition.rs @@ -0,0 +1 @@ +pub type Transition = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/transitions/transition_delay.rs b/crates/hdx_ast/src/css/values/transitions/transition_delay.rs new file mode 100644 index 00000000..0834d5c4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/transition_delay.rs @@ -0,0 +1 @@ +pub type TransitionDelay = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/transitions/transition_duration.rs b/crates/hdx_ast/src/css/values/transitions/transition_duration.rs new file mode 100644 index 00000000..81e010e4 --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/transition_duration.rs @@ -0,0 +1 @@ +pub type TransitionDuration = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/transitions/transition_property.rs b/crates/hdx_ast/src/css/values/transitions/transition_property.rs new file mode 100644 index 00000000..2b7f7d67 --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/transition_property.rs @@ -0,0 +1 @@ +pub type TransitionProperty = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/transitions/transition_timing_function.rs b/crates/hdx_ast/src/css/values/transitions/transition_timing_function.rs new file mode 100644 index 00000000..f999c05d --- /dev/null +++ b/crates/hdx_ast/src/css/values/transitions/transition_timing_function.rs @@ -0,0 +1 @@ +pub type TransitionTimingFunction = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui.rs b/crates/hdx_ast/src/css/values/ui.rs deleted file mode 100644 index 327eba69..00000000 --- a/crates/hdx_ast/src/css/values/ui.rs +++ /dev/null @@ -1,135 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Expr, Length}; -use crate::{atom, Atom, Atomizable, Span}; - -// https://drafts.csswg.org/css-ui-4/#propdef-cursor -#[derive(Default, Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub enum CursorValue<'a> { - Custom(Expr<'a, Length>), // todo - #[default] - Auto, // atom!("auto") - Default, // atom!("default") - None, // atom!("none") - ContextMenu, // atom!("context-menu") - Help, // atom!("help") - Pointer, // atom!("pointer") - Progress, // atom!("progress") - Wait, // atom!("wait") - Cell, // atom!("cell") - Crosshair, // atom!("crosshair") - Text, // atom!("text") - VerticalText, // atom!("vertical-text") - Alias, // atom!("alias") - Copy, // atom!("copy") - Move, // atom!("move") - NoDrop, // atom!("no-drop") - NotAllowed, // atom!("not-allowed") - Grab, // atom!("grab") - Grabbing, // atom!("grabbing") - EResize, // atom!("e-resize") - NResize, // atom!("n-resize") - NeResize, // atom!("ne-resize") - NwResize, // atom!("nw-resize") - SResize, // atom!("s-resize") - SeResize, // atom!("se-resize") - SwResize, // atom!("sw-resize") - WResize, // atom!("w-resize") - EwResize, // atom!("ew-resize") - NsResize, // atom!("ns-resize") - NeswResize, // atom!("nesw-resize") - NwseResize, // atom!("nwse-resize") - ColResize, // atom!("col-resize") - RowResize, // atom!("row-resize") - AllResize, // atom!("all-resize") - ZoomIn, // atom!("zoom-in") - ZoomOut, // atom!("zoom-in") -} - -impl<'a> Atomizable for CursorValue<'a> { - fn from_atom(atom: Atom) -> Option { - match atom { - atom!("auto") => Some(Self::Auto), - atom!("default") => Some(Self::Default), - atom!("none") => Some(Self::None), - atom!("context-menu") => Some(Self::ContextMenu), - atom!("help") => Some(Self::Help), - atom!("pointer") => Some(Self::Pointer), - atom!("progress") => Some(Self::Progress), - atom!("wait") => Some(Self::Wait), - atom!("cell") => Some(Self::Cell), - atom!("crosshair") => Some(Self::Crosshair), - atom!("text") => Some(Self::Text), - atom!("vertical-text") => Some(Self::VerticalText), - atom!("alias") => Some(Self::Alias), - atom!("copy") => Some(Self::Copy), - atom!("move") => Some(Self::Move), - atom!("no-drop") => Some(Self::NoDrop), - atom!("not-allowed") => Some(Self::NotAllowed), - atom!("grab") => Some(Self::Grab), - atom!("grabbing") => Some(Self::Grabbing), - atom!("e-resize") => Some(Self::EResize), - atom!("n-resize") => Some(Self::NResize), - atom!("ne-resize") => Some(Self::NeResize), - atom!("nw-resize") => Some(Self::NwResize), - atom!("s-resize") => Some(Self::SResize), - atom!("se-resize") => Some(Self::SeResize), - atom!("sw-resize") => Some(Self::SwResize), - atom!("w-resize") => Some(Self::WResize), - atom!("ew-resize") => Some(Self::EwResize), - atom!("ns-resize") => Some(Self::NsResize), - atom!("nesw-resize") => Some(Self::NeswResize), - atom!("nwse-resize") => Some(Self::NwseResize), - atom!("col-resize") => Some(Self::ColResize), - atom!("row-resize") => Some(Self::RowResize), - atom!("all-resize") => Some(Self::AllResize), - atom!("zoom-in") => Some(Self::ZoomIn), - atom!("zoom-out") => Some(Self::ZoomOut), - _ => None, - } - } - - fn to_atom(&self) -> Atom { - match &self { - Self::Auto => atom!("auto"), - Self::Default => atom!("default"), - Self::None => atom!("none"), - Self::ContextMenu => atom!("context-menu"), - Self::Help => atom!("help"), - Self::Pointer => atom!("pointer"), - Self::Progress => atom!("progress"), - Self::Wait => atom!("wait"), - Self::Cell => atom!("cell"), - Self::Crosshair => atom!("crosshair"), - Self::Text => atom!("text"), - Self::VerticalText => atom!("vertical-text"), - Self::Alias => atom!("alias"), - Self::Copy => atom!("copy"), - Self::Move => atom!("move"), - Self::NoDrop => atom!("no-drop"), - Self::NotAllowed => atom!("not-allowed"), - Self::Grab => atom!("grab"), - Self::Grabbing => atom!("grabbing"), - Self::EResize => atom!("e-resize"), - Self::NResize => atom!("n-resize"), - Self::NeResize => atom!("ne-resize"), - Self::NwResize => atom!("nw-resize"), - Self::SResize => atom!("s-resize"), - Self::SeResize => atom!("se-resize"), - Self::SwResize => atom!("sw-resize"), - Self::WResize => atom!("w-resize"), - Self::EwResize => atom!("ew-resize"), - Self::NsResize => atom!("ns-resize"), - Self::NeswResize => atom!("nesw-resize"), - Self::NwseResize => atom!("nwse-resize"), - Self::ColResize => atom!("col-resize"), - Self::RowResize => atom!("row-resize"), - Self::AllResize => atom!("all-resize"), - Self::ZoomIn => atom!("zoom-in"), - Self::ZoomOut => atom!("zoom-out"), - Self::Custom(_) => atom!(""), - } - } -} diff --git a/crates/hdx_ast/src/css/values/ui/accent_color.rs b/crates/hdx_ast/src/css/values/ui/accent_color.rs new file mode 100644 index 00000000..c53347d7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/accent_color.rs @@ -0,0 +1 @@ +pub type AccentColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/appearance.rs b/crates/hdx_ast/src/css/values/ui/appearance.rs new file mode 100644 index 00000000..05ce7049 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/appearance.rs @@ -0,0 +1 @@ +pub type Appearance = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/caret.rs b/crates/hdx_ast/src/css/values/ui/caret.rs new file mode 100644 index 00000000..8ccc6283 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/caret.rs @@ -0,0 +1 @@ +pub type Caret = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/caret_color.rs b/crates/hdx_ast/src/css/values/ui/caret_color.rs new file mode 100644 index 00000000..9e2f27de --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/caret_color.rs @@ -0,0 +1 @@ +pub type CaretColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/caret_shape.rs b/crates/hdx_ast/src/css/values/ui/caret_shape.rs new file mode 100644 index 00000000..6ed594d7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/caret_shape.rs @@ -0,0 +1 @@ +pub type CaretShape = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/cursor.rs b/crates/hdx_ast/src/css/values/ui/cursor.rs new file mode 100644 index 00000000..676617fe --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/cursor.rs @@ -0,0 +1,59 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-ui-4/#propdef-cursor +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum Cursor { + #[default] + Auto, // atom!("auto") + Default, // atom!("default") + None, // atom!("none") + ContextMenu, // atom!("context-menu") + Help, // atom!("help") + Pointer, // atom!("pointer") + Progress, // atom!("progress") + Wait, // atom!("wait") + Cell, // atom!("cell") + Crosshair, // atom!("crosshair") + Text, // atom!("text") + VerticalText, // atom!("vertical-text") + Alias, // atom!("alias") + Copy, // atom!("copy") + Move, // atom!("move") + NoDrop, // atom!("no-drop") + NotAllowed, // atom!("not-allowed") + Grab, // atom!("grab") + Grabbing, // atom!("grabbing") + EResize, // atom!("e-resize") + NResize, // atom!("n-resize") + NeResize, // atom!("ne-resize") + NwResize, // atom!("nw-resize") + SResize, // atom!("s-resize") + SeResize, // atom!("se-resize") + SwResize, // atom!("sw-resize") + WResize, // atom!("w-resize") + EwResize, // atom!("ew-resize") + NsResize, // atom!("ns-resize") + NeswResize, // atom!("nesw-resize") + NwseResize, // atom!("nwse-resize") + ColResize, // atom!("col-resize") + RowResize, // atom!("row-resize") + AllResize, // atom!("all-resize") + ZoomIn, // atom!("zoom-in") + ZoomOut, /* atom!("zoom-out") + * TODO: Custom? */ +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/css/values/ui/input_security.rs b/crates/hdx_ast/src/css/values/ui/input_security.rs new file mode 100644 index 00000000..f5ed4d35 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/input_security.rs @@ -0,0 +1 @@ +pub type InputSecurity = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/mod.rs b/crates/hdx_ast/src/css/values/ui/mod.rs new file mode 100644 index 00000000..ac8fae34 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/mod.rs @@ -0,0 +1,38 @@ +mod accent_color; +mod appearance; +mod caret; +mod caret_color; +mod caret_shape; +mod cursor; +mod input_security; +mod nav_down; +mod nav_left; +mod nav_right; +mod nav_up; +mod outline; +mod outline_color; +mod outline_offset; +mod outline_style; +mod outline_width; +mod pointer_events; +mod resize; +mod user_select; +pub use accent_color::*; +pub use appearance::*; +pub use caret::*; +pub use caret_color::*; +pub use caret_shape::*; +pub use cursor::*; +pub use input_security::*; +pub use nav_down::*; +pub use nav_left::*; +pub use nav_right::*; +pub use nav_up::*; +pub use outline::*; +pub use outline_color::*; +pub use outline_offset::*; +pub use outline_style::*; +pub use outline_width::*; +pub use pointer_events::*; +pub use resize::*; +pub use user_select::*; diff --git a/crates/hdx_ast/src/css/values/ui/nav_down.rs b/crates/hdx_ast/src/css/values/ui/nav_down.rs new file mode 100644 index 00000000..b0cb4880 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/nav_down.rs @@ -0,0 +1 @@ +pub type NavDown = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/nav_left.rs b/crates/hdx_ast/src/css/values/ui/nav_left.rs new file mode 100644 index 00000000..9271879a --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/nav_left.rs @@ -0,0 +1 @@ +pub type NavLeft = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/nav_right.rs b/crates/hdx_ast/src/css/values/ui/nav_right.rs new file mode 100644 index 00000000..08126d7d --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/nav_right.rs @@ -0,0 +1 @@ +pub type NavRight = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/nav_up.rs b/crates/hdx_ast/src/css/values/ui/nav_up.rs new file mode 100644 index 00000000..9db7441d --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/nav_up.rs @@ -0,0 +1 @@ +pub type NavUp = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/outline.rs b/crates/hdx_ast/src/css/values/ui/outline.rs new file mode 100644 index 00000000..3ac5d33b --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/outline.rs @@ -0,0 +1 @@ +pub type Outline = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/outline_color.rs b/crates/hdx_ast/src/css/values/ui/outline_color.rs new file mode 100644 index 00000000..5e57cb81 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/outline_color.rs @@ -0,0 +1 @@ +pub type OutlineColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/outline_offset.rs b/crates/hdx_ast/src/css/values/ui/outline_offset.rs new file mode 100644 index 00000000..8810c915 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/outline_offset.rs @@ -0,0 +1 @@ +pub type OutlineOffset = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/outline_style.rs b/crates/hdx_ast/src/css/values/ui/outline_style.rs new file mode 100644 index 00000000..b2fb1288 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/outline_style.rs @@ -0,0 +1 @@ +pub type OutlineStyle = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/outline_width.rs b/crates/hdx_ast/src/css/values/ui/outline_width.rs new file mode 100644 index 00000000..33919ef8 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/outline_width.rs @@ -0,0 +1 @@ +pub type OutlineWidth = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/pointer_events.rs b/crates/hdx_ast/src/css/values/ui/pointer_events.rs new file mode 100644 index 00000000..3c03948c --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/pointer_events.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +#[derive(Parsable, Writable, Atomizable, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] +pub enum PointerEvents { + Auto, // atom!("auto") + None, // atom!("none") +} diff --git a/crates/hdx_ast/src/css/values/ui/resize.rs b/crates/hdx_ast/src/css/values/ui/resize.rs new file mode 100644 index 00000000..1d3c509c --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/resize.rs @@ -0,0 +1 @@ +pub type Resize = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/ui/user_select.rs b/crates/hdx_ast/src/css/values/ui/user_select.rs new file mode 100644 index 00000000..d2b6dfd1 --- /dev/null +++ b/crates/hdx_ast/src/css/values/ui/user_select.rs @@ -0,0 +1 @@ +pub type UserSelect = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/units/angles.rs b/crates/hdx_ast/src/css/values/units/angles.rs new file mode 100644 index 00000000..e3752da9 --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/angles.rs @@ -0,0 +1,46 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +const DEG_GRAD: f32 = 0.9; +const DEG_RAD: f32 = 57.29577951308232; +const DEG_TURN: f32 = 360.0; + +use super::{AbsoluteUnit, CSSFloat}; +use crate::{Parsable, Writable}; + +// https://drafts.csswg.org/css-values/#angles +#[derive(Parsable, Writable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum Angle { + #[writable(suffix = "grad")] + #[parsable(Dimension)] + Grad(CSSFloat), + #[writable(suffix = "rad")] + #[parsable(Dimension)] + Rad(CSSFloat), + #[writable(suffix = "turn")] + #[parsable(Dimension)] + Turn(CSSFloat), + #[writable(suffix = "deg")] + #[parsable(Dimension)] + Deg(CSSFloat), +} + +impl Into for Angle { + fn into(self) -> CSSFloat { + match self { + Self::Grad(f) | Self::Rad(f) | Self::Turn(f) | Self::Deg(f) => f, + } + } +} + +impl AbsoluteUnit for Angle { + fn to_base(&self) -> Self { + Self::Deg(match self { + Self::Grad(f) => *f * DEG_GRAD, + Self::Rad(f) => *f * DEG_RAD, + Self::Turn(f) => *f * DEG_TURN, + Self::Deg(f) => *f, + }) + } +} diff --git a/crates/hdx_ast/src/css/values/units/custom.rs b/crates/hdx_ast/src/css/values/units/custom.rs new file mode 100644 index 00000000..5eca8087 --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/custom.rs @@ -0,0 +1,16 @@ +use hdx_atom::Atom; +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::CSSFloat; +use crate::Writable; + +#[derive(Writable, Debug, Clone, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub struct Custom(CSSFloat, Atom); + +impl Into for Custom { + fn into(self) -> CSSFloat { + self.0 + } +} diff --git a/crates/hdx_ast/src/css/values/units/float.rs b/crates/hdx_ast/src/css/values/units/float.rs new file mode 100644 index 00000000..fd7e2578 --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/float.rs @@ -0,0 +1,101 @@ +use std::{ + fmt::{Display, Result as DisplayResult}, + hash::{Hash, Hasher}, + ops::{Add, Div, Mul, Sub}, +}; + +use hdx_derive::Writable; +#[cfg(feature = "serde")] +use serde::Serialize; + +// CSS floats are different to f32s in that they do not represent NaN +#[derive(Writable, Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(transparent))] +pub struct CSSFloat(f32); + +impl CSSFloat { + pub fn normalize(&self) -> Self { + if self.0.is_nan() { Self(0.0) } else { Self(self.0) } + } +} + +impl Display for CSSFloat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> DisplayResult { + self.normalize().0.fmt(f) + } +} + +impl Hash for CSSFloat { + fn hash(&self, state: &mut H) { + let n = if self.0.is_nan() { 0.0 } else { self.0 }; + let sign = n.signum() as i8; + sign.hash(state); + (n as u32).hash(state); + } +} + +impl From for CSSFloat { + fn from(f: f32) -> Self { + Self(f).normalize() + } +} + +impl Mul for CSSFloat { + type Output = Self; + + fn mul(self, rhs: f32) -> Self::Output { + Self(self.0 * rhs).normalize() + } +} + +impl Div for CSSFloat { + type Output = Self; + + fn div(self, rhs: f32) -> Self::Output { + Self(self.0 / rhs).normalize() + } +} + +impl Add for CSSFloat { + type Output = Self; + + fn add(self, rhs: f32) -> Self::Output { + Self(self.0 + rhs).normalize() + } +} + +impl Sub for CSSFloat { + type Output = Self; + + fn sub(self, rhs: f32) -> Self::Output { + Self(self.0 - rhs).normalize() + } +} + +impl PartialEq for CSSFloat { + fn eq(&self, rhs: &f32) -> bool { + self.0.eq(rhs) + } +} + +impl PartialOrd for CSSFloat { + fn lt(&self, rhs: &f32) -> bool { + self.0.lt(rhs) + } + + fn le(&self, rhs: &f32) -> bool { + self.0.le(rhs) + } + + fn gt(&self, rhs: &f32) -> bool { + self.0.gt(rhs) + } + + fn ge(&self, rhs: &f32) -> bool { + self.0.ge(rhs) + } + + fn partial_cmp(&self, rhs: &f32) -> Option { + self.0.partial_cmp(rhs) + } +} diff --git a/crates/hdx_ast/src/css/values/units/frequency.rs b/crates/hdx_ast/src/css/values/units/frequency.rs new file mode 100644 index 00000000..2e97b5aa --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/frequency.rs @@ -0,0 +1,70 @@ +use hdx_atom::atom; +use hdx_writer::{CssWriter, Result as WriterResult, WriteCss}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::{AbsoluteUnit, CSSFloat}; +use crate::{Parsable}; + +// https://drafts.csswg.org/css-values/#resolution +#[derive(Parsable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum Frequency { + #[parsable(Dimension)] + Hz(CSSFloat), + #[parsable(Dimension)] + Khz(CSSFloat), +} + +impl Into for Frequency { + fn into(self) -> CSSFloat { + match self { + Self::Hz(f) | Self::Khz(f) => f, + } + } +} + +impl AbsoluteUnit for Frequency { + fn to_base(&self) -> Self { + Self::Hz(match self { + Self::Khz(f) => *f * 1000.0, + Self::Hz(f) => *f, + }) + } +} + +impl<'a> WriteCss<'a> for Frequency { + fn write_css(&self, sink: &mut W) -> WriterResult { + let (f, unit) = match self { + Self::Khz(f) => (f, atom!("khz")), + Self::Hz(f) => (f, atom!("hz")), + }; + f.write_css(sink)?; + unit.write_css(sink)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use oxc_allocator::Allocator; + + use super::*; + use crate::test_helpers::test_write; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + } + + #[test] + fn test_variants() { + let allocator = Allocator::default(); + test_write::(&allocator, "40hz", "40hz"); + // Truncates to 7dp + test_write::(&allocator, "1.2345678901234hz", "1.2345679hz"); + // Removes redundant dp + test_write::(&allocator, "-1.0hz", "-1hz"); + } +} diff --git a/crates/hdx_ast/src/css/values/units/length.rs b/crates/hdx_ast/src/css/values/units/length.rs new file mode 100644 index 00000000..9c72a8c7 --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/length.rs @@ -0,0 +1,207 @@ +use hdx_atom::{atom, Atom}; +use hdx_lexer::Token; +use hdx_parser::{diagnostics::UnexpectedDimension, unexpected, Parse, Parser, Result as ParserResult, Spanned}; +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::CSSFloat; +use crate::Writable; + +const PX_CM: f32 = PX_IN / 2.54; +const PX_MM: f32 = PX_IN / 25.4; +const PX_Q: f32 = PX_MM / 4.0; +const PX_IN: f32 = 96.0; +const PX_PC: f32 = PX_IN / 6.0; +const PX_PT: f32 = PX_IN / 72.0; + +macro_rules! length { + ( $( + $name: ident: $atom: tt, + )+ ) => { + + #[derive(Writable, Debug, Clone, Copy, PartialEq, Hash)] + #[cfg_attr(feature = "serde", derive(Serialize), serde())] + pub enum Length { + #[writable(rename = "0")] + Zero, // TODO: atom!("zero") <- shouldn't need to be an atom but something weird is happening + $( + #[writable(suffix = $atom)] + $name(CSSFloat), + )+ + } + + impl Length { + pub fn new(val: CSSFloat, atom: Atom) -> Option { + match atom { + $(atom!($atom) => Some(Length::$name(val)),)+ + _ => None + } + } + } + + impl Into for Length { + fn into(self) -> CSSFloat { + match self { + $(Self::$name(f) => f,)+ + Self::Zero => 0.0.into(), + } + } + } + + impl<'a> Parse<'a> for Length { + fn parse(parser: &mut Parser) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => { + parser.advance(); + Ok(Self::Zero.spanned(span)) + } + Token::Dimension(n, unit, _) => { + if let Some(length) = Self::new(n.into(), unit.clone()) { + parser.advance(); + Ok(length.spanned(span)) + } else { + Err(UnexpectedDimension(unit, span))? + } + } + token => unexpected!(parser, token), + } + } + } + + #[derive(Writable, Debug, Clone, Copy, PartialEq, Hash)] + #[cfg_attr(feature = "serde", derive(Serialize), serde())] + pub enum LengthPercentage { + #[writable(rename = "0")] + Zero, + $( + #[writable(suffix = $atom)] + $name(CSSFloat), + )+ + Percent(CSSFloat), + } + + impl LengthPercentage { + pub fn new(val: CSSFloat, atom: Atom) -> Option { + match atom { + $(atom!($atom) => Some(LengthPercentage::$name(val)),)+ + _ => None + } + } + } + + impl Into for LengthPercentage { + fn into(self) -> CSSFloat { + match self { + $(Self::$name(f) => f,)+ + Self::Percent(f) => f, + Self::Zero => 0.0.into(), + } + } + } + + impl<'a> Parse<'a> for LengthPercentage { + fn parse(parser: &mut Parser) -> ParserResult> { + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => { + parser.advance(); + Ok(Self::Zero.spanned(span)) + }, + Token::Dimension(n, unit, _) => { + parser.advance(); + if let Some(length) = Self::new(n.into(), unit.clone()) { + Ok(length.spanned(span)) + } else { + Err(UnexpectedDimension(unit, span))? + } + } + token => unexpected!(parser, token), + } + } + } + } +} + +length! { + // https://drafts.csswg.org/css-values/#font-relative-lengths + Em: "em", // atom!("em") + Rem: "rem", // atom!("rem") + Ex: "ex", // atom!("ex") + Rex: "rex", // atom!("rex") + Cap: "cap", // atom!("cap") + Rcap: "rcap", // atom!("rcap") + Ch: "ch", // atom!("ch") + Rch: "rch", // atom!("rch") + Ic: "ic", // atom!("ic") + Ric: "ric", // atom!("ric") + Lh: "lh", // atom!("lh") + Rlh: "rlh", // atom!("rlh") + + // https://drafts.csswg.org/css-values/#viewport-relative-units + Vw: "vw", // atom!("vw") + Svw: "svw", // atom!("svw") + Lvw: "lvw", // atom!("lvw") + Dvw: "dvw", // atom!("dvw") + Vh: "vh", // atom!("vh") + Svh: "svh", // atom!("svh") + Lvh: "lvh", // atom!("lvh") + Dvh: "dvh", // atom!("dvh") + Vi: "vi", // atom!("vi") + Svi: "svi", // atom!("svi") + Lvi: "lvi", // atom!("lvi") + Dvi: "dvi", // atom!("dvi") + Vb: "vb", // atom!("vb") + Svb: "svb", // atom!("svb") + Lvb: "lvb", // atom!("lvb") + Dvb: "dvb", // atom!("dvb") + Vmin: "vmin", // atom!("vmin") + Svmin: "svmin", // atom!("svmin") + Lvmin: "lvmin", // atom!("lvmin") + Dvmin: "dvmin", // atom!("dvmin") + Vmax: "vmax", // atom!("vmax") + Svmax: "svmax", // atom!("svmax") + Lvmax: "lvmax", // atom!("lvmax") + Dvmax: "dvmax", // atom!("dvmax") + + // https://drafts.csswg.org/css-values/#absolute-lengths + Cm: "cm", // atom!("cm") + Mm: "mm", // atom!("mm") + Q: "q", // atom!("q") + In: "in", // atom!("in") + Pc: "pc", // atom!("pc") + Pt: "pt", // atom!("pt") + Px: "px", // atom!("px") + + // https://www.w3.org/TR/css-contain-3/#container-lengths + Cqw: "cqw", // atom!("cqw") + Cqh: "cqh", // atom!("cqh") + Cqi: "cqi", // atom!("cqi") + Cqb: "cqb", // atom!("cqb") + Cqmin: "cqmin", // atom!("cqmin") + Cqmax: "cqmax", // atom!("cqmax") +} + +#[cfg(test)] +mod tests { + use oxc_allocator::Allocator; + + use super::*; + use crate::test_helpers::test_write; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 8); + assert_eq!(::std::mem::size_of::(), 8); + } + + #[test] + fn test_variants() { + let allocator = Allocator::default(); + test_write::(&allocator, "10px", "10px"); + // Truncates to 7dp + test_write::(&allocator, "1.2345678901234px", "1.2345679px"); + // Removes redundant dp + test_write::(&allocator, "-1.0px", "-1px"); + } +} diff --git a/crates/hdx_ast/src/css/values/units/lengths.rs b/crates/hdx_ast/src/css/values/units/lengths.rs deleted file mode 100644 index e983efc3..00000000 --- a/crates/hdx_ast/src/css/values/units/lengths.rs +++ /dev/null @@ -1,388 +0,0 @@ -use std::hash::{Hash, Hasher}; - -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::Percentage; -use crate::{atom, Atom, Atomizable}; - -macro_rules! expr { - ($expr: expr) => { - $expr - }; -} -macro_rules! pat { - ($pat: pat) => { - $pat - }; -} - -macro_rules! length_units { - ( $($unit: ident($($atom: tt)*),)+ ) => { - $( - #[derive(Default, Clone, Copy, Debug, PartialEq)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub struct $unit(pub f32); - - impl Hash for $unit { - fn hash(&self, state: &mut H) { - self.0.to_bits().hash(state); - expr!($($atom)*).hash(state); - } - } - - impl Atomizable for $unit { - fn from_atom(atom: Atom) -> Option { - if atom == expr!($($atom)*) { - Some(Self(0.0)) - } else { - None - } - } - fn to_atom(&self) -> Atom { - expr!($($atom)*) - } - } - )+ - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum Length { - #[default] - Zero, - $( - $unit($unit), - )+ - } - - impl Length { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None, - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum LengthOrAuto { - #[default] - Zero, - Auto, - $( - $unit($unit), - )+ - } - - impl LengthOrAuto { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None, - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Auto => (0.0, atom!("auto")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum PositiveLength { - #[default] - Zero, - $( - $unit($unit), - )+ - } - - impl PositiveLength { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - if n < 0.0 { - return None; - } - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum LengthPercentage { - #[default] - Zero, - Percentage(Percentage), - $( - $unit($unit), - )+ - } - - impl LengthPercentage { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Percentage(n) => (n.0, atom!("%")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum LengthPercentageOrNormal { - #[default] - Zero, - Normal, - Percentage(Percentage), - $( - $unit($unit), - )+ - } - - impl LengthPercentageOrNormal { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Normal => (0.0, atom!("normal")), - Self::Percentage(n) => (n.0, atom!("%")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum PositiveLengthPercentage { - #[default] - Zero, - Percentage(Percentage), - $( - $unit($unit), - )+ - } - - impl PositiveLengthPercentage { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - if n < 0.0 { - return None; - } - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Percentage(n) => (n.0, atom!("%")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum PositiveLengthPercentageOrNormal { - #[default] - Zero, - Normal, - Percentage(Percentage), - $( - $unit($unit), - )+ - } - - impl PositiveLengthPercentageOrNormal { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - if n < 0.0 { - return None; - } - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None, - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Percentage(n) => (n.0, atom!("%")), - Self::Normal => (0.0, atom!("normal")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - - #[derive(Default, Clone, Copy, Debug, PartialEq, Hash)] - #[cfg_attr(feature = "serde", derive(Serialize), serde())] - pub enum LengthPercentageOrAuto { - #[default] - Zero, - Auto, - Percentage(Percentage), - $( - $unit($unit), - )+ - } - - impl LengthPercentageOrAuto { - pub fn from_f32_and_atom(n: f32, atom: Atom) -> Option { - match atom { - $( - pat!($($atom)*) => Some(Self::$unit($unit(n))), - )+ - _ => None, - } - } - pub fn to_f32_and_atom(&self) -> (f32, Atom) { - match self { - Self::Zero => (0.0, atom!("")), - Self::Auto => (0.0, atom!("auto")), - Self::Percentage(n) => (n.0, atom!("%")), - $( - Self::$unit(n) => (n.0, n.to_atom()), - )+ - } - } - } - }; -} - -length_units! { - // Absolute Units - // https://drafts.csswg.org/css-values/#absolute-lengths - Cm(atom!("cm")), - Mm(atom!("mm")), - Q(atom!("q")), - In(atom!("in")), - Pc(atom!("pc")), - Pt(atom!("pt")), - Px(atom!("px")), - - // Font Relative Units - // https://drafts.csswg.org/css-values/#font-relative-lengths - Em(atom!("em")), - Rem(atom!("rem")), - Ex(atom!("ex")), - Rex(atom!("rex")), - Cap(atom!("cap")), - Rcap(atom!("rcap")), - Ch(atom!("ch")), - Rch(atom!("rch")), - Ic(atom!("ic")), - Ric(atom!("ric")), - Lh(atom!("lh")), - Rlh(atom!("rlh")), - - // Viewport Relative Units - // https://drafts.csswg.org/css-values/#viewport-relative-units - Vw(atom!("vw")), - Svw(atom!("svw")), - Lvw(atom!("lvw")), - Dvw(atom!("dvw")), - Vh(atom!("vh")), - Svh(atom!("svh")), - Lvh(atom!("lvh")), - Dvh(atom!("dvh")), - Vi(atom!("vi")), - Svi(atom!("svi")), - Lvi(atom!("lvi")), - Dvi(atom!("dvi")), - Vb(atom!("vb")), - Svb(atom!("svb")), - Lvb(atom!("lvb")), - Dvb(atom!("dvb")), - Vmin(atom!("vmin")), - Svmin(atom!("svmin")), - Lvmin(atom!("lvmin")), - Dvmin(atom!("dvmin")), - Vmax(atom!("vmax")), - Svmax(atom!("svmax")), - Lvmax(atom!("lvmax")), - Dvmax(atom!("dvmax")), - - // Container Relative Units - // https://www.w3.org/TR/css-contain-3/#container-lengths - Cqw(atom!("cqw")), - Cqh(atom!("cqh")), - Cqi(atom!("cqi")), - Cqb(atom!("cqb")), - Cqmin(atom!("cqmin")), - Cqmax(atom!("cqmax")), - -} - -#[cfg(test)] -mod tests { - - use super::super::*; - - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), 8); - } -} diff --git a/crates/hdx_ast/src/css/values/units/mod.rs b/crates/hdx_ast/src/css/values/units/mod.rs index a697fca9..f4b6b8f0 100644 --- a/crates/hdx_ast/src/css/values/units/mod.rs +++ b/crates/hdx_ast/src/css/values/units/mod.rs @@ -1,30 +1,70 @@ -use std::hash::{Hash, Hasher}; - #[cfg(feature = "serde")] use serde::Serialize; -pub mod lengths; +use crate::Writable; -pub use lengths::*; +mod angles; +mod custom; +mod float; +mod frequency; +mod length; +mod percent; +mod resolution; +mod time; -#[derive(Default, Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Percentage(pub f32); +pub use angles::*; +pub use custom::*; +pub use float::*; +pub use frequency::*; +pub use length::*; +pub use percent::*; +pub use resolution::*; +pub use time::*; -impl Hash for Percentage { - fn hash(&self, state: &mut H) { - self.0.to_bits().hash(state); - } +#[derive(Writable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum CSSNumeric { + Length(Length), + Angle(Angle), + Time(Time), + Frequency(Frequency), + Resolution(Resolution), + #[writable(suffix = "fr")] + Flex(CSSFloat), + Percent(Percent), } -#[cfg(test)] -mod tests { +impl Into for CSSNumeric { + fn into(self) -> CSSFloat { + match self { + Self::Length(v) => v.into(), + Self::Angle(v) => v.into(), + Self::Time(v) => v.into(), + Self::Frequency(v) => v.into(), + Self::Resolution(v) => v.into(), + Self::Flex(v) => v.into(), + Self::Percent(v) => v.into(), + } + } +} - use super::*; +pub trait AbsoluteUnit: Unit { + fn to_base(&self) -> Self; +} - #[test] - fn size_test() { - use std::mem::size_of; - assert_eq!(size_of::(), 4); - } +pub trait Unit: Into + Copy + PartialEq + Sized { + fn is_negative(&self) -> bool { + let f: CSSFloat = (*self).into(); + f < 0.0 + } + fn is_positive(&self) -> bool { + let f: CSSFloat = (*self).into(); + f >= 0.0 + } + fn is_zero(&self) -> bool { + let f: CSSFloat = (*self).into(); + f >= 0.0 + } } + +impl + Copy + PartialEq + Sized> Unit for T {} diff --git a/crates/hdx_ast/src/css/values/units/percent.rs b/crates/hdx_ast/src/css/values/units/percent.rs new file mode 100644 index 00000000..660b1a9f --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/percent.rs @@ -0,0 +1,22 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::CSSFloat; +use crate::Writable; + +#[derive(Writable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +#[writable(suffix = "%")] +pub struct Percent(CSSFloat); + +impl From for Percent { + fn from(value: f32) -> Self { + Self(value.into()) + } +} + +impl Into for Percent { + fn into(self) -> CSSFloat { + self.0 + } +} diff --git a/crates/hdx_ast/src/css/values/units/resolution.rs b/crates/hdx_ast/src/css/values/units/resolution.rs new file mode 100644 index 00000000..1a16ff7b --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/resolution.rs @@ -0,0 +1,41 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +const DPPX_IN: f32 = 96.0; +const DPPX_CM: f32 = DPPX_IN / 2.54; + +use super::{AbsoluteUnit, CSSFloat}; +use crate::{Parsable, Writable}; + +// https://drafts.csswg.org/css-values/#resolution +#[derive(Parsable, Writable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum Resolution { + #[writable(suffix = "dpi")] + #[parsable(Dimension)] + Dpi(CSSFloat), + #[writable(suffix = "dpcm")] + #[parsable(Dimension)] + Dpcm(CSSFloat), + #[writable(suffix = "dppx")] + #[parsable(Dimension)] + Dppx(CSSFloat), +} + +impl Into for Resolution { + fn into(self) -> CSSFloat { + match self { + Self::Dpi(f) | Self::Dpcm(f) | Self::Dppx(f) => f, + } + } +} + +impl AbsoluteUnit for Resolution { + fn to_base(&self) -> Self { + Self::Dppx(match self { + Self::Dpi(f) => *f * DPPX_IN, + Self::Dpcm(f) => *f * DPPX_CM, + Self::Dppx(f) => *f, + }) + } +} diff --git a/crates/hdx_ast/src/css/values/units/time.rs b/crates/hdx_ast/src/css/values/units/time.rs new file mode 100644 index 00000000..f0038c4c --- /dev/null +++ b/crates/hdx_ast/src/css/values/units/time.rs @@ -0,0 +1,34 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use super::{AbsoluteUnit, CSSFloat}; +use crate::{Parsable, Writable}; + +// https://drafts.csswg.org/css-values/#resolution +#[derive(Parsable, Writable, Debug, Clone, Copy, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub enum Time { + #[writable(suffix = "ms")] + #[parsable(Dimension)] + Ms(CSSFloat), + #[writable(suffix = "s")] + #[parsable(Dimension)] + S(CSSFloat), +} + +impl Into for Time { + fn into(self) -> CSSFloat { + match self { + Self::Ms(f) | Self::S(f) => f, + } + } +} + +impl AbsoluteUnit for Time { + fn to_base(&self) -> Self { + Self::S(match self { + Self::Ms(f) => *f / 1000.0, + Self::S(f) => *f, + }) + } +} diff --git a/crates/hdx_ast/src/css/values/view_transitions/mod.rs b/crates/hdx_ast/src/css/values/view_transitions/mod.rs new file mode 100644 index 00000000..a960c543 --- /dev/null +++ b/crates/hdx_ast/src/css/values/view_transitions/mod.rs @@ -0,0 +1,2 @@ +mod view_transition_name; +pub use view_transition_name::*; diff --git a/crates/hdx_ast/src/css/values/view_transitions/view_transition_name.rs b/crates/hdx_ast/src/css/values/view_transitions/view_transition_name.rs new file mode 100644 index 00000000..1e51ad00 --- /dev/null +++ b/crates/hdx_ast/src/css/values/view_transitions/view_transition_name.rs @@ -0,0 +1 @@ +pub type ViewTransitionName = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/webkit/mod.rs b/crates/hdx_ast/src/css/values/webkit/mod.rs new file mode 100644 index 00000000..cc2ae19a --- /dev/null +++ b/crates/hdx_ast/src/css/values/webkit/mod.rs @@ -0,0 +1,8 @@ +mod webkit_text_size_adjust; +pub use webkit_text_size_adjust::*; +mod webkit_text_decoration; +pub use webkit_text_decoration::*; +mod webkit_tap_highlight_color; +pub use webkit_tap_highlight_color::*; +mod webkit_text_decoration_skip_ink; +pub use webkit_text_decoration_skip_ink::*; diff --git a/crates/hdx_ast/src/css/values/webkit/webkit_tap_highlight_color.rs b/crates/hdx_ast/src/css/values/webkit/webkit_tap_highlight_color.rs new file mode 100644 index 00000000..7953b749 --- /dev/null +++ b/crates/hdx_ast/src/css/values/webkit/webkit_tap_highlight_color.rs @@ -0,0 +1 @@ +pub type WebkitTapHighlightColor = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration.rs b/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration.rs new file mode 100644 index 00000000..f02af3ed --- /dev/null +++ b/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration.rs @@ -0,0 +1 @@ +pub type WebkitTextDecoration = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration_skip_ink.rs b/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration_skip_ink.rs new file mode 100644 index 00000000..62d7d52b --- /dev/null +++ b/crates/hdx_ast/src/css/values/webkit/webkit_text_decoration_skip_ink.rs @@ -0,0 +1 @@ +pub type WebkitTextDecorationSkipInk = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/webkit/webkit_text_size_adjust.rs b/crates/hdx_ast/src/css/values/webkit/webkit_text_size_adjust.rs new file mode 100644 index 00000000..07d05c9c --- /dev/null +++ b/crates/hdx_ast/src/css/values/webkit/webkit_text_size_adjust.rs @@ -0,0 +1 @@ +pub type WebkitTextSizeAdjust = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/will_change/mod.rs b/crates/hdx_ast/src/css/values/will_change/mod.rs new file mode 100644 index 00000000..3f68336d --- /dev/null +++ b/crates/hdx_ast/src/css/values/will_change/mod.rs @@ -0,0 +1,2 @@ +mod will_change; +pub use will_change::*; diff --git a/crates/hdx_ast/src/css/values/will_change/will_change.rs b/crates/hdx_ast/src/css/values/will_change/will_change.rs new file mode 100644 index 00000000..ea8a93df --- /dev/null +++ b/crates/hdx_ast/src/css/values/will_change/will_change.rs @@ -0,0 +1 @@ +pub type WillChange = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/direction.rs b/crates/hdx_ast/src/css/values/writing_modes/direction.rs new file mode 100644 index 00000000..fcc60d71 --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/direction.rs @@ -0,0 +1 @@ +pub type Direction = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/glyph_orientation_horizontal.rs b/crates/hdx_ast/src/css/values/writing_modes/glyph_orientation_horizontal.rs new file mode 100644 index 00000000..a5451842 --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/glyph_orientation_horizontal.rs @@ -0,0 +1 @@ +pub type GlyphOrientationHorizontal = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/mod.rs b/crates/hdx_ast/src/css/values/writing_modes/mod.rs new file mode 100644 index 00000000..d2cd578c --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/mod.rs @@ -0,0 +1,12 @@ +mod direction; +mod glyph_orientation_horizontal; +mod text_combine_upright; +mod text_orientation; +mod unicode_bidi; +mod writing_mode; +pub use direction::*; +pub use glyph_orientation_horizontal::*; +pub use text_combine_upright::*; +pub use text_orientation::*; +pub use unicode_bidi::*; +pub use writing_mode::*; diff --git a/crates/hdx_ast/src/css/values/writing_modes/text_combine_upright.rs b/crates/hdx_ast/src/css/values/writing_modes/text_combine_upright.rs new file mode 100644 index 00000000..b5c27bb3 --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/text_combine_upright.rs @@ -0,0 +1 @@ +pub type TextCombineUpright = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/text_orientation.rs b/crates/hdx_ast/src/css/values/writing_modes/text_orientation.rs new file mode 100644 index 00000000..8549218d --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/text_orientation.rs @@ -0,0 +1 @@ +pub type TextOrientation = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/unicode_bidi.rs b/crates/hdx_ast/src/css/values/writing_modes/unicode_bidi.rs new file mode 100644 index 00000000..aca11c70 --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/unicode_bidi.rs @@ -0,0 +1 @@ +pub type UnicodeBidi = super::super::Todo; diff --git a/crates/hdx_ast/src/css/values/writing_modes/writing_mode.rs b/crates/hdx_ast/src/css/values/writing_modes/writing_mode.rs new file mode 100644 index 00000000..4ccb09f2 --- /dev/null +++ b/crates/hdx_ast/src/css/values/writing_modes/writing_mode.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "serde")] +use serde::Serialize; + +use crate::{Atomizable, Parsable, Writable}; + +// https://drafts.csswg.org/css-position-3/#propdef-position +#[derive(Parsable, Writable, Atomizable, Default, Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "kebab-case"))] +pub enum WritingMode { + #[default] + HorizontalTb, // atom!("horizontal-tb") + VerticalRl, // atom!("vertical-rl") + VerticalLr, // atom!("vertical-lr") + SidewaysRl, // atom!("sideways-rl") + SidewaysLr, // atom!("sideways-lr") +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn size_test() { + assert_eq!(::std::mem::size_of::(), 1); + } +} diff --git a/crates/hdx_ast/src/lib.rs b/crates/hdx_ast/src/lib.rs index b7f722ac..b5507ec7 100644 --- a/crates/hdx_ast/src/lib.rs +++ b/crates/hdx_ast/src/lib.rs @@ -1,41 +1,21 @@ -extern crate hdx_atomizable_derive; - -pub use hdx_atomizable_derive::Atomizable; -#[cfg(feature = "serde")] -use serde::Serialize; +extern crate hdx_derive; pub mod css; -pub mod span; pub mod traits; +pub mod macros; + +#[cfg(test)] +pub mod test_helpers; +pub(crate) use bitmask_enum::bitmask; pub(crate) use hdx_atom::{atom, Atom, Atomizable}; -pub(crate) use hdx_lexer::{PairWise, Token}; -pub(crate) use oxc_allocator::{Allocator, Box, Vec}; -pub(crate) use span::Span; +pub(crate) use hdx_derive::{Atomizable, Parsable, Writable}; +pub(crate) use hdx_parser::{Box, Spanned, Vec}; +pub(crate) use macros::*; pub use traits::Unit; -#[derive(Debug, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize), serde())] -pub struct Spanned { - pub node: T, - #[cfg_attr(feature = "serde", serde(flatten))] - pub span: Span, -} - -impl Spanned { - pub fn dummy(node: T) -> Self { - Self { node, span: Span::dummy() } - } -} - -impl Atomizable for Spanned { - fn from_atom(atom: Atom) -> Option { - T::from_atom(atom).map(|node| Self { node, span: Span::dummy() }) - } - - fn to_atom(&self) -> Atom { - self.node.to_atom() - } +pub trait ToSpecificity: Sized { + fn specificity(&self) -> Specificity; } impl ToSpecificity for Spanned { @@ -44,16 +24,6 @@ impl ToSpecificity for Spanned { } } -impl Default for Spanned { - fn default() -> Self { - Self::dummy(T::default()) - } -} - -pub trait ToSpecificity: Sized { - fn specificity(&self) -> Specificity; -} - #[derive(Debug, PartialEq, Hash)] pub struct Specificity(u8, u8, u8); diff --git a/crates/hdx_ast/src/macros.rs b/crates/hdx_ast/src/macros.rs new file mode 100644 index 00000000..e3c442a5 --- /dev/null +++ b/crates/hdx_ast/src/macros.rs @@ -0,0 +1,69 @@ +macro_rules! length_percentage_struct { + ($name: ident) => { + #[derive(Debug, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())] + pub struct $name { + length: $crate::css::values::units::LengthPercentage, + } + + impl<'a> hdx_writer::WriteCss<'a> for $name { + fn write_css(&self, sink: &mut W) -> hdx_writer::Result { + self.length.write_css(sink) + } + } + } +} +pub(crate) use length_percentage_struct; + +macro_rules! positive_length_percentage_property { + ($name: ident) => { + $crate::length_percentage_struct!($name); + impl<'a> hdx_parser::Parse<'a> for $name { + fn parse(parser: &mut hdx_parser::Parser<'a>) -> hdx_parser::Result> { + use hdx_lexer::Token; + use $crate::css::values::units::LengthPercentage; + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => Ok(Self { length: LengthPercentage::Zero }.spanned(span)), + Token::Dimension(n, unit, _) => { + if n < 0.0 { + Err(hdx_parser::diagnostics::NumberNotNegative(n, span))? + } + if let Some(length) = LengthPercentage::new(n.into(), unit.clone()) { + Ok(Self { length }.spanned(span)) + } else { + Err(hdx_parser::diagnostics::UnexpectedDimension(unit, span))? + } + } + token => hdx_parser::unexpected!(parser, token), + } + } + } + }; +} +pub(crate) use positive_length_percentage_property; + +macro_rules! length_percentage_property { + ($name: ident) => { + $crate::length_percentage_struct!($name); + impl<'a> hdx_parser::Parse<'a> for $name { + fn parse(parser: &mut hdx_parser::Parser<'a>) -> hdx_parser::Result> { + use hdx_lexer::Token; + use $crate::css::values::units::LengthPercentage; + let span = parser.span(); + match parser.cur() { + Token::Number(n, _) if n == 0.0 => Ok(Self { length: LengthPercentage::Zero }.spanned(span)), + Token::Dimension(n, unit, _) => { + if let Some(length) = LengthPercentage::new(n.into(), unit.clone()) { + Ok(Self { length }.spanned(span)) + } else { + Err(hdx_parser::diagnostics::UnexpectedDimension(unit, span))? + } + } + token => hdx_parser::unexpected!(parser, token), + } + } + } + }; +} +pub(crate) use length_percentage_property; diff --git a/crates/hdx_ast/src/test_helpers.rs b/crates/hdx_ast/src/test_helpers.rs new file mode 100644 index 00000000..e9e7b3ee --- /dev/null +++ b/crates/hdx_ast/src/test_helpers.rs @@ -0,0 +1,19 @@ +use hdx_parser::{Parse, Parser, Features}; +use hdx_writer::{BaseCssWriter, WriteCss}; +use oxc_allocator::Allocator; + +pub fn test_write<'a, T: Parse<'a> + WriteCss<'a>>( + allocator: &'a Allocator, + source_text: &'a str, + expected: &'a str, +) { + let mut string = String::new(); + let mut writer = BaseCssWriter::new(&mut string, true); + let parser = Parser::new(&allocator, source_text, Features::default()); + let result = parser.parse_entirely_with::(); + if !result.errors.is_empty() { + panic!("{:?}", result.errors[0]); + } + result.output.unwrap().write_css(&mut writer).unwrap(); + assert_eq!(string, expected); +} diff --git a/crates/hdx_atom/build.rs b/crates/hdx_atom/build.rs index 6008f338..675489f3 100644 --- a/crates/hdx_atom/build.rs +++ b/crates/hdx_atom/build.rs @@ -1,264 +1,266 @@ use std::{env, path::Path}; use glob::glob; -use grep_matcher::Matcher; +use grep_matcher::{Captures, Matcher}; use grep_regex::RegexMatcher; use grep_searcher::{sinks::UTF8, Searcher}; fn main() { - let matcher = RegexMatcher::new("atom!\\(\"[^\"]+").unwrap(); - let mut matches = vec![]; - for entry in glob("../**/*.rs").unwrap() { - let mut searcher = Searcher::new(); - searcher - .search_path( - &matcher, - entry.unwrap(), - UTF8(|_lnum, line| { - let mymatch = matcher.find(line.as_bytes())?.unwrap(); - let matched = line[mymatch].strip_prefix("atom!(\"").unwrap(); - matches.push(matched.to_owned()); - Ok(true) - }), - ) - .unwrap(); - } + let matcher = + RegexMatcher::new("(?:atom!\\(\"|atom = \"|suffix = \"|prefix = \")([^\"]+)").unwrap(); + let mut matches = vec![]; + for entry in glob("../**/*.rs").unwrap() { + let mut searcher = Searcher::new(); + searcher + .search_path( + &matcher, + entry.unwrap(), + UTF8(|_lnum, line| { + let mut captures = matcher.new_captures()?; + if matcher.captures(line.as_bytes(), &mut captures)? { + matches.push(line[captures.get(1).unwrap()].to_owned()); + } + Ok(true) + }), + ) + .unwrap(); + } - matches.append( - &mut vec![ - // hdx_lexer::Token::Kind names - "unknown", - "EOF", - "Comment", - "Ident", - "Function", - "AtKeyword", - "Hash", - "String", - "BadString", - "Url", - "BadUrl", - "Delim", - "Number", - "Percentage", - "Dimension", - "Whitespace", - "Cdo", - "Cdc", - "Colon", - "Semicolon", - "Comma", - "LeftSquare", - "RightSquare", - "LeftParen", - "RightParen", - "LeftCurly", - "RightCurly", - "", - // HTML Tag Names - "html", - "base", - "head", - "link", - "meta", - "base", - "link", - "script", - "style", - "title", - "style", - "title", - "body", - "address", - "article", - "aside", - "footer", - "header", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "hgroup", - "main", - "nav", - "section", - "search", - "blockquote", - "cite", - "dd", - "dt", - "dl", - "div", - "dl", - "dt", - "dd", - "dt", - "dl", - "dd", - "dd", - "figcaption", - "figure", - "figure", - "figcaption", - "hr", - "li", - "ol", - "ul", - "menu", - "menu", - "ul", - "ul", - "li", - "ol", - "p", - "pre", - "ul", - "a", - "abbr", - "b", - "ont-weigh", - "bdi", - "bdo", - "br", - "cite", - "code", - "data", - "dfn", - "p", - "dt", - "dd", - "em", - "i", - "kbd", - "mark", - "q", - "blockquote", - "rp", - "ruby", - "rt", - "rt", - "ruby", - "ruby", - "s", - "samp", - "small", - "span", - "strong", - "sub", - "sup", - "time", - "u", - "var", - "wbr", - "area", - "audio", - "ediaStrea", - "img", - "map", - "area", - "track", - "video", - "embed", - "iframe", - "object", - "picture", - "source", - "img", - "portal", - "source", - "svg", - "canvas", - "noscript", - "script", - "del", - "ins", - "caption", - "col", - "colgroup", - "colgroup", - "table", - "tbody", - "tr", - "table", - "td", - "tfoot", - "th", - "thead", - "tr", - "td", - "th", - "button", - "datalist", - "option", - "fieldset", - "label", - "form", - "input", - "label", - "legend", - "fieldset", - "meter", - "optgroup", - "select", - "option", - "optgroup", - "datalist", - "output", - "progress", - "select", - "textarea", - "details", - "summary", - "dialog", - "summary", - "details", - "slot", - "template", - "acronym", - "big", - "center", - "slot", - "slot", - "dir", - "ul", - "font", - "frame", - "frameset", - "frameset", - "frame", - "image", - "img", - "marquee", - "menuitem", - "nobr", - "noembed", - "object", - "noframes", - "frame", - "param", - "object", - "plaintext", - "rb", - "rtc", - "rb", - "ruby", - "rb", - "rt", - "rtc", - "slot", - "strike", - "tt", - "xmp", - ] - .iter() - .map(|&s| s.into()) - .collect(), - ); + matches.append( + &mut vec![ + // hdx_lexer::Token::Kind names + "unknown", + "EOF", + "Comment", + "Ident", + "Function", + "AtKeyword", + "Hash", + "String", + "BadString", + "Url", + "BadUrl", + "Delim", + "Number", + "Percentage", + "Dimension", + "Whitespace", + "Cdo", + "Cdc", + "Colon", + "Semicolon", + "Comma", + "LeftSquare", + "RightSquare", + "LeftParen", + "RightParen", + "LeftCurly", + "RightCurly", + "", + // HTML Tag Names + "html", + "base", + "head", + "link", + "meta", + "base", + "link", + "script", + "style", + "title", + "style", + "title", + "body", + "address", + "article", + "aside", + "footer", + "header", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "hgroup", + "main", + "nav", + "section", + "search", + "blockquote", + "cite", + "dd", + "dt", + "dl", + "div", + "dl", + "dt", + "dd", + "dt", + "dl", + "dd", + "dd", + "figcaption", + "figure", + "figure", + "figcaption", + "hr", + "li", + "ol", + "ul", + "menu", + "menu", + "ul", + "ul", + "li", + "ol", + "p", + "pre", + "ul", + "a", + "abbr", + "b", + "ont-weigh", + "bdi", + "bdo", + "br", + "cite", + "code", + "data", + "dfn", + "p", + "dt", + "dd", + "em", + "i", + "kbd", + "mark", + "q", + "blockquote", + "rp", + "ruby", + "rt", + "rt", + "ruby", + "ruby", + "s", + "samp", + "small", + "span", + "strong", + "sub", + "sup", + "time", + "u", + "var", + "wbr", + "area", + "audio", + "ediaStrea", + "img", + "map", + "area", + "track", + "video", + "embed", + "iframe", + "object", + "picture", + "source", + "img", + "portal", + "source", + "svg", + "canvas", + "noscript", + "script", + "del", + "ins", + "caption", + "col", + "colgroup", + "colgroup", + "table", + "tbody", + "tr", + "table", + "td", + "tfoot", + "th", + "thead", + "tr", + "td", + "th", + "button", + "datalist", + "option", + "fieldset", + "label", + "form", + "input", + "label", + "legend", + "fieldset", + "meter", + "optgroup", + "select", + "option", + "optgroup", + "datalist", + "output", + "progress", + "select", + "textarea", + "details", + "summary", + "dialog", + "summary", + "details", + "slot", + "template", + "acronym", + "big", + "center", + "slot", + "slot", + "dir", + "ul", + "font", + "frame", + "frameset", + "frameset", + "frame", + "image", + "img", + "marquee", + "menuitem", + "nobr", + "noembed", + "object", + "noframes", + "frame", + "param", + "object", + "plaintext", + "rb", + "rtc", + "rb", + "ruby", + "rb", + "rt", + "rtc", + "slot", + "strike", + "tt", + "xmp", + ] + .iter() + .map(|&s| s.into()) + .collect(), + ); - string_cache_codegen::AtomType::new("Atom", "atom!") - .atoms(matches) - .write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("hdx_atom.rs")) - .unwrap() + string_cache_codegen::AtomType::new("Atom", "atom!") + .atoms(matches) + .write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("hdx_atom.rs")) + .unwrap() } diff --git a/crates/hdx_atomizable_derive/src/lib.rs b/crates/hdx_atomizable_derive/src/lib.rs deleted file mode 100644 index 7821c732..00000000 --- a/crates/hdx_atomizable_derive/src/lib.rs +++ /dev/null @@ -1,133 +0,0 @@ -use quote::quote; -use syn::{parse_macro_input, Data, DeriveInput, Error, Expr, Lit, LitStr, Meta}; - -#[derive(Debug, Copy, Clone, PartialEq)] -enum RenameRule { - PascalCase, - LowerCase, - UpperCase, - CamelCase, - SnakeCase, - ScreamingSnakeCase, - KebabCase, - ScreamingKebabCase, -} - -// Copied from Serde -// https://github.com/serde-rs/serde/blob/6e0b13eedbe24c54d49b421ae1ef36e007e8e592/serde_derive/src/internals/case.rs#L10C1-L84 -impl RenameRule { - pub fn apply_to_variant(&self, variant: &str) -> String { - match *self { - Self::PascalCase => variant.to_owned(), - Self::LowerCase => variant.to_ascii_lowercase(), - Self::UpperCase => variant.to_ascii_uppercase(), - Self::CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], - Self::SnakeCase => { - let mut snake = String::new(); - for (i, ch) in variant.char_indices() { - if i > 0 && ch.is_uppercase() { - snake.push('_'); - } - snake.push(ch.to_ascii_lowercase()); - } - snake - } - Self::ScreamingSnakeCase => { - Self::SnakeCase.apply_to_variant(variant).to_ascii_uppercase() - } - Self::KebabCase => Self::SnakeCase.apply_to_variant(variant).replace('_', "-"), - Self::ScreamingKebabCase => { - Self::ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-") - } - } - } -} - -fn get_rename_rule(input: &DeriveInput) -> Result { - for attr in &input.attrs { - if attr.path().is_ident("atomizable") { - if let Meta::NameValue(meta) = attr.parse_args().unwrap() { - if meta.path.is_ident("rename_all") { - if let Expr::Lit(lit) = meta.value { - if let Lit::Str(str) = lit.lit { - return match str.value().as_str() { - "PascalCase" => Ok(RenameRule::PascalCase), - "lowercase" => Ok(RenameRule::LowerCase), - "UPPERCASE" => Ok(RenameRule::UpperCase), - "camelCase" => Ok(RenameRule::CamelCase), - "snake_case" => Ok(RenameRule::SnakeCase), - "SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase), - "kebab-case" => Ok(RenameRule::KebabCase), - "SCREAMING-KEBAB-CASE" => Ok(RenameRule::ScreamingKebabCase), - _ => Err(Error::new_spanned( - meta.path, - "expected a valid rename rule", - )), - }; - } else { - Err(Error::new_spanned(meta.path, "expected a string literal"))?; - } - } else { - Err(Error::new_spanned(meta.path, "expected `rename_all`"))?; - } - } else { - Err(Error::new_spanned(meta.path, "expected `rename_all`"))?; - } - } - } - } - Ok(RenameRule::KebabCase) -} - -#[proc_macro_derive(Atomizable, attributes(atomizable))] -pub fn derive_atomizable(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let rename_rule = get_rename_rule(&input).unwrap(); - match input.data { - Data::Enum(syn::DataEnum { variants, .. }) => { - let ident = input.ident; - let mut match_atom_to_enum_variant = Vec::new(); - let mut match_enum_variant_to_atom = Vec::new(); - for var in variants { - let var_ident = var.ident; - let str = LitStr::new( - rename_rule.apply_to_variant(format!("{}", var_ident).as_str()).as_str(), - var_ident.span(), - ); - match_atom_to_enum_variant.push(quote! { - atom!(#str) => Some(Self::#var_ident), - }); - match_enum_variant_to_atom.push(quote! { - Self::#var_ident => atom!(#str), - }); - } - let from_atom_match = quote! { - match atom.to_ascii_lowercase() { - #(#match_atom_to_enum_variant)* - _ => None - } - }; - let to_atom_match = quote! { - match self { - #(#match_enum_variant_to_atom)* - } - }; - quote! { - impl Atomizable for #ident { - fn from_atom(atom: Atom) -> Option { - #from_atom_match - } - fn to_atom(&self) -> Atom { - #to_atom_match - } - } - } - } - _ => { - let error = Error::new(input.ident.span(), "can only derive atomizable for enums") - .into_compile_error(); - quote! {#error} - } - } - .into() -} diff --git a/crates/hdx_atomizable_derive/Cargo.toml b/crates/hdx_derive/Cargo.toml similarity index 82% rename from crates/hdx_atomizable_derive/Cargo.toml rename to crates/hdx_derive/Cargo.toml index fdaae5ba..20241ac4 100644 --- a/crates/hdx_atomizable_derive/Cargo.toml +++ b/crates/hdx_derive/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hdx_atomizable_derive" +name = "hdx_derive" version = "0.0.0" authors.workspace = true description.workspace = true @@ -14,9 +14,11 @@ proc-macro = true [dependencies] hdx_atom.workspace = true +hdx_lexer.workspace = true syn = { workspace = true, features = ["extra-traits"] } quote = { workspace = true } +proc-macro2 = { workspace = true } [features] default = [] diff --git a/crates/hdx_derive/src/atomizable.rs b/crates/hdx_derive/src/atomizable.rs new file mode 100644 index 00000000..9c33aaa3 --- /dev/null +++ b/crates/hdx_derive/src/atomizable.rs @@ -0,0 +1,74 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Data, DataEnum, DataStruct, DeriveInput, Fields, LitStr}; + +use crate::{err, kebab}; + +pub fn derive(input: DeriveInput) -> TokenStream { + let ident = input.ident; + match input.data { + Data::Enum(DataEnum { variants, .. }) => { + let mut match_atom_to_enum_variant = Vec::new(); + let mut match_enum_variant_to_atom = Vec::new(); + for var in variants { + let var_ident = var.ident; + let str = LitStr::new(kebab(format!("{}", var_ident)).as_str(), var_ident.span()); + match_atom_to_enum_variant.push(quote! { + hdx_atom::atom!(#str) => Some(Self::#var_ident), + }); + // To allow for bitmasks, we match with equality + match_enum_variant_to_atom.push(quote! { + s if *s == Self::#var_ident => hdx_atom::atom!(#str), + }); + } + let from_atom_match = quote! { + match atom.to_ascii_lowercase() { + #(#match_atom_to_enum_variant)* + _ => None + } + }; + let to_atom_match = quote! { + match self { + #(#match_enum_variant_to_atom)* + s => unreachable!(), + } + }; + quote! { + #[automatically_derived] + impl hdx_atom::Atomizable for #ident { + fn from_atom(atom: hdx_atom::Atom) -> Option { + #from_atom_match + } + fn to_atom(&self) -> hdx_atom::Atom { + #to_atom_match + } + } + } + } + Data::Struct(DataStruct { fields: Fields::Unnamed(fields), .. }) => { + if fields.unnamed.len() != 1 { + return err(ident.span(), "Cannot drive Writable on struct with multiple fields"); + } + let str = LitStr::new(kebab(format!("{}", ident)).as_str(), ident.span()); + quote! { + #[automatically_derived] + impl hdx_atom::Atomizable for #ident { + fn from_atom(atom: hdx_atom::Atom) -> Option { + if atom == hdx_atom::atom!(#str) { + Some(Self(::core::default::Default::default())) + } else { + None + } + } + fn to_atom(&self) -> hdx_atom::Atom { + hdx_atom::atom!(#str) + } + } + } + } + Data::Struct(_) => { + err(ident.span(), "Cannot derive Atomizable on a struct with named or no fields") + } + Data::Union(_) => err(ident.span(), "Cannot derive Atomizable on a Union"), + } +} diff --git a/crates/hdx_derive/src/lib.rs b/crates/hdx_derive/src/lib.rs new file mode 100644 index 00000000..44df6ab7 --- /dev/null +++ b/crates/hdx_derive/src/lib.rs @@ -0,0 +1,34 @@ +use proc_macro::TokenStream; + +mod string_transform; + +mod atomizable; +mod parsable; +mod writable; + +use proc_macro2::Span; +pub(crate) use string_transform::*; +use syn::Error; + +#[proc_macro_derive(Atomizable, attributes(atomizable))] +pub fn derive_atomizable(stream: TokenStream) -> TokenStream { + let input = syn::parse(stream).unwrap(); + atomizable::derive(input).into() +} + +#[proc_macro_derive(Parsable, attributes(parsable))] +pub fn derive_parsable(stream: TokenStream) -> TokenStream { + let input = syn::parse(stream).unwrap(); + parsable::derive(input).into() +} + +#[proc_macro_derive(Writable, attributes(writable))] +pub fn derive_writable(stream: TokenStream) -> TokenStream { + let input = syn::parse(stream).unwrap(); + writable::derive(input).into() +} + +fn err(span: Span, msg: &str) -> proc_macro2::TokenStream { + let err = Error::new(span, msg).into_compile_error(); + quote::quote! {#err} +} diff --git a/crates/hdx_derive/src/parsable.rs b/crates/hdx_derive/src/parsable.rs new file mode 100644 index 00000000..14b6c815 --- /dev/null +++ b/crates/hdx_derive/src/parsable.rs @@ -0,0 +1,396 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{ + parse::Parse, punctuated::Punctuated, spanned::Spanned, Attribute, Data, DataEnum, DeriveInput, Error, Fields, + FieldsUnnamed, Ident, LitStr, Meta, Token, +}; + +use crate::{err, kebab}; + +#[derive(Clone, Debug)] +enum Kind { + Ident, + Number, + String, + Function, + Dimension, + AtKeyword, +} + +#[derive(Clone, Debug)] +enum Check { + Int, + Float, + Signed, + Unsigned, +} + +#[derive(Clone, Debug)] +enum ParsableArg { + ParseInner, + Kind(Kind), + Atom(String), + Check(Check), +} + +impl Parse for ParsableArg { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + match input.parse::()? { + i if i == "parse_inner" => Ok(Self::ParseInner), + i if i == "Number" => Ok(Self::Kind(Kind::Number)), + i if i == "String" => Ok(Self::Kind(Kind::String)), + i if i == "Function" => Ok(Self::Kind(Kind::Function)), + i if i == "Dimension" => Ok(Self::Kind(Kind::Dimension)), + i if i == "AtKeyword" => Ok(Self::Kind(Kind::AtKeyword)), + i if i == "atom" => { + input.parse::()?; + Ok(Self::Atom(input.parse::()?.value())) + }, + i if i == "Check" => { + input.parse::()?; + match input.parse::()? { + i if i == "Int" => Ok(Self::Check(Check::Int)), + i if i == "Float" => Ok(Self::Check(Check::Float)), + i if i == "Signed" => Ok(Self::Check(Check::Signed)), + i if i == "Unsigned" => Ok(Self::Check(Check::Unsigned)), + ident => Err(Error::new(ident.span(), format!("Unrecognized Parsable value Check::{:?}", ident)))? + } + }, + ident => Err(Error::new(ident.span(), format!("Unrecognized Parsable arg {:?}", ident)))? + } + } +} + +pub struct ParsableArgs { + kind: Kind, + parse_inner: bool, + atom: Option, + check: Option, +} + +impl ParsableArgs { + fn parse(attrs: &[Attribute]) -> Self { + let mut ret = Self { kind: Kind::Ident, parse_inner: false, atom: None, check: None }; + if let Some(Attribute { meta: Meta::List(meta), .. }) = &attrs.iter().find(|a| a.path().is_ident("parsable")) { + let args = meta.parse_args_with(Punctuated::::parse_terminated).unwrap(); + for arg in args { + match arg { + ParsableArg::Kind(k) => ret.kind = k, + ParsableArg::ParseInner => ret.parse_inner = true, + ParsableArg::Check(c) => ret.check = Some(c), + ParsableArg::Atom(s) => ret.atom = Some(s), + } + } + return ret; + } + ret + } +} + +pub fn derive(input: DeriveInput) -> TokenStream { + let ident = input.ident; + match input.data { + Data::Struct(_) => err(ident.span(), "Cannot derive Parsable on a struct with named or no fields"), + + Data::Union(_) => err(ident.span(), "Cannot derive Parsable on a Union"), + + Data::Enum(DataEnum { variants, .. }) => { + let mut ident_matchers = vec![]; + let mut function_matchers = vec![]; + let mut at_matchers = vec![]; + let mut string_matcher = None; + let mut number_matcher = None; + let mut dimension_matcher = None; + let mut dimension_matchers = vec![]; + + // Each variant in the Enum will be handled in its own way + for var in variants { + let var_ident = var.ident; + let args = ParsableArgs::parse(&var.attrs); + let str = LitStr::new(&args.atom.unwrap_or_else(|| kebab(format!("{}", var_ident))), var_ident.span()); + + // The fields in each variant need to be handled differently + match var.fields { + // Named Struct Variants are simply too complex to support + // enum Foo { A({ b, c }) } will fail + Fields::Named(_) => { + ident_matchers.push(err(var.fields.span(), "Cannot derive on Parsable on named fields")) + } + + // Unit fields can only take an ident. E.g. + // enum Foo { A, B } will only match the matching idents "a" and "b" + Fields::Unit => ident_matchers.push(match args.kind { + Kind::Ident => quote! { + hdx_atom::atom!(#str) => { + parser.advance(); + Ok(Self::#var_ident.spanned(parser.span())) + } + }, + _ => err(ident.span(), "Parsable only matches Unit variants to Kind::Ident arms"), + }), + + // Unnamed structs can be handled but each one must must be annotated to deal with diffetent token + // types, and each token type can support a limited set of fields. + Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => match args.kind { + // Dimensions can be assigned to a single unnamed field: + // enum Foo { + // #[parsable(Dimension)] + // A(the_dimension_f32) + // #[parsable(Dimension)] + // B(the_dimension_f32) + // } + // + // Multiple match arms can exist, one for each named unit of the dimension. + // Alternatively the `parse_inner` flag can be used, in which case only one march arm can exist: + // + // enum Foo { + // #[parsable(Dimension, parse_inner)] + // A(TheParsable) + // } + Kind::Dimension => { + if dimension_matcher.is_some() { + dimension_matcher = + Some(err(ident.span(), "Cannot have multiple fields match Kind::Dimension")); + } else if unnamed.len() > 1 { + dimension_matcher = Some(err( + ident.span(), + "The match arm for Kind::Dimension can only have a single unnamed value", + )); + } else { + let field = unnamed[0].clone().ty; + if args.parse_inner { + dimension_matcher = Some(quote! { + val @ hdx_lexer::Token::Dimension(_, _, _) => { + use hdx_parser::{Parse}; + let span = parser.span(); + let parsed = #field::parse(parser); + Ok(Self::#var_ident(parsed).spanned(span.end(parser.pos()))) + }, + }); + } else { + dimension_matchers.push(quote! { + hdx_atom::atom!(#str) => { + parser.advance(); + Ok(Self::#var_ident(val.into()).spanned(parser.span())) + }, + }); + } + } + } + // Numbers can be assigned to a single unnamed field: + // enum Foo { + // #[parsable(Number)] + // A(the_number_f32) + // } + // + // Only one enum variant can be a Number, if multiple are present it'll error. + Kind::Number => { + number_matcher = Some(if number_matcher.is_some() { + err(ident.span(), "Cannot have multiple fields match Kind::Number") + } else if unnamed.len() > 1 { + err(ident.span(), "The match arm for Kind::Number can only have a single unnamed value") + } else { + let field = unnamed[0].clone().ty; + let checks = match args.check { + Some(Check::Float) => Some(quote! { + if !ty.is_float() { + Err(hdx_parser::diagnostics::ExpectedFloat(val, parser.span()))? + } + }), + Some(Check::Int) => Some(quote! { + if !ty.is_int() { + Err(hdx_parser::diagnostics::ExpectedInt(val, parser.span()))? + } + }), + Some(Check::Signed) => Some(quote! { + if !ty.is_signed() { + Err(hdx_parser::diagnostics::ExpectedSign(atom, parser.span()))? + } + }), + Some(Check::Unsigned) => Some(quote! { + if ty.is_signed() { + Err(hdx_parser::diagnostics::ExpectedUnsigned(atom, parser.span()))? + } + }), + _ => None, + }; + if args.parse_inner { + quote! { + val @ hdx_lexer::Token::Number(_, ty) => { + use hdx_parser::{Parse}; + let span = parser.span(); + let parsed = #field::parse(parser); + #checks + Ok(Self::#var_ident(parsed).spanned(span.end(parser.pos()))) + }, + } + } else { + quote! { + hdx_lexer::Token::Number(val, ty) => { + #checks + parser.advance(); + Ok(Self::#var_ident(val.into()).spanned(parser.span())) + }, + } + } + }) + } + // Strings can be assigned to a single unnamed field: + // enum Foo { + // #[parsable(String)] + // A(the_atom) + // } + // + // Only one enum variant can be a String, if multiple are present it'll error. + Kind::String => { + string_matcher = Some(if string_matcher.is_some() { + err(ident.span(), "Cannot have multiple fields match Kind::String") + } else if unnamed.len() > 1 { + err(ident.span(), "The match arm for Kind::String can only have a single unnamed value") + } else { + let field = unnamed[0].clone().ty; + if args.parse_inner { + quote! { + hdx_lexer::Token::String(_) => { + use hdx_parser::{Parse}; + let span = parser.span(); + let parsed = #field::parse(parser); + Ok(Self::#var_ident(parsed).spanned(span.end(parser.pos()))) + }, + } + } else { + quote! { + hdx_lexer::Token::String(val) => { + use hdx_parser::{Parse}; + parser.advance(); + Ok(Self::#var_ident(val.into()).spanned(parser.span())) + }, + } + } + }); + } + // Strings can be assigned to a single unnamed field: + // enum Foo { + // #[parsable(Function)] + // Bar(the_atom) + // #[parsable(Function)] + // Baz(the_atom) + // } + // + // Multiple match arms can exist, one for each named function + Kind::Function => { + function_matchers.push(if unnamed.len() > 1 { + err( + ident.span(), + "The match arm for a Kind::Function can only have a single unnamed value", + ) + } else { + let field = unnamed[0].clone().ty; + quote! { + hdx_atom::atom!(#str) => { + let span = parser.span(); + parser.advance(); + let val = #field::parse(parser)?; + hdx_parser::expect!(parser, Token::RightParen); + Ok(Self::#var_ident(val).spanned(span.end(parser.cur()))) + } + } + }); + } + // AtKeywords can be assigned to a single unnamed field: + // enum Foo { + // #[parsable(AtKeyword)] + // Bar(the_atom) + // #[parsable(AtKeyword)] + // Baz(the_atom) + // } + // + // Multiple match arms can exist, one for each named keyword + Kind::AtKeyword => { + at_matchers.push(if unnamed.len() > 1 { + err( + ident.span(), + "The match arm for a Kind::AtKeyword can only have a single unnamed value", + ) + } else { + let field = unnamed[0].clone().ty; + quote! { + hdx_atom::atom!(#str) => { + let span = parser.span(); + parser.advance(); + let val = #field::parse(parser)?; + Ok(Self::#var_ident(val).spanned(span.end(parser.pos()))) + } + } + }); + } + k => { + ident_matchers.push(err( + ident.span(), + &format!("Parsable cannot match Unnamed fields in a {:?} arm", k), + )); + } + }, + } + } + let ident_match_arm = if ident_matchers.is_empty() { + quote! {} + } else { + quote! { + hdx_lexer::Token::Ident(atom) => match atom.to_ascii_lowercase() { + #(#ident_matchers)* + _ => Err(hdx_parser::diagnostics::UnexpectedIdent(atom, parser.span()))? + } + } + }; + let function_match_arm = if function_matchers.is_empty() { + quote! {} + } else { + quote! { + hdx_lexer::Token::Function(atom) => match atom.to_ascii_lowercase() { + #(#function_matchers)* + _ => Err(hdx_parser::diagnostics::UnexpectedFunction(atom, parser.span()))? + } + } + }; + let at_match_arm = if at_matchers.is_empty() { + quote! {} + } else { + quote! { + hdx_lexer::Token::AtKeyword(atom) => match atom.to_ascii_lowercase() { + #(#at_matchers)* + _ => Err(hdx_parser::diagnostics::UnexpectedAtRule(atom, parser.span()))? + } + } + }; + let dimension_match_arm = if dimension_matchers.is_empty() && dimension_matcher.is_none() { + quote! {} + } else if let Some(quote) = dimension_matcher { + quote + } else { + quote! { + hdx_lexer::Token::Dimension(val, unit, _) => match unit.to_ascii_lowercase() { + #(#dimension_matchers)* + _ => Err(hdx_parser::diagnostics::UnexpectedDimension(unit, parser.span()))? + } + } + }; + quote! { + #[automatically_derived] + impl<'a> hdx_parser::Parse<'a> for #ident { + fn parse(parser: &mut hdx_parser::Parser<'a>) -> hdx_parser::Result> { + match parser.cur() { + #ident_match_arm + #function_match_arm + #at_match_arm + #dimension_match_arm + #string_matcher + #number_matcher + token => hdx_parser::unexpected!(parser, token) + } + } + } + } + } + } +} diff --git a/crates/hdx_derive/src/string_transform.rs b/crates/hdx_derive/src/string_transform.rs new file mode 100644 index 00000000..5e8e86df --- /dev/null +++ b/crates/hdx_derive/src/string_transform.rs @@ -0,0 +1,10 @@ +pub fn kebab(str: String) -> String { + let mut kebab = String::new(); + for (i, ch) in str.char_indices() { + if i > 0 && ch.is_uppercase() { + kebab.push('-'); + } + kebab.push(ch.to_ascii_lowercase()); + } + kebab +} diff --git a/crates/hdx_derive/src/writable.rs b/crates/hdx_derive/src/writable.rs new file mode 100644 index 00000000..6582a3c4 --- /dev/null +++ b/crates/hdx_derive/src/writable.rs @@ -0,0 +1,224 @@ +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{ + parse::Parse, punctuated::Punctuated, spanned::Spanned, Attribute, Data, DataEnum, DataStruct, + DeriveInput, Error, Fields, FieldsUnnamed, Ident, Index, LitStr, Meta, Token, +}; + +use crate::{err, kebab}; + +#[derive(Clone, Debug)] +pub enum WritableArg { + AsFunction(String), + Suffix(String), + Prefix(String), + Rename(String), +} + +impl Parse for WritableArg { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let ident = input.parse::()?; + if ident == "as_function" { + input.parse::()?; + Ok(Self::AsFunction(input.parse::()?.value())) + } else if ident == "suffix" { + input.parse::()?; + Ok(Self::Suffix(input.parse::()?.value())) + } else if ident == "prefix" { + input.parse::()?; + Ok(Self::Prefix(input.parse::()?.value())) + } else if ident == "rename" { + input.parse::()?; + Ok(Self::Rename(input.parse::()?.value())) + } else { + Err(Error::new(ident.span(), "Unrecognized Writable arg"))? + } + } +} + +pub struct WritableArgs(Vec); + +impl WritableArgs { + fn parse(attrs: &[Attribute]) -> Self { + if let Some(Attribute { meta: Meta::List(meta), .. }) = + &attrs.iter().find(|a| a.path().is_ident("writable")) + { + return Self( + meta.parse_args_with(Punctuated::::parse_terminated) + .unwrap() + .iter() + .cloned() + .collect(), + ); + } + Self(vec![]) + } +} + +pub fn derive(input: DeriveInput) -> TokenStream { + let ident = input.ident; + let input_args = WritableArgs::parse(&input.attrs); + match input.data { + Data::Enum(DataEnum { variants, .. }) => { + let mut matchers = vec![]; + for var in variants { + let var_ident = var.ident; + let args = WritableArgs::parse(&var.attrs); + if args.0.len() > 1 { + return err(var_ident.span(), "#[writable] can only have one argument"); + } + match var.fields { + Fields::Unit => { + let str = + LitStr::new(kebab(format!("{}", var_ident)).as_str(), var_ident.span()); + match args.0.first() { + Some(WritableArg::AsFunction(name)) => { + matchers.push(quote! { + Self::#var_ident => { + hdx_atom::atom!(#name).write_css(sink)?; + sink.write_char('(')?; + hdx_atom::atom!(#str).write_css(sink)?; + sink.write_char(')')?; + } + }); + } + Some(WritableArg::Prefix(prefix)) => { + matchers.push(quote! { + Self::#var_ident => { + sink.write_str(#prefix)?; + hdx_atom::atom!(#str).write_css(sink)?; + } + }); + } + Some(WritableArg::Suffix(suffix)) => { + matchers.push(quote! { + Self::#var_ident => { + hdx_atom::atom!(#str).write_css(sink)?; + sink.write_str(#suffix)?; + } + }); + } + _ => { + matchers.push(quote! { + Self::#var_ident => hdx_atom::atom!(#str).write_css(sink)?, + }); + } + } + } + Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => { + let mut field_extract = vec![]; + let mut field_writes = vec![]; + for i in 0..unnamed.len() { + let fname = Ident::new(&format!("f{:?}", i), Span::call_site()); + field_extract.push(fname.clone()); + field_writes.push(quote! { + #fname.write_css(sink)?; + }); + } + match args.0.first() { + Some(WritableArg::AsFunction(name)) => { + matchers.push(quote! { + Self::#var_ident(#(#field_extract)*) => { + hdx_atom::atom!(#name).write_css(sink)?; + sink.write_char('(')?; + #(#field_writes)* + sink.write_char(')')?; + }, + }); + } + Some(WritableArg::Prefix(prefix)) => { + matchers.push(quote! { + Self::#var_ident(#(#field_extract)*) => { + hdx_atom::atom!(#prefix).write_css(sink)?; + #(#field_writes)* + } + }); + } + Some(WritableArg::Suffix(suffix)) => { + matchers.push(quote! { + Self::#var_ident(#(#field_extract)*) => { + #(#field_writes)* + hdx_atom::atom!(#suffix).write_css(sink)?; + } + }); + } + _ => matchers.push(quote! { + Self::#var_ident(#(#field_extract)*) => { + #(#field_writes)* + } + }), + }; + } + Fields::Named(_) => matchers + .push(err(var.fields.span(), "Cannot derive on Writable on named fields")), + } + } + let match_block = quote! { + match self { + #(#matchers)* + } + }; + quote! { + #[automatically_derived] + impl<'a> ::hdx_writer::WriteCss<'a> for #ident { + fn write_css(&self, sink: &mut W) -> ::hdx_writer::Result { + use ::hdx_writer::{WriteCss, CssWriter}; + #match_block + Ok(()) + } + } + } + } + Data::Struct(DataStruct { fields: Fields::Unnamed(fields), .. }) => { + if input_args.0.len() > 1 { + return err(ident.span(), "#[writable] can only have one argument"); + } + let mut field_writes = vec![]; + for i in 0..fields.unnamed.len() { + let idx = Index::from(i); + field_writes.push(quote! { + self.#idx.write_css(sink)?; + }); + } + let write = match input_args.0.first() { + Some(WritableArg::AsFunction(name)) => { + quote! { + hdx_atom::atom!(#name).write_css(sink)?; + sink.write_char('(')?; + #(#field_writes)* + sink.write_char(')')?; + } + } + Some(WritableArg::Prefix(prefix)) => { + quote! { + hdx_atom::atom!(#prefix).write_css(sink)?; + #(#field_writes)* + } + } + Some(WritableArg::Suffix(suffix)) => { + quote! { + #(#field_writes)* + hdx_atom::atom!(#suffix).write_css(sink)?; + } + } + _ => quote! { + #(#field_writes)* + }, + }; + quote! { + #[automatically_derived] + impl<'a> ::hdx_writer::WriteCss<'a> for #ident { + fn write_css(&self, sink: &mut W) -> ::hdx_writer::Result { + use ::hdx_writer::{WriteCss, CssWriter}; + #write + Ok(()) + } + } + } + } + Data::Struct(_) => { + err(ident.span(), "Cannot derive Writable on a Struct with named or no fields") + } + Data::Union(_) => err(ident.span(), "Cannot derive Writable on a Union"), + } +} diff --git a/crates/hdx_lexer/src/lib.rs b/crates/hdx_lexer/src/lib.rs index dd7d8de1..ebefcedc 100644 --- a/crates/hdx_lexer/src/lib.rs +++ b/crates/hdx_lexer/src/lib.rs @@ -13,7 +13,6 @@ pub use token::{NumType, PairWise, Token}; pub struct LexerCheckpoint<'a> { chars: Chars<'a>, token: Token, - prev_pos: u32, } #[bitmask(u8)] @@ -33,7 +32,7 @@ pub struct Lexer<'a> { impl<'a> Lexer<'a> { pub fn new(allocator: &'a Allocator, source: &'a str) -> Self { let token = Token::default(); - let current = LexerCheckpoint { chars: source.chars(), token, prev_pos: 0 }; + let current = LexerCheckpoint { chars: source.chars(), token }; Self { allocator, source, @@ -57,11 +56,7 @@ impl<'a> Lexer<'a> { /// Creates a checkpoint storing the current lexer state. /// Use `rewind` to restore the lexer to the state stored in the checkpoint. pub fn checkpoint(&self) -> LexerCheckpoint<'a> { - LexerCheckpoint { - prev_pos: self.current.prev_pos, - chars: self.current.chars.clone(), - token: self.current.token.clone(), - } + LexerCheckpoint { chars: self.current.chars.clone(), token: self.current.token.clone() } } /// Rewinds the lexer to the same state as when the passed in `checkpoint` was created. @@ -90,15 +85,10 @@ impl<'a> Lexer<'a> { // `self.current = checkpoint` self.current.token = Token::default(); - let prev_pos = self.pos(); - for _i in self.lookahead.len()..n { let peeked = self.read_next_token(); - self.lookahead.push_back(LexerCheckpoint { - prev_pos, - chars: self.current.chars.clone(), - token: peeked, - }); + self.lookahead + .push_back(LexerCheckpoint { chars: self.current.chars.clone(), token: peeked }); } self.current = checkpoint; @@ -106,16 +96,16 @@ impl<'a> Lexer<'a> { &self.lookahead[n - 1].token } - pub fn jump_token(&mut self) -> Token { + pub fn jump(&mut self) -> Token { if let Some(checkpoint) = self.lookahead.pop_back() { self.current.chars = checkpoint.chars; self.lookahead.clear(); return checkpoint.token; } - self.next_token() + self.advance() } - pub fn next_token(&mut self) -> Token { + pub fn advance(&mut self) -> Token { if let Some(checkpoint) = self.lookahead.pop_front() { self.current.chars = checkpoint.chars; return checkpoint.token; @@ -123,14 +113,14 @@ impl<'a> Lexer<'a> { self.read_next_token() } - pub fn next_including_whitespace(&mut self) -> Token { + pub fn advance_including_whitespace(&mut self) -> Token { self.include = Include::Whitespace; let token = self.read_next_token(); self.include = Include::none(); token } - pub fn next_including_whitespace_and_comments(&mut self) -> Token { + pub fn advance_including_whitespace_and_comments(&mut self) -> Token { self.include = Include::all(); let token = self.read_next_token(); self.include = Include::none(); diff --git a/crates/hdx_lexer/src/private.rs b/crates/hdx_lexer/src/private.rs index 17fd318a..c854f2a1 100644 --- a/crates/hdx_lexer/src/private.rs +++ b/crates/hdx_lexer/src/private.rs @@ -126,16 +126,31 @@ impl<'a> Lexer<'a> { '*' => { self.current.chars.next(); self.current.chars.next(); - self.consume_comment(); if self.include_comments() { - return Token::Comment; + let mut builder = AutoCow::new(self); + loop { + if self.nth(0) == EOF || (self.nth(0) == '*' && self.nth(1) == '/') { + let str = builder.finish(self); + self.current.chars.next(); + self.current.chars.next(); + return Token::Comment(Atom::from(str)) + } + builder.push_matching(self.current.chars.next().unwrap()); + } + } else { + while let Some(c) = self.current.chars.next() { + if c == '*' && self.nth(0) == '/' { + self.current.chars.next(); + break; + } + } + self.read_next_token() } - self.read_next_token() } _ => Token::Delim(self.current.chars.next().unwrap()), }, c if is_ident_start(c) => { - return self.consume_ident_like_token(); + self.consume_ident_like_token() } _ => Token::Delim(self.current.chars.next().unwrap()), } @@ -254,7 +269,7 @@ impl<'a> Lexer<'a> { let mut builder = AutoCow::new(self); let c = self.current.chars.next().unwrap(); builder.push_matching(c); - let mut num_type = NumType::UnsignedInt; + let mut num_type = NumType::none(); if is_sign(c) { num_type = num_type.signed(); } @@ -282,13 +297,13 @@ impl<'a> Lexer<'a> { match self.nth(0) { '%' => { self.current.chars.next(); - Token::Dimension(num_type, value, atom!("%")) + Token::Dimension(value, atom!("%"), num_type) } c if is_ident_start_sequence(c, self.nth(1), self.nth(2)) => { let unit = self.consume_ident_sequence(); - Token::Dimension(num_type, value, unit) + Token::Dimension(value, unit, num_type) } - _ => Token::Number(num_type, value), + _ => Token::Number(value, num_type), } } @@ -369,15 +384,6 @@ impl<'a> Lexer<'a> { } } - fn consume_comment(&mut self) { - while let Some(c) = self.current.chars.next() { - if c == '*' && self.nth(0) == '/' { - self.current.chars.next(); - return; - } - } - } - fn is_number_start(&mut self) -> bool { self.nth(0).is_ascii_digit() || (is_sign(self.nth(0)) diff --git a/crates/hdx_lexer/src/token.rs b/crates/hdx_lexer/src/token.rs index 12c7ac86..1978464f 100644 --- a/crates/hdx_lexer/src/token.rs +++ b/crates/hdx_lexer/src/token.rs @@ -1,38 +1,43 @@ use std::hash::{Hash, Hasher}; +use bitmask_enum::bitmask; use hdx_atom::Atom; #[cfg(feature = "serde")] use serde::Serialize; -#[derive(Debug, Copy, Clone, PartialEq, Default, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize))] +#[derive(Default)] +#[bitmask(u8)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] pub enum NumType { #[default] - UnsignedInt, - SignedInt, - UnsignedFloat, - SignedFloat, + Float = 0x01, + Signed = 0x10, } impl NumType { + #[inline] pub fn is_int(&self) -> bool { - matches!(*self, NumType::UnsignedInt | NumType::SignedInt) + self.and(NumType::Float) != NumType::Float + } + + #[inline] + pub fn is_float(&self) -> bool { + self.contains(NumType::Float) } + #[inline] + pub fn is_signed(&self) -> bool { + self.contains(NumType::Signed) + } + + #[inline] pub fn signed(&self) -> NumType { - match *self { - NumType::UnsignedInt => NumType::SignedInt, - NumType::UnsignedFloat => NumType::SignedFloat, - x => x, - } + self.or(NumType::Signed) } + #[inline] pub fn float(&self) -> NumType { - match *self { - NumType::UnsignedInt => NumType::UnsignedFloat, - NumType::SignedInt => NumType::SignedFloat, - x => x, - } + self.or(NumType::Float) } } @@ -47,7 +52,7 @@ pub enum Token { Eof, // (https://drafts.csswg.org/css-syntax/#comment-diagram) - Comment, + Comment(Atom), // (https://drafts.csswg.org/css-syntax/#ident-token-diagram) Ident(Atom), @@ -80,10 +85,10 @@ pub enum Token { Delim(char), // (https://drafts.csswg.org/css-syntax/#number-token-diagram) - Number(NumType, f32), + Number(f32, NumType), // (https://drafts.csswg.org/css-syntax/#dimension-token-diagram) - Dimension(NumType, f32, Atom), + Dimension(f32, Atom, NumType), // (https://drafts.csswg.org/css-syntax/#whitespace-token-diagram) Whitespace, @@ -140,7 +145,7 @@ impl Token { #[inline] pub fn is_trivia(&self) -> bool { - matches!(self, Token::Whitespace | Token::Comment) + matches!(self, Token::Whitespace | Token::Comment(_)) } #[inline] @@ -189,16 +194,16 @@ impl Token { pub fn as_f32(&self) -> Option { match self { - Self::Number(_, value) => Some(*value), - Self::Dimension(_, value, _) => Some(*value), + Self::Number(value, _) => Some(*value), + Self::Dimension(value, _, _) => Some(*value), _ => None, } } pub fn as_i32(&self) -> Option { match self { - Self::Number(_, value) => Some(*value as i32), - Self::Dimension(_, value, _) => Some(*value as i32), + Self::Number(value, _) => Some(*value as i32), + Self::Dimension(value, _, _) => Some(*value as i32), _ => None, } } @@ -212,20 +217,20 @@ impl Token { pub fn is_signed(&self) -> bool { match self { - Self::Number(NumType::SignedInt, _) => true, - Self::Number(NumType::SignedFloat, _) => true, - Self::Dimension(NumType::SignedInt, _, _) => true, - Self::Dimension(NumType::SignedFloat, _, _) => true, + Self::Number(_, ty) => ty.is_signed(), + Self::Number(_, ty) => ty.is_signed(), + Self::Dimension(_, _, ty) => ty.is_signed(), + Self::Dimension(_, _, ty) => ty.is_signed(), _ => false, } } pub fn is_int(&self) -> bool { match self { - Self::Number(NumType::SignedInt, _) => true, - Self::Number(NumType::UnsignedInt, _) => true, - Self::Dimension(NumType::SignedInt, _, _) => true, - Self::Dimension(NumType::UnsignedInt, _, _) => true, + Self::Number(_, ty) => ty.is_int(), + Self::Number(_, ty) => ty.is_int(), + Self::Dimension(_, _, ty) => ty.is_int(), + Self::Dimension(_, _, ty) => ty.is_int(), _ => false, } } @@ -280,7 +285,10 @@ impl Hash for Token { match self { Token::Undetermined => {} Token::Eof => 0.hash(state), - Token::Comment => 1.hash(state), + Token::Comment(a) => { + 1.hash(state); + a.hash(state); + } Token::Ident(a) => { 2.hash(state); a.hash(state); @@ -319,16 +327,16 @@ impl Hash for Token { 11.hash(state); c.hash(state); } - Token::Number(n, f) => { + Token::Number(f, n) => { 12.hash(state); - n.hash(state); f.to_bits().hash(state); + n.hash(state); } - Token::Dimension(n, f, a) => { + Token::Dimension(f, a, n) => { 13.hash(state); - n.hash(state); f.to_bits().hash(state); a.hash(state); + n.hash(state); } Token::Whitespace => 14.hash(state), Token::Cdo => 15.hash(state), diff --git a/crates/hdx_lexer/tests/tests.rs b/crates/hdx_lexer/tests/tests.rs index c1520165..2a5390f8 100644 --- a/crates/hdx_lexer/tests/tests.rs +++ b/crates/hdx_lexer/tests/tests.rs @@ -1,4 +1,4 @@ -use hdx_atom::atom; +use hdx_atom::{atom, Atom}; use hdx_lexer::{Lexer, Token}; use oxc_allocator::Allocator; @@ -12,9 +12,9 @@ fn empty() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, ""); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 0); } @@ -23,11 +23,11 @@ fn tokenizes_tilde_as_ddelim() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "~"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Delim('~')); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Delim('~')); assert_eq!(lex.pos(), 1); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 1); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 1); } @@ -36,11 +36,11 @@ fn tokenizes_newlines_as_whitespace() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "\r\n"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 2); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 2); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 2); } @@ -49,11 +49,11 @@ fn tokenizes_multiple_newlines_as_whitespace() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "\r\n"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 2); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 2); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 2); } @@ -62,11 +62,11 @@ fn tokenizes_multiple_whitespace_as_whitespace() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "\t \t \t"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 5); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 5); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 5); } @@ -75,29 +75,29 @@ fn tokenizes_trivial_css_file() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "body { color: black }/* fin */"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Ident(atom!("body"))); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Ident(atom!("body"))); assert_eq!(lex.pos(), 4); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 5); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::LeftCurly); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::LeftCurly); assert_eq!(lex.pos(), 6); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 7); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Ident(atom!("color"))); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Ident(atom!("color"))); assert_eq!(lex.pos(), 12); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Colon); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Colon); assert_eq!(lex.pos(), 13); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 14); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Ident(atom!("black"))); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Ident(atom!("black"))); assert_eq!(lex.pos(), 19); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Whitespace); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Whitespace); assert_eq!(lex.pos(), 20); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::RightCurly); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::RightCurly); assert_eq!(lex.pos(), 21); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Comment); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Comment(Atom::from(" fin "))); assert_eq!(lex.pos(), 30); - assert_eq!(lex.next_including_whitespace_and_comments(), Token::Eof); + assert_eq!(lex.advance_including_whitespace_and_comments(), Token::Eof); assert_eq!(lex.pos(), 30); } @@ -106,18 +106,18 @@ fn skips_whitespace_and_comments_with_next() { let allocator = Allocator::default(); let mut lex = Lexer::new(&allocator, "body { color: black }/* fin */"); assert_eq!(lex.pos(), 0); - assert_eq!(lex.next_token(), Token::Ident(atom!("body"))); + assert_eq!(lex.advance(), Token::Ident(atom!("body"))); assert_eq!(lex.pos(), 4); - assert_eq!(lex.next_token(), Token::LeftCurly); + assert_eq!(lex.advance(), Token::LeftCurly); assert_eq!(lex.pos(), 6); - assert_eq!(lex.next_token(), Token::Ident(atom!("color"))); + assert_eq!(lex.advance(), Token::Ident(atom!("color"))); assert_eq!(lex.pos(), 12); - assert_eq!(lex.next_token(), Token::Colon); + assert_eq!(lex.advance(), Token::Colon); assert_eq!(lex.pos(), 13); - assert_eq!(lex.next_token(), Token::Ident(atom!("black"))); + assert_eq!(lex.advance(), Token::Ident(atom!("black"))); assert_eq!(lex.pos(), 19); - assert_eq!(lex.next_token(), Token::RightCurly); + assert_eq!(lex.advance(), Token::RightCurly); assert_eq!(lex.pos(), 21); - assert_eq!(lex.next_token(), Token::Eof); + assert_eq!(lex.advance(), Token::Eof); assert_eq!(lex.pos(), 30); } diff --git a/crates/hdx_parser/Cargo.toml b/crates/hdx_parser/Cargo.toml index b8e06177..a056ebbd 100644 --- a/crates/hdx_parser/Cargo.toml +++ b/crates/hdx_parser/Cargo.toml @@ -12,7 +12,6 @@ repository.workspace = true [dependencies] hdx_lexer = { workspace = true } hdx_syntax = { workspace = true } -hdx_ast = { workspace = true } hdx_atom = { workspace = true } closestmatch = { workspace = true } @@ -23,6 +22,7 @@ bumpalo = { workspace = true } miette = { workspace = true } thiserror = { workspace = true } +bitmask-enum = { workspace = true } serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } @@ -31,5 +31,5 @@ glob = { workspace = true } [features] default = [] -serde = ["dep:serde", "dep:serde_json", "hdx_ast/serde", "hdx_lexer/serde"] +serde = ["dep:serde", "dep:serde_json", "hdx_lexer/serde"] fancy = ["miette/fancy-no-backtrace"] diff --git a/crates/hdx_parser/src/css/component_values.rs b/crates/hdx_parser/src/css/component_values.rs deleted file mode 100644 index 2d51de46..00000000 --- a/crates/hdx_parser/src/css/component_values.rs +++ /dev/null @@ -1,78 +0,0 @@ -use hdx_ast::css::component_values::{ComponentValue, Function, SimpleBlock}; - -use crate::{diagnostics, Kind, Parse, Parser, Result, Spanned, Vec}; - -impl<'a> Parser<'a> { - // https://drafts.csswg.org/css-syntax-3/#consume-list-of-components - pub(crate) fn parse_component_values( - &mut self, - stop_token: Kind, - nested: bool, - ) -> Result>>> { - let mut values = self.new_vec(); - loop { - match self.cur().kind { - Kind::Eof => { - return Ok(values); - } - Kind::RightCurly => { - if nested { - return Ok(values); - } - self.advance(); - } - c => { - if c == stop_token { - return Ok(values); - } - values.push(ComponentValue::parse(self)?) - } - } - } - } -} - -// https://drafts.csswg.org/css-syntax-3/#consume-component-value -impl<'a> Parse<'a> for ComponentValue<'a> { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::LeftCurly | Kind::LeftSquare | Kind::LeftParen => { - Ok(Self::SimpleBlock(SimpleBlock::parse(parser)?) - .spanned(span.until(parser.cur().span))) - } - Kind::Function => { - Ok(Self::Function(Function::parse(parser)?).spanned(span.until(parser.cur().span))) - } - _ => { - let token = parser.cur().clone(); - parser.advance(); - Ok(Self::Token(token).spanned(span)) - } - } - } -} - -// https://drafts.csswg.org/css-syntax-3/#consume-a-simple-block -impl<'a> Parse<'a> for SimpleBlock<'a> { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let pairwise = parser - .cur() - .to_pairwise() - .ok_or_else(|| diagnostics::Unexpected(parser.cur().kind, span))?; - parser.advance(); - let value = parser.parse_component_values(pairwise.end(), true)?; - Ok(Self { value: parser.boxup(value), pairwise }.spanned(span.until(parser.cur().span))) - } -} - -// https://drafts.csswg.org/css-syntax-3/#consume-function -impl<'a> Parse<'a> for Function<'a> { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let name = parser.expect_function()?; - let value = parser.parse_component_values(Kind::RightParen, false)?; - Ok(Self { name, value: parser.boxup(value) }.spanned(span.until(parser.cur().span))) - } -} diff --git a/crates/hdx_parser/src/css/mod.rs b/crates/hdx_parser/src/css/mod.rs deleted file mode 100644 index d0772168..00000000 --- a/crates/hdx_parser/src/css/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod component_values; -pub mod parser_extensions; -pub mod properties; -pub mod rules; -pub mod selector; -pub mod stylerule; -pub mod stylesheet; -pub mod unknown; -pub mod values; diff --git a/crates/hdx_parser/src/css/parser_extensions.rs b/crates/hdx_parser/src/css/parser_extensions.rs deleted file mode 100644 index 935fa590..00000000 --- a/crates/hdx_parser/src/css/parser_extensions.rs +++ /dev/null @@ -1,210 +0,0 @@ -use core::fmt::Debug; - -use oxc_allocator::Vec; - -use crate::{atom, diagnostics, Atom, Kind, Parse, Parser, Result, Spanned, Token}; - -impl<'a> Parser<'a> { - // https://drafts.csswg.org/css-syntax-3/#consume-a-qualified-rule - pub(crate) fn parse_qualified_rule< - T, - Prelude: Parse<'a> + 'a, - Rule: Parse<'a> + 'a, - Decl: Parse<'a> + 'a, - F, - >( - &mut self, - stop_token: Option, - nested: bool, - finalize: F, - ) -> Result - where - F: FnOnce( - &mut Parser<'a>, - Option>, - Vec<'a, Spanned>, - Vec<'a, Spanned>, - ) -> Result, - { - let span = self.cur().span; - let mut prelude = None; - loop { - match self.cur().kind { - Kind::Eof => Err(diagnostics::Unexpected(Kind::Eof, span.until(self.cur().span)))?, - Kind::RightCurly => { - if nested { - Err(diagnostics::Unexpected(self.cur().kind, self.cur().span))? - } - prelude = Some(Prelude::parse(self)?); - } - Kind::LeftCurly => { - return self.parse_block( - |parser: &mut Parser<'a>, - rules: Vec<'a, Spanned>, - decls: Vec<'a, Spanned>| { finalize(parser, prelude, rules, decls) }, - ); - } - c => { - if let Some(k) = stop_token { - if c == k { - self.advance(); - Err(diagnostics::Unexpected(self.cur().kind, self.cur().span))? - } - } - if prelude.is_some() { - Err(diagnostics::Unexpected(self.cur().kind, self.cur().span))? - } - prelude = Some(Prelude::parse(self)?); - self.skip_trivia(); - } - } - } - } - - // https://drafts.csswg.org/css-syntax-3/#consume-an-at-rule - pub(crate) fn parse_at_rule< - T, - Prelude: Parse<'a> + 'a, - Rule: Parse<'a> + 'a, - Decl: Parse<'a> + 'a, - F, - >( - &mut self, - expected_name: Option, - finalize: F, - ) -> Result - where - F: FnOnce( - &mut Parser<'a>, - Atom, - Option>, - Vec<'a, Spanned>, - Vec<'a, Spanned>, - ) -> Result, - { - let name = self.expect_at_keyword()?; - if let Some(exp_name) = expected_name { - if !exp_name.eq_ignore_ascii_case(&name) { - Err(diagnostics::ExpectedIdent(name.clone(), exp_name, self.token.span))?; - } - } - let mut prelude = None; - loop { - match self.cur().kind { - Kind::Semicolon | Kind::Eof => { - self.advance(); - return finalize(self, name, prelude, self.new_vec(), self.new_vec()); - } - Kind::RightCurly => { - let result = finalize(self, name, prelude, self.new_vec(), self.new_vec()); - if result.is_ok() { - self.advance() - } - return result; - } - Kind::LeftCurly => { - return self.parse_block( - |parser: &mut Parser<'a>, - rules: Vec<'a, Spanned>, - decls: Vec<'a, Spanned>| { - finalize(parser, name, prelude, rules, decls) - }, - ); - } - _ => { - prelude = Some(Prelude::parse(self)?); - } - } - } - } - - // https://drafts.csswg.org/css-syntax-3/#consume-block - pub(crate) fn parse_block + 'a, Decl: Parse<'a> + 'a, F>( - &mut self, - finalize: F, - ) -> Result - where - F: FnOnce(&mut Parser<'a>, Vec<'a, Spanned>, Vec<'a, Spanned>) -> Result, - { - let mut decls = self.new_vec(); - let mut rules = self.new_vec(); - self.expect(Kind::LeftCurly)?; - loop { - match self.cur().kind { - Kind::Whitespace | Kind::Semicolon => { - self.advance(); - } - Kind::Eof | Kind::RightCurly => { - self.next_token(); - let res = finalize(self, rules, decls); - self.skip_trivia(); - return res; - } - Kind::AtKeyword => { - rules.push(Rule::parse(self)?); - } - _ => { - let checkpoint = self.checkpoint(); - match Decl::parse(self) { - Ok(decl) => decls.push(decl), - Err(_) => { - self.rewind(checkpoint); - rules.push(Rule::parse(self)?); - } - } - } - } - } - } - - // https://drafts.csswg.org/css-syntax-3/#consume-declaration - pub(crate) fn parse_declaration + 'a, F>( - &mut self, - expected_name: Option, - finalize: F, - ) -> Result - where - F: FnOnce(&mut Parser<'a>, &Token, Spanned, bool) -> Result, - { - let span = self.cur().span; - let name_token = self.cur().clone(); - let ident = self.expect_ident()?; - if let Some(name) = expected_name { - if ident != name { - Err(diagnostics::ExpectedIdent(name, ident.clone(), span))?; - } - } - if ident.starts_with("--") { - Err(diagnostics::Unimplemented(span))?; - } - if ident == atom!("unicode-range") { - Err(diagnostics::Unimplemented(span))?; - } - self.expect(Kind::Colon) - .map_err(|_| diagnostics::BadDeclaration(span.until(self.cur().span)))?; - let value = Value::parse(self)?; - let mut important = false; - loop { - match self.cur().kind { - Kind::Semicolon => { - // Swallow the last semi and break - self.advance(); - break; - } - Kind::Delim => { - if self.cur().value.as_char().unwrap() == '!' - && self.peek().matches_ignore_case(&atom!("important")) - { - important = true; - self.advance(); - self.advance(); - } else { - break; - } - } - _ => break, - } - } - finalize(self, &name_token, value, important) - } -} diff --git a/crates/hdx_parser/src/css/properties.rs b/crates/hdx_parser/src/css/properties.rs index 6ee46a36..6b0cc157 100644 --- a/crates/hdx_parser/src/css/properties.rs +++ b/crates/hdx_parser/src/css/properties.rs @@ -8,14 +8,14 @@ use crate::{atom, diagnostics, Atomizable, Kind, Parse, Parser, Spanned, Token}; impl<'a> Parse<'a> for Custom<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut important = false; let name = parser.expect_ident_cased()?; parser.expect(Kind::Colon)?; let checkpoint = parser.checkpoint(); - let value_span = parser.cur().span; + let value_span = parser.span(); let value_like = ValueLike::parse(parser) - .unwrap_or(ValueLike::Unknown.spanned(value_span.until(parser.cur().span))); + .unwrap_or(ValueLike::Unknown.spanned(value_span.end(parser.pos()))); parser.rewind(checkpoint); let mut value = parser.parse_component_values(Kind::Semicolon, true)?; if parser.at(Kind::Semicolon) { @@ -33,88 +33,86 @@ impl<'a> Parse<'a> for Custom<'a> { } } Ok(Self { name, value_like, value: parser.boxup(value), important } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for ValueLike<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { let checkpoint = parser.checkpoint(); - let span = parser.cur().span; + let span = parser.span(); let token = parser.cur().clone(); let parsed = MathExpr::::parse(parser); if let Ok(value) = parsed { - return Ok(Self::Length(parser.boxup(value)).spanned(span.until(parser.cur().span))); + return Ok(Self::Length(parser.boxup(value)).spanned(span.end(parser.pos()))); } parser.rewind(checkpoint); let checkpoint = parser.checkpoint(); let parsed = MathExpr::::parse(parser); if let Ok(value) = parsed { - return Ok( - Self::LengthPercentage(parser.boxup(value)).spanned(span.until(parser.cur().span)) - ); + return Ok(Self::LengthPercentage(parser.boxup(value)).spanned(span.end(parser.pos()))); } parser.rewind(checkpoint); let checkpoint = parser.checkpoint(); let parsed = Expr::::parse(parser); if let Ok(value) = parsed { - return Ok(Self::Color(parser.boxup(value)).spanned(span.until(parser.cur().span))); + return Ok(Self::Color(parser.boxup(value)).spanned(span.end(parser.pos()))); } parser.rewind(checkpoint); let parsed = ExprList::::parse(parser); if let Ok(value) = parsed { - return Ok(Self::FontFamily(parser.boxup(value)).spanned(span.until(parser.cur().span))); + return Ok(Self::FontFamily(parser.boxup(value)).spanned(span.end(parser.pos()))); } Err(diagnostics::Unexpected(token.kind, token.span).into()) } } macro_rules! parse_properties { - {$( $prop: ident, )+} => { - $( - impl<'a> Parse<'a> for $prop<'a> { - fn parse(parser: &mut Parser<'a>) -> Result>> { - let span = parser.cur().span; - parser.parse_declaration( - Some($prop::name_as_atom()), - |parser: &mut Parser<'a>, _name: &Token, value: Spanned<<$prop as Declaration>::Value>, important: bool| { - Ok($prop { value: parser.boxup(value), important }.spanned(span.until(parser.cur().span))) - }, - ) - } - } - )+ - - impl<'a> Parse<'a> for Property<'a> { - fn parse(parser: &mut Parser<'a>) -> Result>> { - let span = parser.cur().span; - if parser.cur().is_dashed_ident() { - let custom = Custom::parse(parser)?; - return Ok(Property::Custom(parser.boxup(custom)).spanned(span.until(parser.cur().span))); - } - let checkpoint = parser.checkpoint(); - let property = match PropertyId::from_atom(parser.cur().as_atom_lower().unwrap_or(atom!(""))) { - $( - Some(PropertyId::$prop) => { - $prop::parse(parser).map(|p| Property::$prop(parser.boxup(p))) - } - )+ - _ => { - Err(diagnostics::UnexpectedIdent(parser.cur().as_atom().unwrap(), parser.cur().span))? - } - } - .or_else(|e| { - parser.rewind(checkpoint); - let parsed = - UnknownDeclaration::parse(parser).map(|p| Property::Unknown(parser.boxup(p))); - parser.warnings.push(e); - parser.warnings.push(diagnostics::UnknownDeclaration(span.until(parser.cur().span)).into()); - parsed - })?; - Ok(property.spanned(span.until(parser.cur().span))) - } - } - } + {$( $prop: ident, )+} => { + $( + impl<'a> Parse<'a> for $prop<'a> { + fn parse(parser: &mut Parser<'a>) -> Result>> { + let span = parser.span(); + parser.parse_declaration( + Some($prop::name_as_atom()), + |parser: &mut Parser<'a>, _name: &Token, value: Spanned<<$prop as Declaration>::Value>, important: bool| { + Ok($prop { value: parser.boxup(value), important }.spanned(span.end(parser.pos()))) + }, + ) + } + } + )+ + + impl<'a> Parse<'a> for Property<'a> { + fn parse(parser: &mut Parser<'a>) -> Result>> { + let span = parser.span(); + if parser.cur().is_dashed_ident() { + let custom = Custom::parse(parser)?; + return Ok(Property::Custom(parser.boxup(custom)).spanned(span.end(parser.pos()))); + } + let checkpoint = parser.checkpoint(); + let property = match PropertyId::from_atom(parser.cur().as_atom_lower().unwrap_or(atom!(""))) { + $( + Some(PropertyId::$prop) => { + $prop::parse(parser).map(|p| Property::$prop(parser.boxup(p))) + } + )+ + _ => { + Err(diagnostics::UnexpectedIdent(parser.cur().as_atom().unwrap(), parser.span()))? + } + } + .or_else(|e| { + parser.rewind(checkpoint); + let parsed = + UnknownDeclaration::parse(parser).map(|p| Property::Unknown(parser.boxup(p))); + parser.warnings.push(e); + parser.warnings.push(diagnostics::UnknownDeclaration(span.end(parser.pos())).into()); + parsed + })?; + Ok(property.spanned(span.end(parser.pos()))) + } + } + } } parse_properties! { diff --git a/crates/hdx_parser/src/css/rules/charset.rs b/crates/hdx_parser/src/css/rules/charset.rs index fa8eff19..f8faf404 100644 --- a/crates/hdx_parser/src/css/rules/charset.rs +++ b/crates/hdx_parser/src/css/rules/charset.rs @@ -4,10 +4,10 @@ use crate::{atom, Kind, Parse, Parser, Result, Spanned}; impl<'a> Parse<'a> for CSSCharsetRule { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.expect_at_keyword_of(atom!("charset"))?; let encoding = parser.expect_string()?; parser.expect(Kind::Semicolon)?; - Ok(Self { encoding }.spanned(span.until(parser.cur().span))) + Ok(Self { encoding }.spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/rules/mod.rs b/crates/hdx_parser/src/css/rules/mod.rs index 848617d2..f959b1da 100644 --- a/crates/hdx_parser/src/css/rules/mod.rs +++ b/crates/hdx_parser/src/css/rules/mod.rs @@ -6,8 +6,8 @@ use crate::{Kind, Parse, Parser, Result, Spanned}; pub struct NoPreludeAllowed; impl<'a> Parse<'a> for NoPreludeAllowed { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.expect_without_advance(Kind::LeftCurly)?; - Ok(Self {}.spanned(span.until(parser.cur().span))) + Ok(Self {}.spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/rules/page.rs b/crates/hdx_parser/src/css/rules/page.rs index d58dbf26..268b2825 100644 --- a/crates/hdx_parser/src/css/rules/page.rs +++ b/crates/hdx_parser/src/css/rules/page.rs @@ -11,7 +11,7 @@ use crate::{atom, diagnostics, Atom, Atomizable, Kind, Parse, Parser, Result, Sp impl<'a> Parse<'a> for CSSPageRule<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.parse_at_rule( Some(atom!("page")), |parser: &mut Parser<'a>, @@ -26,7 +26,7 @@ impl<'a> Parse<'a> for CSSPageRule<'a> { declarations: parser.boxup(declarations), rules: parser.boxup(rules), } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) }, ) } @@ -34,16 +34,16 @@ impl<'a> Parse<'a> for CSSPageRule<'a> { impl<'a> Parse<'a> for PageSelectorList<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let ok = Ok(Self { children: parser.parse_comma_list_of::()? } - .spanned(span.until(parser.cur().span))); + .spanned(span.end(parser.pos()))); ok } } impl<'a> Parse<'a> for PageSelector<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut page_type = None; let mut pseudos = parser.new_vec(); if parser.at(Kind::Ident) { @@ -59,17 +59,17 @@ impl<'a> Parse<'a> for PageSelector<'a> { } } } - Ok(Self { page_type, pseudos }.spanned(span.until(parser.cur().span))) + Ok(Self { page_type, pseudos }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for PagePseudoClass { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.expect(Kind::Colon)?; let name = parser.expect_ident()?; match Self::from_atom(name.clone()) { - Some(v) => Ok(v.spanned(span.until(parser.cur().span))), + Some(v) => Ok(v.spanned(span.end(parser.pos()))), _ => Err(diagnostics::UnexpectedPseudo(name, span).into()), } } @@ -77,7 +77,7 @@ impl<'a> Parse<'a> for PagePseudoClass { impl<'a> Parse<'a> for CSSMarginRule<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.parse_at_rule( None, |parser: &mut Parser<'a>, @@ -86,7 +86,7 @@ impl<'a> Parse<'a> for CSSMarginRule<'a> { _rules: Vec<'a, Spanned>>, declarations: Vec<'a, Spanned>>| { Ok(Self { name: PageMarginBox::TopLeft, declarations } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) }, ) } diff --git a/crates/hdx_parser/src/css/selector/mod.rs b/crates/hdx_parser/src/css/selector/mod.rs index ef4ef600..9393d696 100644 --- a/crates/hdx_parser/src/css/selector/mod.rs +++ b/crates/hdx_parser/src/css/selector/mod.rs @@ -10,9 +10,9 @@ fn parse_wq_name(parser: &mut Parser) -> Result<(NSPrefix, Atom)> { let peeked = parser.peek(); let mut nsprefix = NSPrefix::None; if peeked.kind == Kind::Delim && peeked.value.as_char().unwrap() == '|' { - match parser.cur().kind { + match parser.cur() { Kind::Delim => { - let span = parser.cur().span; + let span = parser.span(); let ch = parser.expect_delim()?; if ch == '*' { nsprefix = NSPrefix::Wildcard; @@ -24,9 +24,9 @@ fn parse_wq_name(parser: &mut Parser) -> Result<(NSPrefix, Atom)> { let ident = parser.expect_ident()?; nsprefix = NSPrefix::Named(ident); } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } - let span = parser.cur().span; + let span = parser.span(); let ch = parser.expect_delim()?; if ch != '|' { Err(diagnostics::UnexpectedDelim(ch, span))? @@ -34,7 +34,7 @@ fn parse_wq_name(parser: &mut Parser) -> Result<(NSPrefix, Atom)> { Ok((nsprefix, parser.expect_ident()?)) } else { if parser.at(Kind::Delim) && parser.cur_char().unwrap() == '|' { - parser.next_token(); + parser.advance(); } Ok((nsprefix, parser.expect_ident()?)) } @@ -42,10 +42,10 @@ fn parse_wq_name(parser: &mut Parser) -> Result<(NSPrefix, Atom)> { impl<'a> Parse<'a> for Selector<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut components: Vec<'a, Spanned> = parser.new_vec(); loop { - match parser.cur().kind { + match parser.cur() { Kind::Eof | Kind::Semicolon | Kind::Comma | Kind::LeftCurly => { break; } @@ -91,69 +91,69 @@ impl<'a> Parse<'a> for Selector<'a> { } components.push(component); } - Ok(Self { components: parser.boxup(components) }.spanned(span.until(parser.cur().span))) + Ok(Self { components: parser.boxup(components) }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for Component<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Whitespace => { - parser.next_token(); - Ok(Self::Combinator(Combinator::Descendant).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::Combinator(Combinator::Descendant).spanned(span.end(parser.pos()))) } Kind::Ident => { let name = parser.cur().as_atom_lower().unwrap(); - parser.next_token(); + parser.advance(); Ok(Self::Type(name).spanned(span)) } Kind::Colon => { - parser.next_token(); - match parser.cur().kind { + parser.advance(); + match parser.cur() { Kind::Colon => { - parser.next_token(); + parser.advance(); parser.expect_without_advance(Kind::Ident)?; let ident = parser.cur().as_atom().unwrap(); if let Some(selector) = PseudoElement::from_atom(ident) { - parser.next_token(); - Ok(Self::PseudoElement(selector).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::PseudoElement(selector).spanned(span.end(parser.pos()))) } else { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } Kind::Ident => { parser.expect_without_advance(Kind::Ident)?; let ident = parser.cur().as_atom().unwrap(); if let Some(selector) = PseudoClass::from_atom(ident.clone()) { - parser.next_token(); - Ok(Self::PseudoClass(selector).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::PseudoClass(selector).spanned(span.end(parser.pos()))) } else if let Some(e) = LegacyPseudoElement::from_atom(ident.clone()) { - parser.next_token(); - Ok(Self::LegacyPseudoElement(e).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::LegacyPseudoElement(e).spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident, parser.span()))? } } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, } } Kind::Hash => { let name = parser.cur().as_atom().unwrap(); - parser.next_token(); - Ok(Self::Id(name).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::Id(name).spanned(span.end(parser.pos()))) } Kind::Delim => match parser.cur().value.as_char() { Some('.') => { let next_token = parser.peek_including_trivia(); match next_token.kind { Kind::Ident => { - parser.next_token(); + parser.advance(); let ident = parser.cur().as_atom().unwrap(); - parser.next_token(); - Ok(Self::Class(ident).spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::Class(ident).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, } } Some('*') => { @@ -162,43 +162,43 @@ impl<'a> Parse<'a> for Component<'a> { Kind::Delim if next_token.value.as_char().unwrap() == '|' => { let (prefix, atom) = parse_wq_name(parser)?; Ok(Self::NSPrefixedType(parser.boxup((prefix, atom))) - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } _ => { - parser.next_token(); - Ok(Self::Wildcard.spanned(span.until(parser.cur().span))) + parser.advance(); + Ok(Self::Wildcard.spanned(span.end(parser.pos()))) } } } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, }, Kind::LeftSquare => { let attr = Attribute::parse(parser)?; - Ok(Component::Attribute(parser.boxup(attr)).spanned(span.until(parser.cur().span))) + Ok(Component::Attribute(parser.boxup(attr)).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, } } } impl<'a> Parse<'a> for Attribute { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.expect(Kind::LeftSquare)?; let (ns_prefix, name) = parse_wq_name(parser)?; let mut matcher = AttributeMatch::Any; let mut modifier = AttributeModifier::None; let mut value = atom!(""); - match parser.cur().kind { + match parser.cur() { Kind::RightSquare => { - parser.next_token(); + parser.advance(); return Ok(Self { ns_prefix, name, value, modifier, matcher } - .spanned(span.until(parser.cur().span))); + .spanned(span.end(parser.pos()))); } Kind::Delim => { - let delim_span = parser.cur().span; + let delim_span = parser.span(); let ch = parser.cur().value.as_char().unwrap(); - parser.next_token(); + parser.advance(); if matcher != AttributeMatch::Any { Err(diagnostics::UnexpectedDelim(ch, delim_span))?; } @@ -218,23 +218,23 @@ impl<'a> Parse<'a> for Attribute { } } } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } - match parser.cur().kind { + match parser.cur() { Kind::Ident | Kind::String => { value = parser.cur().as_atom().unwrap(); parser.advance(); } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } - match parser.cur().kind { + match parser.cur() { Kind::RightSquare => { - parser.next_token(); + parser.advance(); Ok(Self { ns_prefix, name, value, modifier, matcher } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } Kind::Ident => { - let ident_span = parser.cur().span; + let ident_span = parser.span(); modifier = match parser.expect_ident()? { atom!("i") => AttributeModifier::Insensitive, atom!("s") => AttributeModifier::Sensitive, @@ -242,9 +242,9 @@ impl<'a> Parse<'a> for Attribute { }; parser.expect(Kind::RightSquare)?; Ok(Self { ns_prefix, name, value, modifier, matcher } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/stylerule.rs b/crates/hdx_parser/src/css/stylerule.rs index 9c885859..05c52374 100644 --- a/crates/hdx_parser/src/css/stylerule.rs +++ b/crates/hdx_parser/src/css/stylerule.rs @@ -7,7 +7,7 @@ use crate::{diagnostics, Parse, Parser, Result, Spanned, Vec}; impl<'a> Parse<'a> for CSSStyleRule<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.parse_qualified_rule( None, false, @@ -16,14 +16,14 @@ impl<'a> Parse<'a> for CSSStyleRule<'a> { rules: Vec<'a, Spanned>>, declarations: Vec<'a, Spanned>>| { if selectors.is_none() { - Err(diagnostics::NoSelector(span, span.until(parser.cur().span)))? + Err(diagnostics::NoSelector(span, span.end(parser.pos())))? } Ok(Self { selectors: parser.boxup(selectors.unwrap()), declarations: parser.boxup(declarations), rules: parser.boxup(rules), } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) }, ) } diff --git a/crates/hdx_parser/src/css/stylesheet.rs b/crates/hdx_parser/src/css/stylesheet.rs deleted file mode 100644 index 74f561e3..00000000 --- a/crates/hdx_parser/src/css/stylesheet.rs +++ /dev/null @@ -1,121 +0,0 @@ -use hdx_ast::css::{ - rules::{CSSCharsetRule, CSSPageRule}, - selector::Selector, - stylesheet::{AtRuleId, CSSRule, CSSStyleRule, CSSStyleSheet, SelectorSet}, - unknown::{UnknownAtRule, UnknownRule}, -}; -use hdx_lexer::Kind; - -use crate::{diagnostics, Atomizable, Parse, Parser, Result, Span, Spanned}; - -// https://drafts.csswg.org/css-syntax-3/#consume-stylesheet-contents -impl<'a> Parse<'a> for CSSStyleSheet<'a> { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let mut rules = parser.new_vec(); - loop { - match parser.cur().kind { - Kind::Eof => break, - Kind::Comment | Kind::Whitespace | Kind::Cdc | Kind::Cdo => parser.advance(), - Kind::AtKeyword => { - rules.push(match AtRuleId::from_atom(parser.cur_atom_lower().unwrap()) { - Some(AtRuleId::Charset) => { - let rule = CSSCharsetRule::parse(parser)?; - CSSRule::Charset(parser.boxup(rule)) - } - Some(AtRuleId::Page) => { - let rule = CSSPageRule::parse(parser)?; - CSSRule::Page(parser.boxup(rule)) - } - None => { - let rule = UnknownAtRule::parse(parser)?; - parser.warnings.push(diagnostics::UnknownRule(rule.span).into()); - CSSRule::UnknownAt(parser.boxup(rule)) - } - }); - } - _ => { - // The spec talks of QualifiedRules but in the context of a Stylesheet - // the only non-At Rule is a StyleRule, so parse that: - let checkpoint = parser.checkpoint(); - match CSSStyleRule::parse(parser) { - Ok(rule) => rules.push(CSSRule::Style(parser.boxup(rule))), - Err(err) => { - parser.rewind(checkpoint); - parser.warnings.push(err); - let rule = UnknownRule::parse(parser)?; - rules.push(CSSRule::Unknown(parser.boxup(rule))); - } - } - } - } - } - Ok(Self { rules }.spanned(span.until(parser.cur().span))) - } -} - -impl<'a> Parse<'a> for SelectorSet<'a> { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(Self { children: parser.parse_comma_list_of::()? } - .spanned(span.until(parser.cur().span))) - } -} - -#[cfg(test)] -mod test { - use hdx_ast::css::rules::CSSCharsetRule; - use oxc_allocator::Allocator; - - use super::{CSSRule, CSSStyleSheet}; - use crate::{atom, Parser, ParserOptions, Span, Spanned}; - - #[test] - fn smoke_test() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "", ParserOptions::default()); - let parser_return = parser.parse_with::(); - let ast = parser_return.output.unwrap(); - assert_eq!(ast.node.rules.len(), 0); - } - - #[test] - fn parses_charset() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "@charset \"utf-8\";", ParserOptions::default()); - let mut rules = parser.new_vec(); - rules.push(CSSRule::Charset(parser.boxup(Spanned { - span: Span::new(0, 17), - node: CSSCharsetRule { encoding: atom!("utf-8") }, - }))); - let expected = Spanned { span: Span::new(0, 17), node: CSSStyleSheet { rules } }; - let parser_return = parser.parse_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - if !parser_return.warnings.is_empty() { - panic!("{:?}", parser_return.warnings[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!(ast, expected); - } - - #[test] - fn parses_two_rules() { - let allocator = Allocator::default(); - let parser = Parser::new( - &allocator, - "a{overflow:hidden !important;position:relative}.b{}", - ParserOptions::default(), - ); - let parser_return = parser.parse_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - if !parser_return.warnings.is_empty() { - panic!("{:?}", parser_return.warnings[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!(ast.node.rules.len(), 2); - } -} diff --git a/crates/hdx_parser/src/css/unknown.rs b/crates/hdx_parser/src/css/unknown.rs index 6ccfc97e..b6678ab1 100644 --- a/crates/hdx_parser/src/css/unknown.rs +++ b/crates/hdx_parser/src/css/unknown.rs @@ -9,7 +9,7 @@ use crate::{atom, Atom, Parse, Parser, Spanned}; impl<'a> Parse<'a> for UnknownAtRule<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.parse_at_rule( None, |parser: &mut Parser<'a>, name: Atom, prelude, rules, properties| { @@ -19,7 +19,7 @@ impl<'a> Parse<'a> for UnknownAtRule<'a> { rules: parser.boxup(rules), properties: parser.boxup(properties), } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) }, ) } @@ -27,7 +27,7 @@ impl<'a> Parse<'a> for UnknownAtRule<'a> { impl<'a> Parse<'a> for UnknownRule<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); parser.parse_qualified_rule( Some(Kind::Semicolon), true, @@ -37,7 +37,7 @@ impl<'a> Parse<'a> for UnknownRule<'a> { rules: parser.boxup(rules), properties: parser.boxup(properties), } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) }, ) } @@ -45,16 +45,16 @@ impl<'a> Parse<'a> for UnknownRule<'a> { impl<'a> Parse<'a> for UnknownPrelude<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let value = parser.parse_component_values(Kind::Semicolon, false)?; - Ok(Self { value: parser.boxup(value) }.spanned(span.until(parser.cur().span))) + Ok(Self { value: parser.boxup(value) }.spanned(span.end(parser.pos()))) } } // https://drafts.csswg.org/css-syntax-3/#consume-the-remnants-of-a-bad-declaration impl<'a> Parse<'a> for UnknownDeclaration<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut name = atom!(""); let mut value_like = Spanned::dummy(ValueLike::Unknown); let value; @@ -77,11 +77,11 @@ impl<'a> Parse<'a> for UnknownDeclaration<'a> { } else { value = parser.parse_component_values(Kind::Semicolon, true)?; } - if parser.cur().kind == Kind::Semicolon { + if parser.cur() == Kind::Semicolon { parser.advance(); } Ok(Self { name, value_like, value: parser.boxup(value), important: false } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/values/angle.rs b/crates/hdx_parser/src/css/values/angle.rs deleted file mode 100644 index 28e5b3bd..00000000 --- a/crates/hdx_parser/src/css/values/angle.rs +++ /dev/null @@ -1,35 +0,0 @@ -use hdx_ast::css::values::Angle; - -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; - -impl<'a> Parse<'a> for Angle { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Number => { - let value = parser.cur().value.as_f32().unwrap(); - if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("deg"), - parser.cur().span, - ))? - } - parser.advance(); - Ok(Self::Zero.spanned(span.until(parser.cur().span))) - } - Kind::Dimension => { - let value = parser.cur().value.as_f32().unwrap(); - let unit = parser.cur_atom().unwrap(); - parser.advance(); - match unit { - atom!("deg") => Ok(Self::Deg(value).spanned(span.until(parser.cur().span))), - atom!("grad") => Ok(Self::Grad(value).spanned(span.until(parser.cur().span))), - atom!("rad") => Ok(Self::Rad(value).spanned(span.until(parser.cur().span))), - atom!("turn") => Ok(Self::Turn(value).spanned(span.until(parser.cur().span))), - _ => Err(diagnostics::UnexpectedIdent(unit, parser.cur().span))?, - } - } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, - } - } -} diff --git a/crates/hdx_parser/src/css/values/backgrounds.rs b/crates/hdx_parser/src/css/values/backgrounds.rs index cc3eb55f..9d0c99ca 100644 --- a/crates/hdx_parser/src/css/values/backgrounds.rs +++ b/crates/hdx_parser/src/css/values/backgrounds.rs @@ -6,12 +6,12 @@ use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; impl<'a> Parse<'a> for BorderShorthand<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut line_width = Shorthand::Implicit; let mut line_style = Shorthand::Implicit; let mut color = Shorthand::Implicit; loop { - match parser.cur().kind { + match parser.cur() { Kind::Ident => { let ident = parser.cur_atom().unwrap(); if line_style.is_implicit() @@ -35,7 +35,7 @@ impl<'a> Parse<'a> for BorderShorthand<'a> { let node = MathExpr::::parse(parser)?; color = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::UnexpectedIdent(ident.clone(), parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident.clone(), parser.span()))? } } Kind::Semicolon | Kind::Comma | Kind::Eof => { @@ -46,7 +46,7 @@ impl<'a> Parse<'a> for BorderShorthand<'a> { let node = MathExpr::::parse(parser)?; line_width = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::Unexpected(Kind::Dimension, parser.cur().span))? + Err(diagnostics::Unexpected(Kind::Dimension, parser.span()))? } } k => { @@ -72,23 +72,23 @@ impl<'a> Parse<'a> for BorderShorthand<'a> { Err(_) => parser.rewind(checkpoint), } } - Err(diagnostics::Unexpected(k, parser.cur().span))? + Err(diagnostics::Unexpected(k, parser.span()))? } } if color.is_explicit() && line_style.is_explicit() && line_width.is_explicit() { break; } } - Ok(Self { color, line_style, line_width }.spanned(span.until(parser.cur().span))) + Ok(Self { color, line_style, line_width }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for LineWidth { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Number | Kind::Dimension => { - Ok(Self::Length(Length::parse(parser)?).spanned(span.until(parser.cur().span))) + Ok(Self::Length(Length::parse(parser)?).spanned(span.end(parser.pos()))) } Kind::Ident => { let ident = parser.cur_atom().unwrap(); diff --git a/crates/hdx_parser/src/css/values/box.rs b/crates/hdx_parser/src/css/values/box.rs index febdc3ad..44c66da1 100644 --- a/crates/hdx_parser/src/css/values/box.rs +++ b/crates/hdx_parser/src/css/values/box.rs @@ -4,7 +4,7 @@ use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; impl<'a> Parse<'a> for MarginTrimValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let ident = parser.expect_ident()?; if ident == atom!("none") { Ok(Self { @@ -13,13 +13,13 @@ impl<'a> Parse<'a> for MarginTrimValue { inline_start: false, inline_end: false, } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } else if ident == atom!("block") { Ok(Self { block_start: true, block_end: true, inline_start: false, inline_end: false } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } else if ident == atom!("inline") { Ok(Self { block_start: false, block_end: false, inline_start: true, inline_end: true } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } else { let mut value = Self { block_start: ident == atom!("block-start"), @@ -31,7 +31,7 @@ impl<'a> Parse<'a> for MarginTrimValue { if !parser.at(Kind::Ident) { break; } - let span = parser.cur().span; + let span = parser.span(); let ident = parser.expect_ident()?; match ident { atom!("block-start") => { @@ -61,7 +61,7 @@ impl<'a> Parse<'a> for MarginTrimValue { _ => break, } } - Ok(value.spanned(span.until(parser.cur().span))) + Ok(value.spanned(span.end(parser.pos()))) } } } diff --git a/crates/hdx_parser/src/css/values/color.rs b/crates/hdx_parser/src/css/values/color.rs index 0dc8427f..d074aa89 100644 --- a/crates/hdx_parser/src/css/values/color.rs +++ b/crates/hdx_parser/src/css/values/color.rs @@ -7,13 +7,13 @@ use crate::{atom, diagnostics, Atomizable, Kind, Parse, Parser, Result, Spanned} impl<'a> Parse<'a> for ColorValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { // https://drafts.csswg.org/css-color/#hex-notation Kind::Hash => { let hash = parser.expect_hash()?; if let Some(hex) = ColorValue::from_hex(hash.as_ref()) { - Ok(hex.spanned(span.until(parser.cur().span))) + Ok(hex.spanned(span.end(parser.pos()))) } else { Err(diagnostics::BadHexColor(hash.clone(), span))? } @@ -22,10 +22,10 @@ impl<'a> Parse<'a> for ColorValue<'a> { let name = parser.expect_ident()?; match name { atom!("transparent") => { - Ok(ColorValue::Transparent.spanned(span.until(parser.cur().span))) + Ok(ColorValue::Transparent.spanned(span.end(parser.pos()))) } _ => match NamedColor::from_atom(name.clone()) { - Some(n) => Ok(ColorValue::Named(n).spanned(span.until(parser.cur().span))), + Some(n) => Ok(ColorValue::Named(n).spanned(span.end(parser.pos()))), None => Err(diagnostics::UnknownColor(name, span))?, }, } @@ -35,8 +35,7 @@ impl<'a> Parse<'a> for ColorValue<'a> { match name { atom!("rgb") | atom!("rgba") => { let node = RGB::parse(parser)?; - Ok(ColorValue::RGB(parser.boxup(node)) - .spanned(span.until(parser.cur().span))) + Ok(ColorValue::RGB(parser.boxup(node)).spanned(span.end(parser.pos()))) } _ => Err(diagnostics::Unimplemented(span))?, } @@ -48,7 +47,7 @@ impl<'a> Parse<'a> for ColorValue<'a> { impl<'a> Parse<'a> for RGB<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let ident = parser.expect_function()?; let mut legacy = false; let r = MathExpr::::parse(parser)?; @@ -72,23 +71,24 @@ impl<'a> Parse<'a> for RGB<'a> { alpha = MathExpr::::parse(parser)?; } parser.expect(Kind::RightParen)?; - Ok(Self { r, g, b, alpha }.spanned(span.until(parser.cur().span))) + Ok(Self { r, g, b, alpha }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for NumberPercentageOrNone { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Number => { - Ok(Self::Number(parser.expect_number()?).spanned(span.until(parser.cur().span))) + Ok(Self::Number(parser.expect_number()?).spanned(span.end(parser.pos()))) + } + Kind::Percentage => { + Ok(Self::Percentage(parser.expect_percentage()?).spanned(span.end(parser.pos()))) } - Kind::Percentage => Ok(Self::Percentage(parser.expect_percentage()?) - .spanned(span.until(parser.cur().span))), Kind::Ident => match parser.expect_ident()? { atom!("none") => { parser.advance(); - Ok(Self::None.spanned(span.until(parser.cur().span))) + Ok(Self::None.spanned(span.end(parser.pos()))) } _ => Err(diagnostics::Unimplemented(span))?, }, diff --git a/crates/hdx_parser/src/css/values/content.rs b/crates/hdx_parser/src/css/values/content.rs index 36a9fc25..48f687a9 100644 --- a/crates/hdx_parser/src/css/values/content.rs +++ b/crates/hdx_parser/src/css/values/content.rs @@ -4,16 +4,16 @@ use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; impl<'a> Parse<'a> for ContentsValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); if parser.at(Kind::Ident) { match parser.cur_atom_lower().unwrap() { atom!("normal") => { parser.advance(); - return Ok(Self::Normal.spanned(span.until(parser.cur().span))); + return Ok(Self::Normal.spanned(span.end(parser.pos()))); } atom!("none") => { parser.advance(); - return Ok(Self::None.spanned(span.until(parser.cur().span))); + return Ok(Self::None.spanned(span.end(parser.pos()))); } _ => {} } @@ -26,17 +26,17 @@ impl<'a> Parse<'a> for ContentsValue<'a> { // return Ok(Self::Replacement(ContentReplacement { image, alt: list.alt })); // } // } - Ok(Self::List(list).spanned(span.until(parser.cur().span))) + Ok(Self::List(list).spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for ContentList<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut values = parser.new_vec(); let alt = parser.new_vec(); loop { - match parser.cur().kind { + match parser.cur() { Kind::String => { values.push(ContentElement::String(parser.cur_atom().unwrap())); parser.advance(); @@ -44,29 +44,29 @@ impl<'a> Parse<'a> for ContentList<'a> { Kind::Semicolon | Kind::Eof | Kind::RightCurly => { break; } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, } } - Ok(Self { values, alt }.spanned(span.until(parser.cur().span))) + Ok(Self { values, alt }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for QuotesValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let ident = parser.expect_ident()?; match ident { atom!("none") => { parser.advance(); - return Ok(Self::None.spanned(span.until(parser.cur().span))); + return Ok(Self::None.spanned(span.end(parser.pos()))); } atom!("auto") => { parser.advance(); - return Ok(Self::Auto.spanned(span.until(parser.cur().span))); + return Ok(Self::Auto.spanned(span.end(parser.pos()))); } - _ => Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))?, + _ => Err(diagnostics::UnexpectedIdent(ident, parser.span()))?, } } Kind::String => { @@ -79,9 +79,9 @@ impl<'a> Parse<'a> for QuotesValue<'a> { break; } } - Ok(Self::Custom(custom).spanned(span.until(parser.cur().span))) + Ok(Self::Custom(custom).spanned(span.end(parser.pos()))) } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/counter_styles.rs b/crates/hdx_parser/src/css/values/counter_styles.rs index ad18c6c0..3bb20042 100644 --- a/crates/hdx_parser/src/css/values/counter_styles.rs +++ b/crates/hdx_parser/src/css/values/counter_styles.rs @@ -4,8 +4,8 @@ use crate::{atom, diagnostics, Atomizable, Kind, Parse, Parser, Result, Spanned} impl<'a> Parse<'a> for CounterStyle<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let ident = parser.expect_ident()?; if let Some(node) = PredefinedCounterStyle::from_atom(ident.clone()) { @@ -18,18 +18,18 @@ impl<'a> Parse<'a> for CounterStyle<'a> { let ident = parser.expect_ident()?; if ident == atom!("symbols") { let node = Symbols::parse(parser)?; - Ok(Self::Symbols(node).spanned(span.until(parser.cur().span))) + Ok(Self::Symbols(node).spanned(span.end(parser.pos()))) } else { - Err(diagnostics::ExpectedFunction(atom!("symbols"), ident, parser.cur().span))? + Err(diagnostics::ExpectedFunction(atom!("symbols"), ident, parser.span()))? } } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } } } impl<'a> Parse<'a> for Symbols<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } diff --git a/crates/hdx_parser/src/css/values/display.rs b/crates/hdx_parser/src/css/values/display.rs deleted file mode 100644 index a2f902c6..00000000 --- a/crates/hdx_parser/src/css/values/display.rs +++ /dev/null @@ -1,268 +0,0 @@ -use hdx_ast::css::values::display::{DisplayInside, DisplayMarker, DisplayOutside, DisplayValue}; - -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; - -impl<'a> Parse<'a> for DisplayValue { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let first = parser.expect_ident()?; - let mut second_option = None; - let mut third_option = None; - if parser.at(Kind::Ident) { - second_option = Some(parser.expect_ident()?); - if parser.at(Kind::Ident) { - third_option = Some(parser.expect_ident()?); - } - } - let mut inside = DisplayInside::default(); - let mut outside = DisplayOutside::default(); - match (second_option, third_option) { - // && [ flow | flow-root ] && list-item - (Some(second), Some(third)) => { - if let Some(display) = DisplayOutside::from_atom(first.clone()) { - outside = display; - } else { - Err(diagnostics::UnexpectedIdent(first, parser.cur().span))?; - } - // second must be flow or flow-root - if second != atom!("flow") && second != atom!("flow-root") { - Err(diagnostics::UnexpectedIdent(second.clone(), parser.cur().span))?; - } - inside = DisplayInside::from_atom(second).unwrap(); - if let Some(marker) = DisplayMarker::from_atom(third.clone()) { - Ok(DisplayValue::PairAndMarker(outside, inside, marker) - .spanned(span.until(parser.cur().span))) - } else { - Err(diagnostics::UnexpectedIdent(third, parser.cur().span).into()) - } - } - // [ || ] - (Some(second), None) => { - if let Some(display) = DisplayOutside::from_atom(first.clone()) { - outside = display; - if let Some(display) = DisplayMarker::from_atom(second.clone()) { - Ok(DisplayValue::PairAndMarker(outside, inside, display) - .spanned(span.until(parser.cur().span))) - } else if let Some(display) = DisplayInside::from_atom(second.clone()) { - Ok(DisplayValue::Pair(outside, display) - .spanned(span.until(parser.cur().span))) - } else { - Err(diagnostics::UnexpectedIdent(second, parser.cur().span).into()) - } - } else if let Some(display) = DisplayInside::from_atom(first.clone()) { - inside = display; - if let Some(display) = DisplayOutside::from_atom(second.clone()) { - Ok(DisplayValue::Pair(display, inside) - .spanned(span.until(parser.cur().span))) - } else { - Err(diagnostics::UnexpectedIdent(second, parser.cur().span).into()) - } - } else { - Err(diagnostics::UnexpectedIdent(first, parser.cur().span).into()) - } - } - // | | | - _ => { - if let Some(display) = DisplayValue::from_atom(first.clone()) { - Ok(display.spanned(span.until(parser.cur().span))) - } else { - Err(diagnostics::UnexpectedIdent(first, parser.cur().span).into()) - } - } - } - } -} - -#[cfg(test)] -mod test { - use hdx_ast::css::values::{DisplayInside, DisplayMarker, DisplayOutside, DisplayValue}; - use oxc_allocator::Allocator; - - use crate::{Parser, ParserOptions, Span, Spanned}; - - #[test] - fn parses_block() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "block", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 5), - node: DisplayValue::Pair(DisplayOutside::Block, DisplayInside::Implicit) - } - ); - } - - #[test] - fn parses_flow_root() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "flow-root", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 9), - node: DisplayValue::Pair(DisplayOutside::Block, DisplayInside::FlowRoot) - } - ); - } - - #[test] - fn parses_inline() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "inline", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 6), - node: DisplayValue::Pair(DisplayOutside::Inline, DisplayInside::Implicit) - } - ); - } - - #[test] - fn parses_inline_block() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "inline-block", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!(ast, Spanned { span: Span::new(0, 12), node: DisplayValue::InlineBlock }); - } - - #[test] - fn parses_run_in() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "run-in", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 6), - node: DisplayValue::Pair(DisplayOutside::RunIn, DisplayInside::Implicit) - } - ); - } - - #[test] - fn parses_list_item() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "list-item", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 9), - node: DisplayValue::PairAndMarker( - DisplayOutside::Implicit, - DisplayInside::Implicit, - DisplayMarker::ListItem - ) - } - ); - } - - #[test] - fn parses_inline_list_item() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "inline list-item", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 16), - node: DisplayValue::PairAndMarker( - DisplayOutside::Inline, - DisplayInside::Flow, - DisplayMarker::ListItem - ) - } - ); - } - - #[test] - fn parses_inline_flow_root_list_item() { - let allocator = Allocator::default(); - let parser = - Parser::new(&allocator, "inline flow-root list-item", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 26), - node: DisplayValue::PairAndMarker( - DisplayOutside::Inline, - DisplayInside::FlowRoot, - DisplayMarker::ListItem - ) - } - ); - } - - #[test] - fn parses_ruby_run_in() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "ruby run-in", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - if !parser_return.errors.is_empty() { - panic!("{:?}", parser_return.errors[0]); - } - let ast = parser_return.output.unwrap(); - assert_eq!( - ast, - Spanned { - span: Span::new(0, 11), - node: DisplayValue::Pair(DisplayOutside::RunIn, DisplayInside::Ruby) - } - ); - } - - #[test] - fn errors_block_inline() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "block inline", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - assert_eq!(parser_return.errors.len(), 1); - } - - #[test] - fn errors_flow_root_inline_list_item() { - let allocator = Allocator::default(); - let parser = - Parser::new(&allocator, "flow-root inline list-item", ParserOptions::default()); - let parser_return = parser.parse_entirely_with::(); - assert_eq!(parser_return.errors.len(), 1); - } -} diff --git a/crates/hdx_parser/src/css/values/expr.rs b/crates/hdx_parser/src/css/values/expr.rs index 994dcaa0..0102c2ce 100644 --- a/crates/hdx_parser/src/css/values/expr.rs +++ b/crates/hdx_parser/src/css/values/expr.rs @@ -10,32 +10,32 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { + let span = parser.span(); + Ok(match parser.cur() { Kind::Ident => { if let Some(val) = GlobalValue::from_atom(parser.cur().as_atom().unwrap()) { parser.advance(); - Self::GlobalValue(val).spanned(span.until(parser.cur().span)) + Self::GlobalValue(val).spanned(span.end(parser.pos())) } else { - Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)) + Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())) } } Kind::Function => match parser.cur().as_atom().unwrap() { atom!("var") | atom!("env") => { let node = Reference::parse(parser)?; - Self::Reference(node).spanned(span.until(parser.cur().span)) + Self::Reference(node).spanned(span.end(parser.pos())) } atom!("calc") /*TODO! ...*/ => { - Err(diagnostics::DisallowedMathFunction(parser.cur().as_atom().unwrap(), parser.cur().span))? + Err(diagnostics::DisallowedMathFunction(parser.cur().as_atom().unwrap(), parser.span()))? }, _ => { let node = T::parse(parser)?; - Self::Literal(node).spanned(span.until(parser.cur().span)) + Self::Literal(node).spanned(span.end(parser.pos())) } }, _ => { let node = T::parse(parser)?; - Self::Literal(node).spanned(span.until(parser.cur().span)) + Self::Literal(node).spanned(span.end(parser.pos())) } }) } @@ -46,31 +46,31 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { + let span = parser.span(); + Ok(match parser.cur() { Kind::Ident => { if let Some(val) = GlobalValue::from_atom(parser.cur().as_atom().unwrap()) { parser.advance(); - Self::GlobalValue(val).spanned(span.until(parser.cur().span)) + Self::GlobalValue(val).spanned(span.end(parser.pos())) } else { let node = T::parse(parser)?; - Self::Literal(node).spanned(span.until(parser.cur().span)) + Self::Literal(node).spanned(span.end(parser.pos())) } } Kind::Function => { match parser.cur().value.as_atom().unwrap() { atom!("var") | atom!("env") => { let node = Reference::parse(parser)?; - Self::Reference(node).spanned(span.until(parser.cur().span)) + Self::Reference(node).spanned(span.end(parser.pos())) }, atom!("calc") /*TODO! ...*/ => { let node = MathFunc::parse(parser)?; - Self::Math(node).spanned(span.until(parser.cur().span)) + Self::Math(node).spanned(span.end(parser.pos())) }, - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)) + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())) } } - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), }) } } @@ -80,19 +80,19 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { + let span = parser.span(); + Ok(match parser.cur() { Kind::Ident => { if let Some(val) = GlobalValue::from_atom(parser.cur().as_atom().unwrap()) { parser.advance(); - Self::GlobalValue(val).spanned(span.until(parser.cur().span)) + Self::GlobalValue(val).spanned(span.end(parser.pos())) } else { Self::Values(parser.parse_comma_list_of::>()?) - .spanned(span.until(parser.cur().span)) + .spanned(span.end(parser.pos())) } } _ => Self::Values(parser.parse_comma_list_of::>()?) - .spanned(span.until(parser.cur().span)), + .spanned(span.end(parser.pos())), }) } } @@ -102,19 +102,19 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { + let span = parser.span(); + Ok(match parser.cur() { Kind::Ident => { if let Some(val) = GlobalValue::from_atom(parser.cur().as_atom().unwrap()) { parser.advance(); - Self::GlobalValue(val).spanned(span.until(parser.cur().span)) + Self::GlobalValue(val).spanned(span.end(parser.pos())) } else { Self::Values(parser.parse_comma_list_of::>()?) - .spanned(span.until(parser.cur().span)) + .spanned(span.end(parser.pos())) } } _ => Self::Values(parser.parse_comma_list_of::>()?) - .spanned(span.until(parser.cur().span)), + .spanned(span.end(parser.pos())), }) } } @@ -124,17 +124,17 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { - Kind::Ident => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + let span = parser.span(); + Ok(match parser.cur() { + Kind::Ident => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), Kind::Function => match parser.cur().as_atom().unwrap() { - atom!("var") | atom!("env") => Self::Reference(Reference::parse(parser)?).spanned(span.until(parser.cur().span)), + atom!("var") | atom!("env") => Self::Reference(Reference::parse(parser)?).spanned(span.end(parser.pos())), atom!("calc") /*TODO! ...*/ => { - Err(diagnostics::DisallowedMathFunction(parser.cur().as_atom().unwrap(), parser.cur().span))? + Err(diagnostics::DisallowedMathFunction(parser.cur().as_atom().unwrap(), parser.span()))? }, - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), }, - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), }) } } @@ -144,21 +144,21 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - Ok(match parser.cur().kind { - Kind::Ident => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + let span = parser.span(); + Ok(match parser.cur() { + Kind::Ident => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), Kind::Function => { match parser.cur().as_atom().unwrap() { atom!("var") | atom!("env") => { - Self::Reference(Reference::parse(parser)?).spanned(span.until(parser.cur().span)) + Self::Reference(Reference::parse(parser)?).spanned(span.end(parser.pos())) }, atom!("calc") /*TODO! ...*/ => { - Self::Math(MathFunc::parse(parser)?).spanned(span.until(parser.cur().span)) + Self::Math(MathFunc::parse(parser)?).spanned(span.end(parser.pos())) }, - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)) + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())) } } - _ => Self::Literal(T::parse(parser)?).spanned(span.until(parser.cur().span)), + _ => Self::Literal(T::parse(parser)?).spanned(span.end(parser.pos())), }) } } @@ -175,7 +175,7 @@ where T: Parse<'a>, { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let ident = parser.expect_function()?; Ok(match ident { atom!("var") => { @@ -186,7 +186,7 @@ where inner = Some(T::parse(parser)?) } parser.expect(Kind::RightParen)?; - Self::Var(name, parser.boxup(inner)).spanned(span.until(parser.cur().span)) + Self::Var(name, parser.boxup(inner)).spanned(span.end(parser.pos())) } atom!("env") => { let name = parser.expect_ident()?; @@ -196,9 +196,9 @@ where inner = Some(T::parse(parser)?) } parser.expect(Kind::RightParen)?; - Self::Env(name, parser.boxup(inner)).spanned(span.until(parser.cur().span)) + Self::Env(name, parser.boxup(inner)).spanned(span.end(parser.pos())) } - _ => Err(diagnostics::UnexpectedFunction(ident, parser.cur().span))?, + _ => Err(diagnostics::UnexpectedFunction(ident, parser.span()))?, }) } } diff --git a/crates/hdx_parser/src/css/values/fonts.rs b/crates/hdx_parser/src/css/values/fonts.rs index f591fc23..fa88efe9 100644 --- a/crates/hdx_parser/src/css/values/fonts.rs +++ b/crates/hdx_parser/src/css/values/fonts.rs @@ -7,57 +7,57 @@ use crate::{atom, diagnostics, Atom, Atomizable, Kind, Parse, Parser, Result, Sp impl<'a> Parse<'a> for FontWeightValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let ident = parser.expect_ident()?; if ident == atom!("normal") { - Ok(Self::Normal.spanned(span.until(parser.cur().span))) + Ok(Self::Normal.spanned(span.end(parser.pos()))) } else if ident == atom!("bold") { - Ok(Self::Bold.spanned(span.until(parser.cur().span))) + Ok(Self::Bold.spanned(span.end(parser.pos()))) } else if ident == atom!("bolder") { - Ok(Self::Bolder.spanned(span.until(parser.cur().span))) + Ok(Self::Bolder.spanned(span.end(parser.pos()))) } else if ident == atom!("lighter") { - Ok(Self::Lighter.spanned(span.until(parser.cur().span))) + Ok(Self::Lighter.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident, parser.span()))? } } Kind::Number => { let num = parser.cur().value.as_f32().unwrap(); parser.advance(); if (1.0..=1000.0).contains(&num) { - Ok(Self::Number(num as u16).spanned(span.until(parser.cur().span))) + Ok(Self::Number(num as u16).spanned(span.end(parser.pos()))) } else { - Err(diagnostics::NumberOutOfBounds(1.0, 1000.0, parser.cur().span))? + Err(diagnostics::NumberOutOfBounds(1.0, 1000.0, parser.span()))? } } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } } } impl<'a> Parse<'a> for FontSizeValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let ident = parser.expect_ident()?; if ident == atom!("math") { - Ok(Self::Math.spanned(span.until(parser.cur().span))) + Ok(Self::Math.spanned(span.end(parser.pos()))) } else if let Some(val) = AbsoluteSize::from_atom(ident.clone()) { parser.advance(); - Ok(Self::Absolute(val).spanned(span.until(parser.cur().span))) + Ok(Self::Absolute(val).spanned(span.end(parser.pos()))) } else if let Some(val) = RelativeSize::from_atom(ident.clone()) { parser.advance(); - Ok(Self::Relative(val).spanned(span.until(parser.cur().span))) + Ok(Self::Relative(val).spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident, parser.span()))? } } _ => { let node = PositiveLengthPercentage::parse(parser)?; - Ok(Self::LengthPercentage(node).spanned(span.until(parser.cur().span))) + Ok(Self::LengthPercentage(node).spanned(span.end(parser.pos()))) } } } @@ -65,34 +65,24 @@ impl<'a> Parse<'a> for FontSizeValue { impl<'a> Parse<'a> for FontFamilyValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let mut ident = parser.expect_ident_cased()?; match ident.to_ascii_lowercase() { - atom!("serif") => Ok(Self::Serif.spanned(span.until(parser.cur().span))), - atom!("sans-serif") => { - Ok(Self::SansSerif.spanned(span.until(parser.cur().span))) - } - atom!("cursive") => Ok(Self::Cursive.spanned(span.until(parser.cur().span))), - atom!("fantasy") => Ok(Self::Fantasy.spanned(span.until(parser.cur().span))), - atom!("monospace") => { - Ok(Self::Monospace.spanned(span.until(parser.cur().span))) - } - atom!("system-ui") => Ok(Self::SystemUi.spanned(span.until(parser.cur().span))), - atom!("emoji") => Ok(Self::Emoji.spanned(span.until(parser.cur().span))), - atom!("math") => Ok(Self::Math.spanned(span.until(parser.cur().span))), - atom!("fangsong") => Ok(Self::Fangsong.spanned(span.until(parser.cur().span))), - atom!("ui-serif") => Ok(Self::UiSerif.spanned(span.until(parser.cur().span))), - atom!("ui-sans-serif") => { - Ok(Self::UiSansSerif.spanned(span.until(parser.cur().span))) - } - atom!("ui-monospace") => { - Ok(Self::UiMonospace.spanned(span.until(parser.cur().span))) - } - atom!("ui-rounded") => { - Ok(Self::UiRounded.spanned(span.until(parser.cur().span))) - } + atom!("serif") => Ok(Self::Serif.spanned(span.end(parser.pos()))), + atom!("sans-serif") => Ok(Self::SansSerif.spanned(span.end(parser.pos()))), + atom!("cursive") => Ok(Self::Cursive.spanned(span.end(parser.pos()))), + atom!("fantasy") => Ok(Self::Fantasy.spanned(span.end(parser.pos()))), + atom!("monospace") => Ok(Self::Monospace.spanned(span.end(parser.pos()))), + atom!("system-ui") => Ok(Self::SystemUi.spanned(span.end(parser.pos()))), + atom!("emoji") => Ok(Self::Emoji.spanned(span.end(parser.pos()))), + atom!("math") => Ok(Self::Math.spanned(span.end(parser.pos()))), + atom!("fangsong") => Ok(Self::Fangsong.spanned(span.end(parser.pos()))), + atom!("ui-serif") => Ok(Self::UiSerif.spanned(span.end(parser.pos()))), + atom!("ui-sans-serif") => Ok(Self::UiSansSerif.spanned(span.end(parser.pos()))), + atom!("ui-monospace") => Ok(Self::UiMonospace.spanned(span.end(parser.pos()))), + atom!("ui-rounded") => Ok(Self::UiRounded.spanned(span.end(parser.pos()))), _ => { let mut name = String::new(); loop { @@ -103,44 +93,44 @@ impl<'a> Parse<'a> for FontFamilyValue { name.push(' '); ident = parser.expect_ident_cased()?; } - Ok(Self::Named(Atom::from(name)).spanned(span.until(parser.cur().span))) + Ok(Self::Named(Atom::from(name)).spanned(span.end(parser.pos()))) } } } Kind::String => { let string = parser.cur_atom().unwrap(); parser.advance(); - Ok(Self::Named(string).spanned(span.until(parser.cur().span))) + Ok(Self::Named(string).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } impl<'a> Parse<'a> for FontStyleValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { let ident = parser.expect_ident()?; match ident { - atom!("normal") => Ok(Self::Normal.spanned(span.until(parser.cur().span))), - atom!("italic") => Ok(Self::Italic.spanned(span.until(parser.cur().span))), + atom!("normal") => Ok(Self::Normal.spanned(span.end(parser.pos()))), + atom!("italic") => Ok(Self::Italic.spanned(span.end(parser.pos()))), atom!("oblique") => { - if matches!(parser.cur().kind, Kind::Dimension | Kind::Number) { + if matches!(parser.cur(), Kind::Dimension | Kind::Number) { let degrees = MathExpr::::parse(parser)?; - Ok(Self::Oblique(degrees).spanned(span.until(parser.cur().span))) + Ok(Self::Oblique(degrees).spanned(span.end(parser.pos()))) } else { Ok(Self::Oblique(Spanned::dummy(MathExpr::Literal(Spanned::dummy( Angle::Deg(14.0), )))) - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } } - _ => Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))?, + _ => Err(diagnostics::UnexpectedIdent(ident, parser.span()))?, } } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + k => Err(diagnostics::Unexpected(k, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/inline.rs b/crates/hdx_parser/src/css/values/inline.rs index 5fa1089f..8612f353 100644 --- a/crates/hdx_parser/src/css/values/inline.rs +++ b/crates/hdx_parser/src/css/values/inline.rs @@ -3,28 +3,27 @@ use hdx_ast::css::values::{ LineHeightValue, MathExpr, Shorthand, VerticalAlignShorthand, }; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for LineHeightValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let ident = parser.expect_ident()?; - if ident == atom!("normal") { - Ok(Self::Normal.spanned(span.until(parser.cur().span))) + match parser.cur() { + Token::Ident(ident) => { + if ident.eq_ignore_ascii_case(&atom!("normal")) { + Ok(Self::Normal.spanned(parser.advance())) } else { - Err(diagnostics::UnexpectedIdent(ident, parser.cur().span))? + Err(diagnostics::UnexpectedIdentSuggest( + *ident, + atom!("normal"), + parser.span(), + ))? } } - Kind::Number => { - let value = parser.cur().value.as_f32().unwrap(); - parser.advance(); - Ok(Self::Number(value).spanned(span.until(parser.cur().span))) - } + Token::Number(_, value) => Ok(Self::Number(*value).spanned(parser.advance())), _ => { + let span = parser.span(); let node = LengthPercentage::parse(parser)?; - Ok(Self::LengthPercentage(node).spanned(span.until(parser.cur().span))) + Ok(Self::LengthPercentage(node).spanned(span.end(parser.pos()))) } } } @@ -32,23 +31,19 @@ impl<'a> Parse<'a> for LineHeightValue { impl<'a> Parse<'a> for BaselineShiftValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let span = parser.cur().span; - let ident = parser.expect_ident()?; - match ident { - atom!("sub") => Ok(Self::Sub.spanned(span.until(parser.cur().span))), - atom!("super") => Ok(Self::Super.spanned(span.until(parser.cur().span))), - atom!("top") => Ok(Self::Top.spanned(span.until(parser.cur().span))), - atom!("center") => Ok(Self::Center.spanned(span.until(parser.cur().span))), - atom!("bottom") => Ok(Self::Bottom.spanned(span.until(parser.cur().span))), - _ => Err(diagnostics::UnexpectedIdent(ident, span))?, - } - } + match parser.cur() { + Token::Ident(ident) => match ident.as_ascii_lower() { + atom!("sub") => Ok(Self::Sub.spanned(parser.advance())), + atom!("super") => Ok(Self::Super.spanned(parser.advance())), + atom!("top") => Ok(Self::Top.spanned(parser.advance())), + atom!("center") => Ok(Self::Center.spanned(parser.advance())), + atom!("bottom") => Ok(Self::Bottom.spanned(parser.advance())), + _ => Err(diagnostics::UnexpectedIdent(*ident, parser.span()))?, + }, _ => { + let span = parser.span(); let node = LengthPercentage::parse(parser)?; - Ok(Self::LengthPercentage(node).spanned(span.until(parser.cur().span))) + Ok(Self::LengthPercentage(node).spanned(span.end(parser.pos()))) } } } @@ -56,41 +51,30 @@ impl<'a> Parse<'a> for BaselineShiftValue { impl<'a> Parse<'a> for VerticalAlignShorthand<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let mut baseline_source = Shorthand::Implicit; + let span = parser.span(); let mut alignment_baseline = Shorthand::Implicit; let mut baseline_shift = Shorthand::Implicit; - if parser.at(Kind::Ident) { - match parser.cur().as_atom().unwrap() { - atom!("first") => { - baseline_source = Shorthand::Explicit( - parser.boxup( - Expr::Literal( - BaselineSourceValue::First.spanned(span.until(parser.cur().span)), - ) - .spanned(span.until(parser.cur().span)), - ), - ); - parser.advance(); - } - atom!("last") => { - baseline_source = Shorthand::Explicit( - parser.boxup( - Expr::Literal( - BaselineSourceValue::Last.spanned(span.until(parser.cur().span)), - ) - .spanned(span.until(parser.cur().span)), - ), - ); - parser.advance(); - } - _ => {} - } - } + let mut baseline_source = match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lower() { + atom!("first") => Shorthand::Explicit( + parser.boxup( + Expr::Literal(BaselineSourceValue::First.spanned(parser.span())) + .spanned(parser.advance()), + ), + ), + atom!("last") => Shorthand::Explicit( + parser.boxup( + Expr::Literal(BaselineSourceValue::Last.spanned(parser.span())) + .spanned(parser.advance()), + ), + ), + }, + _ => Shorthand::Implicit, + }; loop { if !matches!( - parser.cur().kind, - Kind::Ident | Kind::Number | Kind::Percentage | Kind::Dimension + parser.cur(), + Token::Ident(_) | Token::Number(_, _) | Token::Dimension(_, _, _) ) { break; } @@ -123,6 +107,6 @@ impl<'a> Parse<'a> for VerticalAlignShorthand<'a> { } } Ok(Self { baseline_source, alignment_baseline, baseline_shift } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/values/length.rs b/crates/hdx_parser/src/css/values/length.rs index 6fb9d06c..5cea5007 100644 --- a/crates/hdx_parser/src/css/values/length.rs +++ b/crates/hdx_parser/src/css/values/length.rs @@ -1,29 +1,24 @@ use hdx_ast::css::values::{lengths::*, Percentage}; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; // https://drafts.csswg.org/css-values-4/#lengths impl<'a> Parse<'a> for Length { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Dimension => { - let (value, atom) = parser.expect_dimension()?; - if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { - Ok(unit.spanned(span.until(parser.cur().span))) + let span = parser.span(); + match parser.cur() { + Token::Dimension(_, value, atom) => { + if let Some(unit) = Self::from_f32_and_atom(value, *atom) { + Ok(unit.spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedDimension(atom, span))? } } - Kind::Number => { - let value = parser.expect_number()?; - if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("px"), - parser.cur().span, - ))? + Token::Number(_, value) => { + if *value != 0.0 { + Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), parser.span()))? } - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } k => Err(diagnostics::Unexpected(k, span))?, } @@ -33,22 +28,21 @@ impl<'a> Parse<'a> for Length { // https://drafts.csswg.org/css-values-4/#lengths impl<'a> Parse<'a> for PositiveLength { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Dimension => { + let span = parser.span(); + match parser.cur() { + Token::Dimension(_, value, atom) => { let (value, atom) = parser.expect_dimension_gte(0.0)?; if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedDimension(atom, span))? } } - Kind::Number => { - let value = parser.expect_number()?; + Token::Number(_, value) => { if value != 0.0 { Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), span))? } - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } k => Err(diagnostics::Unexpected(k, span))?, } @@ -58,30 +52,30 @@ impl<'a> Parse<'a> for PositiveLength { // https://drafts.csswg.org/css-values-4/#lengths impl<'a> Parse<'a> for PositiveLengthPercentageOrNormal { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { + let span = parser.span(); + match parser.cur() { + Token::Ident => { parser.expect_ident_of(atom!("normal"))?; - Ok(Self::Normal.spanned(span.until(parser.cur().span))) + Ok(Self::Normal.spanned(span.end(parser.pos()))) } - Kind::Dimension => { + Token::Dimension => { let (value, atom) = parser.expect_dimension_gte(0.0)?; if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedDimension(atom, span))? } } - Kind::Percentage => { + Token::Percentage => { let value = parser.expect_percentage_gte(0.0)?; - Ok(Self::Percentage(Percentage(value)).spanned(span.until(parser.cur().span))) + Ok(Self::Percentage(Percentage(value)).spanned(span.end(parser.pos()))) } - Kind::Number => { + Token::Number => { let value = parser.expect_number()?; if value != 0.0 { Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), span))? } - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } k => Err(diagnostics::Unexpected(k, span))?, } @@ -91,35 +85,32 @@ impl<'a> Parse<'a> for PositiveLengthPercentageOrNormal { // https://drafts.csswg.org/css-values-4/#typedef-length-percentage impl<'a> Parse<'a> for LengthPercentage { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Dimension => { + let span = parser.span(); + match parser.cur() { + Token::Dimension => { let value = parser.cur().value.as_f32().unwrap(); let atom = parser.cur().value.as_atom().unwrap(); if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { parser.advance(); - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedDimension(atom, parser.cur().span))? + Err(diagnostics::UnexpectedDimension(atom, parser.span()))? } } - Kind::Number => { + Token::Number => { let value = parser.cur().value.as_f32().unwrap(); if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("px"), - parser.cur().span, - ))? + Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), parser.span()))? } parser.advance(); - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } - Kind::Percentage => { + Token::Percentage => { let value = parser.cur().value.as_f32().unwrap(); parser.advance(); - Ok(Self::Percentage(Percentage(value)).spanned(span.until(parser.cur().span))) + Ok(Self::Percentage(Percentage(value)).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } @@ -127,46 +118,43 @@ impl<'a> Parse<'a> for LengthPercentage { // https://drafts.csswg.org/css-values-4/#typedef-length-percentage impl<'a> Parse<'a> for LengthPercentageOrNormal { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { + let span = parser.span(); + match parser.cur() { + Token::Ident => { if parser.cur_atom_lower().unwrap() == atom!("normal") { parser.advance(); - Ok(Self::Normal.spanned(span.until(parser.cur().span))) + Ok(Self::Normal.spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedIdent( parser.cur_atom_lower().unwrap(), - parser.cur().span, + parser.span(), ))? } } - Kind::Dimension => { + Token::Dimension => { let value = parser.cur().value.as_f32().unwrap(); let atom = parser.cur().value.as_atom().unwrap(); if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { parser.advance(); - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedDimension(atom, parser.cur().span))? + Err(diagnostics::UnexpectedDimension(atom, parser.span()))? } } - Kind::Number => { + Token::Number => { let value = parser.cur().value.as_f32().unwrap(); if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("px"), - parser.cur().span, - ))? + Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), parser.span()))? } parser.advance(); - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } - Kind::Percentage => { + Token::Percentage => { let value = parser.cur().value.as_f32().unwrap(); parser.advance(); - Ok(Self::Percentage(Percentage(value)).spanned(span.until(parser.cur().span))) + Ok(Self::Percentage(Percentage(value)).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } @@ -174,87 +162,81 @@ impl<'a> Parse<'a> for LengthPercentageOrNormal { // https://drafts.csswg.org/css-values-4/#typedef-length-percentage impl<'a> Parse<'a> for PositiveLengthPercentage { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Dimension => { + let span = parser.span(); + match parser.cur() { + Token::Dimension => { let value = parser.cur().value.as_f32().unwrap(); if value < 0.0 { - Err(diagnostics::NumberOutOfBounds(value, 0.0, parser.cur().span))?; + Err(diagnostics::NumberOutOfBounds(value, 0.0, parser.span()))?; } let atom = parser.cur().value.as_atom().unwrap(); if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { parser.advance(); - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedDimension(atom, parser.cur().span))? + Err(diagnostics::UnexpectedDimension(atom, parser.span()))? } } - Kind::Number => { + Token::Number => { let value = parser.cur().value.as_f32().unwrap(); if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("px"), - parser.cur().span, - ))? + Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), parser.span()))? } parser.advance(); - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } - Kind::Percentage => { + Token::Percentage => { let value = parser.cur().value.as_f32().unwrap(); if value < 0.0 { - Err(diagnostics::NumberOutOfBounds(value, 0.0, parser.cur().span))?; + Err(diagnostics::NumberOutOfBounds(value, 0.0, parser.span()))?; } parser.advance(); - Ok(Self::Percentage(Percentage(value)).spanned(span.until(parser.cur().span))) + Ok(Self::Percentage(Percentage(value)).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } impl<'a> Parse<'a> for LengthPercentageOrAuto { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { + let span = parser.span(); + match parser.cur() { + Token::Ident => { if parser.cur_atom_lower().unwrap() == atom!("auto") { parser.advance(); - Ok(Self::Auto.spanned(span.until(parser.cur().span))) + Ok(Self::Auto.spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedIdent( parser.cur_atom_lower().unwrap(), - parser.cur().span, + parser.span(), ))? } } - Kind::Dimension => { + Token::Dimension => { let value = parser.cur().value.as_f32().unwrap(); let atom = parser.cur().value.as_atom().unwrap(); if let Some(unit) = Self::from_f32_and_atom(value, atom.clone()) { parser.advance(); - Ok(unit.spanned(span.until(parser.cur().span))) + Ok(unit.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedDimension(atom, parser.cur().span))? + Err(diagnostics::UnexpectedDimension(atom, parser.span()))? } } - Kind::Number => { + Token::Number => { let value = parser.cur().value.as_f32().unwrap(); if value != 0.0 { - Err(diagnostics::DisallowedValueWithoutDimension( - atom!("px"), - parser.cur().span, - ))? + Err(diagnostics::DisallowedValueWithoutDimension(atom!("px"), parser.span()))? } parser.advance(); - Ok(Self::Zero.spanned(span.until(parser.cur().span))) + Ok(Self::Zero.spanned(span.end(parser.pos()))) } - Kind::Percentage => { + Token::Percentage => { let value = parser.cur().value.as_f32().unwrap(); parser.advance(); - Ok(Self::Percentage(Percentage(value)).spanned(span.until(parser.cur().span))) + Ok(Self::Percentage(Percentage(value)).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/lists.rs b/crates/hdx_parser/src/css/values/lists.rs index fde42b79..cfeee4f0 100644 --- a/crates/hdx_parser/src/css/values/lists.rs +++ b/crates/hdx_parser/src/css/values/lists.rs @@ -3,33 +3,35 @@ use hdx_ast::css::values::{ ListStyleTypeValue, Shorthand, }; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for ListStyleShorthand<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut position = Shorthand::Implicit; let mut image = Shorthand::Implicit; let mut marker = Shorthand::Implicit; loop { - match parser.cur().kind { - Kind::Semicolon | Kind::Comma | Kind::Eof => { + match parser.cur() { + Token::Semicolon | Token::Comma | Token::Eof => { break; } - Kind::Ident => { - let ident = parser.cur_atom().unwrap(); - if position.is_implicit() && matches!(ident, atom!("inside") | atom!("outside")) + Token::Ident(ident) => { + if position.is_implicit() + && matches!(ident.to_ascii_lowercase(), atom!("inside") | atom!("outside")) { let node = Expr::::parse(parser)?; position = Shorthand::Explicit(parser.boxup(node)); - } else if image.is_implicit() && matches!(ident, atom!("none")) { + } else if image.is_implicit() + && matches!(ident.to_ascii_lowercase(), atom!("none")) + { let node = Expr::::parse(parser)?; image = Shorthand::Explicit(parser.boxup(node)); } else if marker.is_implicit() { let node = Expr::::parse(parser)?; marker = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::UnexpectedIdent(ident.clone(), parser.cur().span))? + Err(diagnostics::UnexpectedIdent(*ident, parser.span()))? } } k => { @@ -55,35 +57,34 @@ impl<'a> Parse<'a> for ListStyleShorthand<'a> { Err(_) => parser.rewind(checkpoint), } } - Err(diagnostics::Unexpected(k, parser.cur().span))? + Err(diagnostics::Unexpected(*k, parser.span()))? } } if position.is_explicit() && image.is_explicit() && marker.is_explicit() { break; } } - Ok(Self { position, image, marker }.spanned(span.until(parser.cur().span))) + Ok(Self { position, image, marker }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for ListStyleTypeValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let ident = parser.cur_atom().unwrap(); - if ident == atom!("none") { - parser.advance(); - Ok(Self::None.spanned(span)) + match parser.cur() { + Token::Ident(ident) => { + if ident.to_ascii_lowercase() == atom!("none") { + Ok(Self::None.spanned(parser.advance())) } else { + let span = parser.span(); let node = CounterStyle::parse(parser)?; - Ok(Self::CounterStyle(node).spanned(span.until(parser.cur().span))) + Ok(Self::CounterStyle(node).spanned(span.end(parser.pos()))) } } - Kind::String => Ok(Self::String(parser.expect_string()?).spanned(span)), + Token::String(value) => Ok(Self::String(*value).spanned(parser.advance())), _ => { + let span = parser.span(); let node = CounterStyle::parse(parser)?; - Ok(Self::CounterStyle(node).spanned(span.until(parser.cur().span))) + Ok(Self::CounterStyle(node).spanned(span.end(parser.pos()))) } } } @@ -91,21 +92,20 @@ impl<'a> Parse<'a> for ListStyleTypeValue<'a> { impl<'a> Parse<'a> for ListStyleImageValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let ident = parser.cur_atom().unwrap(); - if ident == atom!("none") { - parser.advance(); - Ok(Self::None.spanned(span)) + match parser.cur() { + Token::Ident(ident) => { + if ident.to_ascii_lowercase() == atom!("none") { + Ok(Self::None.spanned(parser.advance())) } else { + let span = parser.span(); let node = Image::parse(parser)?; - Ok(Self::Image(node).spanned(span.until(parser.cur().span))) + Ok(Self::Image(node).spanned(span.end(parser.pos()))) } } _ => { + let span = parser.span(); let node = Image::parse(parser)?; - Ok(Self::Image(node).spanned(span.until(parser.cur().span))) + Ok(Self::Image(node).spanned(span.end(parser.pos()))) } } } diff --git a/crates/hdx_parser/src/css/values/mod.rs b/crates/hdx_parser/src/css/values/mod.rs index 8c9c0a48..b1e5f783 100644 --- a/crates/hdx_parser/src/css/values/mod.rs +++ b/crates/hdx_parser/src/css/values/mod.rs @@ -21,24 +21,28 @@ pub mod ui; use hdx_ast::css::{properties::Todo, values::*}; -use crate::{diagnostics, Atomizable, Parse, Parser, Result, Spanned}; +use crate::{diagnostics, Atomizable, Parse, Parser, Result, Spanned, Token}; macro_rules! parse_for_enums { - {$( $prop: ident, )+} => { - $( - impl<'a> Parse<'a> for $prop { - fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let ident = parser.expect_ident()?; - if let Some(val) = $prop::from_atom(ident.clone()) { - Ok(val.spanned(span.until(parser.cur().span))) - } else { - Err(diagnostics::UnexpectedIdent(ident, span))? - } - } - } - )+ - } + {$( $prop: ident, )+} => { + $( + impl<'a> Parse<'a> for $prop { + fn parse(parser: &mut Parser<'a>) -> Result> { + let span = parser.span(); + match parser.cur() { + Token::Ident(ident) => { + if let Some(val) = $prop::from_atom(*ident) { + Ok(val.spanned(span)) + } else { + Err(diagnostics::UnexpectedIdent(*ident, span))? + } + } + token => Err(diagnostics::ExpectedIdent(*token, span))?, + } + } + } + )+ + } } parse_for_enums! { @@ -76,33 +80,33 @@ parse_for_enums! { // TODO: impl<'a> Parse<'a> for Image<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } // TODO: impl<'a> Parse<'a> for RatioOrAuto { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } // TODO: impl<'a> Parse<'a> for TimeOrAuto { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } impl<'a> Parse<'a> for NoNonGlobalValuesAllowed { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))? + unexpected!(parser); } } // TODO: impl<'a> Parse<'a> for Todo { fn parse(parser: &mut Parser<'a>) -> Result> { - Err(diagnostics::Unimplemented(parser.cur().span))? + Err(diagnostics::Unimplemented(parser.span()))? } } diff --git a/crates/hdx_parser/src/css/values/non_standard.rs b/crates/hdx_parser/src/css/values/non_standard.rs index 079a2890..cfdb3ddd 100644 --- a/crates/hdx_parser/src/css/values/non_standard.rs +++ b/crates/hdx_parser/src/css/values/non_standard.rs @@ -1,33 +1,20 @@ use hdx_ast::css::values::non_standard::ZoomValue; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for ZoomValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let ident = parser.cur_atom().unwrap(); - match ident.to_ascii_lowercase() { - atom!("normal") => Ok(Self::Normal.spanned(span.until(parser.cur().span))), - atom!("reset") => Ok(Self::Reset.spanned(span.until(parser.cur().span))), - _ => Err(diagnostics::UnexpectedIdent( - parser.cur_atom().unwrap(), - parser.cur().span, - ))?, - } + match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lowercase() { + atom!("normal") => Ok(Self::Normal.spanned(parser.advance())), + atom!("reset") => Ok(Self::Reset.spanned(parser.advance())), + _ => Err(diagnostics::UnexpectedIdent(*ident, parser.span()))?, + }, + Token::Dimension(_, value, atom!("%")) => { + Ok(Self::Percentage(*value).spanned(parser.advance())) } - Kind::Percentage => { - let value = parser.cur().value.as_f32().unwrap(); - parser.advance(); - Ok(Self::Percentage(value).spanned(span.until(parser.cur().span))) - } - Kind::Number => { - let value = parser.cur().value.as_f32().unwrap(); - parser.advance(); - Ok(Self::Number(value).spanned(span.until(parser.cur().span))) - } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + Token::Number(_, value) => Ok(Self::Number(*value).spanned(parser.advance())), + token => Err(diagnostics::Unexpected(*token, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/page_floats.rs b/crates/hdx_parser/src/css/values/page_floats.rs index 82ff5fdf..8fbd128c 100644 --- a/crates/hdx_parser/src/css/values/page_floats.rs +++ b/crates/hdx_parser/src/css/values/page_floats.rs @@ -7,39 +7,33 @@ use crate::{atom, diagnostics, Atomizable, Kind, Parse, Parser, Result, Spanned} impl<'a> Parse<'a> for FloatDeferValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { if let Some(val) = Self::from_atom(parser.expect_ident()?) { - Ok(val.spanned(span.until(parser.cur().span))) + Ok(val.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedIdent( - parser.cur_atom().unwrap(), - parser.cur().span, - ))? + Err(diagnostics::UnexpectedIdent(parser.cur_atom().unwrap(), parser.span()))? } } Kind::Number => { let node = parser.expect_int()?; - Ok(Self::Integer(node).spanned(span.until(parser.cur().span))) + Ok(Self::Integer(node).spanned(span.end(parser.pos()))) } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } impl<'a> Parse<'a> for FloatValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { + let span = parser.span(); + match parser.cur() { Kind::Ident => { if let Some(val) = Self::from_atom(parser.expect_ident()?) { - Ok(val.spanned(span.until(parser.cur().span))) + Ok(val.spanned(span.end(parser.pos()))) } else { - Err(diagnostics::UnexpectedIdent( - parser.cur_atom().unwrap(), - parser.cur().span, - ))? + Err(diagnostics::UnexpectedIdent(parser.cur_atom().unwrap(), parser.span()))? } } Kind::Function => { @@ -51,11 +45,11 @@ impl<'a> Parse<'a> for FloatValue { atom!("snap-block") => { if let Some(floated) = SnapBlockFloat::from_atom(floated_atom) { Ok(Self::SnapBlockFunction(length, floated) - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedIdent( parser.cur_atom().unwrap(), - parser.cur().span, + parser.span(), ) .into()) } @@ -63,23 +57,22 @@ impl<'a> Parse<'a> for FloatValue { atom!("snap-inline") => { if let Some(floated) = SnapInlineFloat::from_atom(floated_atom) { Ok(Self::SnapInlineFunction(length, floated) - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } else { Err(diagnostics::UnexpectedIdent( parser.cur_atom().unwrap(), - parser.cur().span, + parser.span(), ) .into()) } } - _ => Err(diagnostics::UnexpectedIdent( - parser.cur_atom().unwrap(), - parser.cur().span, - ) - .into()), + _ => { + Err(diagnostics::UnexpectedIdent(parser.cur_atom().unwrap(), parser.span()) + .into()) + } } } - _ => Err(diagnostics::Unexpected(parser.cur().kind, parser.cur().span))?, + _ => Err(diagnostics::Unexpected(parser.cur(), parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/shorthand.rs b/crates/hdx_parser/src/css/values/shorthand.rs index c973c625..84cb71f6 100644 --- a/crates/hdx_parser/src/css/values/shorthand.rs +++ b/crates/hdx_parser/src/css/values/shorthand.rs @@ -1,17 +1,17 @@ use hdx_ast::css::values::{shorthand::*, Shorthand}; -use crate::{Kind, Parse, Parser, Result, Spanned}; +use crate::{Parse, Parser, Result, Spanned, Token}; impl<'a, T: Parse<'a>> Parse<'a> for BoxShorthand<'a, T> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut top = Shorthand::Implicit; let mut right = Shorthand::Implicit; let mut bottom = Shorthand::Implicit; let mut left = Shorthand::Implicit; while matches!( - parser.cur().kind, - Kind::Dimension | Kind::Percentage | Kind::Number | Kind::Ident | Kind::Function + parser.cur(), + Token::Dimension(_, _, _) | Token::Number(_, _) | Token::Ident(_) | Token::Function(_) ) { let parsed = T::parse(parser)?; if top.is_implicit() { @@ -25,38 +25,38 @@ impl<'a, T: Parse<'a>> Parse<'a> for BoxShorthand<'a, T> { break; } } - Ok(Self { top, right, bottom, left }.spanned(span.until(parser.cur().span))) + Ok(Self { top, right, bottom, left }.spanned(span.end(parser.pos()))) } } impl<'a, T: Parse<'a>> Parse<'a> for XYShorthand<'a, T> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let node = T::parse(parser)?; let x = Shorthand::Explicit(parser.boxup(node)); - match parser.cur().kind { - Kind::Ident | Kind::Function => { + match parser.cur() { + Token::Ident(_) | Token::Function(_) => { let node = T::parse(parser)?; Ok(Self { x, y: Shorthand::Explicit(parser.boxup(node)) } - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } - _ => Ok(Self { x, y: Shorthand::Implicit }.spanned(span.until(parser.cur().span))), + _ => Ok(Self { x, y: Shorthand::Implicit }.spanned(span.end(parser.pos()))), } } } impl<'a, T: Parse<'a>> Parse<'a> for DoubleShorthand<'a, T> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let node = T::parse(parser)?; let first = Shorthand::Explicit(parser.boxup(node)); - match parser.cur().kind { - Kind::Ident | Kind::Function => { + match parser.cur() { + Token::Ident(_) | Token::Function(_) => { let node = T::parse(parser)?; Ok(Self(first, Shorthand::Explicit(parser.boxup(node))) - .spanned(span.until(parser.cur().span))) + .spanned(span.end(parser.pos()))) } - _ => Ok(Self(first, Shorthand::Implicit).spanned(span.until(parser.cur().span))), + _ => Ok(Self(first, Shorthand::Implicit).spanned(span.end(parser.pos()))), } } } diff --git a/crates/hdx_parser/src/css/values/size_adjust.rs b/crates/hdx_parser/src/css/values/size_adjust.rs index f86525c1..68c33103 100644 --- a/crates/hdx_parser/src/css/values/size_adjust.rs +++ b/crates/hdx_parser/src/css/values/size_adjust.rs @@ -1,29 +1,19 @@ use hdx_ast::css::values::TextSizeAdjustValue; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for TextSizeAdjustValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let ident = parser.expect_ident()?; - match ident { - atom!("none") => { - Ok(TextSizeAdjustValue::None.spanned(span.until(parser.cur().span))) - } - atom!("auto") => { - Ok(TextSizeAdjustValue::Auto.spanned(span.until(parser.cur().span))) - } - _ => Err(diagnostics::UnexpectedIdent(ident, span))?, - } + match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lowercase() { + atom!("none") => Ok(TextSizeAdjustValue::None.spanned(parser.advance())), + atom!("auto") => Ok(TextSizeAdjustValue::Auto.spanned(parser.advance())), + _ => Err(diagnostics::UnexpectedIdent(*ident, parser.span()))?, + }, + Token::Dimension(_, value, atom!("%")) => { + Ok(TextSizeAdjustValue::Percentage(*value).spanned(parser.advance())) } - Kind::Percentage => { - let value = parser.cur().value.as_f32().unwrap(); - parser.advance(); - Ok(TextSizeAdjustValue::Percentage(value).spanned(span.until(parser.cur().span))) - } - k => Err(diagnostics::Unexpected(k, span))?, + token => Err(diagnostics::Unexpected(*token, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/css/values/sizing.rs b/crates/hdx_parser/src/css/values/sizing.rs index d0b9fd7b..77eb6131 100644 --- a/crates/hdx_parser/src/css/values/sizing.rs +++ b/crates/hdx_parser/src/css/values/sizing.rs @@ -1,64 +1,58 @@ use hdx_ast::css::values::{LengthPercentage, MaxSizing, Sizing}; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, expect, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for Sizing { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let sizing = match parser.cur().kind { - Kind::Ident => { - let name = parser.expect_ident()?; - match name { - atom!("auto") => Sizing::Auto, - atom!("max-content") => Sizing::MaxContent, - atom!("min-content") => Sizing::MinContent, - atom!("stretch") => Sizing::Stretch, - atom!("fit-content") => Sizing::FitContent, - _ => Err(diagnostics::UnexpectedIdent(name, parser.cur().span))?, - } - } - Kind::Percentage | Kind::Dimension | Kind::Number => { + let span = parser.span(); + let sizing = match parser.cur() { + Token::Ident(name) => match name.to_ascii_lowercase() { + atom!("auto") => Sizing::Auto, + atom!("max-content") => Sizing::MaxContent, + atom!("min-content") => Sizing::MinContent, + atom!("stretch") => Sizing::Stretch, + atom!("fit-content") => Sizing::FitContent, + _ => Err(diagnostics::UnexpectedIdent(*name, parser.span()))?, + }, + Token::Dimension(_, _, _) | Token::Number(_, _) => { Sizing::LengthPercentage(LengthPercentage::parse(parser)?) } - Kind::Function => { - parser.expect_function_of(atom!("fit-content"))?; + Token::Function(_) => { + parser.expect_function_of(&atom!("fit-content"))?; let result = LengthPercentage::parse(parser)?; - parser.expect(Kind::RightParen)?; + expect!(Token::RightParen); Sizing::FitContentFunction(result) } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, }; - Ok(sizing.spanned(span.until(parser.cur().span))) + Ok(sizing.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for MaxSizing { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - let sizing = match parser.cur().kind { - Kind::Ident => { - let name = parser.expect_ident()?; - match name { - atom!("none") => MaxSizing::None, - atom!("max-content") => MaxSizing::MaxContent, - atom!("min-content") => MaxSizing::MinContent, - atom!("stretch") => MaxSizing::Stretch, - atom!("fit-content") => MaxSizing::FitContent, - _ => Err(diagnostics::UnexpectedIdent(name, parser.cur().span))?, - } - } - Kind::Percentage | Kind::Dimension | Kind::Number => { + let span = parser.span(); + let sizing = match parser.cur() { + Token::Ident(name) => match name.to_ascii_lowercase() { + atom!("none") => MaxSizing::None, + atom!("max-content") => MaxSizing::MaxContent, + atom!("min-content") => MaxSizing::MinContent, + atom!("stretch") => MaxSizing::Stretch, + atom!("fit-content") => MaxSizing::FitContent, + _ => Err(diagnostics::UnexpectedIdent(*name, parser.span()))?, + }, + Token::Dimension(_, _, _) | Token::Number(_, _) => { MaxSizing::LengthPercentage(LengthPercentage::parse(parser)?) } - Kind::Function => { - let name = parser.expect_function_of(atom!("fit-content"))?; + Token::Function(_) => { + let name = parser.expect_function_of(&atom!("fit-content"))?; let result = LengthPercentage::parse(parser)?; - parser.expect(Kind::RightParen)?; + expect!(Token::RightParen); MaxSizing::FitContentFunction(result) } - _ => Err(diagnostics::Unimplemented(parser.cur().span))?, + _ => Err(diagnostics::Unimplemented(parser.span()))?, }; - Ok(sizing.spanned(span.until(parser.cur().span))) + Ok(sizing.spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/values/text.rs b/crates/hdx_parser/src/css/values/text.rs index 805f62f4..a048673d 100644 --- a/crates/hdx_parser/src/css/values/text.rs +++ b/crates/hdx_parser/src/css/values/text.rs @@ -2,22 +2,20 @@ use hdx_ast::css::values::{ Expr, Shorthand, TextWrapValue, WhiteSpaceCollapseValue, WhiteSpaceShorthand, WhiteSpaceTrimValue, }; -use hdx_lexer::Kind; -use crate::{atom, diagnostics, Atomizable, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Atomizable, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for WhiteSpaceTrimValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut inner = false; let mut after = false; let mut before = false; loop { - match parser.cur().kind { - Kind::Ident => match parser.cur_atom_lower().unwrap() { + match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lowercase() { atom!("none") => { - parser.advance(); - return Ok(Self::None.spanned(span)); + return Ok(Self::None.spanned(parser.advance())); } atom!("discard-inner") => { parser.advance(); @@ -39,51 +37,46 @@ impl<'a> Parse<'a> for WhiteSpaceTrimValue { break; } } - Ok(Self::Discard { inner, after, before }.spanned(span.until(parser.cur().span))) + Ok(Self::Discard { inner, after, before }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for WhiteSpaceShorthand<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - if parser.at(Kind::Ident) { - match parser.cur_atom_lower().unwrap() { + let span = parser.span(); + match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lowercase() { //normal | pre | nowrap | pre-wrap | pre-line atom!("normal") => { - parser.advance(); - return Ok(Self::Normal.spanned(span)); + return Ok(Self::Normal.spanned(parser.advance())); } atom!("pre") => { - parser.advance(); - return Ok(Self::Pre.spanned(span)); + return Ok(Self::Pre.spanned(parser.advance())); } atom!("nowrap") => { - parser.advance(); - return Ok(Self::Nowrap.spanned(span)); + return Ok(Self::Nowrap.spanned(parser.advance())); } atom!("pre-wrap") => { - parser.advance(); - return Ok(Self::PreWrap.spanned(span)); + return Ok(Self::PreWrap.spanned(parser.advance())); } atom!("pre-line") => { - parser.advance(); - return Ok(Self::PreLine.spanned(span)); + return Ok(Self::PreLine.spanned(parser.advance())); } _ => {} - } + }, + _ => {} } let mut collapse = Shorthand::Implicit; let mut wrap = Shorthand::Implicit; let mut trim = Shorthand::Implicit; loop { - match parser.cur().kind { - Kind::Semicolon | Kind::Comma | Kind::Eof => { + match parser.cur() { + Token::Semicolon | Token::Comma | Token::Eof => { break; } - Kind::Ident => { - let ident = parser.cur_atom_lower().unwrap(); + Token::Ident(ident) => { if collapse.is_implicit() - && WhiteSpaceCollapseValue::from_atom(ident.clone()).is_some() + && WhiteSpaceCollapseValue::from_atom(ident.to_ascii_lowercase()).is_some() { let node = Expr::::parse(parser)?; collapse = Shorthand::Explicit(parser.boxup(node)); @@ -94,7 +87,7 @@ impl<'a> Parse<'a> for WhiteSpaceShorthand<'a> { wrap = Shorthand::Explicit(parser.boxup(node)); } else if trim.is_implicit() && matches!( - ident, + ident.to_ascii_lowercase(), atom!("none") | atom!("discard-inner") | atom!("discard-after") | atom!("discard-before") @@ -102,7 +95,7 @@ impl<'a> Parse<'a> for WhiteSpaceShorthand<'a> { let node = Expr::::parse(parser)?; trim = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::UnexpectedIdent(ident.clone(), parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident.clone(), parser.span()))? } } k => { @@ -139,13 +132,13 @@ impl<'a> Parse<'a> for WhiteSpaceShorthand<'a> { Err(_) => parser.rewind(checkpoint), } } - Err(diagnostics::Unexpected(k, parser.cur().span))? + Err(diagnostics::Unexpected(*k, parser.span()))? } } if collapse.is_explicit() && wrap.is_explicit() && trim.is_explicit() { break; } } - Ok(Self::Expanded { collapse, wrap, trim }.spanned(span.until(parser.cur().span))) + Ok(Self::Expanded { collapse, wrap, trim }.spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/values/text_decor.rs b/crates/hdx_parser/src/css/values/text_decor.rs index 17eb1c2b..dcd513a8 100644 --- a/crates/hdx_parser/src/css/values/text_decor.rs +++ b/crates/hdx_parser/src/css/values/text_decor.rs @@ -3,21 +3,20 @@ use hdx_ast::css::values::{ TextDecorationStyleValue, }; -use crate::{atom, diagnostics, Kind, Parse, Parser, Result, Spanned}; +use crate::{atom, diagnostics, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for TextDecorationShorthand<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; + let span = parser.span(); let mut color = Shorthand::Implicit; let mut style = Shorthand::Implicit; let mut line = Shorthand::Implicit; loop { - match parser.cur().kind { - Kind::Ident => { - let ident = parser.cur_atom().unwrap(); + match parser.cur() { + Token::Ident(ident) => { if style.is_implicit() && matches!( - ident, + ident.to_ascii_lowercase(), atom!("solid") | atom!("double") | atom!("dotted") | atom!("dashed") | atom!("wavy") @@ -26,7 +25,7 @@ impl<'a> Parse<'a> for TextDecorationShorthand<'a> { style = Shorthand::Explicit(parser.boxup(node)); } else if line.is_implicit() && matches!( - ident, + *ident, atom!("none") | atom!("underline") | atom!("overline") | atom!("line-through") | atom!("blink") @@ -37,18 +36,18 @@ impl<'a> Parse<'a> for TextDecorationShorthand<'a> { let node = MathExpr::::parse(parser)?; color = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::UnexpectedIdent(ident.clone(), parser.cur().span))? + Err(diagnostics::UnexpectedIdent(ident.clone(), parser.span()))? } } - Kind::Semicolon | Kind::Comma | Kind::Eof => { + Token::Semicolon | Token::Comma | Token::Eof => { break; } - k => { + token => { if color.is_implicit() { let node = MathExpr::::parse(parser)?; color = Shorthand::Explicit(parser.boxup(node)); } else { - Err(diagnostics::Unexpected(k, parser.cur().span))? + Err(diagnostics::Unexpected(*token, parser.span()))? } } } @@ -56,57 +55,62 @@ impl<'a> Parse<'a> for TextDecorationShorthand<'a> { break; } } - Ok(Self { color, style, line }.spanned(span.until(parser.cur().span))) + Ok(Self { color, style, line }.spanned(span.end(parser.pos()))) } } impl<'a> Parse<'a> for TextDecorationLineValue { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - if parser.at(Kind::Ident) && parser.cur().as_atom_lower().unwrap() == atom!("none") { - parser.advance(); - return Ok(Self::None.spanned(span.until(parser.cur().span))); + let span = parser.span(); + match parser.cur() { + Token::Ident(ident) => match ident.to_ascii_lowercase() { + atom!("none") => { + return Ok(Self::None.spanned(parser.advance())); + } + _ => {} + }, + _ => {} } let mut underline = false; let mut overline = false; let mut line_through = false; let mut blink = false; loop { - if !parser.at(Kind::Ident) { - break; - } - let ident = parser.cur_atom().unwrap(); - match ident { - atom!("underline") => { - if underline { - break; - } - underline = true - } - atom!("overline") => { - if overline { - break; - } - overline = true - } - atom!("line-through") => { - if overline { - break; - } - line_through = true - } - atom!("blink") => { - if overline { - break; - } - blink = true + match parser.cur() { + Token::Ident(ident) => { + match ident.to_ascii_lowercase() { + atom!("underline") => { + if underline { + break; + } + underline = true + } + atom!("overline") => { + if overline { + break; + } + overline = true + } + atom!("line-through") => { + if overline { + break; + } + line_through = true + } + atom!("blink") => { + if overline { + break; + } + blink = true + } + _ => break, + }; + parser.advance(); } _ => break, } - parser.advance() } - Ok(Self::Style { underline, overline, line_through, blink } - .spanned(span.until(parser.cur().span))) + Ok(Self::Style { underline, overline, line_through, blink }.spanned(span.end(parser.pos()))) } } diff --git a/crates/hdx_parser/src/css/values/ui.rs b/crates/hdx_parser/src/css/values/ui.rs index 88bfee8c..de7faa8f 100644 --- a/crates/hdx_parser/src/css/values/ui.rs +++ b/crates/hdx_parser/src/css/values/ui.rs @@ -1,21 +1,18 @@ use hdx_ast::css::values::CursorValue; -use crate::{diagnostics, Atomizable, Kind, Parse, Parser, Result, Spanned}; +use crate::{diagnostics, Atomizable, Parse, Parser, Result, Spanned, Token}; impl<'a> Parse<'a> for CursorValue<'a> { fn parse(parser: &mut Parser<'a>) -> Result> { - let span = parser.cur().span; - match parser.cur().kind { - Kind::Ident => { - let span = parser.cur().span; - let ident = parser.expect_ident()?; - if let Some(val) = CursorValue::from_atom(ident.clone()) { - Ok(val.spanned(span.until(parser.cur().span))) + match parser.cur() { + Token::Ident(ident) => { + if let Some(val) = CursorValue::from_atom(*ident) { + Ok(val.spanned(parser.advance())) } else { - Err(diagnostics::UnexpectedIdent(ident, span))? + Err(diagnostics::UnexpectedIdent(*ident, parser.span()))? } } - k => Err(diagnostics::Unexpected(k, parser.cur().span))?, + token => Err(diagnostics::Unexpected(*token, parser.span()))?, } } } diff --git a/crates/hdx_parser/src/cursor.rs b/crates/hdx_parser/src/cursor.rs index 5c81a918..0520bd11 100644 --- a/crates/hdx_parser/src/cursor.rs +++ b/crates/hdx_parser/src/cursor.rs @@ -1,287 +1,186 @@ use std::ops::Range; -use hdx_lexer::{LexerCheckpoint, Span, Token}; +use hdx_atom::Atom; +use hdx_lexer::{LexerCheckpoint, Token}; -use crate::{diagnostics, Atom, Error, Parser, Result}; +use crate::{diagnostics, span::Span, Parser, Result}; pub struct ParserCheckpoint<'a> { lexer: LexerCheckpoint<'a>, token: Token, + prev_pos: u32, warnings_pos: usize, errors_pos: usize, } impl<'a> Parser<'a> { #[inline] - pub(crate) fn cur(&self) -> &Token { - &self.token + pub fn cur(&self) -> Token { + self.token.clone() } #[inline] - pub(crate) fn cur_atom(&self) -> Option { - self.token.value.as_atom() + pub fn pos(&self) -> u32 { + self.lexer.pos() } #[inline] - pub(crate) fn cur_atom_lower(&self) -> Option { - self.token.value.as_atom_lower() + pub fn span(&self) -> Span { + Span::new(self.prev_pos, self.lexer.pos()) } #[inline] - pub(crate) fn cur_char(&self) -> Option { - self.token.value.as_char() - } - - pub(crate) fn at(&self, kind: Kind) -> bool { - self.cur().kind == kind - } - - pub(crate) fn expect(&mut self, kind: Kind) -> Result<()> { - self.expect_without_advance(kind)?; - self.advance(); - Ok(()) - } - - #[inline] - pub(crate) fn expect_ident_cased(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::Ident)?.value.as_atom().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_ident(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::Ident)?.value.as_atom_lower().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_ident_of(&mut self, atom: Atom) -> Result<()> { - let ident = self.expect_without_advance(Kind::Ident)?.value.as_atom_lower().unwrap(); - if atom != ident { - Err(diagnostics::ExpectedIdent(atom, ident, self.pos()))? - } - self.advance(); - Ok(()) - } - - #[inline] - pub(crate) fn expect_function(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::Function)?.value.as_atom_lower().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_function_of(&mut self, atom: Atom) -> Result<()> { - let ident = self.expect_without_advance(Kind::Function)?.value.as_atom_lower().unwrap(); - if atom != ident { - Err(diagnostics::ExpectedFunction(atom, ident, self.pos()))? - } - self.advance(); - Ok(()) - } - - #[inline] - pub(crate) fn expect_at_keyword(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::AtKeyword)?.value.as_atom_lower().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_at_keyword_of(&mut self, atom: Atom) -> Result<()> { - let ident = self.expect_without_advance(Kind::AtKeyword)?.value.as_atom_lower().unwrap(); - if atom != ident { - Err(diagnostics::ExpectedAtKeyword(atom, ident, self.pos()))? - } - self.advance(); - Ok(()) - } - - #[inline] - pub(crate) fn expect_hash(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::Hash)?.value.as_atom().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_string(&mut self) -> Result { - let atom = self.expect_without_advance(Kind::String)?.value.as_atom().unwrap(); - self.advance(); - Ok(atom) - } - - #[inline] - pub(crate) fn expect_delim(&mut self) -> Result { - let char = self.expect_without_advance(Kind::Delim)?.value.as_char().unwrap(); - self.advance(); - Ok(char) - } - - #[inline] - pub(crate) fn expect_delim_of(&mut self, ch: char) -> Result<()> { - if ch != self.expect_without_advance(Kind::Delim)?.value.as_char().unwrap() { - Err(diagnostics::UnexpectedDelim(ch, self.pos()))? + pub fn expect_ident_of(&mut self, expected_atom: &Atom) -> Result<()> { + match self.cur() { + Token::Ident(atom) => { + if atom.eq_ignore_ascii_case(expected_atom) { + self.advance(); + Ok(()) + } else { + Err(diagnostics::ExpectedIdentOf(expected_atom.clone(), atom, self.span()))? + } + } + token => Err(diagnostics::ExpectedIdent(token, self.span()))?, } - self.advance(); - Ok(()) - } - - #[inline] - pub(crate) fn expect_number(&mut self) -> Result { - let n = self.expect_without_advance(Kind::Number)?.value.as_f32().unwrap(); - self.advance(); - Ok(n) } #[inline] - pub(crate) fn expect_number_gte(&mut self, min: f32) -> Result { - let n = self.expect_without_advance(Kind::Number)?.value.as_f32().unwrap(); - if n < min { - Err(diagnostics::NumberTooSmall(min, self.pos()))? + pub fn expect_function_of(&mut self, expected_atom: &Atom) -> Result<()> { + match self.cur() { + Token::Function(atom) => { + if atom.eq_ignore_ascii_case(expected_atom) { + self.advance(); + Ok(()) + } else { + Err(diagnostics::ExpectedFunctionOf(expected_atom.clone(), atom, self.span()))? + } + } + token => Err(diagnostics::ExpectedFunction(token, self.span()))?, } - self.advance(); - Ok(n) } #[inline] - pub(crate) fn expect_number_in_range(&mut self, range: Range) -> Result { - let n = self.expect_without_advance(Kind::Number)?.value.as_f32().unwrap(); - if !range.contains(&n) { - Err(diagnostics::NumberOutOfBounds(range.start, range.end, self.pos()))? + pub fn expect_delim_of(&mut self, expected_ch: char) -> Result<()> { + match self.cur() { + Token::Delim(ch) => { + if expected_ch != ch { + Err(diagnostics::ExpectedDelimOf(expected_ch, ch, Span::new(self.pos(), self.pos())))? + } + self.advance(); + Ok(()) + } + token => Err(diagnostics::ExpectedDelim(token, self.span()))?, } - self.advance(); - Ok(n) } #[inline] - pub(crate) fn expect_int(&mut self) -> Result { - self.expect_without_advance(Kind::Number)?; - if !self.cur().value.is_int() { - Err(diagnostics::DisallowedFloat(self.cur().value.as_i32().unwrap(), self.pos()))? + pub fn expect_number_gte(&mut self, min: f32) -> Result { + match self.cur() { + Token::Number(n, _) => { + if n < min { + Err(diagnostics::NumberTooSmall(min, self.span()))? + } + self.advance(); + Ok(n) + } + token => Err(diagnostics::ExpectedNumber(token, self.span()))?, } - let n = self.cur().value.as_i32().unwrap(); - self.advance(); - Ok(n) - } - - #[inline] - pub(crate) fn expect_percentage(&mut self) -> Result { - let n = self.expect_without_advance(Kind::Percentage)?.value.as_f32().unwrap(); - self.advance(); - Ok(n) } #[inline] - pub(crate) fn expect_percentage_gte(&mut self, min: f32) -> Result { - let n = self.expect_without_advance(Kind::Percentage)?.value.as_f32().unwrap(); - if n < min { - Err(diagnostics::NumberTooSmall(min, self.pos()))? + pub fn expect_number_in_range(&mut self, range: Range) -> Result { + match self.cur() { + Token::Number(n, _) => { + if !range.contains(&n) { + Err(diagnostics::NumberOutOfBounds(range.start, range.end, self.span()))? + } + self.advance(); + Ok(n) + } + token => Err(diagnostics::ExpectedNumber(token, self.span()))?, } - self.advance(); - Ok(n) - } - - #[inline] - pub(crate) fn expect_dimension(&mut self) -> Result<(f32, Atom)> { - let value = &self.expect_without_advance(Kind::Dimension)?.value; - let (n, atom) = (value.as_f32().unwrap(), value.as_atom_lower().unwrap()); - self.advance(); - Ok((n, atom)) } #[inline] - pub(crate) fn expect_dimension_gte(&mut self, min: f32) -> Result<(f32, Atom)> { - let value = &self.expect_without_advance(Kind::Dimension)?.value; - let (n, atom) = (value.as_f32().unwrap(), value.as_atom_lower().unwrap()); - if n < min { - Err(diagnostics::NumberTooSmall(min, self.pos()))? + pub fn expect_int(&mut self) -> Result { + match self.cur() { + Token::Number(n, ty) => { + if !ty.is_int() { + Err(diagnostics::ExpectedInt(n, self.span()))? + } + self.advance(); + Ok(n as i32) + } + token => Err(diagnostics::ExpectedNumber(token, self.span()))?, } - self.advance(); - Ok((n, atom)) } #[inline] - pub(crate) fn expect_dimension_in_range(&mut self, range: Range) -> Result<(f32, Atom)> { - let value = &self.expect_without_advance(Kind::Dimension)?.value; - let (n, atom) = (value.as_f32().unwrap(), value.as_atom_lower().unwrap()); - if !range.contains(&n) { - Err(diagnostics::NumberOutOfBounds(range.start, range.end, self.pos()))? + pub fn expect_dimension_gte(&mut self, min: f32) -> Result<(f32, Atom)> { + match self.cur() { + Token::Dimension(n, atom, _) => { + if n < min { + Err(diagnostics::NumberTooSmall(min, self.span()))? + } + self.advance(); + Ok((n, atom)) + } + token => Err(diagnostics::ExpectedDimension(token, self.span()))?, } - self.advance(); - Ok((n, atom)) } #[inline] - pub(crate) fn expect_without_advance(&mut self, kind: Kind) -> Result<&Token> { - if !self.at(kind) { - let range = self.pos(); - Err::<(), Error>(diagnostics::ExpectedToken(kind, self.cur().kind, range).into())?; + pub fn expect_dimension_in_range(&mut self, range: Range) -> Result<(f32, Atom)> { + match self.cur() { + Token::Dimension(n, atom, _) => { + if !range.contains(&n) { + Err(diagnostics::NumberOutOfBounds(range.start, range.end, self.span()))? + } + self.advance(); + Ok((n, atom)) + } + token => Err(diagnostics::ExpectedDimension(token, self.span()))?, } - Ok(self.cur()) } #[inline] - pub(crate) fn peek_including_trivia(&mut self) -> &Token { + pub fn peek(&mut self) -> &Token { self.lexer.lookahead(1) } - pub(crate) fn peek(&mut self) -> &Token { - let mut i: u8 = 0; - loop { - i += 1; - if !self.lexer.lookahead(i).is_trivia() { - return self.lexer.lookahead(i); - } - } - } - #[inline] - pub(crate) fn next_token_include_comments(&mut self) { - self.token = self.lexer.next_token(); + pub fn advance_including_whitespace_and_comments(&mut self) { + self.prev_pos = self.lexer.pos(); + self.token = self.lexer.advance_including_whitespace_and_comments(); } - pub(crate) fn next_token(&mut self) { - loop { - let token = self.lexer.next_token(); - if token.kind != Kind::Comment { - self.token = token; - return; - } - } - } - - pub(crate) fn advance(&mut self) { - loop { - let token = self.lexer.next_token(); - if !token.is_trivia() { - self.token = token; - return; - } - } + #[inline] + pub fn advance_including_whitespace(&mut self) { + self.prev_pos = self.lexer.pos(); + self.token = self.lexer.advance_including_whitespace(); } #[inline] - pub(crate) fn skip_trivia(&mut self) { - if self.cur().is_trivia() { - self.advance(); - } + pub fn advance(&mut self) -> Span { + let span = self.span(); + self.prev_pos = span.end; + self.token = self.lexer.advance(); + span } - pub(crate) fn rewind(&mut self, checkpoint: ParserCheckpoint<'a>) { - let ParserCheckpoint { lexer, token, warnings_pos, errors_pos } = checkpoint; + pub fn rewind(&mut self, checkpoint: ParserCheckpoint<'a>) { + let ParserCheckpoint { lexer, prev_pos, token, warnings_pos, errors_pos } = checkpoint; self.lexer.rewind(lexer); self.token = token; + self.prev_pos = prev_pos; self.warnings.truncate(warnings_pos); self.errors.truncate(errors_pos); } - pub(crate) fn checkpoint(&self) -> ParserCheckpoint<'a> { + pub fn checkpoint(&self) -> ParserCheckpoint<'a> { ParserCheckpoint { lexer: self.lexer.checkpoint(), + prev_pos: self.prev_pos, token: self.token.clone(), warnings_pos: self.warnings.len(), errors_pos: self.errors.len(), diff --git a/crates/hdx_parser/src/diagnostics.rs b/crates/hdx_parser/src/diagnostics.rs index 6528657a..9c1575e7 100644 --- a/crates/hdx_parser/src/diagnostics.rs +++ b/crates/hdx_parser/src/diagnostics.rs @@ -1,16 +1,42 @@ +use hdx_atom::Atom; +use hdx_lexer::Token; use miette::{self, Diagnostic}; use thiserror::{self, Error}; -use crate::{Atom, Span, Token}; +use crate::span::Span; #[derive(Debug, Error, Diagnostic)] -#[error("The token as {0} cannot yet be parsed by the parser :(")] +#[error("The token at {0} cannot yet be parsed by the parser :(")] #[diagnostic( help("This feature needs to be implemented within hdx. This file won't parse without it."), code(hdx_parser::Unimplemented) )] pub struct Unimplemented(#[label("Didn't recognise this bit")] pub Span); +#[derive(Debug, Error, Diagnostic)] +#[error("This at-rule mut not have a 'prelude'.")] +#[diagnostic( + help("The 'prelude' is the bit between the @keyword and the {{"), + code(hdx_parser::DisllowedAtRulePrelude) +)] +pub struct DisallowedAtRulePrelude(#[label("Remove this part")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("This at-rule must not have a 'block'.")] +#[diagnostic( + help("The 'block' is the bit between the {{ and }}"), + code(hdx_parser::DisllowedAtRuleBlock) +)] +pub struct DisallowedAtRuleBlock(#[label("Remove this part")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("This at-rule must have a 'block'.")] +#[diagnostic( + help("The 'block' is the bit between the {{ and }}"), + code(hdx_parser::MissingAtRuleBlock) +)] +pub struct MissingAtRuleBlock(#[label("Add {{}} here")] pub Span); + #[derive(Debug, Error, Diagnostic)] #[error("This declaration wasn't understood, and so was disregarded.")] #[diagnostic( @@ -29,6 +55,15 @@ pub struct Unexpected(pub Token, #[label("This wasn't expected here")] pub Span) #[diagnostic(help("Try removing the word here."), code(hdx_parser::UnexpectedIdent))] pub struct UnexpectedIdent(pub Atom, #[label("??")] pub Span); +#[derive(Debug, Error, Diagnostic)] +#[error("Unexpected identifier '{0}'. '{0}' isn't allowed here, but '{1}' is.")] +#[diagnostic(help("Try changing this to '{1}'"), code(hdx_parser::UnexpectedIdentSuggest))] +pub struct UnexpectedIdentSuggest( + pub Atom, + pub Atom, + #[label("This keyword is not allowed here")] pub Span, +); + #[derive(Debug, Error, Diagnostic)] #[error("Unexpected duplicate '{0}'")] #[diagnostic(help("Try removing the word here."), code(hdx_parser::UnexpectedDuplicateIdent))] @@ -122,20 +157,55 @@ pub struct ExpectedEnd(#[label("All of this extra content was ignored.")] pub Sp #[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedToken))] pub struct ExpectedToken(pub Token, pub Token, #[label("`{0}` expected")] pub Span); +#[derive(Debug, Error, Diagnostic)] +#[error("Expected a dimension but found `{1}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedDimension))] +pub struct ExpectedDimension(pub Token, #[label("dimension expected")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected an identifier but found `{0}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedIdent))] +pub struct ExpectedIdent(pub Token, #[label("This should be `{0}`")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected an identifier but not `{0}`")] +#[diagnostic(help("This is wrong. Maybe it is misspelled?"), code(hdx_parser::ExpectedOtherIdent))] +pub struct ExpectedOtherIdent(pub Atom, #[label("This cannot be `{0}`")] pub Span); + #[derive(Debug, Error, Diagnostic)] #[error("Expected the identifier `{0}` but found `{1}`")] -#[diagnostic(help("Try changing `{1}` to `{0}`."), code(hdx_parser::ExpectedIdent))] -pub struct ExpectedIdent(pub Atom, pub Atom, #[label("This should be `{0}`")] pub Span); +#[diagnostic(help("Try changing `{1}` to `{0}`."), code(hdx_parser::ExpectedIdentOf))] +pub struct ExpectedIdentOf(pub Atom, pub Atom, #[label("This should be `{0}`")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected a function but found `{0}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedFunction))] +pub struct ExpectedFunction(pub Token, #[label("This token")] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("Expected to see {0}() but saw {1}()")] -#[diagnostic(help("Try changing the {1}() to {0}()"), code(hdx_parser::ExpectedFunction))] -pub struct ExpectedFunction(pub Atom, pub Atom, #[label("This funtion")] pub Span); +#[diagnostic(help("Try changing the {1}() to {0}()"), code(hdx_parser::ExpectedFunctionOf))] +pub struct ExpectedFunctionOf(pub Atom, pub Atom, #[label("This function")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected an @ keyword but saw `{0}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedAtKeyword))] +pub struct ExpectedAtKeyword(pub Token, #[label("This at-keyword")] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("Expected to see @{0} but saw @{1}")] -#[diagnostic(help("Try changing the @{1} to @{0}"), code(hdx_parser::ExpectedAtKeyword))] -pub struct ExpectedAtKeyword(pub Atom, pub Atom, #[label("This at-keyword")] pub Span); +#[diagnostic(help("Try changing the @{1} to @{0}"), code(hdx_parser::ExpectedAtKeywordOf))] +pub struct ExpectedAtKeywordOf(pub Atom, pub Atom, #[label("This at-keyword")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected a delimiter but saw `{0}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedDelim))] +pub struct ExpectedDelim(pub Token, #[label("This at-keyword")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected to see {0} but saw {1}")] +#[diagnostic(help("Try changing the {1} to {0}"), code(hdx_parser::ExpectedDelimOf))] +pub struct ExpectedDelimOf(pub char, pub char, #[label("This delimiter")] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("Unexpected trailing `{0}`")] @@ -194,9 +264,19 @@ pub struct DisallowedValueWithoutDimension(pub Atom, #[label("This value")] pub pub struct DisallowedMathFunction(pub Atom, #[label("This value")] pub Span); #[derive(Debug, Error, Diagnostic)] -#[error("This value isn't allowed to have a fraction, it must be a whole number (integer).")] -#[diagnostic(help("Try using {0} instead"), code(hdx_parser::DisallowedFloat))] -pub struct DisallowedFloat(pub i32, #[label("This value")] pub Span); +#[error("Expected a number but saw `{0}`")] +#[diagnostic(help("This is not correct CSS syntax."), code(hdx_parser::ExpectedNumber))] +pub struct ExpectedNumber(pub Token, #[label("This value")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected a signed number but saw `{0}`")] +#[diagnostic(help("This number needs a + or a -."), code(hdx_parser::ExpectedSign))] +pub struct ExpectedSign(pub f32, #[label("Add a + here")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Expected an unsigned number but saw `{0}`")] +#[diagnostic(help("This number cannot have a + or a -."), code(hdx_parser::ExpectedUnsigned))] +pub struct ExpectedUnsigned(pub f32, #[label("Remove the sign")] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("This number is out of bounds.")] @@ -206,7 +286,27 @@ pub struct DisallowedFloat(pub i32, #[label("This value")] pub Span); )] pub struct NumberOutOfBounds(pub f32, pub f32, #[label("This value")] pub Span); +#[derive(Debug, Error, Diagnostic)] +#[error("This number cannot be negative.")] +#[diagnostic(help("This needs to be greater or equal to 0"), code(hdx_parser::NumberNotNegative))] +pub struct NumberNotNegative(pub f32, #[label("This value")] pub Span); + #[derive(Debug, Error, Diagnostic)] #[error("This number is too small.")] #[diagnostic(help("This needs to be larger than {0}"), code(hdx_parser::NumberTooSmall))] pub struct NumberTooSmall(pub f32, #[label("This value")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("This value isn't allowed to have a fraction, it must be a whole number (integer).")] +#[diagnostic(help("Try using {0} instead"), code(hdx_parser::ExpectedInt))] +pub struct ExpectedInt(pub f32, #[label("This value")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("This value must have a fraction, it must be float.")] +#[diagnostic(help("Try using {0} instead"), code(hdx_parser::ExpectedFloat))] +pub struct ExpectedFloat(pub f32, #[label("This value")] pub Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Display 'list-item' can only be combined with 'flow' or 'flow-root'")] +#[diagnostic(help("{0} is not valid in combination with list-item, try changing it to flow or flow-root"), code(hdx_parser::DisplayHasInvalidListItemCombo))] +pub struct DisplayHasInvalidListItemCombo(pub Atom, pub Span); diff --git a/crates/hdx_parser/src/lib.rs b/crates/hdx_parser/src/lib.rs index fdbf5f87..49498951 100644 --- a/crates/hdx_parser/src/lib.rs +++ b/crates/hdx_parser/src/lib.rs @@ -1,172 +1,13 @@ -#![cfg_attr(not(target_arch = "wasm32"), feature(portable_simd))] -#![feature(slice_as_chunks)] - -mod css; mod cursor; -mod diagnostics; +pub mod diagnostics; +mod macros; +mod parser; +mod span; +mod traits; -pub use hdx_ast::{css::stylesheet::CSSStyleSheet, Spanned, Unit}; -pub use hdx_atom::{atom, Atom, Atomizable}; -pub use hdx_lexer::{Kind, Lexer, PairWise, Span, Token}; pub use miette::{Error, Result}; -pub use oxc_allocator::Allocator; -pub(crate) use oxc_allocator::Vec; - -pub trait Parse<'a>: Sized { - fn parse(parser: &mut Parser<'a>) -> Result>; - - fn spanned(self, span: Span) -> Spanned { - Spanned { node: self, span } - } -} - -#[derive(Debug, Default)] -pub enum SourceType { - #[default] - CSS, - SCSS, -} - -pub struct Parser<'a> { - lexer: Lexer<'a>, - - pub source_type: SourceType, - - sloppy: bool, - - warnings: std::vec::Vec, - - errors: std::vec::Vec, - - token: Token, - - prev_span: Span, - - allocator: &'a Allocator, -} - -#[derive(Debug, Default)] -pub struct ParserOptions { - source_type: SourceType, - sloppy: bool, -} - -pub struct ParserReturn { - pub output: Option, - pub errors: std::vec::Vec, - pub warnings: std::vec::Vec, - pub panicked: bool, -} - -impl<'a> Parser<'a> { - /// Create a new parser - pub fn new(allocator: &'a Allocator, source_text: &'a str, options: ParserOptions) -> Self { - Self { - lexer: Lexer::new(allocator, source_text), - source_type: options.source_type, - sloppy: options.sloppy, - warnings: std::vec::Vec::new(), - errors: std::vec::Vec::new(), - token: Token::default(), - prev_span: Span::dummy(), - allocator, - // state: ParserState::new(allocator), - // ctx: Self::default_context(source_type), - } - } - - #[inline] - pub fn new_vec(&self) -> crate::Vec<'a, T> { - crate::Vec::new_in(self.allocator) - } - - #[inline] - pub fn boxup(&self, value: T) -> oxc_allocator::Box<'a, T> { - oxc_allocator::Box(self.allocator.alloc(value)) - } - - pub fn parse(self) -> ParserReturn>> { - self.parse_entirely_with::>() - } - - pub fn parse_entirely_with>(mut self) -> ParserReturn> { - self.advance(); - let (output, panicked) = match T::parse(&mut self) { - Ok(output) => (Some(output), false), - Err(error) => { - self.errors.push(error); - (None, true) - } - }; - self.skip_trivia(); - if !self.at(Kind::Eof) { - let span = self.cur().span; - loop { - if self.at(Kind::Eof) { - break; - } - self.advance() - } - self.errors.push(diagnostics::ExpectedEnd(span.until(self.cur().span)).into()); - } - ParserReturn { output, warnings: self.warnings, errors: self.errors, panicked } - } - - pub fn parse_with>(mut self) -> ParserReturn> { - self.advance(); - let (output, panicked) = match T::parse(&mut self) { - Ok(output) => (Some(output), false), - Err(error) => { - self.errors.push(error); - (None, true) - } - }; - ParserReturn { output, warnings: self.warnings, errors: self.errors, panicked } - } - - fn parse_comma_list_of>(&mut self) -> Result>> { - let mut vec = self.new_vec(); - let mut last_kind; - loop { - vec.push(T::parse(self)?); - match self.cur().kind { - Kind::Comma => { - self.expect(Kind::Comma)?; - last_kind = Kind::Comma; - } - k => { - last_kind = k; - break; - } - } - } - if last_kind == Kind::Comma { - let warn: Error = - diagnostics::WarnTrailing(self.cur().kind, Span::from(self.pos() - 1, self.pos())) - .into(); - if !self.sloppy { - Err(warn)?; - } - } - Ok(vec) - } -} - -#[cfg(test)] -mod test { - use oxc_allocator::Allocator; - - use crate::{Parser, ParserOptions}; - - #[test] - fn smoke_basic_error() { - let allocator = Allocator::default(); - let parser = Parser::new(&allocator, "c", ParserOptions::default()); - let parser_return = parser.parse(); - assert_eq!(parser_return.warnings.len(), 1); - assert_eq!(parser_return.errors.len(), 1); - assert!(parser_return.output.is_none()); - println!("{:?}", parser_return.warnings.get(0).unwrap()); - println!("{:?}", parser_return.errors.get(0).unwrap()); - } -} +pub use oxc_allocator::{Box, Vec}; +pub use parser::*; +pub use span::*; +pub use macros::*; +pub use traits::*; diff --git a/crates/hdx_parser/src/macros.rs b/crates/hdx_parser/src/macros.rs new file mode 100644 index 00000000..ef5aeb6d --- /dev/null +++ b/crates/hdx_parser/src/macros.rs @@ -0,0 +1,38 @@ +#[macro_export] +macro_rules! unexpected { + ($parser: ident, $token: ident) => { + Err($crate::diagnostics::Unexpected($token, $parser.span()))? + }; + ($parser: ident) => { + Err($crate::diagnostics::Unexpected($parser.cur(), $parser.span()))? + }; +} + +#[macro_export] +macro_rules! unexpected_ident { + ($parser: ident, $atom: ident) => { + Err($crate::diagnostics::UnexpectedIdent($atom, $parser.span()))? + }; +} + +#[macro_export] +macro_rules! expect { + ($parser: ident, $pattern:pat $(if $guard:expr)? $(,)?) => { + match $parser.cur() { + $pattern $(if $guard)? => {}, + token => unexpected!($parser, token), + } + }; +} + +#[macro_export] +macro_rules! discard { + ($parser: ident, $pattern:pat $(if $guard:expr)? $(,)?) => { + match $parser.cur() { + $pattern $(if $guard)? => { + $parser.advance(); + }, + _ => {}, + } + }; +} diff --git a/crates/hdx_parser/src/parser.rs b/crates/hdx_parser/src/parser.rs new file mode 100644 index 00000000..1de07b4d --- /dev/null +++ b/crates/hdx_parser/src/parser.rs @@ -0,0 +1,168 @@ +use bitmask_enum::bitmask; +use hdx_lexer::{Lexer, Token}; +use miette::{Error, Result}; +use oxc_allocator::Allocator; + +use crate::{diagnostics, span::Spanned, traits::Parse}; + +pub struct Parser<'a> { + pub(crate) lexer: Lexer<'a>, + + pub(crate) features: Features, + + pub(crate) warnings: std::vec::Vec, + + pub(crate) errors: std::vec::Vec, + + pub(crate) token: Token, + + pub(crate) state: State, + + pub(crate) prev_pos: u32, + + pub(crate) allocator: &'a Allocator, +} + +#[bitmask(u8)] +pub enum Features { + Sloppy = 0x01, +} + +impl Default for Features { + fn default() -> Self { + Self::none() + } +} + +#[bitmask(u8)] +pub enum State { + Nested = 0x01, + + // Stop Tokens for some algorithms + StopOnSemicolon = 0xF0, + StopOnComma = 0xF1, +} + +pub struct ParserReturn { + pub output: Option, + pub errors: std::vec::Vec, + pub warnings: std::vec::Vec, + pub panicked: bool, +} + +impl<'a> Parser<'a> { + /// Create a new parser + pub fn new(allocator: &'a Allocator, source_text: &'a str, features: Features) -> Self { + Self { + lexer: Lexer::new(allocator, source_text), + features, + warnings: std::vec::Vec::new(), + errors: std::vec::Vec::new(), + token: Token::default(), + state: State::none(), + prev_pos: 0, + allocator, + } + } + + #[inline] + pub fn new_vec(&self) -> crate::Vec<'a, T> { + crate::Vec::new_in(self.allocator) + } + + #[inline] + pub fn boxup(&self, value: T) -> oxc_allocator::Box<'a, T> { + oxc_allocator::Box(self.allocator.alloc(value)) + } + + #[inline] + fn enabled(&self, other: Features) -> bool { + self.features.contains(other) + } + + #[inline] + pub fn is(&self, state: State) -> bool { + self.state.contains(state) + } + + #[inline] + pub fn set(&mut self, state: State) { + self.state |= state; + } + + #[inline] + pub fn unset(&mut self, state: State) { + self.state &= !state; + } + + #[inline] + pub fn with_state(&mut self, state: State, call: F) -> T where F: FnOnce(&mut Parser) -> T { + self.set(state); + let ret = call(self); + self.unset(state); + ret + } + + pub fn parse_entirely_with>(mut self) -> ParserReturn> { + self.advance(); + let (output, panicked) = match T::parse(&mut self) { + Ok(output) => (Some(output), false), + Err(error) => { + self.errors.push(error); + (None, true) + } + }; + if !matches!(self.cur(), Token::Eof) { + let span = self.span(); + loop { + self.advance(); + if matches!(self.cur(), Token::Eof) { + break; + } + } + self.errors.push(diagnostics::ExpectedEnd(span.end(self.pos())).into()); + } + ParserReturn { output, warnings: self.warnings, errors: self.errors, panicked } + } + + pub fn parse_with>(mut self) -> ParserReturn> { + self.advance(); + let (output, panicked) = match T::parse(&mut self) { + Ok(output) => (Some(output), false), + Err(error) => { + self.errors.push(error); + (None, true) + } + }; + ParserReturn { output, warnings: self.warnings, errors: self.errors, panicked } + } + + pub fn parse_comma_list_of>(&mut self) -> Result>> { + let mut vec = self.new_vec(); + let mut last_kind; + loop { + vec.push(T::parse(self)?); + match self.cur() { + Token::Comma => { + self.advance(); + last_kind = Token::Comma; + } + t => { + last_kind = t; + break; + } + } + } + if matches!(last_kind, Token::Comma) { + let warn: Error = diagnostics::WarnTrailing(self.cur(), self.span()).into(); + if !self.enabled(Features::Sloppy) { + Err(warn)?; + } + } + Ok(vec) + } + + pub fn warn(&mut self, error: Error) { + self.warnings.push(error); + } +} diff --git a/crates/hdx_ast/src/span.rs b/crates/hdx_parser/src/span.rs similarity index 55% rename from crates/hdx_ast/src/span.rs rename to crates/hdx_parser/src/span.rs index 4c76dd22..76d04f60 100644 --- a/crates/hdx_ast/src/span.rs +++ b/crates/hdx_parser/src/span.rs @@ -1,5 +1,6 @@ use std::{fmt::Display, hash::Hash}; +use hdx_atom::{Atom, Atomizable}; use miette::{SourceOffset, SourceSpan}; #[cfg(feature = "serde")] use serde::Serialize; @@ -17,6 +18,11 @@ impl Span { Self { start, end } } + #[inline] + pub fn end(self, end: u32) -> Self { + Self { start: self.start, end } + } + pub fn dummy() -> Self { Self::new(u32::default(), u32::default()) } @@ -33,17 +39,6 @@ impl Span { pub fn source_text<'a>(&self, source_text: &'a str) -> &'a str { &source_text[self.start as usize..self.end as usize] } - - /// Returns a `Span` from the beginning of `self` until the beginning of `end`. - /// - /// ```text - /// ____ ___ - /// self lorem ipsum end - /// ^^^^^^^^^^^^^^^^^ - /// ``` - pub fn until(&self, span: Self) -> Self { - Self { start: self.start, end: span.start } - } } impl Display for Span { @@ -54,6 +49,36 @@ impl Display for Span { impl From for SourceSpan { fn from(val: Span) -> Self { - Self::new(SourceOffset::from(val.start as usize), SourceOffset::from(val.size() as usize)) + Self::new(SourceOffset::from(val.start as usize), val.size() as usize) + } +} + +#[derive(Debug, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize), serde())] +pub struct Spanned { + pub node: T, + #[cfg_attr(feature = "serde", serde(flatten))] + pub span: Span, +} + +impl Spanned { + pub fn dummy(node: T) -> Self { + Self { node, span: Span::dummy() } + } +} + +impl Atomizable for Spanned { + fn from_atom(atom: Atom) -> Option { + T::from_atom(atom).map(|node| Self { node, span: Span::dummy() }) + } + + fn to_atom(&self) -> Atom { + self.node.to_atom() + } +} + +impl Default for Spanned { + fn default() -> Self { + Self::dummy(T::default()) } } diff --git a/crates/hdx_parser/src/traits.rs b/crates/hdx_parser/src/traits.rs new file mode 100644 index 00000000..1af48375 --- /dev/null +++ b/crates/hdx_parser/src/traits.rs @@ -0,0 +1,117 @@ +use hdx_atom::Atom; +use hdx_lexer::Token; + +use crate::{ + diagnostics, discard, expect, + parser::Parser, + span::{Span, Spanned}, + unexpected, Result, + Vec +}; + +pub trait Parse<'a>: Sized { + fn parse(parser: &mut Parser<'a>) -> Result>; + + fn spanned(self, span: Span) -> Spanned { + Spanned { node: self, span } + } +} + +// An AtRule represents a block or statement with an @keyword in the leading +// position, such as @media, @charset, @import and so-on. +pub trait AtRule<'a>: Sized + Parse<'a> { + type Prelude: Parse<'a>; + type Block: Parse<'a>; + + // AtRules can have an optional prelude (e.g. @supoports requires one, + // @starting-style must not have one, and in @page it is optional). Consequently + // parse_prelude returns an Option, and rules that either require can check + // in parse() or override parse_prelude() to err. + fn parse_prelude(parser: &mut Parser<'a>) -> Result>> { + // Prelude lands just after the at-keyword token. + match parser.cur() { + Token::LeftCurly | Token::Semicolon | Token::Eof => Ok(None), + _ => Ok(Some(Self::Prelude::parse(parser)?)), + } + } + + // AtRules can have an optional block (e.g. @charset, @import must not have + // one). The default parse_prelude returns an Option, and rules that either + // require can check in parse() or override parse_prelude() to err. + fn parse_block(parser: &mut Parser<'a>) -> Result>> { + match parser.cur() { + Token::Semicolon | Token::Eof => Ok(None), + Token::LeftCurly => Ok(Some(Self::Block::parse(parser)?)), + token => unexpected!(parser, token), + } + } + + // https://drafts.csswg.org/css-syntax-3/#consume-an-at-rule + fn parse_at_rule( + parser: &mut Parser<'a>, + ) -> Result<(Option>, Option>)> { + match parser.cur() { + Token::AtKeyword(_) => { + parser.advance(); + let prelude = Self::parse_prelude(parser)?; + let block = Self::parse_block(parser)?; + Ok((prelude, block)) + } + token => unexpected!(parser, token), + } + } +} + +pub trait QualifiedRule<'a>: Sized + Parse<'a> { + type Prelude: Parse<'a>; + type Block: Parse<'a>; + + // QualifiedRules must have a prelude, consequently parse_prelude must be + // implemented. + // parse_prelude is called right away, so could start with any token. + fn parse_prelude(parser: &mut Parser<'a>) -> Result> { + Self::Prelude::parse(parser) + } + + // QualifiedRules must have a block, consequently parse_prelude must be + // implemented. + // parse_block will always start with a {-token. + fn parse_block(parser: &mut Parser<'a>) -> Result> { + Self::Block::parse(parser) + } + + // https://drafts.csswg.org/css-syntax-3/#consume-a-qualified-rule + fn parse_qualified_rule(parser: &mut Parser<'a>) -> Result<(Spanned, Spanned)> { + let prelude = Self::parse_prelude(parser)?; + expect!(parser, Token::LeftCurly); + Ok((prelude, Self::parse_block(parser)?)) + } +} + +pub trait DeclarationRuleList<'a>: Sized + Parse<'a> { + type Declaration: Parse<'a>; + type AtRule: AtRule<'a> + Parse<'a>; + + // https://drafts.csswg.org/css-syntax-3/#consume-a-qualified-rule + fn parse_declaration_rule_list(parser: &mut Parser<'a>) -> Result<(Vec<'a, Spanned>, Vec<'a, Spanned>)> { + expect!(parser, Token::LeftCurly); + parser.advance(); + let mut declarations = parser.new_vec(); + let mut rules = parser.new_vec(); + loop { + match parser.cur() { + Token::AtKeyword(_) => { + rules.push(Self::AtRule::parse(parser)?); + }, + Token::Ident(_) => { + declarations.push(Self::Declaration::parse(parser)?); + }, + Token::RightCurly => { + parser.advance(); + return Ok((declarations, rules)); + } + token => unexpected!(parser, token) + } + } + } +} diff --git a/crates/hdx_wasm/src/lib.rs b/crates/hdx_wasm/src/lib.rs index 3a320718..6151eaea 100644 --- a/crates/hdx_wasm/src/lib.rs +++ b/crates/hdx_wasm/src/lib.rs @@ -1,5 +1,6 @@ -use hdx_lexer::{Kind, Lexer}; -use hdx_parser::{Parser, ParserOptions}; +use hdx_ast::css::StyleSheet; +use hdx_lexer::{Token, Lexer}; +use hdx_parser::{Parser, Features}; use hdx_writer::{BaseCssWriter, WriteCss}; use miette::{GraphicalReportHandler, GraphicalTheme, NamedSource}; use oxc_allocator::Allocator; @@ -19,8 +20,9 @@ pub fn lex(source_text: String) -> Result { let serializer = serde_wasm_bindgen::Serializer::json_compatible(); let mut tokens = vec![]; loop { - tokens.push(lex.next_token()); - if tokens.last().unwrap().kind == Kind::Eof { + let token = lex.advance(); + tokens.push(token.clone()); + if matches!(token, Token::Eof) { break; } } @@ -30,7 +32,8 @@ pub fn lex(source_text: String) -> Result { #[wasm_bindgen] pub fn parse(source_text: String) -> Result { let allocator = Allocator::default(); - let result = Parser::new(&allocator, source_text.as_str(), ParserOptions::default()).parse(); + let result = Parser::new(&allocator, source_text.as_str(), Features::default()) + .parse_with::(); let serializer = serde_wasm_bindgen::Serializer::json_compatible(); let diagnostics = result .errors @@ -60,7 +63,8 @@ pub fn parse(source_text: String) -> Result Result { let allocator = Allocator::default(); - let result = Parser::new(&allocator, source_text.as_str(), ParserOptions::default()).parse(); + let result = Parser::new(&allocator, source_text.as_str(), Features::default()) + .parse_with::(); if !result.errors.is_empty() { return Err(serde_wasm_bindgen::Error::new("Parse error")); } @@ -73,7 +77,8 @@ pub fn minify(source_text: String) -> Result #[wasm_bindgen] pub fn parse_error_report(source_text: String) -> String { let allocator = Allocator::default(); - let result = Parser::new(&allocator, source_text.as_str(), ParserOptions::default()).parse(); + let result = Parser::new(&allocator, source_text.as_str(), Features::default()) + .parse_with::(); let handler = GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor()); let mut report = String::new(); for err in result.errors { diff --git a/crates/hdx_writer/Cargo.toml b/crates/hdx_writer/Cargo.toml index bfa576f4..8705b0f6 100644 --- a/crates/hdx_writer/Cargo.toml +++ b/crates/hdx_writer/Cargo.toml @@ -11,8 +11,8 @@ repository.workspace = true [dependencies] hdx_lexer = { workspace = true } -hdx_ast = { workspace = true } hdx_atom = { workspace = true } +hdx_parser = { workspace = true } hdx_syntax = { workspace = true } oxc_allocator = { workspace = true } diff --git a/crates/hdx_writer/src/css/mod.rs b/crates/hdx_writer/src/css/mod.rs deleted file mode 100644 index 81699e7a..00000000 --- a/crates/hdx_writer/src/css/mod.rs +++ /dev/null @@ -1,388 +0,0 @@ -mod properties; -mod selector; -mod values; - -use std::{fmt::Result, ops::Deref}; - -use hdx_ast::{ - css::{ - component_values::{ComponentValue, Function, SimpleBlock}, - rules::{CSSCharsetRule, CSSMarginRule, CSSPageRule, PageSelector, PageSelectorList}, - stylesheet::{CSSRule, CSSStyleRule, CSSStyleSheet}, - unknown::{UnknownAtRule, UnknownDeclaration, UnknownPrelude, UnknownRule}, - values::ValueLike, - }, - Spanned, -}; -use hdx_atom::Atomizable; -use hdx_lexer::{Kind, PairWise, Token}; -use oxc_allocator::Box; - -use crate::{CssWriter, WriteCss}; - -impl<'a> WriteCss<'a> for CSSCharsetRule { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str("@charset \"")?; - sink.write_str(self.encoding.as_ref())?; - sink.write_str("\";")?; - Ok(()) - } -} - -impl<'a> WriteCss<'a> for CSSStyleSheet<'a> { - fn write_css(&self, sink: &mut W) -> Result { - for rule in &self.rules { - rule.write_css(sink)?; - sink.write_newline()?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for CSSRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Style(rule) => rule.write_css(sink), - Self::Charset(rule) => rule.write_css(sink), - Self::Page(rule) => rule.write_css(sink), - Self::UnknownAt(rule) => rule.write_css(sink), - Self::Unknown(rule) => rule.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for CSSStyleRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - self.selectors.write_css(sink)?; - sink.write_trivia_char(' ')?; - sink.write_char('{')?; - sink.indent(); - sink.write_newline()?; - let mut iter = self.declarations.deref().iter().peekable(); - while let Some(decl) = iter.next() { - sink.write_indent()?; - decl.write_css(sink)?; - if iter.peek().is_none() { - sink.write_trivia_char(';')?; - } else { - sink.write_char(';')?; - } - sink.write_newline()?; - } - sink.dedent(); - sink.write_indent()?; - sink.write_char('}')?; - Ok(()) - } -} - -impl<'a> WriteCss<'a> for CSSPageRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str("@page")?; - if self.selectors.node.children.len() > 0 { - sink.write_char(' ')?; - } - self.selectors.write_css(sink)?; - if self.selectors.node.children.len() > 0 { - sink.write_trivia_char(' ')?; - } - sink.write_char('{')?; - sink.indent(); - sink.write_newline()?; - let mut iter = self.declarations.iter().peekable(); - let mut rule_iter = self.rules.iter().peekable(); - while let Some(decl) = iter.next() { - decl.write_css(sink)?; - if iter.peek().is_none() && rule_iter.peek().is_none() { - sink.write_trivia_char(';')?; - } else { - sink.write_char(';')?; - } - sink.write_newline()?; - } - for rule in rule_iter { - sink.write_newline()?; - rule.write_css(sink)?; - sink.write_newline()?; - } - sink.dedent(); - sink.write_indent()?; - sink.write_char('}')?; - Ok(()) - } -} - -impl<'a> WriteCss<'a> for PageSelectorList<'a> { - fn write_css(&self, sink: &mut W) -> Result { - let mut iter = self.children.iter().peekable(); - while let Some(selector) = iter.next() { - selector.write_css(sink)?; - if iter.peek().is_some() { - sink.write_char(',')?; - sink.write_trivia_char(' ')?; - } - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for PageSelector<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Some(page_type) = &self.page_type { - sink.write_str(page_type.as_ref())?; - } - for pseudo in self.pseudos.iter() { - sink.write_char(':')?; - sink.write_str(pseudo.to_atom().as_ref())?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for CSSMarginRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_char('@')?; - sink.write_str(self.name.to_atom().as_ref())?; - sink.write_trivia_char(' ')?; - sink.write_char('{')?; - sink.indent(); - sink.write_newline()?; - let mut iter = self.declarations.iter().peekable(); - while let Some(decl) = iter.next() { - decl.write_css(sink)?; - if iter.peek().is_none() { - sink.write_trivia_char(';')?; - } else { - sink.write_char(';')?; - } - sink.write_newline()?; - } - sink.dedent(); - sink.write_indent()?; - sink.write_char('}')?; - Ok(()) - } -} - -impl<'a> WriteCss<'a> for UnknownAtRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str("@")?; - sink.write_str(self.name.as_ref())?; - if let Some(prelude) = &*self.prelude { - prelude.write_css(sink)?; - sink.write_trivia_char(' ')?; - } - sink.write_char('{')?; - sink.indent(); - sink.write_newline()?; - let mut iter = self.properties.iter().peekable(); - let mut rule_iter = self.rules.iter().peekable(); - while let Some(decl) = iter.next() { - decl.write_css(sink)?; - if iter.peek().is_none() && rule_iter.peek().is_none() { - sink.write_trivia_char(';')?; - } else { - sink.write_char(';')?; - } - sink.write_newline()?; - } - for rule in rule_iter { - sink.write_newline()?; - rule.write_css(sink)?; - sink.write_newline()?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for UnknownRule<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Some(prelude) = &*self.prelude { - prelude.write_css(sink)?; - sink.write_trivia_char(' ')?; - } - sink.write_char('{')?; - sink.indent(); - sink.write_newline()?; - let mut iter = self.properties.iter().peekable(); - let mut rule_iter = self.rules.iter().peekable(); - while let Some(decl) = iter.next() { - decl.write_css(sink)?; - if iter.peek().is_none() && rule_iter.peek().is_none() { - sink.write_trivia_char(';')?; - } else { - sink.write_char(';')?; - } - sink.write_newline()?; - } - for rule in rule_iter { - sink.write_newline()?; - rule.write_css(sink)?; - sink.write_newline()?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for UnknownPrelude<'a> { - fn write_css(&self, sink: &mut W) -> Result { - let mut iter = self.value.iter().peekable(); - while let Some(value) = iter.next() { - value.write_css(sink)?; - if iter.peek().is_some() { - sink.write_char(' ')?; - } - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for UnknownDeclaration<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str(self.name.as_ref())?; - sink.write_char(':')?; - sink.write_trivia_char(' ')?; - match &self.value_like { - Spanned { span: _, node: ValueLike::Color(color) } => color.write_css(sink)?, - Spanned { span: _, node: ValueLike::Length(length) } => length.write_css(sink)?, - Spanned { span: _, node: ValueLike::LengthPercentage(length) } => { - length.write_css(sink)? - } - Spanned { span: _, node: ValueLike::FontFamily(font) } => font.write_css(sink)?, - _ => { - let mut values = self.value.iter().peekable(); - while let Some(value) = values.next() { - value.write_css(sink)?; - if values.peek().is_some() { - sink.write_char(' ')?; - } - } - } - } - if self.important { - sink.write_trivia_char(' ')?; - sink.write_str("!important")?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for ComponentValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::SimpleBlock(b) => b.write_css(sink), - Self::Function(f) => f.write_css(sink), - Self::Token(t) => t.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for SimpleBlock<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self.pairwise { - PairWise::Square => sink.write_char('[')?, - PairWise::Curly => sink.write_char('{')?, - PairWise::Paren => sink.write_char('(')?, - } - for value in &*self.value { - value.write_css(sink)?; - } - match self.pairwise { - PairWise::Square => sink.write_char(']')?, - PairWise::Curly => sink.write_char('}')?, - PairWise::Paren => sink.write_char(')')?, - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for Function<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str(self.name.as_ref())?; - sink.write_char('(')?; - for value in &*self.value { - value.write_css(sink)?; - } - sink.write_char(')')?; - Ok(()) - } -} - -impl<'a> WriteCss<'a> for Token { - fn write_css(&self, sink: &mut W) -> Result { - match self.kind { - Kind::Ident => sink.write_str(self.value.as_atom().unwrap().as_ref())?, - Kind::AtKeyword => { - sink.write_char('@')?; - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - } - Kind::Hash => { - sink.write_char('#')?; - if self.escaped { - sink.write_char('\\')?; - } - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - } - Kind::BadString | Kind::String => { - if self.escaped { - sink.write_char('\\')?; - } - sink.write_char('"')?; - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - sink.write_char('"')?; - } - Kind::BadUrl | Kind::Url => { - sink.write_str("url(")?; - if self.escaped { - sink.write_char('\\')?; - } - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - sink.write_char(')')?; - } - Kind::Delim => { - sink.write_char(self.value.as_char().unwrap())?; - } - Kind::Number => sink.write_str(&format!("{}", self.value.as_f32().unwrap()))?, - Kind::Percentage => { - sink.write_str(&format!("{}", self.value.as_f32().unwrap()))?; - sink.write_char('%')?; - } - Kind::Dimension => { - sink.write_str(&format!("{}", self.value.as_f32().unwrap()))?; - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - } - Kind::Whitespace => sink.write_char(' ')?, - Kind::Cdo => sink.write_str("")?, - Kind::Colon => sink.write_char(':')?, - Kind::Semicolon => sink.write_char(';')?, - Kind::Comma => sink.write_char(',')?, - Kind::LeftSquare => sink.write_char('[')?, - Kind::RightSquare => sink.write_char(']')?, - Kind::LeftParen => sink.write_char('(')?, - Kind::RightParen => sink.write_char(')')?, - Kind::LeftCurly => sink.write_char('{')?, - Kind::RightCurly => sink.write_char('}')?, - Kind::Undetermined => {} - Kind::Comment => sink.write_trivia_str(self.value.as_atom().unwrap().as_ref())?, - Kind::Function => { - sink.write_str(self.value.as_atom().unwrap().as_ref())?; - sink.write_char('(')?; - } - Kind::Eof => {} - } - Ok(()) - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for Box<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - self.deref().write_css(sink) - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for Spanned { - fn write_css(&self, sink: &mut W) -> Result { - self.node.write_css(sink) - } -} diff --git a/crates/hdx_writer/src/css/properties.rs b/crates/hdx_writer/src/css/properties.rs deleted file mode 100644 index 3096534b..00000000 --- a/crates/hdx_writer/src/css/properties.rs +++ /dev/null @@ -1,1094 +0,0 @@ -use std::fmt::Result; - -use hdx_ast::{ - css::{properties::*, values::ValueLike}, - Spanned, -}; - -use crate::{CssWriter, WriteCss}; - -impl<'a> WriteCss<'a> for Todo { - fn write_css(&self, sink: &mut W) -> Result { - todo!("Cannot write out Todo values") - } -} - -impl<'a> WriteCss<'a> for Custom<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str(self.name.as_ref())?; - sink.write_char(':')?; - sink.write_trivia_char(' ')?; - match &self.value_like { - Spanned { span: _, node: ValueLike::Color(color) } => color.write_css(sink)?, - Spanned { span: _, node: ValueLike::Length(length) } => length.write_css(sink)?, - Spanned { span: _, node: ValueLike::LengthPercentage(length) } => { - length.write_css(sink)? - } - Spanned { span: _, node: ValueLike::FontFamily(font) } => font.write_css(sink)?, - _ => { - let mut values = self.value.iter().peekable(); - while let Some(value) = values.next() { - value.write_css(sink)?; - if values.peek().is_some() { - sink.write_char(' ')?; - } - } - } - } - if self.important { - sink.write_str("!important")?; - } - Ok(()) - } -} - -macro_rules! write_properties { - {$( $prop: ident, )+} => { - $( - impl<'a> WriteCss<'a> for $prop<'a> { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str(Self::name_as_atom().as_ref())?; - sink.write_char(':')?; - sink.write_trivia_char(' ')?; - self.value.write_css(sink)?; - if self.important { - sink.write_str("!important")?; - } - Ok(()) - } - } - - )+ - - impl<'a> WriteCss<'a> for Property<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - $(Property::$prop(value) => value.write_css(sink),)+ - Property::Custom(value) => value.write_css(sink), - Property::Unknown(value) => value.write_css(sink), - } - } - } - - } -} - -write_properties! { - // https://drafts.csswg.org/css-align-3/#property-index - AlignContent, - AlignItems, - AlignSelf, - ColumnGap, - Gap, - JustifyContent, - JustifyItems, - JustifySelf, - PlaceContent, - PlaceItems, - PlaceSelf, - RowGap, - - // https://drafts.csswg.org/css-anchor-position-1/#property-index - AnchorDefault, - AnchorPosition, - PositionFallback, - PositionFallbackBounds, - - // https://drafts.csswg.org/css-animations-1/#property-index - Animation, - AnimationDelay, - AnimationDirection, - // ! animation-duration redefined in css-animations-2 - AnimationFillMode, - AnimationIterationCount, - AnimationName, - AnimationPlayState, - AnimationTimingFunction, - - // https://drafts.csswg.org/css-animations-2/#property-index - AnimationDuration, - AnimationComposition, - AnimationTimeline, - - // https://drafts.csswg.org/css-backgrounds-3/#property-index - Background, - BackgroundAttachment, - // ! background-clip redefined in css-backgrounds-4 - BackgroundColor, - BackgroundImage, - BackgroundOrigin, - // ! background-position redefined in css-backgrounds-4 - BackgroundRepeat, - BackgroundSize, - Border, - BorderBottom, - BorderBottomColor, - BorderBottomLeftRadius, - BorderBottomRightRadius, - BorderBottomStyle, - BorderBottomWidth, - BorderColor, - BorderImage, - BorderImageOutset, - BorderImageRepeat, - BorderImageSlice, - BorderImageSource, - BorderImageWidth, - BorderLeft, - BorderLeftColor, - BorderLeftStyle, - BorderLeftWidth, - BorderRadius, - BorderRight, - BorderRightColor, - BorderRightStyle, - BorderRightWidth, - BorderStyle, - BorderTop, - BorderTopColor, - BorderTopLeftRadius, - BorderTopRightRadius, - BorderTopStyle, - BorderTopWidth, - BorderWidth, - BoxShadow, - - // https://drafts.csswg.org/css-backgrounds-4/#property-index - BackgroundClip, - BackgroundPosition, - BackgroundPositionBlock, - BackgroundPositionInline, - BackgroundPositionX, - BackgroundPositionY, - - - // https://drafts.csswg.org/css-box-3/#property-index - // ! margin redefined in css-box-4 - // ! margin-bottom redefined in css-box-4 - // ! margin-left redefined in css-box-4 - // ! margin-right redefined in css-box-4 - // ! margin-top redefined in css-box-4 - // ! padding redefined in css-box-4 - // ! padding-bottom redefined in css-box-4 - // ! padding-left redefined in css-box-4 - // ! padding-right redefined in css-box-4 - // ! padding-top redefined in css-box-4 - - // https://drafts.csswg.org/css-box-4/#property-index - Margin, - MarginBottom, - MarginLeft, - MarginRight, - MarginTop, - MarginTrim, - Padding, - PaddingBottom, - PaddingLeft, - PaddingRight, - PaddingTop, - - // https://drafts.csswg.org/css-break-3/#property-index - // ! box-decoration-break redefined in css-break-4 - // ! break-after redefined in css-break-4 - // ! break-before redefined in css-break-4 - // ! break-inside redefined in css-break-4 - // ! orphans redefined in css-break-4 - // ! widows redefined in css-break-4 - - // https://drafts.csswg.org/css-break-4/#property-index - BoxDecorationBreak, - BreakAfter, - BreakBefore, - BreakInside, - BreakMargin, - PageBreakAfter, - PageBreakBefore, - PageBreakInside, - Orphans, - Widows, - - // https://drafts.csswg.org/css-cascade-3/#property-index - // ! all redefined in css-cascade-4 - - // https://drafts.csswg.org/css-cascade-4/#property-index - // ! all redefined in css-cascade-5 - - // https://drafts.csswg.org/css-cascade-5/#property-index - All, - - // https://drafts.csswg.org/css-cascade-6/#property-index - // - - // https://drafts.csswg.org/css-color-3/#property-index - // ! color redefined in css-color-4 - // ! opacity redefined in css-color-4 - - // https://drafts.csswg.org/css-color-4/#property-index - Color, - Opacity, - - // https://drafts.csswg.org/css-color-5/#property-index - // - - // https://drafts.csswg.org/css-color-6/#property-index - // - - // https://drafts.csswg.org/css-color-adjust-1/#property-index - ColorAdjust, - ColorScheme, - ForcedColorAdjust, - PrintColorAdjust, - - // https://drafts.csswg.org/css-color-hdr/#property-index - // - - // https://drafts.csswg.org/css-conditional-3/#property-index - // https://drafts.csswg.org/css-conditional-4/#property-index - // https://drafts.csswg.org/css-conditional-5/#property-index - // - - // https://drafts.csswg.org/css-conditional-values-1/#property-index - // - - // https://drafts.csswg.org/css-contain-1/#property-index - // ! contain redefined in css-contain-2 - // ! content-visibility redefined in css-contain-3 - - // https://drafts.csswg.org/css-contain-2/#property-index - Contain, - // ! content-visibility redefined in css-contain-3 - - - // https://drafts.csswg.org/css-contain-3/#property-index - Container, - ContainerName, - ContainerType, - ContentVisibility, - - // https://drafts.csswg.org/css-content-3/#property-index - BookmarkLabel, - BookmarkLevel, - BookmarkState, - Content, - Quotes, - StringSet, - - // https://drafts.csswg.org/css-counter-styles-3/#property-index - // - - // https://drafts.csswg.org/css-display-3/#property-index - // ! display redefined in css-display-4 - // ! order redefined in css-display-4 - // ! visibility redefined in css-display-4 - - // https://drafts.csswg.org/css-display-4/#property-index - Display, - LayoutOrder, - Order, - ReadingOrder, - Visibility, - - // https://drafts.csswg.org/css-easing-1/#property-index - // - - // https://drafts.csswg.org/css-easing-2/#property-index - // - - // https://drafts.csswg.org/css-egg-1/#property-index - // - - // https://drafts.csswg.org/css-env-1/#property-index - // - - // https://drafts.csswg.org/css-exclusions-1/#property-index - WrapFlow, - WrapThrough, - - // https://drafts.csswg.org/css-extensions-1/#property-index - // - - // https://drafts.csswg.org/css-flexbox-1/#property-index - // ! align-content redefined in css-align-3 - // ! align-items redefined in css-align-3 - // ! align-self redefined in css-align-3 - Flex, - FlexBasis, - FlexDirection, - FlexFlow, - FlexGrow, - FlexShrink, - FlexWrap, - // ! justify-content redefined in css-align-3 - - // https://drafts.csswg.org/css-font-loading-3/#property-index - // - - // https://drafts.csswg.org/css-fonts-3/#property-index - // ! font redefined in css-fonts-4 - // ! font-family redefined in css-fonts-4 - // ! font-feature-settings redefined in css-fonts-4 - // ! font-kerning redefined in css-fonts-4 - // ! font-size redefined in css-fonts-4 - // ! font-size-adjust redefined in css-fonts-4 - // ! font-stretch redefined in css-fonts-4 - // ! font-style redefined in css-fonts-4 - // ! font-synthesis redefined in css-fonts-4 - // ! font-variant redefined in css-fonts-4 - // ! font-variant-caps redefined in css-fonts-4 - // ! font-variant-east-asian redefined in css-fonts-4 - // ! font-variant-ligatures redefined in css-fonts-4 - // ! font-variant-numeric redefined in css-fonts-4 - // ! font-variant-position redefined in css-fonts-4 - // ! font-weight redefined in css-fonts-4 - - // https://drafts.csswg.org/css-fonts-4/#property-index - Font, - FontFamily, - FontFeatureSettings, - FontKerning, - FontLanguageOverride, - FontOpticalSizing, - FontPalette, - FontSize, - // ! font-size-adjust redefined in css-fonts-5 - FontStretch, - FontStyle, - FontSynthesis, - FontSynthesisSmallCaps, - FontSynthesisStyle, - FontSynthesisWeight, - FontVariant, - FontVariantAlternates, - FontVariantCaps, - FontVariantEastAsian, - FontVariantEmoji, - FontVariantLigatures, - FontVariantNumeric, - FontVariantPosition, - FontVariationSettings, - FontWeight, - - // https://drafts.csswg.org/css-fonts-5/#property-index - FontSizeAdjust, - - // https://drafts.csswg.org/css-forms-1/#property-index - // - - // https://drafts.csswg.org/css-gcpm-3/#property-index - FootnoteDisplay, - FootnotePolicy, - Running, - // ! string-set redefined in css-content-3 - - // https://drafts.csswg.org/css-gcpm-4/#property-index - CopyInto, - - // https://drafts.csswg.org/css-grid-1/#property-index - // ! grid redefined in css-grid-2 - // ! grid-area redefined in css-grid-2 - // ! grid-auto-columns redefined in css-grid-2 - // ! grid-auto-flow redefined in css-grid-2 - // ! grid-auto-rows redefined in css-grid-2 - // ! grid-column redefined in css-grid-2 - // ! grid-column-end redefined in css-grid-2 - // ! grid-column-start redefined in css-grid-2 - // ! grid-row redefined in css-grid-2 - // ! grid-row-end redefined in css-grid-2 - // ! grid-row-start redefined in css-grid-2 - // ! grid-template redefined in css-grid-2 - // ! grid-template-areas redefined in css-grid-2 - // ! grid-template-columns redefined in css-grid-2 - // ! grid-template-rows redefined in css-grid-2 - - // https://drafts.csswg.org/css-grid-2/#property-index - Grid, - GridArea, - GridAutoColumns, - GridAutoFlow, - GridAutoRows, - GridColumn, - GridColumnEnd, - GridColumnStart, - GridRow, - GridRowEnd, - GridRowStart, - GridTemplate, - GridTemplateAreas, - GridTemplateColumns, - GridTemplateRows, - - // https://drafts.csswg.org/css-grid-3/#property-index - AlignTracks, - JustifyTracks, - MasonryAutoFlow, - - // https://drafts.csswg.org/css-images-3/#property-index - ImageOrientation, - ImageRendering, - // ! object-fit redefined in css-images-4 - ObjectPosition, - - // https://drafts.csswg.org/css-images-4/#property-index - ImageResolution, - ObjectFit, - - // https://drafts.csswg.org/css-images-5/#property-index - ObjectViewBox, - - // https://drafts.csswg.org/css-inline-3/#property-index - AlignmentBaseline, - BaselineShift, - BaselineSource, - DominantBaseline, - InitialLetter, - InitialLetterAlign, - InitialLetterWrap, - InlineSizing, - LineHeight, - TextBoxEdge, - TextBoxTrim, - VerticalAlign, - - // https://drafts.csswg.org/css-line-grid-1/#property-index - BoxSnap, - LineGrid, - LineSnap, - - // https://drafts.csswg.org/css-link-params-1/#property-index - LinkParameters, - - // https://drafts.csswg.org/css-lists-3/#property-index - CounterIncrement, - CounterReset, - CounterSet, - ListStyle, - ListStyleImage, - ListStylePosition, - ListStyleType, - MarkerSide, - - // https://drafts.csswg.org/css-logical-1/#property-index - BlockSize, - BorderBlock, - BorderBlockColor, - BorderBlockEnd, - BorderBlockEndColor, - BorderBlockEndStyle, - BorderBlockEndWidth, - BorderBlockStart, - BorderBlockStartColor, - BorderBlockStartStyle, - BorderBlockStartWidth, - BorderBlockStyle, - BorderBlockWidth, - BorderEndEndRadius, - BorderEndStartRadius, - BorderInline, - BorderInlineColor, - BorderInlineEnd, - BorderInlineEndColor, - BorderInlineEndStyle, - BorderInlineEndWidth, - BorderInlineStart, - BorderInlineStartColor, - BorderInlineStartStyle, - BorderInlineStartWidth, - BorderInlineStyle, - BorderInlineWidth, - BorderStartEndRadius, - BorderStartStartRadius, - InlineSize, - // ! inset redefined in css-position-3 - // ! inset-block redefined in css-position-3 - // ! inset-inline redefined in css-position-3 - // ! inset-block-end redefined in css-position-3 - // ! inset-inline redefined in css-position-3 - // ! inset-inline-end redefined in css-position-3 - // ! inset-inline-start redefined in css-position-3 - MarginBlock, - MarginBlockEnd, - MarginBlockStart, - MarginInline, - MarginInlineEnd, - MarginInlineStart, - MaxBlockSize, - MaxInlineSize, - MinBlockSize, - MinInlineSize, - PaddingBlock, - PaddingBlockEnd, - PaddingBlockStart, - PaddingInline, - PaddingInlineEnd, - PaddingInlineStart, - - // https://drafts.csswg.org/css-mobile/#property-index - // - - // https://drafts.csswg.org/css-multicol-1/#property-index - ColumnCount, - ColumnFill, - ColumnRule, - ColumnRuleColor, - ColumnRuleStyle, - ColumnRuleWidth, - // ! column-span redined in css-multicol-2 - ColumnWidth, - Columns, - - // https://drafts.csswg.org/css-multicol-2/#property-index - ColumnSpan, - - // https://drafts.csswg.org/css-namespaces-3/#property-index - // - - // https://drafts.csswg.org/css-nav-1/#property-index - SpatialNavigationAction, - SpatialNavigationContain, - SpatialNavigationFunction, - - // https://drafts.csswg.org/css-nesting-1/#property-index - // - - // https://drafts.csswg.org/css-overflow-3/#property-index - Overflow, - OverflowBlock, - // ! overflow-clip-margin redined in css-overflow-4 - OverflowInline, - OverflowX, - OverflowY, - ScrollBehavior, - ScrollbarGutter, - // ! text-overflow redined in css-overflow-4 - - // https://drafts.csswg.org/css-overflow-4/#property-index - // (Yes this is really in the spec as -webkit-line-clamp) - WebkitLineClamp, - BlockEllipsis, - Continue, - LineClamp, - MaxLines, - OverflowClipMargin, - OverflowClipMarginBlock, - OverflowClipMarginBlockEnd, - OverflowClipMarginBlockStart, - OverflowClipMarginBottom, - OverflowClipMarginInline, - OverflowClipMarginInlineEnd, - OverflowClipMarginInlineStart, - OverflowClipMarginLeft, - OverflowClipMarginRight, - OverflowClipMarginTop, - TextOverflow, - - // https://drafts.csswg.org/css-overscroll-1/#property-index - OverscrollBehavior, - OverscrollBehaviorBlock, - OverscrollBehaviorInline, - OverscrollBehaviorX, - OverscrollBehaviorY, - - // https://drafts.csswg.org/css-page-3/#property-index - Page, - - // https://drafts.csswg.org/css-page-4/#property-index - // - - // https://drafts.csswg.org/css-page-floats-3/#property-index - Clear, - Float, - FloatDefer, - FloatOffset, - FloatReference, - - // https://drafts.csswg.org/css-page-template-1/#property-index - // - - // https://drafts.csswg.org/css-position-3/#property-index - Bottom, - Inset, - InsetBlock, - InsetBlockEnd, - InsetBlockStart, - InsetInline, - InsetInlineEnd, - InsetInlineStart, - Left, - Position, - Right, - Top, - - // https://drafts.csswg.org/css-preslev-1/#property-index - // - - // https://drafts.csswg.org/css-print/#property-index - // - - // https://drafts.csswg.org/css-pseudo-4/#property-index - // - - // https://drafts.csswg.org/css-regions-1/#property-index - FlowFrom, - FlowInto, - RegionFragment, - - // https://drafts.csswg.org/css-rhythm-1/#property-index - BlockStep, - BlockStepAlign, - BlockStepInsert, - BlockStepRound, - BlockStepSize, - LineHeightStep, - - // https://drafts.csswg.org/css-round-display-1/#property-index - BorderBoundary, - ShapeInside, - - // https://drafts.csswg.org/css-ruby-1/#property-index - RubyAlign, - RubyMerge, - RubyOverhang, - RubyPosition, - - // https://drafts.csswg.org/css-scoping-1/#property-index - // - - // https://drafts.csswg.org/css-scroll-anchoring-1/#property-index - OverflowAnchor, - - // https://drafts.csswg.org/css-scroll-snap-1/#property-index - ScrollMargin, - ScrollMarginBlock, - ScrollMarginBlockEnd, - ScrollMarginBlockStart, - ScrollMarginBottom, - ScrollMarginInline, - ScrollMarginInlineEnd, - ScrollMarginInlineStart, - ScrollMarginLeft, - ScrollMarginRight, - ScrollMarginTop, - ScrollPadding, - ScrollPaddingBlock, - ScrollPaddingBlockEnd, - ScrollPaddingBlockStart, - ScrollPaddingBottom, - ScrollPaddingInline, - ScrollPaddingInlineEnd, - ScrollPaddingInlineStart, - ScrollPaddingLeft, - ScrollPaddingRight, - ScrollPaddingTop, - ScrollSnapAlign, - ScrollSnapStop, - ScrollSnapType, - - // https://drafts.csswg.org/css-scroll-snap-2/#property-index - ScrollStart, - ScrollStartBlock, - ScrollStartInline, - ScrollStartTarget, - ScrollStartTargetBlock, - ScrollStartTargetInline, - ScrollStartTargetX, - ScrollStartTargetY, - ScrollStartX, - ScrollStartY, - - // https://drafts.csswg.org/css-scrollbars-1/#property-index - ScrollbarColor, - ScrollbarWidth, - - // https://drafts.csswg.org/css-shadow-parts-1/#property-index - // - - // https://drafts.csswg.org/css-shapes-1/#property-index - ShapeImageThreshold, - ShapeMargin, - ShapeOutside, - - // https://drafts.csswg.org/css-size-adjust-1/#property-index - TextSizeAdjust, - - // https://drafts.csswg.org/css-shapes-2/#property-index - // ! shape-inside is redefined in css-round-display-1 - ShapePadding, - - // https://drafts.csswg.org/css-sizing-3/#property-index - BoxSizing, - Height, - MaxHeight, - MaxWidth, - MinHeight, - MinWidth, - Width, - - // https://drafts.csswg.org/css-sizing-4/#property-index - AspecRatio, - ContainIntrinsicBlockSize, - ContainIntrinsicHeight, - ContainIntrinsicInlineSize, - ContainIntrinsicSize, - ContainIntrinsicWidth, - MinIntrinsicSizing, - - // https://drafts.csswg.org/css-speech-1/#property-index - Cue, - CueAfter, - CueBefore, - Pause, - PauseAfter, - PauseBefore, - Rest, - RestAfter, - RestBefore, - Speak, - SpeakAs, - VoiceBalance, - VoiceDuration, - VoiceFamily, - VoicePitch, - VoiceRange, - VoiceRate, - VoiceStress, - VoiceVolume, - - // https://drafts.csswg.org/css-style-attr-1/#property-index - // - - // https://drafts.csswg.org/css-syntax-3/#property-index - // - - // https://drafts.csswg.org/css-tables-3/#property-index - BorderCollapse, - BorderSpacing, - CaptionSide, - EmptyCells, - TableLayout, - - // https://drafts.csswg.org/css-template-1/#property-index - // TODO: Is this even a thing? - - - // https://drafts.csswg.org/css-text-3/#property-index - // ! hanging-punctuation redefined in css-text-4 - // ! hypens redefined in css-text-4 - // ! letter-spacing redefined in css-text-4 - // ! line-break redefined in css-text-4 - // ! overflow-wrap redefined in css-text-4 - // ! tab-size redefined in css-text-4 - // ! text-align redefined in css-text-4 - // ! text-align-all redefined in css-text-4 - // ! text-align-last redefined in css-text-4 - // ! text-indent redefined in css-text-4 - // ! text-justify redefined in css-text-4 - // ! text-transform redefined in css-text-4 - // ! white-space redefined in css-text-4 - // ! word-break redefined in css-text-4 - // ! word-spacing redefined in css-text-4 - // ! word-wrap redefined in css-text-4 - - // https://drafts.csswg.org/css-text-4/#property-index - HangingPunctuation, - HyphenateCharacter, - HyphenateLimitChars, - HyphenateLimitLast, - HyphenateLimitLines, - HyphenateLimitZone, - Hyphens, - LetterSpacing, - LineBreak, - LinePadding, - OverflowWrap, - TabSize, - TextAlign, - TextAlignAll, - TextAlignLast, - TextAutospace, - TextGroupAlign, - TextIndent, - TextJustify, - TextSpacing, - TextSpacingTrim, - TextTransform, - TextWrap, - WhiteSpace, - WhiteSpaceCollapse, - WhiteSpaceTrim, - WordBoundaryDetection, - WordBoundaryExpansion, - WordBreak, - WordSpacing, - WordWrap, - WrapAfter, - WrapBefore, - WrapInside, - - // https://drafts.csswg.org/css-text-decor-3/#property-index - // ! text-decoration redefined in css-text-decor-4 - // ! text-decoration-color redefined in css-text-decor-4 - // ! text-decoration-line redefined in css-text-decor-4 - // ! text-emphasis redefined in css-text-decor-4 - // ! text-emphasis-color redefined in css-text-decor-4 - // ! text-emphasis-position redefined in css-text-decor-4 - // ! text-emphasis-style redefined in css-text-decor-4 - // ! tex-tshadow redefined in css-text-decor-4 - // ! text-underline-position redefined in css-text-decor-4 - - // https://drafts.csswg.org/css-text-decor-4/#property-index - TextDecoration, - TextDecorationColor, - TextDecorationLine, - TextDecorationSkip, - TextDecorationSkipInk, - TextDecorationSkipSelf, - TextDecorationSkipSpaces, - TextDecorationStyle, - TextDecorationThickness, - TextDecorationTrim, - TextEmphasis, - TextEmphasisColor, - TextEmphasisPosition, - TextEmphasisSkip, - TextEmphasisStyle, - TextShadow, - TextUnderlineOffset, - TextUnderlinePosition, - - // https://drafts.csswg.org/css-transitions-1/#property-index - Transition, - TransitionDelay, - TransitionDuration, - TransitionProperty, - TransitionTimingFunction, - - // https://drafts.csswg.org/css-transitions-2/#property-index - // - - // https://drafts.csswg.org/css-tv/#property-index - // - - // https://drafts.csswg.org/css-ui-3/#property-index - // ! box-sizing refined in css-sizing-3 - // ! caret-color redefined in css-ui-4 - // ! outline redefined in css-ui-4 - // ! outline redefined in css-ui-4 - // ! outline-color redefined in css-ui-4 - // ! outline-offset redefined in css-ui-4 - // ! outline-style redefined in css-ui-4 - // ! outline-width redefined in css-ui-4 - // ! resize redefined in css-ui-4 - // ! text-overflow redefined in css-overflow-4 - - // https://drafts.csswg.org/css-ui-4/#property-index - AccentColor, - Appearance, - Caret, - CaretColor, - CaretShape, - Cursor, - InputSecurity, - NavDown, - NavLeft, - NavRight, - NavUp, - Outline, - OutlineColor, - OutlineOffset, - OutlineStyle, - OutlineWidth, - PointerEvents, - Resize, - UserSelect, - - // https://drafts.csswg.org/css-values-3/#property-index - // - - // https://drafts.csswg.org/css-values-4/#property-index - // - - // https://drafts.csswg.org/css-values-5/#property-index - // - - // https://drafts.csswg.org/css-variables-1/#property-index - // This spec defines the properties. - - // https://drafts.csswg.org/css-variables-2/#property-index - // This spec defines the properties. - - // https://drafts.csswg.org/css-view-transitions-1/#property-index - ViewTransitionName, - - // https://drafts.csswg.org/css-viewport/#property-index - // - - // https://drafts.csswg.org/css-will-change-1/#property-index - WillChange, - - // https://drafts.csswg.org/css-writing-modes-3/#property-index - // ! direction is redefined in css-text-decor-4 - // ! glyph-orientation-horizontal is redefined in css-text-decor-4 - // ! text-combine-upright is redefined in css-text-decor-4 - // ! text-orientation is redefined in css-text-decor-4 - // ! unicode-bidi is redefined in css-text-decor-4 - // ! writing-mode is redefined in css-text-decor-4 - - // https://drafts.csswg.org/css-writing-modes-4/#property-index - Direction, - GlyphOrientationHorizontal, - TextCombineUpright, - TextOrientation, - UnicodeBidi, - WritingMode, - - // https://drafts.csswg.org/css2/#property-index - // ! background is redefined in css-backgrounds-3 - // ! background-attachment is redefined in css-backgrounds-3 - // ! background-color is redefined in css-backgrounds-3 - // ! background-image is redefined in css-backgrounds-3 - // ! background-position is redefined in css-backgrounds-3 - // ! background-repeat is redefined in css-backgrounds-3 - // ! border is redefined in css-backgrounds-3 - // ! border-bottom is redefined in css-backgrounds-3 - // ! border-bottom-color is redefined in css-backgrounds-3 - // ! border-bottom-style is redefined in css-backgrounds-3 - // ! border-bottom-width is redefined in css-backgrounds-3 - // ! border-collapse is redefined in css-tables-3 - // ! border-color is redefined in css-backgrounds-3 - // ! border-left is redefined in css-backgrounds-3 - // ! border-left-color is redefined in css-backgrounds-3 - // ! border-left-style is redefined in css-backgrounds-3 - // ! border-left-width is redefined in css-backgrounds-3 - // ! border-right is redefined in css-backgrounds-3 - // ! border-right-color is redefined in css-backgrounds-3 - // ! border-right-style is redefined in css-backgrounds-3 - // ! border-right-width is redefined in css-backgrounds-3 - // ! border-spacing is redefined in css-tables-3 - // ! border-style is redefined in css-backgrounds-3 - // ! border-top is redefined in css-backgrounds-3 - // ! border-top-color is redefined in css-backgrounds-3 - // ! border-top-style is redefined in css-backgrounds-3 - // ! border-top-width is redefined in css-backgrounds-3 - // ! border-width is redefined in css-backgrounds-3 - // ! bottom is redefined in css-position-3 - // ! caption-side is redefined in css-tables-3 - // ! clear is redefined in css-page-floats-3 - // ! clip is redefined in css-masking-3 - // ! color is redefined in css-color-3 - // ! content is redefined in css-content-3 - // ! counter-increment is redefined in css-lists-3 - // ! counter-reset is redefined in css-lists-3 - // ! cursor is redefined in css-ui-4 - // ! direction is redefined in css-writing-modes-4 - // ! display is redefined in css-display-3 - // ! empty-cells is redefined in css-tables-3 - // ! float is redefined in css-page-floats-3 - // ! font is redefined in css-fonts-3 - // ! font-family is redefined in css-fonts-3 - // ! font-size is redefined in css-fonts-3 - // ! font-style is redefined in css-fonts-3 - // ! font-variant is redefined in css-fonts-3 - // ! font-weight is redefined in css-fonts-3 - // ! height is redefined in css-sizing-3 - // ! left is redefined in css-position-3 - // ! letter-spacing is redefined in css-text-decor-4 - // ! line-height is redefined in css-line-grid-1 - // ! list-style is redefined in css-lists-3 - // ! list-style-image is redefined in css-lists-3 - // ! list-style-position is redefined in css-lists-3 - // ! list-style-type is redefined in css-lists-3 - // ! margin is redefined in css-box-3 - // ! margin-bottom is redefined in css-box-3 - // ! margin-left is redefined in css-box-3 - // ! margin-right is redefined in css-box-3 - // ! margin-top is redefined in css-box-3 - // ! max-height is redefined in css-sizing-3 - // ! max-width is redefined in css-sizing-3 - // ! min-height is redefined in css-sizing-3 - // ! min-width is redefined in css-sizing-3 - // ! orphans is redefined in css-page-3 - // ! outline is redefined in css-ui-4 - // ! outline-color is redefined in css-ui-4 - // ! outline-style is redefined in css-ui-4 - // ! outline-width is redefined in css-ui-4 - // ! overflow is redefined in css-overflow-3 - // ! padding is redefined in css-box-3 - // ! padding-bottom is redefined in css-box-3 - // ! padding-left is redefined in css-box-3 - // ! padding-right is redefined in css-box-3 - // ! padding-top is redefined in css-box-3 - // ! page-break-after is redefined in css-page-3 - // ! page-break-before is redefined in css-page-3 - // ! page-break-inside is redefined in css-page-3 - // ! position is redefined in css-position-3 - // ! quotes is redefined in css-content-3 - // ! right is redefined in css-position-3 - // ! table-layout is redefined in css-tables-3 - // ! text-align is redefined in css-text-3 - // ! text-decoration is redefined in css-text-decor-4 - // ! text-indent is redefined in css-text-3 - // ! text-transform is redefined in css-text-decor-4 - // ! top is redefined in css-position-3 - // ! unicode-bidi is redefined in css-writing-modes-4 - // ! vertical-align is redefined in css-inline-3 - // ! visibility is redefined in css-ui-4 - // ! white-space is redefined in css-text-3 - // ! widows is redefined in css-page-3 - // ! word-spacing is redefined in css-text-decor-4 - ZIndex, - - // https://drafts.csswg.org/cssom-1/#property-index - // - - // https://drafts.csswg.org/cssom-view-1/#property-index - // - - // https://drafts.csswg.org/mediaqueries-3/#property-index - // - - // https://drafts.csswg.org/mediaqueries-4/#property-index - // - - // https://drafts.csswg.org/mediaqueries-5/#property-index - // - - // https://drafts.csswg.org/resize-observer-1/#property-index - // - - // https://drafts.csswg.org/scroll-animations-1/#property-index - AnimationRange, - AnimationRangeEnd, - AnimationRangeStart, - ScrollTimeline, - ScrollTimelineAxis, - ScrollTimelineName, - TimelineScope, - ViewTimeline, - ViewTimelineAxis, - ViewTimelineInset, - ViewTimelineName, - - // https://drafts.csswg.org/selectors-3/#property-index - // - - // https://drafts.csswg.org/selectors-4/#property-index - // - - // https://drafts.csswg.org/selectors-nonelement-1/#property-index - // - - // https://drafts.csswg.org/web-animations-1/#property-index - // - - // https://drafts.csswg.org/web-animations-2/#property-index - - // Non Standard - NonStandardZoom, - NonStandardClip, - - // Webkit Non Standard - WebkitTextSizeAdjust, - WebkitTextDecoration, - WebkitTapHighlightColor, - WebkitTextDecorationSkipInk, -} diff --git a/crates/hdx_writer/src/css/selector.rs b/crates/hdx_writer/src/css/selector.rs deleted file mode 100644 index 0dfe2ea0..00000000 --- a/crates/hdx_writer/src/css/selector.rs +++ /dev/null @@ -1,145 +0,0 @@ -use std::fmt::Result; - -use hdx_ast::css::{ - selector::{Attribute, AttributeMatch, Combinator, Component, NSPrefix, Selector}, - stylesheet::SelectorSet, -}; -use hdx_atom::Atomizable; - -use crate::{CssWriter, WriteCss}; - -impl<'a> WriteCss<'a> for SelectorSet<'a> { - fn write_css(&self, sink: &mut W) -> Result { - let mut iter = self.children.iter().peekable(); - while let Some(selector) = iter.next() { - selector.write_css(sink)?; - if iter.peek().is_some() { - sink.write_char(',')?; - sink.write_trivia_char(' ')?; - } - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for Selector<'a> { - fn write_css(&self, sink: &mut W) -> Result { - for component in &(*self.components) { - component.write_css(sink)?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for Component<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Type(ty) => { - sink.write_str(ty)?; - } - Self::Id(id) => { - sink.write_char('#')?; - sink.write_str(id)?; - } - Self::Class(class) => { - sink.write_char('.')?; - sink.write_str(class)?; - } - Self::PseudoClass(pseudo) => { - sink.write_char(':')?; - sink.write_str(pseudo.to_atom().as_ref())?; - } - Self::LegacyPseudoElement(pseudo) => { - sink.write_char(':')?; - sink.write_str(pseudo.to_atom().as_ref())?; - } - Self::PseudoElement(pseudo) => { - sink.write_char(':')?; - sink.write_char(':')?; - sink.write_str(pseudo.to_atom().as_ref())?; - } - Self::Attribute(attr) => { - attr.write_css(sink)?; - } - Self::Combinator(combinator) => { - sink.write_trivia_char(' ')?; - match combinator { - Combinator::Descendant => { - sink.write_char(' ')?; - } - Combinator::Child => { - sink.write_char('>')?; - } - Combinator::NextSibling => { - sink.write_char('+')?; - } - Combinator::SubsequentSibling => { - sink.write_char('~')?; - } - Combinator::ColumnCombintor => { - sink.write_char('|')?; - sink.write_char('|')?; - } - } - sink.write_trivia_char(' ')?; - } - Self::Wildcard => { - sink.write_char('*')?; - } - _ => todo!(), - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for Attribute { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_char('[')?; - match &self.ns_prefix { - NSPrefix::None => {} - NSPrefix::Named(ns) => { - sink.write_str(ns.as_ref())?; - sink.write_char('|')?; - } - NSPrefix::Wildcard => { - sink.write_char('*')?; - sink.write_char('|')?; - } - } - sink.write_str(self.name.as_ref())?; - match &self.matcher { - AttributeMatch::Any => {} - AttributeMatch::Exact => { - sink.write_char('=')?; - } - AttributeMatch::SpaceList => { - sink.write_char('~')?; - sink.write_char('=')?; - } - AttributeMatch::LangPrefix => { - sink.write_char('|')?; - sink.write_char('=')?; - } - AttributeMatch::Prefix => { - sink.write_char('^')?; - sink.write_char('=')?; - } - AttributeMatch::Suffix => { - sink.write_char('$')?; - sink.write_char('=')?; - } - AttributeMatch::Contains => { - sink.write_char('*')?; - sink.write_char('=')?; - } - } - if &self.matcher != &AttributeMatch::Any { - sink.write_char('"')?; - sink.write_str(self.value.as_ref())?; - sink.write_char('"')?; - } - - sink.write_char(']')?; - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/backgrounds.rs b/crates/hdx_writer/src/css/values/backgrounds.rs deleted file mode 100644 index bad5ed73..00000000 --- a/crates/hdx_writer/src/css/values/backgrounds.rs +++ /dev/null @@ -1,35 +0,0 @@ -use hdx_ast::css::values::{backgrounds::*, Shorthand}; - -use crate::{CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for LineWidth { - fn write_css(&self, sink: &mut W) -> Result { - match self { - LineWidth::Thin => sink.write_str("thin"), - LineWidth::Medium => sink.write_str("medium"), - LineWidth::Thick => sink.write_str("thick"), - LineWidth::Length(l) => l.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for BorderShorthand<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Shorthand::Explicit(line_width) = &self.line_width { - line_width.write_css(sink)?; - if self.line_style.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(line_style) = &self.line_style { - line_style.write_css(sink)?; - if self.color.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(color) = &self.color { - color.write_css(sink)?; - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/box.rs b/crates/hdx_writer/src/css/values/box.rs deleted file mode 100644 index 105ce5a2..00000000 --- a/crates/hdx_writer/src/css/values/box.rs +++ /dev/null @@ -1,9 +0,0 @@ -use hdx_ast::css::values::r#box::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for MarginTrimValue { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} diff --git a/crates/hdx_writer/src/css/values/break.rs b/crates/hdx_writer/src/css/values/break.rs deleted file mode 100644 index 4e74143a..00000000 --- a/crates/hdx_writer/src/css/values/break.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[cfg(feature = "serde")] -use serde::Serialize; - -use super::{Expr, Length}; -use crate::{atom, Atom, Atomizable, Span}; diff --git a/crates/hdx_writer/src/css/values/color.rs b/crates/hdx_writer/src/css/values/color.rs deleted file mode 100644 index 00127fe4..00000000 --- a/crates/hdx_writer/src/css/values/color.rs +++ /dev/null @@ -1,13 +0,0 @@ -use hdx_ast::css::values::color::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for ColorValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Hex(_) => sink.write_str(&self.to_hex(ToHexStyle::Compact).unwrap()), - Self::Named(named) => sink.write_str(named.to_atom().as_ref()), - _ => todo!(), - } - } -} diff --git a/crates/hdx_writer/src/css/values/content.rs b/crates/hdx_writer/src/css/values/content.rs deleted file mode 100644 index 2aed260f..00000000 --- a/crates/hdx_writer/src/css/values/content.rs +++ /dev/null @@ -1,66 +0,0 @@ -use hdx_ast::css::values::content::*; - -use crate::{CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for ContentsValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - ContentsValue::Normal => sink.write_str("normal"), - ContentsValue::None => sink.write_str("none"), - ContentsValue::Replacement(replacement) => replacement.write_css(sink), - ContentsValue::List(list) => list.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for ContentList<'a> { - fn write_css(&self, sink: &mut W) -> Result { - let mut iter = self.values.iter().peekable(); - while let Some(value) = iter.next() { - match value { - ContentElement::String(atom) => { - sink.write_char('"')?; - sink.write_str(atom.as_ref())?; - sink.write_char('"')?; - } - ContentElement::Contents => sink.write_str("contents")?, - ContentElement::Image(_) => todo!(), - ContentElement::Counter(_) => todo!(), - ContentElement::Quote(_) => todo!(), - ContentElement::Leader(_) => todo!(), - } - if iter.peek().is_some() { - sink.write_char(' ')?; - } - } - for alt in &self.alt { - todo!() - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for QuotesValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none")?, - Self::Auto => sink.write_str("auto")?, - Self::Custom(quotes) => { - let mut iter = quotes.iter().peekable(); - while let Some((open, close)) = iter.next() { - sink.write_char('"')?; - sink.write_str(open.as_ref())?; - sink.write_char('"')?; - sink.write_char(' ')?; - sink.write_char('"')?; - sink.write_str(close.as_ref())?; - sink.write_char('"')?; - if iter.peek().is_some() { - sink.write_char(' ')?; - } - } - } - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/counter_styles.rs b/crates/hdx_writer/src/css/values/counter_styles.rs deleted file mode 100644 index a4f1374b..00000000 --- a/crates/hdx_writer/src/css/values/counter_styles.rs +++ /dev/null @@ -1,9 +0,0 @@ -use hdx_ast::css::values::counter_styles::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for CounterStyle<'a> { - fn write_css(&self, sink: &mut W) -> Result { - todo!() - } -} diff --git a/crates/hdx_writer/src/css/values/display.rs b/crates/hdx_writer/src/css/values/display.rs deleted file mode 100644 index 3f1b4ab8..00000000 --- a/crates/hdx_writer/src/css/values/display.rs +++ /dev/null @@ -1,28 +0,0 @@ -use hdx_ast::css::values::display::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for DisplayValue { - fn write_css(&self, sink: &mut W) -> Result { - if let Some(atom) = self.to_atom() { - sink.write_str(atom.as_ref())?; - } else if let DisplayValue::Pair(outside, inside) = self { - if outside != &DisplayOutside::Implicit { - sink.write_str(outside.to_atom().unwrap().as_ref())?; - sink.write_char(' ')?; - } - sink.write_str(inside.to_atom().unwrap().as_ref())?; - } else if let DisplayValue::PairAndMarker(outside, inside, marker) = self { - if outside != &DisplayOutside::Implicit { - sink.write_str(outside.to_atom().unwrap().as_ref())?; - sink.write_char(' ')?; - } - if inside != &DisplayInside::Implicit { - sink.write_str(inside.to_atom().unwrap().as_ref())?; - sink.write_char(' ')?; - } - sink.write_str(marker.to_atom().unwrap().as_ref())?; - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/expr.rs b/crates/hdx_writer/src/css/values/expr.rs deleted file mode 100644 index c52f91d4..00000000 --- a/crates/hdx_writer/src/css/values/expr.rs +++ /dev/null @@ -1,116 +0,0 @@ -use std::ops::Deref; - -use hdx_ast::css::values::expr::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for Expr<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::GlobalValue(g) => sink.write_str(g.to_atom().as_ref()), - Self::Literal(val) => val.write_css(sink), - Self::Reference(f) => f.write_css(sink), - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for MathExpr<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::GlobalValue(g) => sink.write_str(g.to_atom().as_ref()), - Self::Literal(val) => val.write_css(sink), - Self::Reference(f) => f.write_css(sink), - Self::Math(f) => f.write_css(sink), - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for ExprList<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::GlobalValue(g) => sink.write_str(g.to_atom().as_ref()), - Self::Values(v) => { - let mut values = v.iter().peekable(); - while let Some(value) = values.next() { - value.write_css(sink)?; - if values.peek().is_some() { - sink.write_char(',')?; - sink.write_trivia_char(' ')?; - } - } - Ok(()) - } - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for MathExprList<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::GlobalValue(g) => sink.write_str(g.to_atom().as_ref()), - Self::Values(v) => { - let mut values = v.iter().peekable(); - while let Some(value) = values.next() { - value.write_css(sink)?; - if values.peek().is_some() { - sink.write_char(',')?; - sink.write_trivia_char(' ')?; - } - } - Ok(()) - } - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for ExprListItem<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Literal(val) => val.write_css(sink), - Self::Reference(f) => f.write_css(sink), - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for MathExprListItem<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Literal(val) => val.write_css(sink), - Self::Reference(f) => f.write_css(sink), - Self::Math(f) => f.write_css(sink), - } - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for Reference<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Var(atom, opt) => { - sink.write_str("var(")?; - sink.write_str(atom.as_ref())?; - if let Some(val) = opt.deref() { - sink.write_str(",")?; - sink.write_trivia_char(' ')?; - val.write_css(sink)?; - } - sink.write_str(")") - } - Self::Env(atom, opt) => { - sink.write_str("var(")?; - sink.write_str(atom.as_ref())?; - if let Some(val) = opt.deref() { - sink.write_str(",")?; - sink.write_trivia_char(' ')?; - val.write_css(sink)?; - } - sink.write_str(")") - } - } - } -} - -impl<'a> WriteCss<'a> for MathFunc<'a> { - fn write_css(&self, sink: &mut W) -> Result { - todo!() - } -} diff --git a/crates/hdx_writer/src/css/values/fonts.rs b/crates/hdx_writer/src/css/values/fonts.rs deleted file mode 100644 index dc317d9e..00000000 --- a/crates/hdx_writer/src/css/values/fonts.rs +++ /dev/null @@ -1,83 +0,0 @@ -use hdx_ast::css::values::{fonts::*, Angle, MathExpr}; -use hdx_syntax::identifier::is_ident_str; - -use crate::{CssWriter, Result, Spanned, WriteCss}; - -impl<'a> WriteCss<'a> for FontWeightValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Normal => sink.write_str("normal"), - Self::Bold => sink.write_str("bold"), - Self::Bolder => sink.write_str("bolder"), - Self::Lighter => sink.write_str("lighter"), - Self::Number(num) => sink.write_str(num.to_string().as_str()), - } - } -} - -impl<'a> WriteCss<'a> for FontSizeValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Absolute(size) => size.write_css(sink), - Self::Relative(size) => size.write_css(sink), - Self::LengthPercentage(size) => size.write_css(sink), - Self::Math => sink.write_str("math"), - } - } -} - -impl<'a> WriteCss<'a> for FontFamilyValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Named(atom) => { - let bare = atom.as_ref().split_ascii_whitespace().all(is_ident_str); - if !bare { - sink.write_char('"')?; - } - sink.write_str(atom.as_ref())?; - if !bare { - sink.write_char('"')?; - } - Ok(()) - } - Self::Serif => sink.write_str("serif"), - Self::SansSerif => sink.write_str("sans-serif"), - Self::Cursive => sink.write_str("cursive"), - Self::Fantasy => sink.write_str("fantasy"), - Self::Monospace => sink.write_str("monospace"), - Self::SystemUi => sink.write_str("system-ui"), - Self::Emoji => sink.write_str("emoji"), - Self::Math => sink.write_str("math"), - Self::Fangsong => sink.write_str("fangsong"), - Self::UiSerif => sink.write_str("ui-serif"), - Self::UiSansSerif => sink.write_str("ui-sans-serif"), - Self::UiMonospace => sink.write_str("ui-monospace"), - Self::UiRounded => sink.write_str("ui-rounded"), - } - } -} - -impl<'a> WriteCss<'a> for FontStyleValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Normal => sink.write_str("normal"), - Self::Italic => sink.write_str("italic"), - Self::Oblique(Spanned { node: angle, .. }) => { - sink.write_str("oblique")?; - match angle { - MathExpr::Literal(Spanned { node: Angle::Deg(deg), .. }) => { - if *deg != 14.0 { - sink.write_char(' ')?; - angle.write_css(sink)?; - } - } - _ => { - sink.write_char(' ')?; - angle.write_css(sink)?; - } - } - Ok(()) - } - } - } -} diff --git a/crates/hdx_writer/src/css/values/images.rs b/crates/hdx_writer/src/css/values/images.rs deleted file mode 100644 index c8915b5b..00000000 --- a/crates/hdx_writer/src/css/values/images.rs +++ /dev/null @@ -1,9 +0,0 @@ -use hdx_ast::css::values::images::*; - -use crate::{CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for Image<'a> { - fn write_css(&self, sink: &mut W) -> Result { - todo!() - } -} diff --git a/crates/hdx_writer/src/css/values/inline.rs b/crates/hdx_writer/src/css/values/inline.rs deleted file mode 100644 index 3dde9997..00000000 --- a/crates/hdx_writer/src/css/values/inline.rs +++ /dev/null @@ -1,47 +0,0 @@ -use hdx_ast::css::values::{inline::*, Shorthand}; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for BaselineShiftValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Sub => sink.write_str("sub"), - Self::Super => sink.write_str("super"), - Self::Top => sink.write_str("top"), - Self::Center => sink.write_str("center"), - Self::Bottom => sink.write_str("bottom"), - Self::LengthPercentage(val) => val.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for VerticalAlignShorthand<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Shorthand::Explicit(baseline_source) = &self.baseline_source { - baseline_source.write_css(sink)?; - if self.alignment_baseline.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(alignment_baseline) = &self.alignment_baseline { - alignment_baseline.write_css(sink)?; - if self.baseline_shift.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(baseline_shift) = &self.baseline_shift { - baseline_shift.write_css(sink)?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for LineHeightValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Normal => sink.write_str("normal"), - Self::Number(n) => sink.write_str(n.to_string().as_str()), - Self::LengthPercentage(n) => n.write_css(sink), - } - } -} diff --git a/crates/hdx_writer/src/css/values/length.rs b/crates/hdx_writer/src/css/values/length.rs deleted file mode 100644 index 6b569be0..00000000 --- a/crates/hdx_writer/src/css/values/length.rs +++ /dev/null @@ -1,73 +0,0 @@ -use hdx_ast::css::values::units::lengths::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for Length { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - sink.write_str(n.to_string().as_str())?; - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for PositiveLength { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - sink.write_str(n.to_string().as_str())?; - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for LengthOrAuto { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - sink.write_str(n.to_string().as_str())?; - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for LengthPercentageOrNormal { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - if !matches!(self, Self::Normal) { - sink.write_str(n.to_string().as_str())?; - } - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for PositiveLengthPercentageOrNormal { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - if !matches!(self, Self::Normal) { - sink.write_str(n.to_string().as_str())?; - } - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for LengthPercentage { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - sink.write_str(n.to_string().as_str())?; - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for PositiveLengthPercentage { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - sink.write_str(n.to_string().as_str())?; - sink.write_str(atom.as_ref()) - } -} - -impl<'a> WriteCss<'a> for LengthPercentageOrAuto { - fn write_css(&self, sink: &mut W) -> Result { - let (n, atom) = self.to_f32_and_atom(); - if self != &LengthPercentageOrAuto::Auto { - sink.write_str(n.to_string().as_str())?; - } - sink.write_str(atom.as_ref()) - } -} diff --git a/crates/hdx_writer/src/css/values/lists.rs b/crates/hdx_writer/src/css/values/lists.rs deleted file mode 100644 index 4b2a3b78..00000000 --- a/crates/hdx_writer/src/css/values/lists.rs +++ /dev/null @@ -1,47 +0,0 @@ -use hdx_ast::css::values::{lists::*, Shorthand}; - -use crate::{CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for ListStyleShorthand<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Shorthand::Explicit(position) = &self.position { - position.write_css(sink)?; - if self.image.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(image) = &self.image { - image.write_css(sink)?; - if self.marker.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(marker) = &self.marker { - marker.write_css(sink)?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for ListStyleImageValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::Image(image) => image.write_css(sink), - } - } -} - -impl<'a> WriteCss<'a> for ListStyleTypeValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::CounterStyle(c) => c.write_css(sink), - Self::String(s) => { - sink.write_char('"')?; - sink.write_str(s.as_ref())?; - sink.write_char('"') - } - } - } -} diff --git a/crates/hdx_writer/src/css/values/mod.rs b/crates/hdx_writer/src/css/values/mod.rs deleted file mode 100644 index 63a2d2d4..00000000 --- a/crates/hdx_writer/src/css/values/mod.rs +++ /dev/null @@ -1,113 +0,0 @@ -mod backgrounds; -mod r#box; -mod color; -mod content; -mod counter_styles; -mod display; -mod expr; -mod fonts; -mod images; -mod inline; -mod length; -mod lists; -mod non_standard; -mod page_floats; -mod shorthand; -mod size_adjust; -mod sizing; -mod text; -mod text_decor; -mod ui; - -use hdx_ast::css::values::*; -use hdx_atom::Atomizable; - -use crate::{CssWriter, Result, WriteCss}; - -macro_rules! write_atomizable_values { - {$( $prop: ident, )+} => { - $( - impl<'a> WriteCss<'a> for $prop { - fn write_css(&self, sink: &mut W) -> Result { - sink.write_str(self.to_atom().as_ref()) - } - } - )+ - } -} - -write_atomizable_values! { - AbsoluteSize, - AlignmentBaselineValue, - AutoOrNone, - BaselineSourceValue, - BorderCollapseValue, - BoxDecorationBreakValue, - BoxSizingValue, - BreakInsideValue, - BreakValue, - CaptionSideValue, - ClearValue, - DominantBaselineValue, - EmptyCellsValue, - FloatReferenceValue, - InlineSizingValue, - LineStyle, - ListStylePositionValue, - MarginBreakValue, - MinIntrinsicSizingValue, - OverflowKeyword, - PositionValue, - RelativeSize, - TableLayoutValue, - TextAlignAllValue, - TextAlignLastValue, - TextAlignValue, - TextDecorationSkipInkValue, - TextDecorationStyleValue, - TextWrapValue, - VisibilityValue, - WhiteSpaceCollapseValue, -} - -impl<'a> WriteCss<'a> for TimeOrAuto { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} - -impl<'a> WriteCss<'a> for NoNonGlobalValuesAllowed { - fn write_css(&self, _sink: &mut W) -> Result { - Ok(()) - } -} - -impl<'a> WriteCss<'a> for ContentReplacement<'a> { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} - -impl<'a> WriteCss<'a> for InsetShorthand<'a> { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} - -impl<'a> WriteCss<'a> for RatioOrAuto { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} - -impl<'a> WriteCss<'a> for Angle { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Zero => sink.write_char('0'), - Self::Deg(val) => sink.write_str(&format!("{}deg", val)), - Self::Grad(val) => sink.write_str(&format!("{}grad", val)), - Self::Rad(val) => sink.write_str(&format!("{}rad", val)), - Self::Turn(val) => sink.write_str(&format!("{}turn", val)), - } - } -} diff --git a/crates/hdx_writer/src/css/values/non_standard.rs b/crates/hdx_writer/src/css/values/non_standard.rs deleted file mode 100644 index c2b91fb2..00000000 --- a/crates/hdx_writer/src/css/values/non_standard.rs +++ /dev/null @@ -1,14 +0,0 @@ -use hdx_ast::css::values::non_standard::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for ZoomValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Normal => sink.write_str("normal"), - Self::Reset => sink.write_str("reset"), - Self::Number(n) => sink.write_str(&n.to_string()), - Self::Percentage(n) => sink.write_str(&format!("{}%", n)), - } - } -} diff --git a/crates/hdx_writer/src/css/values/page_floats.rs b/crates/hdx_writer/src/css/values/page_floats.rs deleted file mode 100644 index 7cd7cf67..00000000 --- a/crates/hdx_writer/src/css/values/page_floats.rs +++ /dev/null @@ -1,26 +0,0 @@ -use hdx_ast::css::values::page_floats::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for FloatValue { - fn write_css(&self, sink: &mut W) -> Result { - if let Some(atom) = self.to_atom() { - sink.write_str(atom.as_ref())?; - } else if let FloatValue::SnapBlockFunction(first, second) = self { - first.write_css(sink)?; - sink.write_char(' ')?; - sink.write_str(second.to_atom().as_ref())?; - } else if let FloatValue::SnapInlineFunction(first, second) = self { - first.write_css(sink)?; - sink.write_char(' ')?; - sink.write_str(second.to_atom().as_ref())?; - } - Ok(()) - } -} - -impl<'a> WriteCss<'a> for FloatDeferValue { - fn write_css(&self, _sink: &mut W) -> Result { - todo!() - } -} diff --git a/crates/hdx_writer/src/css/values/shorthand.rs b/crates/hdx_writer/src/css/values/shorthand.rs deleted file mode 100644 index 72594c18..00000000 --- a/crates/hdx_writer/src/css/values/shorthand.rs +++ /dev/null @@ -1,84 +0,0 @@ -use hdx_ast::css::values::shorthand::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for BoxShorthand<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match &self.top { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => val.write_css(sink)?, - } - match &self.right { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => { - sink.write_char(' ')?; - val.write_css(sink)?; - } - } - match &self.bottom { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => { - sink.write_char(' ')?; - val.write_css(sink)?; - } - } - match &self.left { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => { - sink.write_char(' ')?; - val.write_css(sink)?; - } - } - Ok(()) - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for XYShorthand<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match &self.x { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => val.write_css(sink)?, - } - match &self.y { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => { - sink.write_char(' ')?; - val.write_css(sink)?; - } - } - Ok(()) - } -} - -impl<'a, T: WriteCss<'a>> WriteCss<'a> for DoubleShorthand<'a, T> { - fn write_css(&self, sink: &mut W) -> Result { - match &self.0 { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => val.write_css(sink)?, - } - match &self.1 { - Shorthand::Implicit => { - return Ok(()); - } - Shorthand::Explicit(val) => { - sink.write_char(' ')?; - val.write_css(sink)?; - } - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/size_adjust.rs b/crates/hdx_writer/src/css/values/size_adjust.rs deleted file mode 100644 index 96a2515f..00000000 --- a/crates/hdx_writer/src/css/values/size_adjust.rs +++ /dev/null @@ -1,13 +0,0 @@ -use hdx_ast::css::values::size_adjust::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for TextSizeAdjustValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::Auto => sink.write_str("auto"), - Self::Percentage(val) => sink.write_str(&format!("{}%", val)), - } - } -} diff --git a/crates/hdx_writer/src/css/values/sizing.rs b/crates/hdx_writer/src/css/values/sizing.rs deleted file mode 100644 index 327e1233..00000000 --- a/crates/hdx_writer/src/css/values/sizing.rs +++ /dev/null @@ -1,41 +0,0 @@ -use hdx_ast::css::values::sizing::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for Sizing { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Auto => sink.write_str("auto"), - Self::LengthPercentage(val) => val.write_css(sink), - Self::MinContent => sink.write_str("min-content"), - Self::MaxContent => sink.write_str("max-content"), - Self::FitContentFunction(val) => { - sink.write_str("fit-content(")?; - val.write_css(sink)?; - sink.write_char(')') - } - Self::Stretch => sink.write_str("stretch"), - Self::FitContent => sink.write_str("fit-content"), - Self::Contain => sink.write_str("contain"), - } - } -} - -impl<'a> WriteCss<'a> for MaxSizing { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::LengthPercentage(val) => val.write_css(sink), - Self::MinContent => sink.write_str("min-content"), - Self::MaxContent => sink.write_str("max-content"), - Self::FitContentFunction(val) => { - sink.write_str("fit-content(")?; - val.write_css(sink)?; - sink.write_char(')') - } - Self::Stretch => sink.write_str("stretch"), - Self::FitContent => sink.write_str("fit-content"), - Self::Contain => sink.write_str("contain"), - } - } -} diff --git a/crates/hdx_writer/src/css/values/text.rs b/crates/hdx_writer/src/css/values/text.rs deleted file mode 100644 index 5a19f3f2..00000000 --- a/crates/hdx_writer/src/css/values/text.rs +++ /dev/null @@ -1,59 +0,0 @@ -use hdx_ast::css::values::{text::*, Shorthand}; - -use crate::{CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for WhiteSpaceTrimValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::Discard { inner, after, before } => { - if *inner { - sink.write_str("discard-inner")?; - if *before { - sink.write_char(' ')?; - } - } - if *before { - sink.write_str("discard-before")?; - if *after { - sink.write_char(' ')?; - } - } - if *after { - sink.write_str("discard-after")?; - } - Ok(()) - } - } - } -} - -impl<'a> WriteCss<'a> for WhiteSpaceShorthand<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Normal => sink.write_str("normal")?, - Self::Pre => sink.write_str("pre")?, - Self::Nowrap => sink.write_str("nowrap")?, - Self::PreWrap => sink.write_str("pre-wrap")?, - Self::PreLine => sink.write_str("pre-line")?, - Self::Expanded { collapse, trim, wrap } => { - if let Shorthand::Explicit(value) = collapse { - value.write_css(sink)?; - if trim.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(value) = trim { - value.write_css(sink)?; - if wrap.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(value) = wrap { - value.write_css(sink)?; - } - } - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/text_decor.rs b/crates/hdx_writer/src/css/values/text_decor.rs deleted file mode 100644 index befe33ca..00000000 --- a/crates/hdx_writer/src/css/values/text_decor.rs +++ /dev/null @@ -1,56 +0,0 @@ -use hdx_ast::css::values::{text_decor::*, Shorthand}; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for TextDecorationLineValue { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::None => sink.write_str("none"), - Self::Style { underline, overline, line_through, blink } => { - if *underline { - sink.write_str("underline")?; - } - if *overline { - if *underline { - sink.write_char(' ')?; - } - sink.write_str("overline")?; - } - if *line_through { - if *underline || *overline { - sink.write_char(' ')?; - } - sink.write_str("line-through")?; - } - if *blink { - if *underline || *overline || *line_through { - sink.write_char(' ')?; - } - sink.write_str("blink")?; - } - Ok(()) - } - } - } -} - -impl<'a> WriteCss<'a> for TextDecorationShorthand<'a> { - fn write_css(&self, sink: &mut W) -> Result { - if let Shorthand::Explicit(color) = &self.color { - color.write_css(sink)?; - if self.style.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(line) = &self.line { - line.write_css(sink)?; - if self.style.is_explicit() { - sink.write_char(' ')?; - } - } - if let Shorthand::Explicit(style) = &self.style { - style.write_css(sink)?; - } - Ok(()) - } -} diff --git a/crates/hdx_writer/src/css/values/ui.rs b/crates/hdx_writer/src/css/values/ui.rs deleted file mode 100644 index cb49a064..00000000 --- a/crates/hdx_writer/src/css/values/ui.rs +++ /dev/null @@ -1,12 +0,0 @@ -use hdx_ast::css::values::ui::*; - -use crate::{Atomizable, CssWriter, Result, WriteCss}; - -impl<'a> WriteCss<'a> for CursorValue<'a> { - fn write_css(&self, sink: &mut W) -> Result { - match self { - Self::Custom(g) => todo!(), - _ => sink.write_str(self.to_atom().as_ref()), - } - } -} diff --git a/crates/hdx_writer/src/lib.rs b/crates/hdx_writer/src/lib.rs index 731fb153..8ce8751c 100644 --- a/crates/hdx_writer/src/lib.rs +++ b/crates/hdx_writer/src/lib.rs @@ -1,9 +1,9 @@ -pub(crate) use std::fmt::{Result, Write}; +pub use std::fmt::{Result, Write}; +use std::ops::Deref; -pub(crate) use hdx_ast::Spanned; -pub(crate) use hdx_atom::Atomizable; - -mod css; +use hdx_atom::Atom; +use hdx_parser::Spanned; +use oxc_allocator::Box; pub trait WriteCss<'a>: Sized { fn write_css(&self, sink: &mut W) -> Result; @@ -102,3 +102,45 @@ where } } } + +impl<'a, T: WriteCss<'a>> WriteCss<'a> for Option { + fn write_css(&self, sink: &mut W) -> Result { + if let Some(value) = self { value.write_css(sink) } else { Ok(()) } + } +} + +impl<'a, T: WriteCss<'a>> WriteCss<'a> for Box<'a, T> { + fn write_css(&self, sink: &mut W) -> Result { + self.deref().write_css(sink) + } +} + +impl<'a, T: WriteCss<'a>> WriteCss<'a> for Spanned { + fn write_css(&self, sink: &mut W) -> Result { + self.node.write_css(sink) + } +} + +impl<'a> WriteCss<'a> for Atom { + fn write_css(&self, sink: &mut W) -> Result { + sink.write_str(self.as_ref()) + } +} + +impl<'a> WriteCss<'a> for f32 { + fn write_css(&self, sink: &mut W) -> Result { + sink.write_str(self.to_string().as_str()) + } +} + +impl<'a> WriteCss<'a> for i32 { + fn write_css(&self, sink: &mut W) -> Result { + sink.write_str(self.to_string().as_str()) + } +} + +impl<'a> WriteCss<'a> for char { + fn write_css(&self, sink: &mut W) -> Result { + sink.write_char(*self) + } +} diff --git a/crates/hdx_writer/tests/tests.rs b/crates/hdx_writer/tests/tests.rs deleted file mode 100644 index cd888b78..00000000 --- a/crates/hdx_writer/tests/tests.rs +++ /dev/null @@ -1,30 +0,0 @@ -use hdx_parser::{Parser, ParserOptions}; -use hdx_writer::{BaseCssWriter, WriteCss}; -use oxc_allocator::Allocator; - -#[test] -fn smoke_test() { - let allocator = Allocator::default(); - let css = " - body { - padding-right: 1px; - } - "; - let result = Parser::new(&allocator, css, ParserOptions::default()).parse(); - let mut output = String::new(); - let mut writer = BaseCssWriter::new(&mut output, true); - result.output.unwrap().write_css(&mut writer).unwrap(); - assert_eq!(output, "body{padding-right:1px}"); -} - -#[test] -fn smoke_test_expand() { - let allocator = Allocator::default(); - let css = "body{padding-right:1px}"; - let result = Parser::new(&allocator, css, ParserOptions::default()).parse(); - let mut output = String::new(); - let mut writer = BaseCssWriter::new(&mut output, false); - result.output.unwrap().write_css(&mut writer).unwrap(); - let expected = "body {\n\tpadding-right: 1px;\n}\n"; - assert_eq!(output, expected); -} diff --git a/rustfmt.toml b/rustfmt.toml index de3c9933..bdb8ef6b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -21,3 +21,10 @@ imports_granularity = "Crate" # Use tab for alignment hard_tabs = true + +# Hard stop line length at 120 chars +max_width = 120 + +# Make comments a little more like prose and have them block to 80 chars +comment_width = 80 +wrap_comments = true diff --git a/tasks/benchmark/Cargo.toml b/tasks/benchmark/Cargo.toml index de82a30e..e765f241 100644 --- a/tasks/benchmark/Cargo.toml +++ b/tasks/benchmark/Cargo.toml @@ -13,6 +13,7 @@ repository.workspace = true [dependencies] hdx_lexer = { workspace = true, features = ["serde"] } hdx_parser = { workspace = true, features = ["serde"] } +hdx_ast = { workspace = true, features = ["serde"] } hdx_writer = { workspace = true, features = [] } # Use OXC Allocator until https://github.com/fitzgen/bumpalo/pull/210 is resolved diff --git a/tasks/benchmark/src/lib.rs b/tasks/benchmark/src/lib.rs index 13a1352f..bf9c8bb4 100644 --- a/tasks/benchmark/src/lib.rs +++ b/tasks/benchmark/src/lib.rs @@ -1,14 +1,13 @@ -use std::{ - fs::{read_to_string, write}, - path::PathBuf, - time::Duration, -}; +use std::{fs::read_to_string, path::PathBuf, time::Duration}; use criterion::{BenchmarkId, Criterion, Throughput}; use glob::glob; +use hdx_ast::css::StyleSheet; use hdx_lexer::Lexer; -use hdx_parser::{Parser, ParserOptions}; +use hdx_parser::{Parser, Features}; use hdx_writer::{BaseCssWriter, WriteCss}; +// use hdx_parser::{Parser, Features}; +// use hdx_writer::{BaseCssWriter, WriteCss}; use oxc_allocator::Allocator; /// # Panics @@ -33,8 +32,8 @@ struct TestFile { impl AppArgs { pub fn run_all(&self) { self.run_lexer(); - self.run_parser(); - self.run_minifier(); + // self.run_parser(); + // self.run_minifier(); } fn get_files(&self) -> Vec { @@ -50,32 +49,29 @@ impl AppArgs { pub fn run_lexer(&self) { let measurement_time = Duration::new(/* seconds */ 15, 0); - let mut criterion = Criterion::default().without_plots().measurement_time(measurement_time); + let mut criterion = Criterion::default().with_plots().measurement_time(measurement_time); if let Some(baseline) = &self.save { criterion = criterion.save_baseline(baseline.into()); } let mut group = criterion.benchmark_group("lexer"); for file in &self.get_files() { group.throughput(Throughput::Bytes(file.source_text.len() as u64)); - group.bench_with_input( - BenchmarkId::from_parameter(&file.name), - &file.source_text, - |b, source_text| { - b.iter_with_large_drop(|| { - // Include the allocator drop time to make time measurement consistent. - // Otherwise the allocator will allocate huge memory chunks (by power of two) from the - // system allocator, which makes time measurement unequal during long runs. - let allocator = Allocator::default(); - let mut lexer = Lexer::new(&allocator, source_text); - loop { - if lexer.next_token().kind == hdx_lexer::Kind::Eof { - break; - } + group.bench_with_input(BenchmarkId::from_parameter(&file.name), &file.source_text, |b, source_text| { + b.iter_with_large_drop(|| { + // Include the allocator drop time to make time measurement consistent. + // Otherwise the allocator will allocate huge memory chunks (by power of two) + // from the system allocator, which makes time measurement unequal during long + // runs. + let allocator = Allocator::default(); + let mut lexer = Lexer::new(&allocator, source_text); + loop { + if lexer.advance() == hdx_lexer::Token::Eof { + break; } - allocator - }); - }, - ); + } + allocator + }); + }); } group.finish(); drop(criterion); @@ -83,25 +79,20 @@ impl AppArgs { pub fn run_parser(&self) { let measurement_time = Duration::new(/* seconds */ 15, 0); - let mut criterion = Criterion::default().without_plots().measurement_time(measurement_time); + let mut criterion = Criterion::default().with_plots().measurement_time(measurement_time); if let Some(baseline) = &self.save { criterion = criterion.save_baseline(baseline.into()); } let mut group = criterion.benchmark_group("parser"); for file in &self.get_files() { group.throughput(Throughput::Bytes(file.source_text.len() as u64)); - group.bench_with_input( - BenchmarkId::from_parameter(&file.name), - &file.source_text, - |b, source_text| { - b.iter_with_large_drop(|| { - let allocator = Allocator::default(); - let _ = - Parser::new(&allocator, source_text, ParserOptions::default()).parse(); - allocator - }); - }, - ); + group.bench_with_input(BenchmarkId::from_parameter(&file.name), &file.source_text, |b, source_text| { + b.iter_with_large_drop(|| { + let allocator = Allocator::default(); + let _ = Parser::new(&allocator, source_text, Features::default()).parse_with::(); + allocator + }); + }); } group.finish(); drop(criterion); @@ -109,34 +100,30 @@ impl AppArgs { pub fn run_minifier(&self) { let measurement_time = Duration::new(/* seconds */ 15, 0); - let mut criterion = Criterion::default().without_plots().measurement_time(measurement_time); + let mut criterion = Criterion::default().with_plots().measurement_time(measurement_time); if let Some(baseline) = &self.save { criterion = criterion.save_baseline(baseline.into()); } let mut group = criterion.benchmark_group("minify"); for file in &self.get_files() { group.throughput(Throughput::Bytes(file.source_text.len() as u64)); - group.bench_with_input( - BenchmarkId::from_parameter(&file.name), - &file.source_text, - |b, source_text| { - b.iter_with_large_drop(|| { - let allocator = Allocator::default(); - let result = - Parser::new(&allocator, source_text.as_str(), ParserOptions::default()) - .parse(); - { - let mut string = String::new(); - let mut writer = BaseCssWriter::new(&mut string, true); - if let Some(stylesheet) = &result.output { - let _ = stylesheet.write_css(&mut writer).unwrap().to_owned(); - } + group.bench_with_input(BenchmarkId::from_parameter(&file.name), &file.source_text, |b, source_text| { + b.iter_with_large_drop(|| { + let allocator = Allocator::default(); + let result = + Parser::new(&allocator, source_text.as_str(), Features::default()).parse_with::(); + { + let mut string = String::new(); + let mut writer = BaseCssWriter::new(&mut string, true); + if let Some(stylesheet) = &result.output { + let _ = stylesheet.write_css(&mut writer).unwrap().to_owned(); } - // TODO: - // Figure out how to drop allocator without borrow checker complaining. - }); - }, - ); + } + // TODO: + // Figure out how to drop allocator without borrow checker + // complaining. + }); + }); } group.finish(); drop(criterion); diff --git a/tasks/benchmark/src/main.rs b/tasks/benchmark/src/main.rs index 49defcde..d492a8b7 100644 --- a/tasks/benchmark/src/main.rs +++ b/tasks/benchmark/src/main.rs @@ -13,9 +13,9 @@ fn main() { let task = command.as_deref().unwrap_or("default"); match task { - "parser" => args.run_parser(), + // "parser" => args.run_parser(), "lexer" => args.run_lexer(), - "minifier" => args.run_minifier(), + // "minifier" => args.run_minifier(), _ => args.run_all(), }; } diff --git a/tasks/coverage/Cargo.toml b/tasks/coverage/Cargo.toml index 571892f3..d96713d2 100644 --- a/tasks/coverage/Cargo.toml +++ b/tasks/coverage/Cargo.toml @@ -11,7 +11,9 @@ license.workspace = true repository.workspace = true [dependencies] +hdx_atom = { workspace = true, features = ["serde"] } hdx_lexer = { workspace = true, features = ["serde"] } +hdx_ast = { workspace = true, features = ["serde"] } hdx_parser = { workspace = true, features = ["serde"] } # Use OXC Allocator until https://github.com/fitzgen/bumpalo/pull/210 is resolved @@ -26,7 +28,6 @@ pico-args = { workspace = true } project-root = { workspace = true } similar = { workspace = true } -cssparser = "0.31.2" console = "0.15.7" encoding_rs = "0.8.32" encoding_rs_io = "0.1.7" diff --git a/tasks/coverage/src/lexer_suite.rs b/tasks/coverage/src/lexer_suite.rs index c6a012f7..6e4afe90 100644 --- a/tasks/coverage/src/lexer_suite.rs +++ b/tasks/coverage/src/lexer_suite.rs @@ -103,7 +103,7 @@ pub trait LexerCase: Sized { let mut tokens = vec![]; let mut pos = 0; loop { - let token = lexer.next_token(); + let token = lexer.advance_including_whitespace_and_comments(); if token == Token::Eof { break; } diff --git a/tasks/coverage/src/parser_suite.rs b/tasks/coverage/src/parser_suite.rs index 248f94f1..0b032a33 100644 --- a/tasks/coverage/src/parser_suite.rs +++ b/tasks/coverage/src/parser_suite.rs @@ -5,7 +5,8 @@ use std::{ }; use console::Style; -use hdx_parser::{CSSStyleSheet, Parser, ParserOptions, Spanned}; +use hdx_ast::css::StyleSheet; +use hdx_parser::{Features, Parser, Spanned}; use miette::{GraphicalReportHandler, GraphicalTheme, NamedSource, Report}; use oxc_allocator::Allocator; use serde::Serialize; @@ -108,11 +109,11 @@ pub trait ParserCase: Sized + Sync + Send + UnwindSafe { fn path(&self) -> &Path; fn desired(&self) -> &Self::AST; fn update_desired(&self, ast: &Self::AST); - fn convert_ast(&self, ast: &Spanned) -> Self::AST; + fn convert_ast(&self, ast: &Spanned) -> Self::AST; fn desired_warnings(&self) -> String; fn update_warnings(&self, warnings: String); - fn parser_options(&self, _args: &AppArgs) -> ParserOptions { - ParserOptions::default() + fn parser_options(&self, _args: &AppArgs) -> Features { + Features::default() } /// Execute the parser once and get the test result @@ -121,14 +122,11 @@ pub trait ParserCase: Sized + Sync + Send + UnwindSafe { let source_text = self.source_text().to_owned(); let source_path = self.path(); let parser = Parser::new(&allocator, &source_text, self.parser_options(args)); - let ret = parser.parse(); + let ret = parser.parse_with::(); let handler = GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor()); let mut warnings = String::new(); for warn in ret.warnings { - let warn = warn.with_source_code(NamedSource::new( - source_path.to_str().unwrap(), - source_text.to_string(), - )); + let warn = warn.with_source_code(NamedSource::new(source_path.to_str().unwrap(), source_text.to_string())); handler.render_report(&mut warnings, warn.as_ref()).unwrap(); } println!("{}", &warnings); diff --git a/tasks/coverage/src/popular_parser.rs b/tasks/coverage/src/popular_parser.rs index 977389fe..ec01e69a 100644 --- a/tasks/coverage/src/popular_parser.rs +++ b/tasks/coverage/src/popular_parser.rs @@ -4,7 +4,8 @@ use std::{ }; use glob::glob; -use hdx_parser::{CSSStyleSheet, Spanned}; +use hdx_ast::css::StyleSheet; +use hdx_parser::Spanned; use serde_json::{from_str, to_string_pretty, Value}; use crate::{ @@ -89,7 +90,7 @@ impl ParserCase for PopularParserTestCase { write(self.warnings_path.clone(), warnings).unwrap(); } - fn convert_ast(&self, ast: &Spanned) -> Value { + fn convert_ast(&self, ast: &Spanned) -> Value { from_str::(&to_string_pretty(ast).unwrap()).unwrap() } } diff --git a/tasks/coverage/src/postcss_parser.rs b/tasks/coverage/src/postcss_parser.rs index 1c039c9d..89995257 100644 --- a/tasks/coverage/src/postcss_parser.rs +++ b/tasks/coverage/src/postcss_parser.rs @@ -4,7 +4,8 @@ use std::{ }; use glob::glob; -use hdx_parser::{CSSStyleSheet, Spanned}; +use hdx_ast::css::StyleSheet; +use hdx_parser::Spanned; use serde_json::{from_str, to_string_pretty, Value}; use crate::{ @@ -47,11 +48,9 @@ impl PostCSSParserTestCase { let json_path: PathBuf = (SNAPSHOTS_PATH.to_owned() + name.as_str() + ".json").into(); let warnings_path: PathBuf = (SNAPSHOTS_PATH.to_owned() + name.as_str() + ".txt").into(); let source_text = read_to_string(&source_path).unwrap(); - let desired: Value = - from_str(read_to_string(json_path.clone()).unwrap_or("{}".to_owned()).as_str()) - .unwrap_or_else(|e| panic!("{} {}", json_path.display(), e)); - let warnings: String = - read_to_string(warnings_path.clone()).unwrap_or("".to_owned()).as_str().to_owned(); + let desired: Value = from_str(read_to_string(json_path.clone()).unwrap_or("{}".to_owned()).as_str()) + .unwrap_or_else(|e| panic!("{} {}", json_path.display(), e)); + let warnings: String = read_to_string(warnings_path.clone()).unwrap_or("".to_owned()).as_str().to_owned(); Self { name, source_path, json_path, source_text, desired, warnings_path, warnings } } } @@ -89,7 +88,7 @@ impl ParserCase for PostCSSParserTestCase { write(self.warnings_path.clone(), warnings).unwrap(); } - fn convert_ast(&self, ast: &Spanned) -> Value { + fn convert_ast(&self, ast: &Spanned) -> Value { from_str::(&to_string_pretty(ast).unwrap()).unwrap() } } diff --git a/tasks/coverage/src/romainmenke.rs b/tasks/coverage/src/romainmenke.rs index 5cd65d7f..777c90f6 100644 --- a/tasks/coverage/src/romainmenke.rs +++ b/tasks/coverage/src/romainmenke.rs @@ -180,11 +180,11 @@ impl LexerCase for CSSTokenizerTestCase { fn convert_token(&self, start: usize, end: usize, token: &Token) -> RomainToken { let raw = self.source_text[start..end].to_string(); let structured = match &token { - Token::Number(numtype, value) => Some(Structured::Number(NumberStructured { + Token::Number(value, numtype) => Some(Structured::Number(NumberStructured { value: *value, kind: Some(String::from(if numtype.is_int() { "integer" } else { "number" })), })), - Token::Dimension(numtype, value, unit) => { + Token::Dimension(value, unit, numtype) => { if unit == &atom!("%") { Some(Structured::Number(NumberStructured { value: *value, kind: None })) } else { @@ -213,7 +213,7 @@ impl LexerCase for CSSTokenizerTestCase { let end_index = start_index + raw.encode_utf16().count() as u32; RomainToken { kind: match token { - Token::Comment => RomainKind::Comment, + Token::Comment(_) => RomainKind::Comment, Token::Ident(_) => RomainKind::Ident, Token::Function(_) => RomainKind::Function, Token::AtKeyword(_) => RomainKind::AtKeyword, @@ -225,7 +225,7 @@ impl LexerCase for CSSTokenizerTestCase { Token::BadUrl => RomainKind::BadUrl, Token::Delim(_) => RomainKind::Delim, Token::Number(_, _) => RomainKind::Number, - Token::Dimension(_, _, unit) => { + Token::Dimension(_, unit, _) => { if unit == &atom!("%") { RomainKind::Percentage } else {