1#![deny(missing_docs)]
92
93pub mod align;
94pub mod animation;
95pub mod background;
96pub mod border;
97pub mod border_image;
98pub mod border_radius;
99pub mod box_shadow;
100pub mod contain;
101pub mod css_modules;
102pub mod custom;
103pub mod display;
104pub mod effects;
105pub mod flex;
106pub mod font;
107#[cfg(feature = "grid")]
108pub mod grid;
109pub mod list;
110pub(crate) mod margin_padding;
111pub mod masking;
112pub mod outline;
113pub mod overflow;
114pub mod position;
115pub(crate) mod prefix_handler;
116pub mod size;
117pub mod svg;
118pub mod text;
119pub mod transform;
120pub mod transition;
121pub mod ui;
122
123use crate::declaration::DeclarationBlock;
124use crate::error::{ParserError, PrinterError};
125use crate::logical::{LogicalGroup, PropertyCategory};
126use crate::macros::enum_property;
127use crate::parser::starts_with_ignore_ascii_case;
128use crate::parser::ParserOptions;
129use crate::prefixes::Feature;
130use crate::printer::{Printer, PrinterOptions};
131use crate::targets::Targets;
132use crate::traits::{Parse, ParseWithOptions, Shorthand, ToCss};
133use crate::values::number::{CSSInteger, CSSNumber};
134use crate::values::string::CowArcStr;
135use crate::values::{
136 alpha::*, color::*, easing::EasingFunction, ident::DashedIdentReference, ident::NoneOrCustomIdentList, image::*,
137 length::*, position::*, rect::*, shape::FillRule, size::Size2D, time::Time,
138};
139use crate::vendor_prefix::VendorPrefix;
140#[cfg(feature = "visitor")]
141use crate::visitor::Visit;
142use align::*;
143use animation::*;
144use background::*;
145use border::*;
146use border_image::*;
147use border_radius::*;
148use box_shadow::*;
149use contain::*;
150use css_modules::*;
151use cssparser::*;
152use custom::*;
153use display::*;
154use effects::*;
155use flex::*;
156use font::*;
157#[cfg(feature = "grid")]
158use grid::*;
159use list::*;
160use margin_padding::*;
161use masking::*;
162use outline::*;
163use overflow::*;
164use size::*;
165use smallvec::{smallvec, SmallVec};
166#[cfg(feature = "into_owned")]
167use static_self::IntoOwned;
168use svg::*;
169use text::*;
170use transform::*;
171use transition::*;
172use ui::*;
173
174macro_rules! define_properties {
175 (
176 $(
177 $(#[$meta: meta])*
178 $name: literal: $property: ident($type: ty $(, $vp: ty)?) $( / $prefix: ident )* $( unprefixed: $unprefixed: literal )? $( options: $options: literal )? $( shorthand: $shorthand: literal )? $( [ logical_group: $logical_group: ident, category: $logical_category: ident ] )? $( if $condition: ident )?,
179 )+
180 ) => {
181 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
183 #[cfg_attr(feature = "visitor", derive(Visit))]
184 #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
185 pub enum PropertyId<'i> {
186 $(
187 #[doc=concat!("The `", $name, "` property.")]
188 $(#[$meta])*
189 $property$(($vp))?,
190 )+
191 All,
193 Custom(CustomPropertyName<'i>)
195 }
196
197 macro_rules! vp_name {
198 ($x: ty, $n: ident) => {
199 $n
200 };
201 ($x: ty, $n: expr) => {
202 $n
203 };
204 }
205
206 macro_rules! get_allowed_prefixes {
207 ($v: literal) => {
208 VendorPrefix::empty()
209 };
210 () => {
211 VendorPrefix::None
212 };
213 }
214
215 impl<'i> From<CowArcStr<'i>> for PropertyId<'i> {
216 fn from(name: CowArcStr<'i>) -> PropertyId<'i> {
217 let name_ref = name.as_ref();
218 let (prefix, name_ref) = if starts_with_ignore_ascii_case(name_ref, "-webkit-") {
219 (VendorPrefix::WebKit, &name_ref[8..])
220 } else if starts_with_ignore_ascii_case(name_ref, "-moz-") {
221 (VendorPrefix::Moz, &name_ref[5..])
222 } else if starts_with_ignore_ascii_case(name_ref, "-o-") {
223 (VendorPrefix::O, &name_ref[3..])
224 } else if starts_with_ignore_ascii_case(name_ref, "-ms-") {
225 (VendorPrefix::Ms, &name_ref[4..])
226 } else {
227 (VendorPrefix::None, name_ref)
228 };
229
230 Self::from_name_and_prefix(name_ref, prefix)
231 .unwrap_or_else(|_| PropertyId::Custom(name.into()))
232 }
233 }
234
235 impl<'i> From<&'i str> for PropertyId<'i> {
236 #[inline]
237 fn from(name: &'i str) -> PropertyId<'i> {
238 PropertyId::from(CowArcStr::from(name))
239 }
240 }
241
242 impl<'i> Parse<'i> for PropertyId<'i> {
243 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
244 let name = input.expect_ident()?;
245 Ok(CowArcStr::from(name).into())
246 }
247 }
248
249 impl<'i> ToCss for PropertyId<'i> {
250 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
251 let mut first = true;
252 macro_rules! delim {
253 () => {
254 #[allow(unused_assignments)]
255 if first {
256 first = false;
257 } else {
258 dest.delim(',', false)?;
259 }
260 };
261 }
262
263 let name = self.name();
264 for p in self.prefix().or_none() {
265 delim!();
266 p.to_css(dest)?;
267 dest.write_str(name)?;
268 }
269
270 Ok(())
271 }
272 }
273
274 impl<'i> PropertyId<'i> {
275 fn from_name_and_prefix(name: &str, prefix: VendorPrefix) -> Result<Self, ()> {
276 match_ignore_ascii_case! { name.as_ref(),
277 $(
278 $(#[$meta])*
279 $name => {
280 macro_rules! get_propertyid {
281 ($v: ty) => {
282 PropertyId::$property(prefix)
283 };
284 () => {
285 PropertyId::$property
286 };
287 }
288
289 let allowed_prefixes = get_allowed_prefixes!($($unprefixed)?) $(| VendorPrefix::$prefix)*;
290 if allowed_prefixes.contains(prefix) {
291 return Ok(get_propertyid!($($vp)?))
292 }
293 },
294 )+
295 "all" => return Ok(PropertyId::All),
296 _ => {}
297 }
298
299 Err(())
300 }
301
302 pub fn prefix(&self) -> VendorPrefix {
304 use PropertyId::*;
305 match self {
306 $(
307 $(#[$meta])*
308 $property$((vp_name!($vp, prefix)))? => {
309 $(
310 macro_rules! return_prefix {
311 ($v: ty) => {
312 return *prefix;
313 };
314 }
315
316 return_prefix!($vp);
317 )?
318 #[allow(unreachable_code)]
319 VendorPrefix::empty()
320 },
321 )+
322 _ => VendorPrefix::empty()
323 }
324 }
325
326 pub(crate) fn with_prefix(&self, prefix: VendorPrefix) -> PropertyId<'i> {
327 use PropertyId::*;
328 match self {
329 $(
330 $(#[$meta])*
331 $property$((vp_name!($vp, _p)))? => {
332 macro_rules! get_prefixed {
333 ($v: ty) => {
334 PropertyId::$property(prefix)
335 };
336 () => {
337 PropertyId::$property
338 }
339 }
340
341 get_prefixed!($($vp)?)
342 },
343 )+
344 _ => self.clone()
345 }
346 }
347
348 pub(crate) fn add_prefix(&mut self, prefix: VendorPrefix) {
349 use PropertyId::*;
350 match self {
351 $(
352 $(#[$meta])*
353 $property$((vp_name!($vp, p)))? => {
354 macro_rules! get_prefixed {
355 ($v: ty) => {{
356 *p |= prefix;
357 }};
358 () => {{}};
359 }
360
361 get_prefixed!($($vp)?)
362 },
363 )+
364 _ => {}
365 }
366 }
367
368 pub(crate) fn set_prefixes_for_targets(&mut self, targets: Targets) {
369 match self {
370 $(
371 $(#[$meta])*
372 #[allow(unused_variables)]
373 PropertyId::$property$((vp_name!($vp, prefix)))? => {
374 macro_rules! get_prefixed {
375 ($v: ty, $u: literal) => {};
376 ($v: ty) => {{
377 *prefix = targets.prefixes(*prefix, Feature::$property);
378 }};
379 () => {};
380 }
381
382 get_prefixed!($($vp)? $(, $unprefixed)?);
383 },
384 )+
385 _ => {}
386 }
387 }
388
389 pub fn name(&self) -> &str {
391 use PropertyId::*;
392
393 match self {
394 $(
395 $(#[$meta])*
396 $property$((vp_name!($vp, _p)))? => $name,
397 )+
398 All => "all",
399 Custom(name) => name.as_ref()
400 }
401 }
402
403 pub fn is_shorthand(&self) -> bool {
405 $(
406 macro_rules! shorthand {
407 ($s: literal) => {
408 if let PropertyId::$property$((vp_name!($vp, _prefix)))? = self {
409 return true
410 }
411 };
412 () => {}
413 }
414
415 shorthand!($($shorthand)?);
416 )+
417
418 false
419 }
420
421 pub(crate) fn shorthand_value<'a>(&self, decls: &DeclarationBlock<'a>) -> Option<(Property<'a>, bool)> {
423 #[inline]
425 fn shorthand_value<'a, 'i>(property_id: &PropertyId<'a>, decls: &DeclarationBlock<'i>) -> Option<(Property<'i>, bool)> {
426 $(
427 #[allow(unused_macros)]
428 macro_rules! prefix {
429 ($v: ty, $p: ident) => {
430 *$p
431 };
432 ($p: ident) => {
433 VendorPrefix::None
434 };
435 }
436
437 macro_rules! shorthand {
438 ($s: literal) => {
439 if let PropertyId::$property$((vp_name!($vp, prefix)))? = &property_id {
440 if let Some((val, important)) = <$type>::from_longhands(decls, prefix!($($vp,)? prefix)) {
441 return Some((Property::$property(val $(, *vp_name!($vp, prefix))?), important))
442 }
443 }
444 };
445 () => {}
446 }
447
448 shorthand!($($shorthand)?);
449 )+
450
451 None
452 }
453
454 shorthand_value(self, decls)
455 }
456
457 pub fn longhands(&self) -> Option<Vec<PropertyId<'static>>> {
459 macro_rules! prefix_default {
460 ($x: ty, $p: ident) => {
461 *$p
462 };
463 () => {
464 VendorPrefix::None
465 };
466 }
467
468 $(
469 macro_rules! shorthand {
470 ($s: literal) => {
471 if let PropertyId::$property$((vp_name!($vp, prefix)))? = self {
472 return Some(<$type>::longhands(prefix_default!($($vp, prefix)?)));
473 }
474 };
475 () => {}
476 }
477
478 shorthand!($($shorthand)?);
479 )+
480
481 None
482 }
483
484 pub(crate) fn logical_group(&self) -> Option<LogicalGroup> {
486 $(
487 macro_rules! group {
488 ($g: ident) => {
489 if let PropertyId::$property$((vp_name!($vp, _prefix)))? = self {
490 return Some(LogicalGroup::$g)
491 }
492 };
493 () => {}
494 }
495
496 group!($($logical_group)?);
497 )+
498
499 None
500 }
501
502 pub(crate) fn category(&self) -> Option<PropertyCategory> {
504 $(
505 macro_rules! category {
506 ($c: ident) => {
507 if let PropertyId::$property$((vp_name!($vp, _prefix)))? = self {
508 return Some(PropertyCategory::$c)
509 }
510 };
511 () => {}
512 }
513
514 category!($($logical_category)?);
515 )+
516
517 None
518 }
519 }
520
521 #[cfg(feature = "serde")]
522 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
523 impl<'i> serde::Serialize for PropertyId<'i> {
524 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
525 where
526 S: serde::Serializer,
527 {
528 use serde::ser::SerializeStruct;
529
530 let name = self.name();
531 let prefix = self.prefix();
532
533 if prefix.is_empty() {
534 let mut s = serializer.serialize_struct("PropertyId", 1)?;
535 s.serialize_field("property", name)?;
536 s.end()
537 } else {
538 let mut s = serializer.serialize_struct("PropertyId", 2)?;
539 s.serialize_field("property", name)?;
540 s.serialize_field("vendor_prefix", &prefix)?;
541 s.end()
542 }
543 }
544 }
545
546 #[cfg(feature = "serde")]
547 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
548 impl<'i, 'de: 'i> serde::Deserialize<'de> for PropertyId<'i> {
549 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
550 where
551 D: serde::Deserializer<'de>,
552 {
553 #[derive(serde::Deserialize)]
554 #[serde(field_identifier, rename_all = "snake_case")]
555 enum Field {
556 Property,
557 VendorPrefix
558 }
559
560 struct PropertyIdVisitor;
561 impl<'de> serde::de::Visitor<'de> for PropertyIdVisitor {
562 type Value = PropertyId<'de>;
563
564 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
565 formatter.write_str("a PropertyId")
566 }
567
568 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
569 where
570 A: serde::de::MapAccess<'de>,
571 {
572 let mut property: Option<CowArcStr> = None;
573 let mut vendor_prefix = None;
574 while let Some(key) = map.next_key()? {
575 match key {
576 Field::Property => {
577 property = Some(map.next_value()?);
578 }
579 Field::VendorPrefix => {
580 vendor_prefix = Some(map.next_value()?);
581 }
582 }
583 }
584
585 let property = property.ok_or_else(|| serde::de::Error::missing_field("property"))?;
586 let vendor_prefix = vendor_prefix.unwrap_or(VendorPrefix::None);
587 let property_id = PropertyId::from_name_and_prefix(property.as_ref(), vendor_prefix)
588 .unwrap_or_else(|_| PropertyId::Custom(property.into()));
589 Ok(property_id)
590 }
591 }
592
593 deserializer.deserialize_any(PropertyIdVisitor)
594 }
595 }
596
597 #[cfg(feature = "jsonschema")]
598 #[cfg_attr(docsrs, doc(cfg(feature = "jsonschema")))]
599 impl<'i> schemars::JsonSchema for PropertyId<'i> {
600 fn is_referenceable() -> bool {
601 true
602 }
603
604 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
605 macro_rules! property {
606 ($n: literal) => {
607 fn property(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
608 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
609 instance_type: Some(schemars::schema::InstanceType::String.into()),
610 enum_values: Some(vec![$n.into()]),
611 ..Default::default()
612 })
613 }
614 }
615 }
616
617 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
618 subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
619 one_of: Some(vec![
620 $(
621 {
622 property!($name);
623
624 macro_rules! with_prefix {
625 ($v: ty) => {{
626 #[derive(schemars::JsonSchema)]
627 struct T<'i> {
628 #[schemars(rename = "property", schema_with = "property")]
629 _property: &'i u8,
630 #[schemars(rename = "vendorPrefix")]
631 _vendor_prefix: VendorPrefix,
632 }
633
634 T::json_schema(gen)
635 }};
636 () => {{
637 #[derive(schemars::JsonSchema)]
638 struct T<'i> {
639 #[schemars(rename = "property", schema_with = "property")]
640 _property: &'i u8,
641 }
642
643 T::json_schema(gen)
644 }};
645 }
646
647 with_prefix!($($vp)?)
648 },
649 )+
650 {
651 property!("all");
652
653 #[derive(schemars::JsonSchema)]
654 struct T<'i> {
655 #[schemars(rename = "property", schema_with = "property")]
656 _property: &'i u8,
657 }
658
659 T::json_schema(gen)
660 },
661 {
662 #[derive(schemars::JsonSchema)]
663 struct T {
664 #[schemars(rename = "property")]
665 _property: String,
666 }
667
668 T::json_schema(gen)
669 }
670 ]),
671 ..Default::default()
672 })),
673 ..Default::default()
674 })
675 }
676
677 fn schema_name() -> String {
678 "PropertyId".into()
679 }
680 }
681
682 #[derive(Debug, Clone, PartialEq)]
684 #[cfg_attr(feature = "visitor", derive(Visit), visit(visit_property, PROPERTIES))]
685 #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
686 pub enum Property<'i> {
687 $(
688 #[doc=concat!("The `", $name, "` property.")]
689 $(#[$meta])*
690 $property($type, $($vp)?),
691 )+
692 All(CSSWideKeyword),
694 Unparsed(UnparsedProperty<'i>),
696 Custom(CustomProperty<'i>),
698 }
699
700 impl<'i> Property<'i> {
701 pub fn parse<'t>(property_id: PropertyId<'i>, input: &mut Parser<'i, 't>, options: &ParserOptions<'_, 'i>) -> Result<Property<'i>, ParseError<'i, ParserError<'i>>> {
703 let state = input.state();
704
705 match property_id {
706 $(
707 $(#[$meta])*
708 PropertyId::$property$((vp_name!($vp, prefix)))? $(if options.$condition.is_some())? => {
709 if let Ok(c) = <$type>::parse_with_options(input, options) {
710 if input.expect_exhausted().is_ok() {
711 return Ok(Property::$property(c $(, vp_name!($vp, prefix))?))
712 }
713 }
714 },
715 )+
716 PropertyId::All => return Ok(Property::All(CSSWideKeyword::parse(input)?)),
717 PropertyId::Custom(name) => return Ok(Property::Custom(CustomProperty::parse(name, input, options)?)),
718 _ => {}
719 };
720
721 input.reset(&state);
726 return Ok(Property::Unparsed(UnparsedProperty::parse(property_id, input, options)?))
727 }
728
729 pub fn property_id(&self) -> PropertyId<'i> {
731 use Property::*;
732
733 match self {
734 $(
735 $(#[$meta])*
736 $property(_, $(vp_name!($vp, p))?) => PropertyId::$property$((*vp_name!($vp, p)))?,
737 )+
738 All(_) => PropertyId::All,
739 Unparsed(unparsed) => unparsed.property_id.clone(),
740 Custom(custom) => PropertyId::Custom(custom.name.clone())
741 }
742 }
743
744 pub fn parse_string(property_id: PropertyId<'i>, input: &'i str, options: ParserOptions<'_, 'i>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
746 let mut input = ParserInput::new(input);
747 let mut parser = Parser::new(&mut input);
748 Self::parse(property_id, &mut parser, &options)
749 }
750
751 pub fn set_prefix(&mut self, prefix: VendorPrefix) {
757 use Property::*;
758 match self {
759 $(
760 $(#[$meta])*
761 $property(_, $(vp_name!($vp, p))?) => {
762 macro_rules! set {
763 ($v: ty) => {
764 *p = (prefix & (get_allowed_prefixes!($($unprefixed)?) $(| VendorPrefix::$prefix)*)).or(*p);
765 };
766 () => {};
767 }
768
769 set!($($vp)?);
770 },
771 )+
772 _ => {}
773 }
774 }
775
776 pub fn value_to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
778 use Property::*;
779
780 match self {
781 $(
782 $(#[$meta])*
783 $property(val, $(vp_name!($vp, _p))?) => {
784 val.to_css(dest)
785 }
786 )+
787 All(keyword) => keyword.to_css(dest),
788 Unparsed(unparsed) => {
789 unparsed.value.to_css(dest, false)
790 }
791 Custom(custom) => {
792 custom.value.to_css(dest, matches!(custom.name, CustomPropertyName::Custom(..)))
793 }
794 }
795 }
796
797 pub fn value_to_css_string(&self, options: PrinterOptions) -> Result<String, PrinterError> {
799 let mut s = String::new();
800 let mut printer = Printer::new(&mut s, options);
801 self.value_to_css(&mut printer)?;
802 Ok(s)
803 }
804
805 pub fn to_css<W>(&self, dest: &mut Printer<W>, important: bool) -> Result<(), PrinterError> where W: std::fmt::Write {
807 use Property::*;
808
809 let mut first = true;
810 macro_rules! start {
811 () => {
812 #[allow(unused_assignments)]
813 if first {
814 first = false;
815 } else {
816 dest.write_char(';')?;
817 dest.newline()?;
818 }
819 };
820 }
821
822 macro_rules! write_important {
823 () => {
824 if important {
825 dest.whitespace()?;
826 dest.write_str("!important")?;
827 }
828 }
829 }
830
831 let (name, prefix) = match self {
832 $(
833 $(#[$meta])*
834 $property(_, $(vp_name!($vp, prefix))?) => {
835 macro_rules! get_prefix {
836 ($v: ty) => {
837 *prefix
838 };
839 () => {
840 VendorPrefix::None
841 };
842 }
843
844 ($name, get_prefix!($($vp)?))
845 },
846 )+
847 All(_) => ("all", VendorPrefix::None),
848 Unparsed(unparsed) => {
849 let mut prefix = unparsed.property_id.prefix();
850 if prefix.is_empty() {
851 prefix = VendorPrefix::None;
852 }
853 (unparsed.property_id.name(), prefix)
854 },
855 Custom(custom) => {
856 custom.name.to_css(dest)?;
857 dest.delim(':', false)?;
858 self.value_to_css(dest)?;
859 write_important!();
860 return Ok(())
861 }
862 };
863 for p in prefix {
864 start!();
865 p.to_css(dest)?;
866 dest.write_str(name)?;
867 dest.delim(':', false)?;
868 self.value_to_css(dest)?;
869 write_important!();
870 }
871 Ok(())
872 }
873
874 pub fn to_css_string(&self, important: bool, options: PrinterOptions) -> Result<String, PrinterError> {
876 let mut s = String::new();
877 let mut printer = Printer::new(&mut s, options);
878 self.to_css(&mut printer, important)?;
879 Ok(s)
880 }
881
882 pub fn longhand(&self, property_id: &PropertyId) -> Option<Property<'i>> {
884 $(
885 macro_rules! shorthand {
886 ($s: literal) => {
887 if let Property::$property(val $(, vp_name!($vp, prefix))?) = self {
888 $(
889 if *vp_name!($vp, prefix) != property_id.prefix() {
890 return None
891 }
892 )?
893 return val.longhand(property_id)
894 }
895 };
896 () => {}
897 }
898
899 shorthand!($($shorthand)?);
900 )+
901
902 None
903 }
904
905 pub fn set_longhand(&mut self, property: &Property<'i>) -> Result<(), ()> {
907 $(
908 macro_rules! shorthand {
909 ($s: literal) => {
910 if let Property::$property(val $(, vp_name!($vp, prefix))?) = self {
911 $(
912 if *vp_name!($vp, prefix) != property.property_id().prefix() {
913 return Err(())
914 }
915 )?
916 return val.set_longhand(property)
917 }
918 };
919 () => {}
920 }
921
922 shorthand!($($shorthand)?);
923 )+
924 Err(())
925 }
926 }
927
928 #[cfg(feature = "serde")]
929 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
930 impl<'i> serde::Serialize for Property<'i> {
931 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
932 where
933 S: serde::Serializer,
934 {
935 use serde::ser::SerializeStruct;
936 use Property::*;
937
938 match self {
939 Unparsed(unparsed) => {
940 let mut s = serializer.serialize_struct("Property", 2)?;
941 s.serialize_field("property", "unparsed")?;
942 s.serialize_field("value", unparsed)?;
943 return s.end()
944 }
945 Custom(unparsed) => {
946 let mut s = serializer.serialize_struct("Property", 2)?;
947 s.serialize_field("property", "custom")?;
948 s.serialize_field("value", unparsed)?;
949 return s.end()
950 }
951 _ => {}
952 }
953
954 let id = self.property_id();
955 let name = id.name();
956 let prefix = id.prefix();
957
958 let mut s = if prefix.is_empty() {
959 let mut s = serializer.serialize_struct("Property", 2)?;
960 s.serialize_field("property", name)?;
961 s
962 } else {
963 let mut s = serializer.serialize_struct("Property", 3)?;
964 s.serialize_field("property", name)?;
965 s.serialize_field("vendorPrefix", &prefix)?;
966 s
967 };
968
969 match self {
970 $(
971 $(#[$meta])*
972 $property(value, $(vp_name!($vp, _p))?) => {
973 s.serialize_field("value", value)?;
974 }
975 )+
976 All(value) => {
977 s.serialize_field("value", value)?;
978 }
979 Unparsed(_) | Custom(_) => unreachable!()
980 }
981
982 s.end()
983 }
984 }
985
986 #[cfg(feature = "serde")]
987 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
988 impl<'i, 'de: 'i> serde::Deserialize<'de> for Property<'i> {
989 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
990 where
991 D: serde::Deserializer<'de>,
992 {
993 enum ContentOrRaw<'de> {
994 Content(serde::__private::de::Content<'de>),
995 Raw(CowArcStr<'de>)
996 }
997
998 struct PartialProperty<'de> {
999 property_id: PropertyId<'de>,
1000 value: ContentOrRaw<'de>,
1001 }
1002
1003 #[derive(serde::Deserialize)]
1004 #[serde(field_identifier, rename_all = "camelCase")]
1005 enum Field {
1006 Property,
1007 VendorPrefix,
1008 Value,
1009 Raw
1010 }
1011
1012 struct PropertyIdVisitor;
1013 impl<'de> serde::de::Visitor<'de> for PropertyIdVisitor {
1014 type Value = PartialProperty<'de>;
1015
1016 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1017 formatter.write_str("a Property")
1018 }
1019
1020 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1021 where
1022 A: serde::de::MapAccess<'de>,
1023 {
1024 let mut property: Option<CowArcStr> = None;
1025 let mut vendor_prefix = None;
1026 let mut value: Option<ContentOrRaw<'de>> = None;
1027 while let Some(key) = map.next_key()? {
1028 match key {
1029 Field::Property => {
1030 property = Some(map.next_value()?);
1031 }
1032 Field::VendorPrefix => {
1033 vendor_prefix = Some(map.next_value()?);
1034 }
1035 Field::Value => {
1036 value = Some(ContentOrRaw::Content(map.next_value()?));
1037 }
1038 Field::Raw => {
1039 value = Some(ContentOrRaw::Raw(map.next_value()?));
1040 }
1041 }
1042 }
1043
1044 let property = property.ok_or_else(|| serde::de::Error::missing_field("property"))?;
1045 let vendor_prefix = vendor_prefix.unwrap_or(VendorPrefix::None);
1046 let value = value.ok_or_else(|| serde::de::Error::missing_field("value"))?;
1047 let property_id = PropertyId::from_name_and_prefix(property.as_ref(), vendor_prefix)
1048 .unwrap_or_else(|_| PropertyId::from(property));
1049 Ok(PartialProperty {
1050 property_id,
1051 value,
1052 })
1053 }
1054 }
1055
1056 let partial = deserializer.deserialize_any(PropertyIdVisitor)?;
1057
1058 let content = match partial.value {
1059 ContentOrRaw::Raw(raw) => {
1060 let res = Property::parse_string(partial.property_id, raw.as_ref(), ParserOptions::default())
1061 .map_err(|_| serde::de::Error::custom("Could not parse value"))?;
1062 return Ok(res.into_owned())
1063 }
1064 ContentOrRaw::Content(content) => content
1065 };
1066
1067 let deserializer = serde::__private::de::ContentDeserializer::new(content);
1068 match partial.property_id {
1069 $(
1070 $(#[$meta])*
1071 PropertyId::$property$((vp_name!($vp, prefix)))? => {
1072 let value = <$type>::deserialize(deserializer)?;
1073 Ok(Property::$property(value $(, vp_name!($vp, prefix))?))
1074 },
1075 )+
1076 PropertyId::Custom(name) => {
1077 if name.as_ref() == "unparsed" {
1078 let value = UnparsedProperty::deserialize(deserializer)?;
1079 Ok(Property::Unparsed(value))
1080 } else {
1081 let value = CustomProperty::deserialize(deserializer)?;
1082 Ok(Property::Custom(value))
1083 }
1084 }
1085 PropertyId::All => {
1086 let value = CSSWideKeyword::deserialize(deserializer)?;
1087 Ok(Property::All(value))
1088 }
1089 }
1090 }
1091 }
1092
1093 #[cfg(feature = "jsonschema")]
1094 #[cfg_attr(docsrs, doc(cfg(feature = "jsonschema")))]
1095 impl<'i> schemars::JsonSchema for Property<'i> {
1096 fn is_referenceable() -> bool {
1097 true
1098 }
1099
1100 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1101 macro_rules! property {
1102 ($n: literal) => {
1103 fn property(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1104 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
1105 instance_type: Some(schemars::schema::InstanceType::String.into()),
1106 enum_values: Some(vec![$n.into()]),
1107 ..Default::default()
1108 })
1109 }
1110 }
1111 }
1112
1113 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
1114 subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
1115 one_of: Some(vec![
1116 $(
1117 {
1118 property!($name);
1119
1120 macro_rules! with_prefix {
1121 ($v: ty) => {{
1122 #[derive(schemars::JsonSchema)]
1123 struct T<'i> {
1124 #[schemars(rename = "property", schema_with = "property")]
1125 _property: &'i u8,
1126 #[schemars(rename = "vendorPrefix")]
1127 _vendor_prefix: VendorPrefix,
1128 #[schemars(rename = "value")]
1129 _value: $type,
1130 }
1131
1132 T::json_schema(gen)
1133 }};
1134 () => {{
1135 #[derive(schemars::JsonSchema)]
1136 struct T<'i> {
1137 #[schemars(rename = "property", schema_with = "property")]
1138 _property: &'i u8,
1139 #[schemars(rename = "value")]
1140 _value: $type,
1141 }
1142
1143 T::json_schema(gen)
1144 }};
1145 }
1146
1147 with_prefix!($($vp)?)
1148 },
1149 )+
1150 {
1151 property!("all");
1152 #[derive(schemars::JsonSchema)]
1153 struct T {
1154 #[schemars(rename = "property", schema_with = "property")]
1155 _property: u8,
1156 #[schemars(rename = "value")]
1157 _value: CSSWideKeyword
1158 }
1159 T::json_schema(gen)
1160 },
1161 {
1162 property!("unparsed");
1163
1164 #[derive(schemars::JsonSchema)]
1165 struct T<'i> {
1166 #[schemars(rename = "property", schema_with = "property")]
1167 _property: &'i u8,
1168 #[schemars(rename = "value")]
1169 _value: UnparsedProperty<'i>,
1170 }
1171
1172 T::json_schema(gen)
1173 },
1174 {
1175 property!("custom");
1176
1177 #[derive(schemars::JsonSchema)]
1178 struct T<'i> {
1179 #[schemars(rename = "property", schema_with = "property")]
1180 _property: &'i u8,
1181 #[schemars(rename = "value")]
1182 _value: CustomProperty<'i>,
1183 }
1184
1185 T::json_schema(gen)
1186 }
1187 ]),
1188 ..Default::default()
1189 })),
1190 ..Default::default()
1191 })
1192 }
1193
1194 fn schema_name() -> String {
1195 "Declaration".into()
1196 }
1197 }
1198 };
1199}
1200
1201define_properties! {
1202 "background-color": BackgroundColor(CssColor),
1203 "background-image": BackgroundImage(SmallVec<[Image<'i>; 1]>),
1204 "background-position-x": BackgroundPositionX(SmallVec<[HorizontalPosition; 1]>),
1205 "background-position-y": BackgroundPositionY(SmallVec<[VerticalPosition; 1]>),
1206 "background-position": BackgroundPosition(SmallVec<[BackgroundPosition; 1]>) shorthand: true,
1207 "background-size": BackgroundSize(SmallVec<[BackgroundSize; 1]>),
1208 "background-repeat": BackgroundRepeat(SmallVec<[BackgroundRepeat; 1]>),
1209 "background-attachment": BackgroundAttachment(SmallVec<[BackgroundAttachment; 1]>),
1210 "background-clip": BackgroundClip(SmallVec<[BackgroundClip; 1]>, VendorPrefix) / WebKit / Moz,
1211 "background-origin": BackgroundOrigin(SmallVec<[BackgroundOrigin; 1]>),
1212 "background": Background(SmallVec<[Background<'i>; 1]>) shorthand: true,
1213
1214 "box-shadow": BoxShadow(SmallVec<[BoxShadow; 1]>, VendorPrefix) / WebKit / Moz,
1215 "opacity": Opacity(AlphaValue),
1216 "color": Color(CssColor),
1217 "display": Display(Display),
1218 "visibility": Visibility(Visibility),
1219
1220 "width": Width(Size) [logical_group: Size, category: Physical],
1221 "height": Height(Size) [logical_group: Size, category: Physical],
1222 "min-width": MinWidth(Size) [logical_group: MinSize, category: Physical],
1223 "min-height": MinHeight(Size) [logical_group: MinSize, category: Physical],
1224 "max-width": MaxWidth(MaxSize) [logical_group: MaxSize, category: Physical],
1225 "max-height": MaxHeight(MaxSize) [logical_group: MaxSize, category: Physical],
1226 "block-size": BlockSize(Size) [logical_group: Size, category: Logical],
1227 "inline-size": InlineSize(Size) [logical_group: Size, category: Logical],
1228 "min-block-size": MinBlockSize(Size) [logical_group: MinSize, category: Logical],
1229 "min-inline-size": MinInlineSize(Size) [logical_group: MinSize, category: Logical],
1230 "max-block-size": MaxBlockSize(MaxSize) [logical_group: MaxSize, category: Logical],
1231 "max-inline-size": MaxInlineSize(MaxSize) [logical_group: MaxSize, category: Logical],
1232 "box-sizing": BoxSizing(BoxSizing, VendorPrefix) / WebKit / Moz,
1233 "aspect-ratio": AspectRatio(AspectRatio),
1234
1235 "overflow": Overflow(Overflow) shorthand: true,
1236 "overflow-x": OverflowX(OverflowKeyword),
1237 "overflow-y": OverflowY(OverflowKeyword),
1238 "text-overflow": TextOverflow(TextOverflow, VendorPrefix) / O,
1239
1240 "position": Position(position::Position),
1242 "top": Top(LengthPercentageOrAuto) [logical_group: Inset, category: Physical],
1243 "bottom": Bottom(LengthPercentageOrAuto) [logical_group: Inset, category: Physical],
1244 "left": Left(LengthPercentageOrAuto) [logical_group: Inset, category: Physical],
1245 "right": Right(LengthPercentageOrAuto) [logical_group: Inset, category: Physical],
1246 "inset-block-start": InsetBlockStart(LengthPercentageOrAuto) [logical_group: Inset, category: Logical],
1247 "inset-block-end": InsetBlockEnd(LengthPercentageOrAuto) [logical_group: Inset, category: Logical],
1248 "inset-inline-start": InsetInlineStart(LengthPercentageOrAuto) [logical_group: Inset, category: Logical],
1249 "inset-inline-end": InsetInlineEnd(LengthPercentageOrAuto) [logical_group: Inset, category: Logical],
1250 "inset-block": InsetBlock(InsetBlock) shorthand: true,
1251 "inset-inline": InsetInline(InsetInline) shorthand: true,
1252 "inset": Inset(Inset) shorthand: true,
1253
1254 "border-spacing": BorderSpacing(Size2D<Length>),
1255
1256 "border-top-color": BorderTopColor(CssColor) [logical_group: BorderColor, category: Physical],
1257 "border-bottom-color": BorderBottomColor(CssColor) [logical_group: BorderColor, category: Physical],
1258 "border-left-color": BorderLeftColor(CssColor) [logical_group: BorderColor, category: Physical],
1259 "border-right-color": BorderRightColor(CssColor) [logical_group: BorderColor, category: Physical],
1260 "border-block-start-color": BorderBlockStartColor(CssColor) [logical_group: BorderColor, category: Logical],
1261 "border-block-end-color": BorderBlockEndColor(CssColor) [logical_group: BorderColor, category: Logical],
1262 "border-inline-start-color": BorderInlineStartColor(CssColor) [logical_group: BorderColor, category: Logical],
1263 "border-inline-end-color": BorderInlineEndColor(CssColor) [logical_group: BorderColor, category: Logical],
1264
1265 "border-top-style": BorderTopStyle(LineStyle) [logical_group: BorderStyle, category: Physical],
1266 "border-bottom-style": BorderBottomStyle(LineStyle) [logical_group: BorderStyle, category: Physical],
1267 "border-left-style": BorderLeftStyle(LineStyle) [logical_group: BorderStyle, category: Physical],
1268 "border-right-style": BorderRightStyle(LineStyle) [logical_group: BorderStyle, category: Physical],
1269 "border-block-start-style": BorderBlockStartStyle(LineStyle) [logical_group: BorderStyle, category: Logical],
1270 "border-block-end-style": BorderBlockEndStyle(LineStyle) [logical_group: BorderStyle, category: Logical],
1271 "border-inline-start-style": BorderInlineStartStyle(LineStyle) [logical_group: BorderStyle, category: Logical],
1272 "border-inline-end-style": BorderInlineEndStyle(LineStyle) [logical_group: BorderStyle, category: Logical],
1273
1274 "border-top-width": BorderTopWidth(BorderSideWidth) [logical_group: BorderWidth, category: Physical],
1275 "border-bottom-width": BorderBottomWidth(BorderSideWidth) [logical_group: BorderWidth, category: Physical],
1276 "border-left-width": BorderLeftWidth(BorderSideWidth) [logical_group: BorderWidth, category: Physical],
1277 "border-right-width": BorderRightWidth(BorderSideWidth) [logical_group: BorderWidth, category: Physical],
1278 "border-block-start-width": BorderBlockStartWidth(BorderSideWidth) [logical_group: BorderWidth, category: Logical],
1279 "border-block-end-width": BorderBlockEndWidth(BorderSideWidth) [logical_group: BorderWidth, category: Logical],
1280 "border-inline-start-width": BorderInlineStartWidth(BorderSideWidth) [logical_group: BorderWidth, category: Logical],
1281 "border-inline-end-width": BorderInlineEndWidth(BorderSideWidth) [logical_group: BorderWidth, category: Logical],
1282
1283 "border-top-left-radius": BorderTopLeftRadius(Size2D<LengthPercentage>, VendorPrefix) / WebKit / Moz [logical_group: BorderRadius, category: Physical],
1284 "border-top-right-radius": BorderTopRightRadius(Size2D<LengthPercentage>, VendorPrefix) / WebKit / Moz [logical_group: BorderRadius, category: Physical],
1285 "border-bottom-left-radius": BorderBottomLeftRadius(Size2D<LengthPercentage>, VendorPrefix) / WebKit / Moz [logical_group: BorderRadius, category: Physical],
1286 "border-bottom-right-radius": BorderBottomRightRadius(Size2D<LengthPercentage>, VendorPrefix) / WebKit / Moz [logical_group: BorderRadius, category: Physical],
1287 "border-start-start-radius": BorderStartStartRadius(Size2D<LengthPercentage>) [logical_group: BorderRadius, category: Logical],
1288 "border-start-end-radius": BorderStartEndRadius(Size2D<LengthPercentage>) [logical_group: BorderRadius, category: Logical],
1289 "border-end-start-radius": BorderEndStartRadius(Size2D<LengthPercentage>) [logical_group: BorderRadius, category: Logical],
1290 "border-end-end-radius": BorderEndEndRadius(Size2D<LengthPercentage>) [logical_group: BorderRadius, category: Logical],
1291 "border-radius": BorderRadius(BorderRadius, VendorPrefix) / WebKit / Moz shorthand: true,
1292
1293 "border-image-source": BorderImageSource(Image<'i>),
1294 "border-image-outset": BorderImageOutset(Rect<LengthOrNumber>),
1295 "border-image-repeat": BorderImageRepeat(BorderImageRepeat),
1296 "border-image-width": BorderImageWidth(Rect<BorderImageSideWidth>),
1297 "border-image-slice": BorderImageSlice(BorderImageSlice),
1298 "border-image": BorderImage(BorderImage<'i>, VendorPrefix) / WebKit / Moz / O shorthand: true,
1299
1300 "border-color": BorderColor(BorderColor) shorthand: true,
1301 "border-style": BorderStyle(BorderStyle) shorthand: true,
1302 "border-width": BorderWidth(BorderWidth) shorthand: true,
1303
1304 "border-block-color": BorderBlockColor(BorderBlockColor) shorthand: true,
1305 "border-block-style": BorderBlockStyle(BorderBlockStyle) shorthand: true,
1306 "border-block-width": BorderBlockWidth(BorderBlockWidth) shorthand: true,
1307
1308 "border-inline-color": BorderInlineColor(BorderInlineColor) shorthand: true,
1309 "border-inline-style": BorderInlineStyle(BorderInlineStyle) shorthand: true,
1310 "border-inline-width": BorderInlineWidth(BorderInlineWidth) shorthand: true,
1311
1312 "border": Border(Border) shorthand: true,
1313 "border-top": BorderTop(BorderTop) shorthand: true,
1314 "border-bottom": BorderBottom(BorderBottom) shorthand: true,
1315 "border-left": BorderLeft(BorderLeft) shorthand: true,
1316 "border-right": BorderRight(BorderRight) shorthand: true,
1317 "border-block": BorderBlock(BorderBlock) shorthand: true,
1318 "border-block-start": BorderBlockStart(BorderBlockStart) shorthand: true,
1319 "border-block-end": BorderBlockEnd(BorderBlockEnd) shorthand: true,
1320 "border-inline": BorderInline(BorderInline) shorthand: true,
1321 "border-inline-start": BorderInlineStart(BorderInlineStart) shorthand: true,
1322 "border-inline-end": BorderInlineEnd(BorderInlineEnd) shorthand: true,
1323
1324 "outline": Outline(Outline) shorthand: true,
1325 "outline-color": OutlineColor(CssColor),
1326 "outline-style": OutlineStyle(OutlineStyle),
1327 "outline-width": OutlineWidth(BorderSideWidth),
1328
1329 "flex-direction": FlexDirection(FlexDirection, VendorPrefix) / WebKit / Ms,
1331 "flex-wrap": FlexWrap(FlexWrap, VendorPrefix) / WebKit / Ms,
1332 "flex-flow": FlexFlow(FlexFlow, VendorPrefix) / WebKit / Ms shorthand: true,
1333 "flex-grow": FlexGrow(CSSNumber, VendorPrefix) / WebKit,
1334 "flex-shrink": FlexShrink(CSSNumber, VendorPrefix) / WebKit,
1335 "flex-basis": FlexBasis(LengthPercentageOrAuto, VendorPrefix) / WebKit,
1336 "flex": Flex(Flex, VendorPrefix) / WebKit / Ms shorthand: true,
1337 "order": Order(CSSInteger, VendorPrefix) / WebKit,
1338
1339 "align-content": AlignContent(AlignContent, VendorPrefix) / WebKit,
1341 "justify-content": JustifyContent(JustifyContent, VendorPrefix) / WebKit,
1342 "place-content": PlaceContent(PlaceContent) shorthand: true,
1343 "align-self": AlignSelf(AlignSelf, VendorPrefix) / WebKit,
1344 "justify-self": JustifySelf(JustifySelf),
1345 "place-self": PlaceSelf(PlaceSelf) shorthand: true,
1346 "align-items": AlignItems(AlignItems, VendorPrefix) / WebKit,
1347 "justify-items": JustifyItems(JustifyItems),
1348 "place-items": PlaceItems(PlaceItems) shorthand: true,
1349 "row-gap": RowGap(GapValue),
1350 "column-gap": ColumnGap(GapValue),
1351 "gap": Gap(Gap) shorthand: true,
1352
1353 "box-orient": BoxOrient(BoxOrient, VendorPrefix) / WebKit / Moz unprefixed: false,
1355 "box-direction": BoxDirection(BoxDirection, VendorPrefix) / WebKit / Moz unprefixed: false,
1356 "box-ordinal-group": BoxOrdinalGroup(CSSInteger, VendorPrefix) / WebKit / Moz unprefixed: false,
1357 "box-align": BoxAlign(BoxAlign, VendorPrefix) / WebKit / Moz unprefixed: false,
1358 "box-flex": BoxFlex(CSSNumber, VendorPrefix) / WebKit / Moz unprefixed: false,
1359 "box-flex-group": BoxFlexGroup(CSSInteger, VendorPrefix) / WebKit unprefixed: false,
1360 "box-pack": BoxPack(BoxPack, VendorPrefix) / WebKit / Moz unprefixed: false,
1361 "box-lines": BoxLines(BoxLines, VendorPrefix) / WebKit / Moz unprefixed: false,
1362
1363 "flex-pack": FlexPack(FlexPack, VendorPrefix) / Ms unprefixed: false,
1365 "flex-order": FlexOrder(CSSInteger, VendorPrefix) / Ms unprefixed: false,
1366 "flex-align": FlexAlign(BoxAlign, VendorPrefix) / Ms unprefixed: false,
1367 "flex-item-align": FlexItemAlign(FlexItemAlign, VendorPrefix) / Ms unprefixed: false,
1368 "flex-line-pack": FlexLinePack(FlexLinePack, VendorPrefix) / Ms unprefixed: false,
1369
1370 "flex-positive": FlexPositive(CSSNumber, VendorPrefix) / Ms unprefixed: false,
1372 "flex-negative": FlexNegative(CSSNumber, VendorPrefix) / Ms unprefixed: false,
1373 "flex-preferred-size": FlexPreferredSize(LengthPercentageOrAuto, VendorPrefix) / Ms unprefixed: false,
1374
1375 #[cfg(feature = "grid")]
1376 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1377 "grid-template-columns": GridTemplateColumns(TrackSizing<'i>),
1378 #[cfg(feature = "grid")]
1379 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1380 "grid-template-rows": GridTemplateRows(TrackSizing<'i>),
1381 #[cfg(feature = "grid")]
1382 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1383 "grid-auto-columns": GridAutoColumns(TrackSizeList),
1384 #[cfg(feature = "grid")]
1385 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1386 "grid-auto-rows": GridAutoRows(TrackSizeList),
1387 #[cfg(feature = "grid")]
1388 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1389 "grid-auto-flow": GridAutoFlow(GridAutoFlow),
1390 #[cfg(feature = "grid")]
1391 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1392 "grid-template-areas": GridTemplateAreas(GridTemplateAreas),
1393 #[cfg(feature = "grid")]
1394 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1395 "grid-template": GridTemplate(GridTemplate<'i>) shorthand: true,
1396 #[cfg(feature = "grid")]
1397 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1398 "grid": Grid(Grid<'i>) shorthand: true,
1399 #[cfg(feature = "grid")]
1400 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1401 "grid-row-start": GridRowStart(GridLine<'i>),
1402 #[cfg(feature = "grid")]
1403 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1404 "grid-row-end": GridRowEnd(GridLine<'i>),
1405 #[cfg(feature = "grid")]
1406 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1407 "grid-column-start": GridColumnStart(GridLine<'i>),
1408 #[cfg(feature = "grid")]
1409 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1410 "grid-column-end": GridColumnEnd(GridLine<'i>),
1411 #[cfg(feature = "grid")]
1412 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1413 "grid-row": GridRow(GridRow<'i>) shorthand: true,
1414 #[cfg(feature = "grid")]
1415 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1416 "grid-column": GridColumn(GridColumn<'i>) shorthand: true,
1417 #[cfg(feature = "grid")]
1418 #[cfg_attr(docsrs, doc(cfg(feature = "grid")))]
1419 "grid-area": GridArea(GridArea<'i>) shorthand: true,
1420
1421 "margin-top": MarginTop(LengthPercentageOrAuto) [logical_group: Margin, category: Physical],
1422 "margin-bottom": MarginBottom(LengthPercentageOrAuto) [logical_group: Margin, category: Physical],
1423 "margin-left": MarginLeft(LengthPercentageOrAuto) [logical_group: Margin, category: Physical],
1424 "margin-right": MarginRight(LengthPercentageOrAuto) [logical_group: Margin, category: Physical],
1425 "margin-block-start": MarginBlockStart(LengthPercentageOrAuto) [logical_group: Margin, category: Logical],
1426 "margin-block-end": MarginBlockEnd(LengthPercentageOrAuto) [logical_group: Margin, category: Logical],
1427 "margin-inline-start": MarginInlineStart(LengthPercentageOrAuto) [logical_group: Margin, category: Logical],
1428 "margin-inline-end": MarginInlineEnd(LengthPercentageOrAuto) [logical_group: Margin, category: Logical],
1429 "margin-block": MarginBlock(MarginBlock) shorthand: true,
1430 "margin-inline": MarginInline(MarginInline) shorthand: true,
1431 "margin": Margin(Margin) shorthand: true,
1432
1433 "padding-top": PaddingTop(LengthPercentageOrAuto) [logical_group: Padding, category: Physical],
1434 "padding-bottom": PaddingBottom(LengthPercentageOrAuto) [logical_group: Padding, category: Physical],
1435 "padding-left": PaddingLeft(LengthPercentageOrAuto) [logical_group: Padding, category: Physical],
1436 "padding-right": PaddingRight(LengthPercentageOrAuto) [logical_group: Padding, category: Physical],
1437 "padding-block-start": PaddingBlockStart(LengthPercentageOrAuto) [logical_group: Padding, category: Logical],
1438 "padding-block-end": PaddingBlockEnd(LengthPercentageOrAuto) [logical_group: Padding, category: Logical],
1439 "padding-inline-start": PaddingInlineStart(LengthPercentageOrAuto) [logical_group: Padding, category: Logical],
1440 "padding-inline-end": PaddingInlineEnd(LengthPercentageOrAuto) [logical_group: Padding, category: Logical],
1441 "padding-block": PaddingBlock(PaddingBlock) shorthand: true,
1442 "padding-inline": PaddingInline(PaddingInline) shorthand: true,
1443 "padding": Padding(Padding) shorthand: true,
1444
1445 "scroll-margin-top": ScrollMarginTop(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Physical],
1446 "scroll-margin-bottom": ScrollMarginBottom(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Physical],
1447 "scroll-margin-left": ScrollMarginLeft(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Physical],
1448 "scroll-margin-right": ScrollMarginRight(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Physical],
1449 "scroll-margin-block-start": ScrollMarginBlockStart(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Logical],
1450 "scroll-margin-block-end": ScrollMarginBlockEnd(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Logical],
1451 "scroll-margin-inline-start": ScrollMarginInlineStart(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Logical],
1452 "scroll-margin-inline-end": ScrollMarginInlineEnd(LengthPercentageOrAuto) [logical_group: ScrollMargin, category: Logical],
1453 "scroll-margin-block": ScrollMarginBlock(ScrollMarginBlock) shorthand: true,
1454 "scroll-margin-inline": ScrollMarginInline(ScrollMarginInline) shorthand: true,
1455 "scroll-margin": ScrollMargin(ScrollMargin) shorthand: true,
1456
1457 "scroll-padding-top": ScrollPaddingTop(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Physical],
1458 "scroll-padding-bottom": ScrollPaddingBottom(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Physical],
1459 "scroll-padding-left": ScrollPaddingLeft(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Physical],
1460 "scroll-padding-right": ScrollPaddingRight(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Physical],
1461 "scroll-padding-block-start": ScrollPaddingBlockStart(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Logical],
1462 "scroll-padding-block-end": ScrollPaddingBlockEnd(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Logical],
1463 "scroll-padding-inline-start": ScrollPaddingInlineStart(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Logical],
1464 "scroll-padding-inline-end": ScrollPaddingInlineEnd(LengthPercentageOrAuto) [logical_group: ScrollPadding, category: Logical],
1465 "scroll-padding-block": ScrollPaddingBlock(ScrollPaddingBlock) shorthand: true,
1466 "scroll-padding-inline": ScrollPaddingInline(ScrollPaddingInline) shorthand: true,
1467 "scroll-padding": ScrollPadding(ScrollPadding) shorthand: true,
1468
1469 "font-weight": FontWeight(FontWeight),
1470 "font-size": FontSize(FontSize),
1471 "font-stretch": FontStretch(FontStretch),
1472 "font-family": FontFamily(Vec<FontFamily<'i>>),
1473 "font-style": FontStyle(FontStyle),
1474 "font-variant-caps": FontVariantCaps(FontVariantCaps),
1475 "line-height": LineHeight(LineHeight),
1476 "font": Font(Font<'i>) shorthand: true,
1477 "vertical-align": VerticalAlign(VerticalAlign),
1478 "font-palette": FontPalette(DashedIdentReference<'i>),
1479
1480 "transition-property": TransitionProperty(SmallVec<[PropertyId<'i>; 1]>, VendorPrefix) / WebKit / Moz / Ms,
1481 "transition-duration": TransitionDuration(SmallVec<[Time; 1]>, VendorPrefix) / WebKit / Moz / Ms,
1482 "transition-delay": TransitionDelay(SmallVec<[Time; 1]>, VendorPrefix) / WebKit / Moz / Ms,
1483 "transition-timing-function": TransitionTimingFunction(SmallVec<[EasingFunction; 1]>, VendorPrefix) / WebKit / Moz / Ms,
1484 "transition": Transition(SmallVec<[Transition<'i>; 1]>, VendorPrefix) / WebKit / Moz / Ms shorthand: true,
1485
1486 "animation-name": AnimationName(AnimationNameList<'i>, VendorPrefix) / WebKit / Moz / O,
1487 "animation-duration": AnimationDuration(SmallVec<[Time; 1]>, VendorPrefix) / WebKit / Moz / O,
1488 "animation-timing-function": AnimationTimingFunction(SmallVec<[EasingFunction; 1]>, VendorPrefix) / WebKit / Moz / O,
1489 "animation-iteration-count": AnimationIterationCount(SmallVec<[AnimationIterationCount; 1]>, VendorPrefix) / WebKit / Moz / O,
1490 "animation-direction": AnimationDirection(SmallVec<[AnimationDirection; 1]>, VendorPrefix) / WebKit / Moz / O,
1491 "animation-play-state": AnimationPlayState(SmallVec<[AnimationPlayState; 1]>, VendorPrefix) / WebKit / Moz / O,
1492 "animation-delay": AnimationDelay(SmallVec<[Time; 1]>, VendorPrefix) / WebKit / Moz / O,
1493 "animation-fill-mode": AnimationFillMode(SmallVec<[AnimationFillMode; 1]>, VendorPrefix) / WebKit / Moz / O,
1494 "animation-composition": AnimationComposition(SmallVec<[AnimationComposition; 1]>),
1495 "animation-timeline": AnimationTimeline(SmallVec<[AnimationTimeline<'i>; 1]>),
1496 "animation-range-start": AnimationRangeStart(SmallVec<[AnimationRangeStart; 1]>),
1497 "animation-range-end": AnimationRangeEnd(SmallVec<[AnimationRangeEnd; 1]>),
1498 "animation-range": AnimationRange(SmallVec<[AnimationRange; 1]>),
1499 "animation": Animation(AnimationList<'i>, VendorPrefix) / WebKit / Moz / O shorthand: true,
1500
1501 "transform": Transform(TransformList, VendorPrefix) / WebKit / Moz / Ms / O,
1503 "transform-origin": TransformOrigin(Position, VendorPrefix) / WebKit / Moz / Ms / O, "transform-style": TransformStyle(TransformStyle, VendorPrefix) / WebKit / Moz,
1505 "transform-box": TransformBox(TransformBox),
1506 "backface-visibility": BackfaceVisibility(BackfaceVisibility, VendorPrefix) / WebKit / Moz,
1507 "perspective": Perspective(Perspective, VendorPrefix) / WebKit / Moz,
1508 "perspective-origin": PerspectiveOrigin(Position, VendorPrefix) / WebKit / Moz,
1509 "translate": Translate(Translate),
1510 "rotate": Rotate(Rotate),
1511 "scale": Scale(Scale),
1512
1513 "text-transform": TextTransform(TextTransform),
1515 "white-space": WhiteSpace(WhiteSpace),
1516 "tab-size": TabSize(LengthOrNumber, VendorPrefix) / Moz / O,
1517 "word-break": WordBreak(WordBreak),
1518 "line-break": LineBreak(LineBreak),
1519 "hyphens": Hyphens(Hyphens, VendorPrefix) / WebKit / Moz / Ms,
1520 "overflow-wrap": OverflowWrap(OverflowWrap),
1521 "word-wrap": WordWrap(OverflowWrap),
1522 "text-align": TextAlign(TextAlign),
1523 "text-align-last": TextAlignLast(TextAlignLast, VendorPrefix) / Moz,
1524 "text-justify": TextJustify(TextJustify),
1525 "word-spacing": WordSpacing(Spacing),
1526 "letter-spacing": LetterSpacing(Spacing),
1527 "text-indent": TextIndent(TextIndent),
1528
1529 "text-decoration-line": TextDecorationLine(TextDecorationLine, VendorPrefix) / WebKit / Moz,
1531 "text-decoration-style": TextDecorationStyle(TextDecorationStyle, VendorPrefix) / WebKit / Moz,
1532 "text-decoration-color": TextDecorationColor(CssColor, VendorPrefix) / WebKit / Moz,
1533 "text-decoration-thickness": TextDecorationThickness(TextDecorationThickness),
1534 "text-decoration": TextDecoration(TextDecoration, VendorPrefix) / WebKit / Moz shorthand: true,
1535 "text-decoration-skip-ink": TextDecorationSkipInk(TextDecorationSkipInk, VendorPrefix) / WebKit,
1536 "text-emphasis-style": TextEmphasisStyle(TextEmphasisStyle<'i>, VendorPrefix) / WebKit,
1537 "text-emphasis-color": TextEmphasisColor(CssColor, VendorPrefix) / WebKit,
1538 "text-emphasis": TextEmphasis(TextEmphasis<'i>, VendorPrefix) / WebKit shorthand: true,
1539 "text-emphasis-position": TextEmphasisPosition(TextEmphasisPosition, VendorPrefix) / WebKit,
1540 "text-shadow": TextShadow(SmallVec<[TextShadow; 1]>),
1541
1542 "text-size-adjust": TextSizeAdjust(TextSizeAdjust, VendorPrefix) / WebKit / Moz / Ms,
1544
1545 "direction": Direction(Direction),
1547 "unicode-bidi": UnicodeBidi(UnicodeBidi),
1548
1549 "box-decoration-break": BoxDecorationBreak(BoxDecorationBreak, VendorPrefix) / WebKit,
1551
1552 "resize": Resize(Resize),
1554 "cursor": Cursor(Cursor<'i>),
1555 "caret-color": CaretColor(ColorOrAuto),
1556 "caret-shape": CaretShape(CaretShape),
1557 "caret": Caret(Caret) shorthand: true,
1558 "user-select": UserSelect(UserSelect, VendorPrefix) / WebKit / Moz / Ms,
1559 "accent-color": AccentColor(ColorOrAuto),
1560 "appearance": Appearance(Appearance<'i>, VendorPrefix) / WebKit / Moz / Ms,
1561
1562 "list-style-type": ListStyleType(ListStyleType<'i>),
1564 "list-style-image": ListStyleImage(Image<'i>),
1565 "list-style-position": ListStylePosition(ListStylePosition),
1566 "list-style": ListStyle(ListStyle<'i>) shorthand: true,
1567 "marker-side": MarkerSide(MarkerSide),
1568
1569 "composes": Composes(Composes<'i>) if css_modules,
1571
1572 "fill": Fill(SVGPaint<'i>),
1574 "fill-rule": FillRule(FillRule),
1575 "fill-opacity": FillOpacity(AlphaValue),
1576 "stroke": Stroke(SVGPaint<'i>),
1577 "stroke-opacity": StrokeOpacity(AlphaValue),
1578 "stroke-width": StrokeWidth(LengthPercentage),
1579 "stroke-linecap": StrokeLinecap(StrokeLinecap),
1580 "stroke-linejoin": StrokeLinejoin(StrokeLinejoin),
1581 "stroke-miterlimit": StrokeMiterlimit(CSSNumber),
1582 "stroke-dasharray": StrokeDasharray(StrokeDasharray),
1583 "stroke-dashoffset": StrokeDashoffset(LengthPercentage),
1584 "marker-start": MarkerStart(Marker<'i>),
1585 "marker-mid": MarkerMid(Marker<'i>),
1586 "marker-end": MarkerEnd(Marker<'i>),
1587 "marker": Marker(Marker<'i>),
1588 "color-interpolation": ColorInterpolation(ColorInterpolation),
1589 "color-interpolation-filters": ColorInterpolationFilters(ColorInterpolation),
1590 "color-rendering": ColorRendering(ColorRendering),
1591 "shape-rendering": ShapeRendering(ShapeRendering),
1592 "text-rendering": TextRendering(TextRendering),
1593 "image-rendering": ImageRendering(ImageRendering),
1594
1595 "clip-path": ClipPath(ClipPath<'i>, VendorPrefix) / WebKit,
1597 "clip-rule": ClipRule(FillRule),
1598 "mask-image": MaskImage(SmallVec<[Image<'i>; 1]>, VendorPrefix) / WebKit,
1599 "mask-mode": MaskMode(SmallVec<[MaskMode; 1]>),
1600 "mask-repeat": MaskRepeat(SmallVec<[BackgroundRepeat; 1]>, VendorPrefix) / WebKit,
1601 "mask-position-x": MaskPositionX(SmallVec<[HorizontalPosition; 1]>),
1602 "mask-position-y": MaskPositionY(SmallVec<[VerticalPosition; 1]>),
1603 "mask-position": MaskPosition(SmallVec<[Position; 1]>, VendorPrefix) / WebKit,
1604 "mask-clip": MaskClip(SmallVec<[MaskClip; 1]>, VendorPrefix) / WebKit,
1605 "mask-origin": MaskOrigin(SmallVec<[GeometryBox; 1]>, VendorPrefix) / WebKit,
1606 "mask-size": MaskSize(SmallVec<[BackgroundSize; 1]>, VendorPrefix) / WebKit,
1607 "mask-composite": MaskComposite(SmallVec<[MaskComposite; 1]>),
1608 "mask-type": MaskType(MaskType),
1609 "mask": Mask(SmallVec<[Mask<'i>; 1]>, VendorPrefix) / WebKit shorthand: true,
1610 "mask-border-source": MaskBorderSource(Image<'i>),
1611 "mask-border-mode": MaskBorderMode(MaskBorderMode),
1612 "mask-border-slice": MaskBorderSlice(BorderImageSlice),
1613 "mask-border-width": MaskBorderWidth(Rect<BorderImageSideWidth>),
1614 "mask-border-outset": MaskBorderOutset(Rect<LengthOrNumber>),
1615 "mask-border-repeat": MaskBorderRepeat(BorderImageRepeat),
1616 "mask-border": MaskBorder(MaskBorder<'i>) shorthand: true,
1617
1618 "-webkit-mask-composite": WebKitMaskComposite(SmallVec<[WebKitMaskComposite; 1]>),
1620 "mask-source-type": WebKitMaskSourceType(SmallVec<[WebKitMaskSourceType; 1]>, VendorPrefix) / WebKit unprefixed: false,
1621 "mask-box-image": WebKitMaskBoxImage(BorderImage<'i>, VendorPrefix) / WebKit unprefixed: false,
1622 "mask-box-image-source": WebKitMaskBoxImageSource(Image<'i>, VendorPrefix) / WebKit unprefixed: false,
1623 "mask-box-image-slice": WebKitMaskBoxImageSlice(BorderImageSlice, VendorPrefix) / WebKit unprefixed: false,
1624 "mask-box-image-width": WebKitMaskBoxImageWidth(Rect<BorderImageSideWidth>, VendorPrefix) / WebKit unprefixed: false,
1625 "mask-box-image-outset": WebKitMaskBoxImageOutset(Rect<LengthOrNumber>, VendorPrefix) / WebKit unprefixed: false,
1626 "mask-box-image-repeat": WebKitMaskBoxImageRepeat(BorderImageRepeat, VendorPrefix) / WebKit unprefixed: false,
1627
1628 "filter": Filter(FilterList<'i>, VendorPrefix) / WebKit,
1630 "backdrop-filter": BackdropFilter(FilterList<'i>, VendorPrefix) / WebKit,
1631
1632 "z-index": ZIndex(position::ZIndex),
1634
1635 "container-type": ContainerType(ContainerType),
1637 "container-name": ContainerName(ContainerNameList<'i>),
1638 "container": Container(Container<'i>) shorthand: true,
1639
1640 "view-transition-name": ViewTransitionName(ViewTransitionName<'i>),
1642 "view-transition-class": ViewTransitionClass(NoneOrCustomIdentList<'i>),
1644 "view-transition-group": ViewTransitionGroup(ViewTransitionGroup<'i>),
1645
1646 "color-scheme": ColorScheme(ColorScheme),
1648}
1649
1650impl<'i, T: smallvec::Array<Item = V>, V: Parse<'i>> Parse<'i> for SmallVec<T> {
1651 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
1652 let mut values = smallvec![];
1654 loop {
1655 input.skip_whitespace(); match input.parse_until_before(Delimiter::Comma, &mut V::parse) {
1657 Ok(v) => values.push(v),
1658 Err(err) => return Err(err),
1659 }
1660 match input.next() {
1661 Err(_) => return Ok(values),
1662 Ok(&cssparser::Token::Comma) => continue,
1663 Ok(_) => unreachable!(),
1664 }
1665 }
1666 }
1667}
1668
1669impl<T: smallvec::Array<Item = V>, V: ToCss> ToCss for SmallVec<T> {
1670 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
1671 where
1672 W: std::fmt::Write,
1673 {
1674 let len = self.len();
1675 for (idx, val) in self.iter().enumerate() {
1676 val.to_css(dest)?;
1677 if idx < len - 1 {
1678 dest.delim(',', false)?;
1679 }
1680 }
1681 Ok(())
1682 }
1683}
1684
1685impl<'i, T: Parse<'i>> Parse<'i> for Vec<T> {
1686 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
1687 input.parse_comma_separated(|input| T::parse(input))
1688 }
1689}
1690
1691impl<T: ToCss> ToCss for Vec<T> {
1692 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
1693 where
1694 W: std::fmt::Write,
1695 {
1696 let len = self.len();
1697 for (idx, val) in self.iter().enumerate() {
1698 val.to_css(dest)?;
1699 if idx < len - 1 {
1700 dest.delim(',', false)?;
1701 }
1702 }
1703 Ok(())
1704 }
1705}
1706
1707enum_property! {
1708 pub enum CSSWideKeyword {
1710 "initial": Initial,
1712 "inherit": Inherit,
1714 "unset": Unset,
1716 "revert": Revert,
1718 "revert-layer": RevertLayer,
1720 }
1721}