sauron_syntax/
to_syntax.rs

1use sauron::{mt_dom::AttValue, prelude::*};
2use std::{fmt, fmt::Write};
3
4/// A trait to convert html string into sauron view syntax
5pub trait ToSyntax {
6    /// convert the html string into sauron view syntax
7    fn to_syntax(
8        &self,
9        buffer: &mut dyn Write,
10        use_macros: bool,
11        indent: usize,
12    ) -> fmt::Result;
13}
14
15impl<MSG: 'static> ToSyntax for Node<MSG> {
16    fn to_syntax(
17        &self,
18        buffer: &mut dyn Write,
19        use_macros: bool,
20        indent: usize,
21    ) -> fmt::Result {
22        match self {
23            Node::Text(text) => write!(buffer, "text(\"{}\")", text),
24            Node::Element(element) => {
25                element.to_syntax(buffer, use_macros, indent)
26            }
27        }
28    }
29}
30
31impl<MSG: 'static> ToSyntax for Attribute<MSG> {
32    fn to_syntax(
33        &self,
34        buffer: &mut dyn Write,
35        use_macros: bool,
36        indent: usize,
37    ) -> fmt::Result {
38        for att_value in self.value() {
39            match att_value {
40                AttValue::Plain(plain) => match plain {
41                    AttributeValue::Simple(simple) => {
42                        if let Some(_ns) = self.namespace() {
43                            write!(
44                                buffer,
45                                "xlink_{}",
46                                self.name().to_string(),
47                            )?;
48                            write!(buffer, "(")?;
49                            simple.to_syntax(buffer, use_macros, indent)?;
50                            write!(buffer, ")")?;
51                        } else {
52                            let matched_attribute_func =
53                                sauron_parse::match_attribute_function(
54                                    &self.name(),
55                                )
56                                .is_some();
57                            if matched_attribute_func {
58                                write!(buffer, "{}", self.name().to_string(),)?;
59                                write!(buffer, "(")?;
60                                simple.to_syntax(buffer, use_macros, indent)?;
61                                write!(buffer, ")")?;
62                            } else {
63                                write!(
64                                    buffer,
65                                    r#"attr("{}","#,
66                                    self.name().to_string(),
67                                )?;
68                                simple.to_syntax(buffer, use_macros, indent)?;
69                                write!(buffer, ")")?;
70                            }
71                        }
72                    }
73                    AttributeValue::Style(styles_att) => {
74                        write!(buffer, "style(\"")?;
75                        for s_att in styles_att {
76                            write!(buffer, "{};", s_att)?;
77                        }
78                        write!(buffer, "\")")?;
79                    }
80                    _ => (),
81                },
82                _ => (),
83            }
84        }
85        Ok(())
86    }
87}
88
89impl ToSyntax for Value {
90    fn to_syntax(
91        &self,
92        buffer: &mut dyn Write,
93        _use_macros: bool,
94        _indent: usize,
95    ) -> fmt::Result {
96        match self.as_str() {
97            Some(v_str) => {
98                if let Ok(v_str) = v_str.parse::<f64>() {
99                    write!(buffer, "{}", v_str)?;
100                } else {
101                    write!(buffer, "\"{}\"", v_str)?;
102                }
103            }
104            None => (),
105        }
106        Ok(())
107    }
108}
109
110impl<MSG: 'static> ToSyntax for Element<MSG> {
111    fn to_syntax(
112        &self,
113        buffer: &mut dyn Write,
114        use_macros: bool,
115        indent: usize,
116    ) -> fmt::Result {
117        if use_macros {
118            write!(buffer, "{}!(", self.tag())?;
119        } else {
120            write!(buffer, "{}(", self.tag())?;
121        }
122        if use_macros {
123            write!(buffer, "[")?;
124        } else {
125            write!(buffer, "vec![")?;
126        }
127        for attr in self.get_attributes().iter() {
128            attr.to_syntax(buffer, use_macros, indent)?;
129            write!(buffer, ",")?;
130        }
131        write!(buffer, "],")?;
132        if use_macros {
133            write!(buffer, "[")?;
134        } else {
135            write!(buffer, "vec![")?;
136        }
137        let children = self.get_children();
138        let first_child = children.get(0);
139        let is_first_child_text_node =
140            first_child.map(|node| node.is_text()).unwrap_or(false);
141
142        let is_lone_child_text_node =
143            children.len() == 1 && is_first_child_text_node;
144
145        if is_lone_child_text_node {
146            first_child.unwrap().to_syntax(buffer, use_macros, indent)?;
147        } else {
148            // otherwise print all child nodes with each line and indented
149            for child in self.get_children() {
150                write!(buffer, "\n{}", "    ".repeat(indent + 1))?;
151                child.to_syntax(buffer, use_macros, indent + 1)?;
152                write!(buffer, ",")?;
153            }
154        }
155        // only make a new line if the child is not a text child node and if there are more than 1
156        // child
157        if !is_lone_child_text_node && !children.is_empty() {
158            write!(buffer, "\n{}", "    ".repeat(indent))?;
159        }
160        write!(buffer, "])")?;
161        Ok(())
162    }
163}