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