Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
item.rs 4.66 KiB
Newer Older
peterrabbit's avatar
peterrabbit committed
use super::css::StyleSheet;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
peterrabbit's avatar
peterrabbit committed

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Item {
    pub contents: Vec<HtmlElement>,
    pub layout: StyleSheet,
peterrabbit's avatar
peterrabbit committed
}

impl std::fmt::Display for Item {
peterrabbit's avatar
peterrabbit committed
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}",
            self.contents
                .iter()
                .map(|item_content| item_content.to_string())
peterrabbit's avatar
peterrabbit committed
                .collect::<Vec<String>>()
                .join("")
        )
peterrabbit's avatar
peterrabbit committed
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct HtmlAttributes(pub HashMap<String, String>);

impl HtmlAttributes {
    pub fn new() -> Self {
        HtmlAttributes(HashMap::new())
    }

    pub fn get<S: Into<String>>(&self, key: S) -> Option<&String> {
        self.0.get(&key.into())
    }
impl std::fmt::Display for HtmlAttributes {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}",
            self.0
                .iter()
                .map(|(key, value)| format!(" {}=\"{}\"", key, value))
                .collect::<Vec<String>>()
                .join("")
        )
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct HtmlElement {
    pub tag: String,
    pub text: Option<String>,
    pub contents: Option<Vec<HtmlElement>>,
    #[serde(default = "HtmlAttributes::new")]
    pub attrs: HtmlAttributes,
}

impl std::fmt::Display for HtmlElement {
peterrabbit's avatar
peterrabbit committed
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let body = match &self.contents {
            Some(contents) => contents
                .iter()
                .map(|item| item.to_string())
                .collect::<Vec<String>>()
                .join(""),
            None => match &self.text {
                Some(text) => text.to_owned(),
                None => String::new(),
            },
        write!(f, "<{}{}>{}</{}>", self.tag, self.attrs, body, self.tag)
peterrabbit's avatar
peterrabbit committed
    }
}

#[cfg(test)]
mod test_items {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn text_item_content_to_string() {
        let item_content = HtmlElement {
peterrabbit's avatar
peterrabbit committed
            tag: String::from("p"),
            text: Some(String::from("Hello")),
            contents: None,
            attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
        };

        assert_eq!(item_content.to_string(), "<p>Hello</p>")
    }

    #[test]
    fn item_content_with_attrs_to_string() {
        let mut attrs = HtmlAttributes::new();
        attrs.0.insert(String::from("id"), String::from("some-id"));

        let mut item_content = HtmlElement {
            tag: String::from("p"),
            text: Some(String::from("Hello")),
            contents: None,
            attrs: attrs.clone(),
        };

        assert_eq!(item_content.to_string(), "<p id=\"some-id\">Hello</p>");

        item_content
            .attrs
            .0
            .insert(String::from("class"), String::from("some-class"));

        assert_eq!(
            item_content.to_string(),
            "<p id=\"some-id\" class=\"some-class\">Hello</p>"
        );
    }

peterrabbit's avatar
peterrabbit committed
    #[test]
    fn complex_item_content_to_string() {
        let item_content = HtmlElement {
peterrabbit's avatar
peterrabbit committed
            tag: String::from("p"),
            text: None,
            attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
            contents: Some(vec![
                HtmlElement {
peterrabbit's avatar
peterrabbit committed
                    tag: String::from("span"),
                    text: Some(String::from("Hello ")),
                    contents: None,
                    attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
                },
                HtmlElement {
peterrabbit's avatar
peterrabbit committed
                    tag: String::from("b"),
                    text: Some(String::from("World")),
                    contents: None,
                    attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
                },
            ]),
        };

        assert_eq!(
            item_content.to_string(),
            "<p><span>Hello </span><b>World</b></p>"
        )
    }

    #[test]
    fn item_to_string() {
        let item = Item {
            layout: StyleSheet(HashMap::new()),
            contents: vec![
                HtmlElement {
peterrabbit's avatar
peterrabbit committed
                    tag: String::from("span"),
                    text: Some(String::from("Hello ")),
                    contents: None,
                    attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
                },
                HtmlElement {
peterrabbit's avatar
peterrabbit committed
                    tag: String::from("b"),
                    text: Some(String::from("World")),
                    contents: None,
                    attrs: HtmlAttributes::new(),
peterrabbit's avatar
peterrabbit committed
                },
            ],
        };

        assert_eq!(item.to_string(), "<span>Hello </span><b>World</b>")
    }
}