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