1use alloc::{string::String, vec::Vec};
3use core::fmt;
4
5use crate::{
6 dynamic_selector::DynamicSelectorVec,
7 props::property::{format_static_css_prop, CssProperty, CssPropertyType},
8 AzString,
9};
10
11#[derive(Debug, Default, PartialEq, PartialOrd, Clone)]
14#[repr(C)]
15pub struct Css {
16 pub stylesheets: StylesheetVec,
20}
21
22impl_vec!(
23 Stylesheet,
24 StylesheetVec,
25 StylesheetVecDestructor,
26 StylesheetVecDestructorType
27);
28impl_vec_mut!(Stylesheet, StylesheetVec);
29impl_vec_debug!(Stylesheet, StylesheetVec);
30impl_vec_partialord!(Stylesheet, StylesheetVec);
31impl_vec_clone!(Stylesheet, StylesheetVec, StylesheetVecDestructor);
32impl_vec_partialeq!(Stylesheet, StylesheetVec);
33
34impl Css {
35 pub fn is_empty(&self) -> bool {
36 self.stylesheets.iter().all(|s| s.rules.as_ref().is_empty())
37 }
38
39 pub fn new(stylesheets: Vec<Stylesheet>) -> Self {
40 Self {
41 stylesheets: stylesheets.into(),
42 }
43 }
44
45 #[cfg(feature = "parser")]
46 pub fn from_string(s: crate::AzString) -> Self {
47 crate::parser2::new_from_str(s.as_str()).0
48 }
49
50 #[cfg(feature = "parser")]
51 pub fn from_string_with_warnings(
52 s: crate::AzString,
53 ) -> (Self, Vec<crate::parser2::CssParseWarnMsgOwned>) {
54 let (css, warnings) = crate::parser2::new_from_str(s.as_str());
55 (
56 css,
57 warnings
58 .into_iter()
59 .map(|w| crate::parser2::CssParseWarnMsgOwned {
60 warning: w.warning.to_contained(),
61 location: w.location,
62 })
63 .collect(),
64 )
65 }
66}
67
68#[derive(Debug, Default, PartialEq, PartialOrd, Clone)]
69#[repr(C)]
70pub struct Stylesheet {
71 pub rules: CssRuleBlockVec,
73}
74
75impl_vec!(
76 CssRuleBlock,
77 CssRuleBlockVec,
78 CssRuleBlockVecDestructor,
79 CssRuleBlockVecDestructorType
80);
81impl_vec_mut!(CssRuleBlock, CssRuleBlockVec);
82impl_vec_debug!(CssRuleBlock, CssRuleBlockVec);
83impl_vec_partialord!(CssRuleBlock, CssRuleBlockVec);
84impl_vec_clone!(CssRuleBlock, CssRuleBlockVec, CssRuleBlockVecDestructor);
85impl_vec_partialeq!(CssRuleBlock, CssRuleBlockVec);
86
87impl Stylesheet {
88 pub fn new(rules: Vec<CssRuleBlock>) -> Self {
89 Self {
90 rules: rules.into(),
91 }
92 }
93}
94
95impl From<Vec<CssRuleBlock>> for Stylesheet {
96 fn from(rules: Vec<CssRuleBlock>) -> Self {
97 Self {
98 rules: rules.into(),
99 }
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
105#[repr(C, u8)]
106pub enum CssDeclaration {
107 Static(CssProperty),
109 Dynamic(DynamicCssProperty),
111}
112
113impl CssDeclaration {
114 pub const fn new_static(prop: CssProperty) -> Self {
115 CssDeclaration::Static(prop)
116 }
117
118 pub const fn new_dynamic(prop: DynamicCssProperty) -> Self {
119 CssDeclaration::Dynamic(prop)
120 }
121
122 pub fn get_type(&self) -> CssPropertyType {
124 use self::CssDeclaration::*;
125 match self {
126 Static(s) => s.get_type(),
127 Dynamic(d) => d.default_value.get_type(),
128 }
129 }
130
131 pub fn is_inheritable(&self) -> bool {
134 use self::CssDeclaration::*;
135 match self {
136 Static(s) => s.get_type().is_inheritable(),
137 Dynamic(d) => d.is_inheritable(),
138 }
139 }
140
141 pub fn can_trigger_relayout(&self) -> bool {
144 use self::CssDeclaration::*;
145 match self {
146 Static(s) => s.get_type().can_trigger_relayout(),
147 Dynamic(d) => d.can_trigger_relayout(),
148 }
149 }
150
151 pub fn to_str(&self) -> String {
152 use self::CssDeclaration::*;
153 match self {
154 Static(s) => format!("{:?}", s),
155 Dynamic(d) => format!("var(--{}, {:?})", d.dynamic_id, d.default_value),
156 }
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
181#[repr(C)]
182pub struct DynamicCssProperty {
183 pub dynamic_id: AzString,
185 pub default_value: CssProperty,
187}
188
189#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
190#[repr(C, u8)] pub enum CssPropertyValue<T> {
192 Auto,
193 None,
194 Initial,
195 Inherit,
196 Revert,
197 Unset,
198 Exact(T),
199}
200
201pub trait PrintAsCssValue {
202 fn print_as_css_value(&self) -> String;
203}
204
205impl<T: PrintAsCssValue> CssPropertyValue<T> {
206 pub fn get_css_value_fmt(&self) -> String {
207 match self {
208 CssPropertyValue::Auto => format!("auto"),
209 CssPropertyValue::None => format!("none"),
210 CssPropertyValue::Initial => format!("initial"),
211 CssPropertyValue::Inherit => format!("inherit"),
212 CssPropertyValue::Revert => format!("revert"),
213 CssPropertyValue::Unset => format!("unset"),
214 CssPropertyValue::Exact(e) => e.print_as_css_value(),
215 }
216 }
217}
218
219impl<T: fmt::Display> fmt::Display for CssPropertyValue<T> {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 use self::CssPropertyValue::*;
222 match self {
223 Auto => write!(f, "auto"),
224 None => write!(f, "none"),
225 Initial => write!(f, "initial"),
226 Inherit => write!(f, "inherit"),
227 Revert => write!(f, "revert"),
228 Unset => write!(f, "unset"),
229 Exact(e) => write!(f, "{}", e),
230 }
231 }
232}
233
234impl<T> From<T> for CssPropertyValue<T> {
235 fn from(c: T) -> Self {
236 CssPropertyValue::Exact(c)
237 }
238}
239
240impl<T> CssPropertyValue<T> {
241 #[inline]
244 pub fn map_property<F: Fn(T) -> U, U>(self, map_fn: F) -> CssPropertyValue<U> {
245 match self {
246 CssPropertyValue::Exact(c) => CssPropertyValue::Exact(map_fn(c)),
247 CssPropertyValue::Auto => CssPropertyValue::Auto,
248 CssPropertyValue::None => CssPropertyValue::None,
249 CssPropertyValue::Initial => CssPropertyValue::Initial,
250 CssPropertyValue::Inherit => CssPropertyValue::Inherit,
251 CssPropertyValue::Revert => CssPropertyValue::Revert,
252 CssPropertyValue::Unset => CssPropertyValue::Unset,
253 }
254 }
255
256 #[inline]
257 pub fn get_property(&self) -> Option<&T> {
258 match self {
259 CssPropertyValue::Exact(c) => Some(c),
260 _ => None,
261 }
262 }
263
264 #[inline]
265 pub fn get_property_owned(self) -> Option<T> {
266 match self {
267 CssPropertyValue::Exact(c) => Some(c),
268 _ => None,
269 }
270 }
271
272 #[inline]
273 pub fn is_auto(&self) -> bool {
274 match self {
275 CssPropertyValue::Auto => true,
276 _ => false,
277 }
278 }
279
280 #[inline]
281 pub fn is_none(&self) -> bool {
282 match self {
283 CssPropertyValue::None => true,
284 _ => false,
285 }
286 }
287
288 #[inline]
289 pub fn is_initial(&self) -> bool {
290 match self {
291 CssPropertyValue::Initial => true,
292 _ => false,
293 }
294 }
295
296 #[inline]
297 pub fn is_inherit(&self) -> bool {
298 match self {
299 CssPropertyValue::Inherit => true,
300 _ => false,
301 }
302 }
303
304 #[inline]
305 pub fn is_revert(&self) -> bool {
306 match self {
307 CssPropertyValue::Revert => true,
308 _ => false,
309 }
310 }
311
312 #[inline]
313 pub fn is_unset(&self) -> bool {
314 match self {
315 CssPropertyValue::Unset => true,
316 _ => false,
317 }
318 }
319}
320
321impl<T: Default> CssPropertyValue<T> {
322 #[inline]
323 pub fn get_property_or_default(self) -> Option<T> {
324 match self {
325 CssPropertyValue::Auto | CssPropertyValue::Initial => Some(T::default()),
326 CssPropertyValue::Exact(c) => Some(c),
327 CssPropertyValue::None
328 | CssPropertyValue::Inherit
329 | CssPropertyValue::Revert
330 | CssPropertyValue::Unset => None,
331 }
332 }
333}
334
335impl<T: Default> Default for CssPropertyValue<T> {
336 #[inline]
337 fn default() -> Self {
338 CssPropertyValue::Exact(T::default())
339 }
340}
341
342impl DynamicCssProperty {
343 pub fn is_inheritable(&self) -> bool {
344 false
348 }
349
350 pub fn can_trigger_relayout(&self) -> bool {
351 self.default_value.get_type().can_trigger_relayout()
352 }
353}
354
355#[derive(Debug, Clone, PartialEq)]
361#[repr(C)]
362pub struct CssRuleBlock {
363 pub path: CssPath,
365 pub declarations: CssDeclarationVec,
368 pub conditions: DynamicSelectorVec,
371}
372
373impl PartialOrd for CssRuleBlock {
374 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
375 match self.path.partial_cmp(&other.path) {
377 Some(core::cmp::Ordering::Equal) => self.declarations.partial_cmp(&other.declarations),
378 ord => ord,
379 }
380 }
381}
382
383impl_vec!(
384 CssDeclaration,
385 CssDeclarationVec,
386 CssDeclarationVecDestructor,
387 CssDeclarationVecDestructorType
388);
389impl_vec_mut!(CssDeclaration, CssDeclarationVec);
390impl_vec_debug!(CssDeclaration, CssDeclarationVec);
391impl_vec_partialord!(CssDeclaration, CssDeclarationVec);
392impl_vec_ord!(CssDeclaration, CssDeclarationVec);
393impl_vec_clone!(
394 CssDeclaration,
395 CssDeclarationVec,
396 CssDeclarationVecDestructor
397);
398impl_vec_partialeq!(CssDeclaration, CssDeclarationVec);
399impl_vec_eq!(CssDeclaration, CssDeclarationVec);
400impl_vec_hash!(CssDeclaration, CssDeclarationVec);
401
402impl CssRuleBlock {
403 pub fn new(path: CssPath, declarations: Vec<CssDeclaration>) -> Self {
404 Self {
405 path,
406 declarations: declarations.into(),
407 conditions: DynamicSelectorVec::from_const_slice(&[]),
408 }
409 }
410
411 pub fn with_conditions(
412 path: CssPath,
413 declarations: Vec<CssDeclaration>,
414 conditions: Vec<crate::dynamic_selector::DynamicSelector>,
415 ) -> Self {
416 Self {
417 path,
418 declarations: declarations.into(),
419 conditions: conditions.into(),
420 }
421 }
422}
423
424pub type CssContentGroup<'a> = Vec<&'a CssPathSelector>;
425
426#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
428#[repr(C)]
429pub enum NodeTypeTag {
430 Html,
432 Head,
433 Body,
434
435 Div,
437 P,
438 Article,
439 Section,
440 Nav,
441 Aside,
442 Header,
443 Footer,
444 Main,
445 Figure,
446 FigCaption,
447
448 H1,
450 H2,
451 H3,
452 H4,
453 H5,
454 H6,
455
456 Br,
458 Hr,
459 Pre,
460 BlockQuote,
461 Address,
462 Details,
463 Summary,
464 Dialog,
465
466 Ul,
468 Ol,
469 Li,
470 Dl,
471 Dt,
472 Dd,
473 Menu,
474 MenuItem,
475 Dir,
476
477 Table,
479 Caption,
480 THead,
481 TBody,
482 TFoot,
483 Tr,
484 Th,
485 Td,
486 ColGroup,
487 Col,
488
489 Form,
491 FieldSet,
492 Legend,
493 Label,
494 Input,
495 Button,
496 Select,
497 OptGroup,
498 SelectOption,
499 TextArea,
500 Output,
501 Progress,
502 Meter,
503 DataList,
504
505 Span,
507 A,
508 Em,
509 Strong,
510 B,
511 I,
512 U,
513 S,
514 Mark,
515 Del,
516 Ins,
517 Code,
518 Samp,
519 Kbd,
520 Var,
521 Cite,
522 Dfn,
523 Abbr,
524 Acronym,
525 Q,
526 Time,
527 Sub,
528 Sup,
529 Small,
530 Big,
531 Bdo,
532 Bdi,
533 Wbr,
534 Ruby,
535 Rt,
536 Rtc,
537 Rp,
538 Data,
539
540 Canvas,
542 Object,
543 Param,
544 Embed,
545 Audio,
546 Video,
547 Source,
548 Track,
549 Map,
550 Area,
551 Svg,
552
553 Title,
555 Meta,
556 Link,
557 Script,
558 Style,
559 Base,
560
561 Text,
563 Img,
564 IFrame,
565 Icon,
567
568 Before,
570 After,
571 Marker,
572 Placeholder,
573}
574
575#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
576pub enum NodeTypeTagParseError<'a> {
577 Invalid(&'a str),
578}
579
580impl<'a> fmt::Display for NodeTypeTagParseError<'a> {
581 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582 match &self {
583 NodeTypeTagParseError::Invalid(e) => write!(f, "Invalid node type: {}", e),
584 }
585 }
586}
587
588#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
589pub enum NodeTypeTagParseErrorOwned {
590 Invalid(String),
591}
592
593impl<'a> NodeTypeTagParseError<'a> {
594 pub fn to_contained(&self) -> NodeTypeTagParseErrorOwned {
595 match self {
596 NodeTypeTagParseError::Invalid(s) => NodeTypeTagParseErrorOwned::Invalid(s.to_string()),
597 }
598 }
599}
600
601impl NodeTypeTagParseErrorOwned {
602 pub fn to_shared<'a>(&'a self) -> NodeTypeTagParseError<'a> {
603 match self {
604 NodeTypeTagParseErrorOwned::Invalid(s) => NodeTypeTagParseError::Invalid(s),
605 }
606 }
607}
608
609impl NodeTypeTag {
611 pub fn from_str(css_key: &str) -> Result<Self, NodeTypeTagParseError> {
612 match css_key {
613 "html" => Ok(NodeTypeTag::Html),
615 "head" => Ok(NodeTypeTag::Head),
616 "body" => Ok(NodeTypeTag::Body),
617
618 "div" => Ok(NodeTypeTag::Div),
620 "p" => Ok(NodeTypeTag::P),
621 "article" => Ok(NodeTypeTag::Article),
622 "section" => Ok(NodeTypeTag::Section),
623 "nav" => Ok(NodeTypeTag::Nav),
624 "aside" => Ok(NodeTypeTag::Aside),
625 "header" => Ok(NodeTypeTag::Header),
626 "footer" => Ok(NodeTypeTag::Footer),
627 "main" => Ok(NodeTypeTag::Main),
628 "figure" => Ok(NodeTypeTag::Figure),
629 "figcaption" => Ok(NodeTypeTag::FigCaption),
630
631 "h1" => Ok(NodeTypeTag::H1),
633 "h2" => Ok(NodeTypeTag::H2),
634 "h3" => Ok(NodeTypeTag::H3),
635 "h4" => Ok(NodeTypeTag::H4),
636 "h5" => Ok(NodeTypeTag::H5),
637 "h6" => Ok(NodeTypeTag::H6),
638
639 "br" => Ok(NodeTypeTag::Br),
641 "hr" => Ok(NodeTypeTag::Hr),
642 "pre" => Ok(NodeTypeTag::Pre),
643 "blockquote" => Ok(NodeTypeTag::BlockQuote),
644 "address" => Ok(NodeTypeTag::Address),
645 "details" => Ok(NodeTypeTag::Details),
646 "summary" => Ok(NodeTypeTag::Summary),
647 "dialog" => Ok(NodeTypeTag::Dialog),
648
649 "ul" => Ok(NodeTypeTag::Ul),
651 "ol" => Ok(NodeTypeTag::Ol),
652 "li" => Ok(NodeTypeTag::Li),
653 "dl" => Ok(NodeTypeTag::Dl),
654 "dt" => Ok(NodeTypeTag::Dt),
655 "dd" => Ok(NodeTypeTag::Dd),
656 "menu" => Ok(NodeTypeTag::Menu),
657 "menuitem" => Ok(NodeTypeTag::MenuItem),
658 "dir" => Ok(NodeTypeTag::Dir),
659
660 "table" => Ok(NodeTypeTag::Table),
662 "caption" => Ok(NodeTypeTag::Caption),
663 "thead" => Ok(NodeTypeTag::THead),
664 "tbody" => Ok(NodeTypeTag::TBody),
665 "tfoot" => Ok(NodeTypeTag::TFoot),
666 "tr" => Ok(NodeTypeTag::Tr),
667 "th" => Ok(NodeTypeTag::Th),
668 "td" => Ok(NodeTypeTag::Td),
669 "colgroup" => Ok(NodeTypeTag::ColGroup),
670 "col" => Ok(NodeTypeTag::Col),
671
672 "form" => Ok(NodeTypeTag::Form),
674 "fieldset" => Ok(NodeTypeTag::FieldSet),
675 "legend" => Ok(NodeTypeTag::Legend),
676 "label" => Ok(NodeTypeTag::Label),
677 "input" => Ok(NodeTypeTag::Input),
678 "button" => Ok(NodeTypeTag::Button),
679 "select" => Ok(NodeTypeTag::Select),
680 "optgroup" => Ok(NodeTypeTag::OptGroup),
681 "option" => Ok(NodeTypeTag::SelectOption),
682 "textarea" => Ok(NodeTypeTag::TextArea),
683 "output" => Ok(NodeTypeTag::Output),
684 "progress" => Ok(NodeTypeTag::Progress),
685 "meter" => Ok(NodeTypeTag::Meter),
686 "datalist" => Ok(NodeTypeTag::DataList),
687
688 "span" => Ok(NodeTypeTag::Span),
690 "a" => Ok(NodeTypeTag::A),
691 "em" => Ok(NodeTypeTag::Em),
692 "strong" => Ok(NodeTypeTag::Strong),
693 "b" => Ok(NodeTypeTag::B),
694 "i" => Ok(NodeTypeTag::I),
695 "u" => Ok(NodeTypeTag::U),
696 "s" => Ok(NodeTypeTag::S),
697 "mark" => Ok(NodeTypeTag::Mark),
698 "del" => Ok(NodeTypeTag::Del),
699 "ins" => Ok(NodeTypeTag::Ins),
700 "code" => Ok(NodeTypeTag::Code),
701 "samp" => Ok(NodeTypeTag::Samp),
702 "kbd" => Ok(NodeTypeTag::Kbd),
703 "var" => Ok(NodeTypeTag::Var),
704 "cite" => Ok(NodeTypeTag::Cite),
705 "dfn" => Ok(NodeTypeTag::Dfn),
706 "abbr" => Ok(NodeTypeTag::Abbr),
707 "acronym" => Ok(NodeTypeTag::Acronym),
708 "q" => Ok(NodeTypeTag::Q),
709 "time" => Ok(NodeTypeTag::Time),
710 "sub" => Ok(NodeTypeTag::Sub),
711 "sup" => Ok(NodeTypeTag::Sup),
712 "small" => Ok(NodeTypeTag::Small),
713 "big" => Ok(NodeTypeTag::Big),
714 "bdo" => Ok(NodeTypeTag::Bdo),
715 "bdi" => Ok(NodeTypeTag::Bdi),
716 "wbr" => Ok(NodeTypeTag::Wbr),
717 "ruby" => Ok(NodeTypeTag::Ruby),
718 "rt" => Ok(NodeTypeTag::Rt),
719 "rtc" => Ok(NodeTypeTag::Rtc),
720 "rp" => Ok(NodeTypeTag::Rp),
721 "data" => Ok(NodeTypeTag::Data),
722
723 "canvas" => Ok(NodeTypeTag::Canvas),
725 "object" => Ok(NodeTypeTag::Object),
726 "param" => Ok(NodeTypeTag::Param),
727 "embed" => Ok(NodeTypeTag::Embed),
728 "audio" => Ok(NodeTypeTag::Audio),
729 "video" => Ok(NodeTypeTag::Video),
730 "source" => Ok(NodeTypeTag::Source),
731 "track" => Ok(NodeTypeTag::Track),
732 "map" => Ok(NodeTypeTag::Map),
733 "area" => Ok(NodeTypeTag::Area),
734 "svg" => Ok(NodeTypeTag::Svg),
735
736 "title" => Ok(NodeTypeTag::Title),
738 "meta" => Ok(NodeTypeTag::Meta),
739 "link" => Ok(NodeTypeTag::Link),
740 "script" => Ok(NodeTypeTag::Script),
741 "style" => Ok(NodeTypeTag::Style),
742 "base" => Ok(NodeTypeTag::Base),
743
744 "img" => Ok(NodeTypeTag::Img),
746 "iframe" => Ok(NodeTypeTag::IFrame),
747 "icon" => Ok(NodeTypeTag::Icon),
748
749 "before" | "::before" => Ok(NodeTypeTag::Before),
751 "after" | "::after" => Ok(NodeTypeTag::After),
752 "marker" | "::marker" => Ok(NodeTypeTag::Marker),
753 "placeholder" | "::placeholder" => Ok(NodeTypeTag::Placeholder),
754
755 other => Err(NodeTypeTagParseError::Invalid(other)),
756 }
757 }
758}
759
760impl fmt::Display for NodeTypeTag {
761 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
762 match self {
763 NodeTypeTag::Html => write!(f, "html"),
765 NodeTypeTag::Head => write!(f, "head"),
766 NodeTypeTag::Body => write!(f, "body"),
767
768 NodeTypeTag::Div => write!(f, "div"),
770 NodeTypeTag::P => write!(f, "p"),
771 NodeTypeTag::Article => write!(f, "article"),
772 NodeTypeTag::Section => write!(f, "section"),
773 NodeTypeTag::Nav => write!(f, "nav"),
774 NodeTypeTag::Aside => write!(f, "aside"),
775 NodeTypeTag::Header => write!(f, "header"),
776 NodeTypeTag::Footer => write!(f, "footer"),
777 NodeTypeTag::Main => write!(f, "main"),
778 NodeTypeTag::Figure => write!(f, "figure"),
779 NodeTypeTag::FigCaption => write!(f, "figcaption"),
780
781 NodeTypeTag::H1 => write!(f, "h1"),
783 NodeTypeTag::H2 => write!(f, "h2"),
784 NodeTypeTag::H3 => write!(f, "h3"),
785 NodeTypeTag::H4 => write!(f, "h4"),
786 NodeTypeTag::H5 => write!(f, "h5"),
787 NodeTypeTag::H6 => write!(f, "h6"),
788
789 NodeTypeTag::Br => write!(f, "br"),
791 NodeTypeTag::Hr => write!(f, "hr"),
792 NodeTypeTag::Pre => write!(f, "pre"),
793 NodeTypeTag::BlockQuote => write!(f, "blockquote"),
794 NodeTypeTag::Address => write!(f, "address"),
795 NodeTypeTag::Details => write!(f, "details"),
796 NodeTypeTag::Summary => write!(f, "summary"),
797 NodeTypeTag::Dialog => write!(f, "dialog"),
798
799 NodeTypeTag::Ul => write!(f, "ul"),
801 NodeTypeTag::Ol => write!(f, "ol"),
802 NodeTypeTag::Li => write!(f, "li"),
803 NodeTypeTag::Dl => write!(f, "dl"),
804 NodeTypeTag::Dt => write!(f, "dt"),
805 NodeTypeTag::Dd => write!(f, "dd"),
806 NodeTypeTag::Menu => write!(f, "menu"),
807 NodeTypeTag::MenuItem => write!(f, "menuitem"),
808 NodeTypeTag::Dir => write!(f, "dir"),
809
810 NodeTypeTag::Table => write!(f, "table"),
812 NodeTypeTag::Caption => write!(f, "caption"),
813 NodeTypeTag::THead => write!(f, "thead"),
814 NodeTypeTag::TBody => write!(f, "tbody"),
815 NodeTypeTag::TFoot => write!(f, "tfoot"),
816 NodeTypeTag::Tr => write!(f, "tr"),
817 NodeTypeTag::Th => write!(f, "th"),
818 NodeTypeTag::Td => write!(f, "td"),
819 NodeTypeTag::ColGroup => write!(f, "colgroup"),
820 NodeTypeTag::Col => write!(f, "col"),
821
822 NodeTypeTag::Form => write!(f, "form"),
824 NodeTypeTag::FieldSet => write!(f, "fieldset"),
825 NodeTypeTag::Legend => write!(f, "legend"),
826 NodeTypeTag::Label => write!(f, "label"),
827 NodeTypeTag::Input => write!(f, "input"),
828 NodeTypeTag::Button => write!(f, "button"),
829 NodeTypeTag::Select => write!(f, "select"),
830 NodeTypeTag::OptGroup => write!(f, "optgroup"),
831 NodeTypeTag::SelectOption => write!(f, "option"),
832 NodeTypeTag::TextArea => write!(f, "textarea"),
833 NodeTypeTag::Output => write!(f, "output"),
834 NodeTypeTag::Progress => write!(f, "progress"),
835 NodeTypeTag::Meter => write!(f, "meter"),
836 NodeTypeTag::DataList => write!(f, "datalist"),
837
838 NodeTypeTag::Span => write!(f, "span"),
840 NodeTypeTag::A => write!(f, "a"),
841 NodeTypeTag::Em => write!(f, "em"),
842 NodeTypeTag::Strong => write!(f, "strong"),
843 NodeTypeTag::B => write!(f, "b"),
844 NodeTypeTag::I => write!(f, "i"),
845 NodeTypeTag::U => write!(f, "u"),
846 NodeTypeTag::S => write!(f, "s"),
847 NodeTypeTag::Mark => write!(f, "mark"),
848 NodeTypeTag::Del => write!(f, "del"),
849 NodeTypeTag::Ins => write!(f, "ins"),
850 NodeTypeTag::Code => write!(f, "code"),
851 NodeTypeTag::Samp => write!(f, "samp"),
852 NodeTypeTag::Kbd => write!(f, "kbd"),
853 NodeTypeTag::Var => write!(f, "var"),
854 NodeTypeTag::Cite => write!(f, "cite"),
855 NodeTypeTag::Dfn => write!(f, "dfn"),
856 NodeTypeTag::Abbr => write!(f, "abbr"),
857 NodeTypeTag::Acronym => write!(f, "acronym"),
858 NodeTypeTag::Q => write!(f, "q"),
859 NodeTypeTag::Time => write!(f, "time"),
860 NodeTypeTag::Sub => write!(f, "sub"),
861 NodeTypeTag::Sup => write!(f, "sup"),
862 NodeTypeTag::Small => write!(f, "small"),
863 NodeTypeTag::Big => write!(f, "big"),
864 NodeTypeTag::Bdo => write!(f, "bdo"),
865 NodeTypeTag::Bdi => write!(f, "bdi"),
866 NodeTypeTag::Wbr => write!(f, "wbr"),
867 NodeTypeTag::Ruby => write!(f, "ruby"),
868 NodeTypeTag::Rt => write!(f, "rt"),
869 NodeTypeTag::Rtc => write!(f, "rtc"),
870 NodeTypeTag::Rp => write!(f, "rp"),
871 NodeTypeTag::Data => write!(f, "data"),
872
873 NodeTypeTag::Canvas => write!(f, "canvas"),
875 NodeTypeTag::Object => write!(f, "object"),
876 NodeTypeTag::Param => write!(f, "param"),
877 NodeTypeTag::Embed => write!(f, "embed"),
878 NodeTypeTag::Audio => write!(f, "audio"),
879 NodeTypeTag::Video => write!(f, "video"),
880 NodeTypeTag::Source => write!(f, "source"),
881 NodeTypeTag::Track => write!(f, "track"),
882 NodeTypeTag::Map => write!(f, "map"),
883 NodeTypeTag::Area => write!(f, "area"),
884 NodeTypeTag::Svg => write!(f, "svg"),
885
886 NodeTypeTag::Title => write!(f, "title"),
888 NodeTypeTag::Meta => write!(f, "meta"),
889 NodeTypeTag::Link => write!(f, "link"),
890 NodeTypeTag::Script => write!(f, "script"),
891 NodeTypeTag::Style => write!(f, "style"),
892 NodeTypeTag::Base => write!(f, "base"),
893
894 NodeTypeTag::Text => write!(f, "text"),
896 NodeTypeTag::Img => write!(f, "img"),
897 NodeTypeTag::IFrame => write!(f, "iframe"),
898 NodeTypeTag::Icon => write!(f, "icon"),
899
900 NodeTypeTag::Before => write!(f, "::before"),
902 NodeTypeTag::After => write!(f, "::after"),
903 NodeTypeTag::Marker => write!(f, "::marker"),
904 NodeTypeTag::Placeholder => write!(f, "::placeholder"),
905 }
906 }
907}
908
909#[derive(Clone, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]
921#[repr(C)]
922pub struct CssPath {
923 pub selectors: CssPathSelectorVec,
924}
925
926impl_vec!(
927 CssPathSelector,
928 CssPathSelectorVec,
929 CssPathSelectorVecDestructor,
930 CssPathSelectorVecDestructorType
931);
932impl_vec_debug!(CssPathSelector, CssPathSelectorVec);
933impl_vec_partialord!(CssPathSelector, CssPathSelectorVec);
934impl_vec_ord!(CssPathSelector, CssPathSelectorVec);
935impl_vec_clone!(
936 CssPathSelector,
937 CssPathSelectorVec,
938 CssPathSelectorVecDestructor
939);
940impl_vec_partialeq!(CssPathSelector, CssPathSelectorVec);
941impl_vec_eq!(CssPathSelector, CssPathSelectorVec);
942impl_vec_hash!(CssPathSelector, CssPathSelectorVec);
943
944impl CssPath {
945 pub fn new(selectors: Vec<CssPathSelector>) -> Self {
946 Self {
947 selectors: selectors.into(),
948 }
949 }
950}
951
952impl fmt::Display for CssPath {
953 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
954 for selector in self.selectors.as_ref() {
955 write!(f, "{}", selector)?;
956 }
957 Ok(())
958 }
959}
960
961impl fmt::Debug for CssPath {
962 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
963 write!(f, "{}", self)
964 }
965}
966
967#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
968#[repr(C, u8)]
969pub enum CssPathSelector {
970 Global,
972 Type(NodeTypeTag),
974 Class(AzString),
976 Id(AzString),
978 PseudoSelector(CssPathPseudoSelector),
980 DirectChildren,
982 Children,
984 AdjacentSibling,
986 GeneralSibling,
988}
989
990impl Default for CssPathSelector {
991 fn default() -> Self {
992 CssPathSelector::Global
993 }
994}
995
996impl fmt::Display for CssPathSelector {
997 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
998 use self::CssPathSelector::*;
999 match &self {
1000 Global => write!(f, "*"),
1001 Type(n) => write!(f, "{}", n),
1002 Class(c) => write!(f, ".{}", c),
1003 Id(i) => write!(f, "#{}", i),
1004 PseudoSelector(p) => write!(f, ":{}", p),
1005 DirectChildren => write!(f, ">"),
1006 Children => write!(f, " "),
1007 AdjacentSibling => write!(f, "+"),
1008 GeneralSibling => write!(f, "~"),
1009 }
1010 }
1011}
1012
1013#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1014#[repr(C, u8)]
1015pub enum CssPathPseudoSelector {
1016 First,
1018 Last,
1020 NthChild(CssNthChildSelector),
1022 Hover,
1024 Active,
1026 Focus,
1028 Lang(AzString),
1030}
1031
1032#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1033#[repr(C, u8)]
1034pub enum CssNthChildSelector {
1035 Number(u32),
1036 Even,
1037 Odd,
1038 Pattern(CssNthChildPattern),
1039}
1040
1041#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1042#[repr(C)]
1043pub struct CssNthChildPattern {
1044 pub pattern_repeat: u32,
1045 pub offset: u32,
1046}
1047
1048impl fmt::Display for CssNthChildSelector {
1049 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050 use self::CssNthChildSelector::*;
1051 match &self {
1052 Number(u) => write!(f, "{}", u),
1053 Even => write!(f, "even"),
1054 Odd => write!(f, "odd"),
1055 Pattern(p) => write!(f, "{}n + {}", p.pattern_repeat, p.offset),
1056 }
1057 }
1058}
1059
1060impl fmt::Display for CssPathPseudoSelector {
1061 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1062 use self::CssPathPseudoSelector::*;
1063 match &self {
1064 First => write!(f, "first"),
1065 Last => write!(f, "last"),
1066 NthChild(u) => write!(f, "nth-child({})", u),
1067 Hover => write!(f, "hover"),
1068 Active => write!(f, "active"),
1069 Focus => write!(f, "focus"),
1070 Lang(lang) => write!(f, "lang({})", lang.as_str()),
1071 }
1072 }
1073}
1074
1075impl Css {
1076 pub fn empty() -> Self {
1078 Default::default()
1079 }
1080
1081 pub fn sort_by_specificity(&mut self) {
1082 self.stylesheets
1083 .as_mut()
1084 .iter_mut()
1085 .for_each(|s| s.sort_by_specificity());
1086 }
1087
1088 pub fn rules<'a>(&'a self) -> RuleIterator<'a> {
1089 RuleIterator {
1090 current_stylesheet: 0,
1091 current_rule: 0,
1092 css: self,
1093 }
1094 }
1095}
1096
1097pub struct RuleIterator<'a> {
1098 current_stylesheet: usize,
1099 current_rule: usize,
1100 css: &'a Css,
1101}
1102
1103impl<'a> Iterator for RuleIterator<'a> {
1104 type Item = &'a CssRuleBlock;
1105 fn next(&mut self) -> Option<&'a CssRuleBlock> {
1106 let current_stylesheet = self.css.stylesheets.get(self.current_stylesheet)?;
1107 match current_stylesheet.rules.get(self.current_rule) {
1108 Some(s) => {
1109 self.current_rule += 1;
1110 Some(s)
1111 }
1112 None => {
1113 self.current_rule = 0;
1114 self.current_stylesheet += 1;
1115 self.next()
1116 }
1117 }
1118 }
1119}
1120
1121impl Stylesheet {
1122 pub fn empty() -> Self {
1124 Default::default()
1125 }
1126
1127 pub fn sort_by_specificity(&mut self) {
1130 self.rules
1131 .as_mut()
1132 .sort_by(|a, b| get_specificity(&a.path).cmp(&get_specificity(&b.path)));
1133 }
1134}
1135
1136pub fn get_specificity(path: &CssPath) -> (usize, usize, usize, usize) {
1139 let id_count = path
1140 .selectors
1141 .iter()
1142 .filter(|x| {
1143 if let CssPathSelector::Id(_) = x {
1144 true
1145 } else {
1146 false
1147 }
1148 })
1149 .count();
1150 let class_count = path
1151 .selectors
1152 .iter()
1153 .filter(|x| {
1154 if let CssPathSelector::Class(_) = x {
1155 true
1156 } else {
1157 false
1158 }
1159 })
1160 .count();
1161 let div_count = path
1162 .selectors
1163 .iter()
1164 .filter(|x| {
1165 if let CssPathSelector::Type(_) = x {
1166 true
1167 } else {
1168 false
1169 }
1170 })
1171 .count();
1172 (id_count, class_count, div_count, path.selectors.len())
1173}
1174
1175pub fn css_to_rust_code(css: &Css) -> String {
1180 let mut output = String::new();
1181
1182 output.push_str("const CSS: Css = Css {\r\n");
1183 output.push_str("\tstylesheets: [\r\n");
1184
1185 for stylesheet in css.stylesheets.iter() {
1186 output.push_str("\t\tStylesheet {\r\n");
1187 output.push_str("\t\t\trules: [\r\n");
1188
1189 for block in stylesheet.rules.iter() {
1190 output.push_str("\t\t\t\tCssRuleBlock: {\r\n");
1191 output.push_str(&format!(
1192 "\t\t\t\t\tpath: {},\r\n",
1193 print_block_path(&block.path, 5)
1194 ));
1195
1196 output.push_str("\t\t\t\t\tdeclarations: [\r\n");
1197
1198 for declaration in block.declarations.iter() {
1199 output.push_str(&format!(
1200 "\t\t\t\t\t\t{},\r\n",
1201 print_declaration(declaration, 6)
1202 ));
1203 }
1204
1205 output.push_str("\t\t\t\t\t]\r\n");
1206
1207 output.push_str("\t\t\t\t},\r\n");
1208 }
1209
1210 output.push_str("\t\t\t]\r\n");
1211 output.push_str("\t\t},\r\n");
1212 }
1213
1214 output.push_str("\t]\r\n");
1215 output.push_str("};");
1216
1217 let output = output.replace("\t", " ");
1218
1219 output
1220}
1221
1222pub fn format_node_type(n: &NodeTypeTag) -> &'static str {
1223 match n {
1224 NodeTypeTag::Html => "NodeTypeTag::Html",
1226 NodeTypeTag::Head => "NodeTypeTag::Head",
1227 NodeTypeTag::Body => "NodeTypeTag::Body",
1228
1229 NodeTypeTag::Div => "NodeTypeTag::Div",
1231 NodeTypeTag::P => "NodeTypeTag::P",
1232 NodeTypeTag::Article => "NodeTypeTag::Article",
1233 NodeTypeTag::Section => "NodeTypeTag::Section",
1234 NodeTypeTag::Nav => "NodeTypeTag::Nav",
1235 NodeTypeTag::Aside => "NodeTypeTag::Aside",
1236 NodeTypeTag::Header => "NodeTypeTag::Header",
1237 NodeTypeTag::Footer => "NodeTypeTag::Footer",
1238 NodeTypeTag::Main => "NodeTypeTag::Main",
1239 NodeTypeTag::Figure => "NodeTypeTag::Figure",
1240 NodeTypeTag::FigCaption => "NodeTypeTag::FigCaption",
1241
1242 NodeTypeTag::H1 => "NodeTypeTag::H1",
1244 NodeTypeTag::H2 => "NodeTypeTag::H2",
1245 NodeTypeTag::H3 => "NodeTypeTag::H3",
1246 NodeTypeTag::H4 => "NodeTypeTag::H4",
1247 NodeTypeTag::H5 => "NodeTypeTag::H5",
1248 NodeTypeTag::H6 => "NodeTypeTag::H6",
1249
1250 NodeTypeTag::Br => "NodeTypeTag::Br",
1252 NodeTypeTag::Hr => "NodeTypeTag::Hr",
1253 NodeTypeTag::Pre => "NodeTypeTag::Pre",
1254 NodeTypeTag::BlockQuote => "NodeTypeTag::BlockQuote",
1255 NodeTypeTag::Address => "NodeTypeTag::Address",
1256 NodeTypeTag::Details => "NodeTypeTag::Details",
1257 NodeTypeTag::Summary => "NodeTypeTag::Summary",
1258 NodeTypeTag::Dialog => "NodeTypeTag::Dialog",
1259
1260 NodeTypeTag::Ul => "NodeTypeTag::Ul",
1262 NodeTypeTag::Ol => "NodeTypeTag::Ol",
1263 NodeTypeTag::Li => "NodeTypeTag::Li",
1264 NodeTypeTag::Dl => "NodeTypeTag::Dl",
1265 NodeTypeTag::Dt => "NodeTypeTag::Dt",
1266 NodeTypeTag::Dd => "NodeTypeTag::Dd",
1267 NodeTypeTag::Menu => "NodeTypeTag::Menu",
1268 NodeTypeTag::MenuItem => "NodeTypeTag::MenuItem",
1269 NodeTypeTag::Dir => "NodeTypeTag::Dir",
1270
1271 NodeTypeTag::Table => "NodeTypeTag::Table",
1273 NodeTypeTag::Caption => "NodeTypeTag::Caption",
1274 NodeTypeTag::THead => "NodeTypeTag::THead",
1275 NodeTypeTag::TBody => "NodeTypeTag::TBody",
1276 NodeTypeTag::TFoot => "NodeTypeTag::TFoot",
1277 NodeTypeTag::Tr => "NodeTypeTag::Tr",
1278 NodeTypeTag::Th => "NodeTypeTag::Th",
1279 NodeTypeTag::Td => "NodeTypeTag::Td",
1280 NodeTypeTag::ColGroup => "NodeTypeTag::ColGroup",
1281 NodeTypeTag::Col => "NodeTypeTag::Col",
1282
1283 NodeTypeTag::Form => "NodeTypeTag::Form",
1285 NodeTypeTag::FieldSet => "NodeTypeTag::FieldSet",
1286 NodeTypeTag::Legend => "NodeTypeTag::Legend",
1287 NodeTypeTag::Label => "NodeTypeTag::Label",
1288 NodeTypeTag::Input => "NodeTypeTag::Input",
1289 NodeTypeTag::Button => "NodeTypeTag::Button",
1290 NodeTypeTag::Select => "NodeTypeTag::Select",
1291 NodeTypeTag::OptGroup => "NodeTypeTag::OptGroup",
1292 NodeTypeTag::SelectOption => "NodeTypeTag::SelectOption",
1293 NodeTypeTag::TextArea => "NodeTypeTag::TextArea",
1294 NodeTypeTag::Output => "NodeTypeTag::Output",
1295 NodeTypeTag::Progress => "NodeTypeTag::Progress",
1296 NodeTypeTag::Meter => "NodeTypeTag::Meter",
1297 NodeTypeTag::DataList => "NodeTypeTag::DataList",
1298
1299 NodeTypeTag::Span => "NodeTypeTag::Span",
1301 NodeTypeTag::A => "NodeTypeTag::A",
1302 NodeTypeTag::Em => "NodeTypeTag::Em",
1303 NodeTypeTag::Strong => "NodeTypeTag::Strong",
1304 NodeTypeTag::B => "NodeTypeTag::B",
1305 NodeTypeTag::I => "NodeTypeTag::I",
1306 NodeTypeTag::U => "NodeTypeTag::U",
1307 NodeTypeTag::S => "NodeTypeTag::S",
1308 NodeTypeTag::Mark => "NodeTypeTag::Mark",
1309 NodeTypeTag::Del => "NodeTypeTag::Del",
1310 NodeTypeTag::Ins => "NodeTypeTag::Ins",
1311 NodeTypeTag::Code => "NodeTypeTag::Code",
1312 NodeTypeTag::Samp => "NodeTypeTag::Samp",
1313 NodeTypeTag::Kbd => "NodeTypeTag::Kbd",
1314 NodeTypeTag::Var => "NodeTypeTag::Var",
1315 NodeTypeTag::Cite => "NodeTypeTag::Cite",
1316 NodeTypeTag::Dfn => "NodeTypeTag::Dfn",
1317 NodeTypeTag::Abbr => "NodeTypeTag::Abbr",
1318 NodeTypeTag::Acronym => "NodeTypeTag::Acronym",
1319 NodeTypeTag::Q => "NodeTypeTag::Q",
1320 NodeTypeTag::Time => "NodeTypeTag::Time",
1321 NodeTypeTag::Sub => "NodeTypeTag::Sub",
1322 NodeTypeTag::Sup => "NodeTypeTag::Sup",
1323 NodeTypeTag::Small => "NodeTypeTag::Small",
1324 NodeTypeTag::Big => "NodeTypeTag::Big",
1325 NodeTypeTag::Bdo => "NodeTypeTag::Bdo",
1326 NodeTypeTag::Bdi => "NodeTypeTag::Bdi",
1327 NodeTypeTag::Wbr => "NodeTypeTag::Wbr",
1328 NodeTypeTag::Ruby => "NodeTypeTag::Ruby",
1329 NodeTypeTag::Rt => "NodeTypeTag::Rt",
1330 NodeTypeTag::Rtc => "NodeTypeTag::Rtc",
1331 NodeTypeTag::Rp => "NodeTypeTag::Rp",
1332 NodeTypeTag::Data => "NodeTypeTag::Data",
1333
1334 NodeTypeTag::Canvas => "NodeTypeTag::Canvas",
1336 NodeTypeTag::Object => "NodeTypeTag::Object",
1337 NodeTypeTag::Param => "NodeTypeTag::Param",
1338 NodeTypeTag::Embed => "NodeTypeTag::Embed",
1339 NodeTypeTag::Audio => "NodeTypeTag::Audio",
1340 NodeTypeTag::Video => "NodeTypeTag::Video",
1341 NodeTypeTag::Source => "NodeTypeTag::Source",
1342 NodeTypeTag::Track => "NodeTypeTag::Track",
1343 NodeTypeTag::Map => "NodeTypeTag::Map",
1344 NodeTypeTag::Area => "NodeTypeTag::Area",
1345 NodeTypeTag::Svg => "NodeTypeTag::Svg",
1346
1347 NodeTypeTag::Title => "NodeTypeTag::Title",
1349 NodeTypeTag::Meta => "NodeTypeTag::Meta",
1350 NodeTypeTag::Link => "NodeTypeTag::Link",
1351 NodeTypeTag::Script => "NodeTypeTag::Script",
1352 NodeTypeTag::Style => "NodeTypeTag::Style",
1353 NodeTypeTag::Base => "NodeTypeTag::Base",
1354
1355 NodeTypeTag::Text => "NodeTypeTag::Text",
1357 NodeTypeTag::Img => "NodeTypeTag::Img",
1358 NodeTypeTag::IFrame => "NodeTypeTag::IFrame",
1359 NodeTypeTag::Icon => "NodeTypeTag::Icon",
1360
1361 NodeTypeTag::Before => "NodeTypeTag::Before",
1363 NodeTypeTag::After => "NodeTypeTag::After",
1364 NodeTypeTag::Marker => "NodeTypeTag::Marker",
1365 NodeTypeTag::Placeholder => "NodeTypeTag::Placeholder",
1366 }
1367}
1368
1369pub fn print_block_path(path: &CssPath, tabs: usize) -> String {
1370 let t = String::from(" ").repeat(tabs);
1371 let t1 = String::from(" ").repeat(tabs + 1);
1372
1373 format!(
1374 "CssPath {{\r\n{}selectors: {}\r\n{}}}",
1375 t1,
1376 format_selectors(path.selectors.as_ref(), tabs + 1),
1377 t
1378 )
1379}
1380
1381pub fn format_selectors(selectors: &[CssPathSelector], tabs: usize) -> String {
1382 let t = String::from(" ").repeat(tabs);
1383 let t1 = String::from(" ").repeat(tabs + 1);
1384
1385 let selectors_formatted = selectors
1386 .iter()
1387 .map(|s| format!("{}{},", t1, format_single_selector(s, tabs + 1)))
1388 .collect::<Vec<String>>()
1389 .join("\r\n");
1390
1391 format!("vec![\r\n{}\r\n{}].into()", selectors_formatted, t)
1392}
1393
1394pub fn format_single_selector(p: &CssPathSelector, _tabs: usize) -> String {
1395 match p {
1396 CssPathSelector::Global => format!("CssPathSelector::Global"),
1397 CssPathSelector::Type(ntp) => format!("CssPathSelector::Type({})", format_node_type(ntp)),
1398 CssPathSelector::Class(class) => {
1399 format!("CssPathSelector::Class(String::from({:?}))", class)
1400 }
1401 CssPathSelector::Id(id) => format!("CssPathSelector::Id(String::from({:?}))", id),
1402 CssPathSelector::PseudoSelector(cps) => format!(
1403 "CssPathSelector::PseudoSelector({})",
1404 format_pseudo_selector_type(cps)
1405 ),
1406 CssPathSelector::DirectChildren => format!("CssPathSelector::DirectChildren"),
1407 CssPathSelector::Children => format!("CssPathSelector::Children"),
1408 CssPathSelector::AdjacentSibling => format!("CssPathSelector::AdjacentSibling"),
1409 CssPathSelector::GeneralSibling => format!("CssPathSelector::GeneralSibling"),
1410 }
1411}
1412
1413pub fn format_pseudo_selector_type(p: &CssPathPseudoSelector) -> String {
1414 match p {
1415 CssPathPseudoSelector::First => format!("CssPathPseudoSelector::First"),
1416 CssPathPseudoSelector::Last => format!("CssPathPseudoSelector::Last"),
1417 CssPathPseudoSelector::NthChild(n) => format!(
1418 "CssPathPseudoSelector::NthChild({})",
1419 format_nth_child_selector(n)
1420 ),
1421 CssPathPseudoSelector::Hover => format!("CssPathPseudoSelector::Hover"),
1422 CssPathPseudoSelector::Active => format!("CssPathPseudoSelector::Active"),
1423 CssPathPseudoSelector::Focus => format!("CssPathPseudoSelector::Focus"),
1424 CssPathPseudoSelector::Lang(lang) => format!(
1425 "CssPathPseudoSelector::Lang(AzString::from_const_str(\"{}\"))",
1426 lang.as_str()
1427 ),
1428 }
1429}
1430
1431pub fn format_nth_child_selector(n: &CssNthChildSelector) -> String {
1432 match n {
1433 CssNthChildSelector::Number(num) => format!("CssNthChildSelector::Number({})", num),
1434 CssNthChildSelector::Even => format!("CssNthChildSelector::Even"),
1435 CssNthChildSelector::Odd => format!("CssNthChildSelector::Odd"),
1436 CssNthChildSelector::Pattern(CssNthChildPattern {
1437 pattern_repeat,
1438 offset,
1439 }) => format!(
1440 "CssNthChildSelector::Pattern(CssNthChildPattern {{ pattern_repeat: {}, offset: {} }})",
1441 pattern_repeat, offset
1442 ),
1443 }
1444}
1445
1446pub fn print_declaration(decl: &CssDeclaration, tabs: usize) -> String {
1447 match decl {
1448 CssDeclaration::Static(s) => format!(
1449 "CssDeclaration::Static({})",
1450 format_static_css_prop(s, tabs)
1451 ),
1452 CssDeclaration::Dynamic(d) => format!(
1453 "CssDeclaration::Dynamic({})",
1454 format_dynamic_css_prop(d, tabs)
1455 ),
1456 }
1457}
1458
1459pub fn format_dynamic_css_prop(decl: &DynamicCssProperty, tabs: usize) -> String {
1460 let t = String::from(" ").repeat(tabs);
1461 format!(
1462 "DynamicCssProperty {{\r\n{} dynamic_id: {:?},\r\n{} default_value: {},\r\n{}}}",
1463 t,
1464 decl.dynamic_id,
1465 t,
1466 format_static_css_prop(&decl.default_value, tabs + 1),
1467 t
1468 )
1469}