html_node_core/node/
element.rs

1use std::fmt::{self, Display, Formatter};
2
3use super::write_children;
4use crate::Node;
5
6/// An element.
7///
8/// ```html
9/// <div class="container">
10///     I'm in an element!
11/// </div>
12/// ```
13#[derive(Debug, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Element {
16    /// The name of the element.
17    ///
18    /// ```html
19    /// <name>
20    /// ```
21    pub name: String,
22
23    /// The attributes of the element.
24    ///
25    /// ```html
26    /// <div attribute="value">
27    /// ```
28    pub attributes: Vec<(String, Option<String>)>,
29
30    /// The children of the element.
31    ///
32    /// ```html
33    /// <div>
34    ///     <!-- I'm a child! -->
35    ///     <child>I'm another child!</child>
36    /// </div>
37    /// ```
38    pub children: Option<Vec<Node>>,
39}
40
41impl Display for Element {
42    /// Format as an HTML element.
43    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
44        write!(f, "<{}", self.name)?;
45
46        for (key, value) in &self.attributes {
47            write!(f, " {key}")?;
48
49            if let Some(value) = value {
50                let encoded_value = html_escape::encode_double_quoted_attribute(value);
51                write!(f, r#"="{encoded_value}""#)?;
52            }
53        }
54        write!(f, ">")?;
55
56        if let Some(children) = &self.children {
57            write_children(f, children, false)?;
58
59            write!(f, "</{}>", self.name)?;
60        };
61
62        Ok(())
63    }
64}
65
66impl<N> From<N> for Element
67where
68    N: Into<String>,
69{
70    /// Create an HTML element directly from a string.
71    ///
72    /// This [`Element`] has no attributes and no children.
73    fn from(name: N) -> Self {
74        Self {
75            name: name.into(),
76            attributes: Vec::new(),
77            children: None,
78        }
79    }
80}