hatmel 0.2.0

HTML model and parser (html5ever)
Documentation
/// The HTML namespace (xhtml)
pub const NS_HTML: &str = "http://www.w3.org/1999/xhtml";
/// Empty (default) namespace
pub const NS_DEFAULT: &str = "";

/// Shortcut for string caching of local names
pub type LocalName = string_cache::Atom<super::LocalNameStaticSet>;
/// Shortcut for string caching of ns prefixes
pub type Prefix = string_cache::Atom<super::PrefixStaticSet>;
/// Shortcut for string caching of namespaces
pub type Namespace = string_cache::Atom<super::NamespaceStaticSet>;
/// The node handle in the tree you can use to query the doc
pub type Handle = usize;

/// Compare two namespaces for equality or equivalence in case of
/// empty (default) namespace and html namespace which is the default
pub fn namespace_equals_or_html(ns1: &str, ns2: &str) -> bool {
    match (ns1, ns2) {
        (NS_DEFAULT, NS_HTML) | (NS_HTML, NS_DEFAULT) => true,
        (want, have) => want == have,
    }
}

/// A document's quirks mode, for compatibility with old browsers. See [quirks mode on wikipedia]
/// for more information.
///
/// [quirks mode on wikipedia]: https://en.wikipedia.org/wiki/Quirks_mode
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum QuirksMode {
    /// Full quirks mode
    Quirks,
    /// Almost standards mode
    LimitedQuirks,
    /// Standards mode
    NoQuirks,
}

/// Represents an HTML element in the DOM tree
#[derive(Default, Debug, Clone)]
pub struct Element {
    pub name: LocalName,
    pub namespace: Namespace,
    pub prefix: Option<Prefix>,
    pub attrs: Vec<Attribute>,
    pub kind: ElementKind,
}
/// Represents an HTML attribute in the DOM tree
#[derive(Default, Debug, Clone)]
pub struct Attribute {
    pub name: LocalName,
    pub namespace: Namespace,
    pub prefix: Option<Prefix>,
    pub value: super::StrTendril,
}

/// Most elements are equal, except...
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ElementKind {
    /// The usual element
    #[default]
    Regular,
    /// Template element is not part of the document per se
    Template,
    /// a.k.a. mathml_annotation_xml_integration_point?
    MathmlPoint,
}

/// Represents the node content in the DOM tree
#[derive(Debug, Clone)]
pub enum Content {
    Document,
    Element(Element),
    Comment {
        text: String,
    },
    ProcessingInstruction {
        target: String,
        data: String,
    },
    Text {
        text: String,
    },
    DocType {
        name: String,
        public_id: String,
        system_id: String,
    },
}
impl Content {
    /// Get the element name (if the node is an element) and return the local name and the namespace
    pub fn element_name(&self) -> Option<(&str, &str)> {
        match self {
            // these nodes are not elements
            Content::Document
            | Content::Element(Element {
                kind: ElementKind::Template,
                ..
            })
            | Content::Comment { .. }
            | Content::ProcessingInstruction { .. }
            | Content::Text { .. }
            | Content::DocType { .. } => None,
            // hey! it's a regular element!
            Content::Element(Element {
                name, namespace, ..
            }) => Some((name, namespace)),
        }
    }
    /// Get attributes if the node is an element
    pub(crate) fn attributes(&self) -> impl DoubleEndedIterator<Item = &Attribute> {
        match self {
            // these nodes are not elements
            Content::Document
            | Content::Element(Element {
                kind: ElementKind::Template,
                ..
            })
            | Content::Comment { .. }
            | Content::ProcessingInstruction { .. }
            | Content::Text { .. }
            | Content::DocType { .. } => [].iter(),
            // hey! it's a regular element!
            Content::Element(Element { attrs, .. }) => attrs.iter(),
        }
    }
    /// Check if the node is a template element
    pub fn is_template(&self) -> bool {
        matches!(
            self,
            Content::Element(Element {
                kind: ElementKind::Template,
                ..
            })
        )
    }
}
impl Default for Content {
    fn default() -> Self {
        Self::Document
    }
}
impl std::fmt::Display for Content {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Content::Document => f.write_str("document"),
            Content::Element(Element { name, attrs, .. }) => {
                f.write_fmt(format_args!("{}", name))?;
                for attr in attrs {
                    f.write_fmt(format_args!(" {}={:?}", attr.name, attr.value.to_string()))?;
                }
                Ok(())
            }
            Content::Comment { text } => f.write_fmt(format_args!("<!-- {text:?} -->")),
            Content::ProcessingInstruction { target, data } => {
                f.write_fmt(format_args!("<?{target} {data} ?>"))
            }
            Content::Text { text } => f.write_fmt(format_args!("{text:?}")),
            Content::DocType {
                name,
                public_id,
                system_id,
            } => f.write_fmt(format_args!("<!DOCTYPE {name} {public_id} {system_id}>")),
        }
    }
}