1#[derive(serde::Deserialize)]
2#[cfg_attr(
3 not(feature = "wasm"),
4 derive(serde::Serialize, PartialEq, Debug, Default, Clone)
5)]
6pub struct DNode {
7 pub classes: Vec<String>,
8 pub node: String,
9 pub attrs: ftd_rt::Map,
10 pub style: ftd_rt::Map,
11 pub children: Vec<DNode>,
12 pub text: Option<String>,
13 pub null: bool,
14 pub visible: bool,
15 pub events: Vec<ftd_rt::Event>, }
17
18impl DNode {
19 fn attrs_to_html(&self) -> String {
20 self.attrs
21 .iter()
22 .map(|(k, v)| format!("{}={}", *k, quote(v))) .collect::<Vec<String>>()
24 .join(" ")
25 }
26
27 pub fn style_to_html(&self, visible: bool) -> String {
28 let mut styles = self.style.to_owned();
29 if !visible {
30 styles.insert("display".to_string(), "none".to_string());
31 }
32 styles
33 .iter()
34 .map(|(k, v)| format!("{}: {}", *k, ftd_rt::html::escape(v))) .collect::<Vec<String>>()
36 .join("; ")
37 }
38
39 pub fn class_to_html(&self) -> String {
40 self.classes
41 .iter()
42 .map(|k| k.to_string())
43 .collect::<Vec<String>>()
44 .join(" ")
45 }
46
47 pub fn to_html(&self, id: &str) -> String {
48 let style = format!("style=\"{}\"", self.style_to_html(self.visible));
49 let classes = format!("class=\"{}\"", self.class_to_html());
50
51 let attrs = {
52 let mut attr = self.attrs_to_html();
53 let events = ftd_rt::event::group_by_js_event(&self.events);
54 for (name, actions) in events {
55 let event = format!(
56 "window.ftd.handle_event(event, '{}', '{}')",
57 id,
58 actions.replace("\"", """)
59 );
60 attr.push(' ');
61 attr.push_str(&format!("{}={}", name, quote(&event)));
62 }
63 attr
64 };
65
66 if self.node == "img" {
67 return format!("<img {attrs} {style}>", attrs = attrs, style = style);
68 }
69 let body = match self.text.as_ref() {
70 Some(v) => v.to_string(),
71 None => self
72 .children
73 .iter()
74 .map(|v| v.to_html(id))
75 .collect::<Vec<String>>()
76 .join("\n"),
77 };
78
79 format!(
81 "<{node} {attrs} {style} {classes}>{body}</{node}>",
82 node = self.node.as_str(),
83 attrs = attrs,
84 style = style,
85 classes = classes,
86 body = body,
87 )
88 }
89}
90
91fn quote(i: &str) -> String {
92 format!("{:?}", i)
93}