Skip to main content

rbatis_codegen/codegen/
loader_html.rs

1use crate::error::Error;
2use scraper::{Html, Node};
3use std::collections::HashMap;
4use std::fmt::{Display, Formatter};
5
6#[derive(Clone, Eq, PartialEq, Debug)]
7pub struct Element {
8    pub tag: String,
9    pub data: String,
10    pub attrs: HashMap<String, String>,
11    pub childs: Vec<Element>,
12}
13
14impl Display for Element {
15    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
16        match self.tag.as_str() {
17            "" => {
18                f.write_str(&self.data)?;
19            }
20            _ => {
21                f.write_str("<")?;
22                f.write_str(&self.tag)?;
23                for (k, v) in &self.attrs {
24                    f.write_str(" ")?;
25                    f.write_str(k)?;
26                    f.write_str("=\"")?;
27                    f.write_str(v)?;
28                    f.write_str("\"")?;
29                }
30                f.write_str(">")?;
31                for x in &self.childs {
32                    std::fmt::Display::fmt(x, f)?;
33                }
34                //</if>
35                f.write_str("</")?;
36                f.write_str(&self.tag)?;
37                f.write_str(">")?;
38            }
39        }
40        return Ok(());
41    }
42}
43
44fn collect_elements(el: scraper::ElementRef<'_>) -> Vec<Element> {
45    let mut els = vec![];
46    for node in el.children() {
47        match node.value() {
48            Node::Text(text) => {
49                let txt = text.to_string();
50                if txt.trim().is_empty() {
51                    continue;
52                }
53                els.push(Element {
54                    tag: String::new(),
55                    data: txt,
56                    attrs: HashMap::new(),
57                    childs: vec![],
58                });
59            }
60            Node::Element(elem) => {
61                if let Some(child_ref) = scraper::ElementRef::wrap(node) {
62                    let mut attrs = HashMap::new();
63                    for (k, v) in elem.attrs() {
64                        attrs.insert(k.to_string(), v.to_string());
65                    }
66                    els.push(Element {
67                        tag: elem.name().to_string(),
68                        data: String::new(),
69                        attrs,
70                        childs: collect_elements(child_ref),
71                    });
72                }
73            }
74            Node::Comment(_) => {}
75            _ => {}
76        }
77    }
78    els
79}
80
81pub fn load_html(html: &str) -> std::result::Result<Vec<Element>, String> {
82    let document = Html::parse_fragment(html);
83    Ok(collect_elements(document.root_element()))
84}
85
86impl Element {
87    /// get all strings
88    pub fn child_strings(&self) -> Vec<&str> {
89        let mut elements = vec![];
90        for x in &self.childs {
91            if x.tag.eq("") {
92                elements.push(x.data.as_str());
93            }
94            let v = x.child_strings();
95            for x in v {
96                elements.push(x);
97            }
98        }
99        elements
100    }
101    /// get all strings
102    pub fn child_string_cup(&self) -> usize {
103        let mut u = 0;
104        for x in self.child_strings() {
105            u += x.len();
106        }
107        u
108    }
109}
110
111/// Loads HTML content into a vector of elements
112pub fn load_mapper_vec(html: &str) -> std::result::Result<Vec<Element>, Error> {
113    let elements = load_html(html).map_err(|e| Error::from(e))?;
114
115    let mut mappers = Vec::new();
116    for element in elements {
117        if element.tag == "mapper" {
118            mappers.extend(element.childs);
119        } else {
120            mappers.push(element);
121        }
122    }
123
124    Ok(mappers)
125}