Skip to main content

muffy_document/
document.rs

1//! Documents.
2
3mod element;
4mod node;
5
6pub use self::{element::*, node::*};
7use alloc::sync::Arc;
8use core::ops::Deref;
9use markup5ever_rcdom::NodeData;
10
11/// A document.
12#[derive(Debug, Eq, PartialEq)]
13pub struct Document {
14    children: Vec<Arc<Node>>,
15}
16
17impl Document {
18    /// Creates a document.
19    pub const fn new(children: Vec<Arc<Node>>) -> Self {
20        Self { children }
21    }
22
23    /// Returns children.
24    pub fn children(&self) -> impl Iterator<Item = &Node> {
25        self.children.iter().map(Deref::deref)
26    }
27
28    /// Returns a base element.
29    pub fn base(&self) -> Option<&str> {
30        self.children()
31            .find_map(|node| Self::find_base(node))
32            .and_then(|element| {
33                element
34                    .attributes()
35                    .find(|(key, _)| *key == "href")
36                    .map(|(_, value)| value)
37            })
38    }
39
40    fn find_base(node: &Node) -> Option<&Element> {
41        match node {
42            Node::Element(element) if element.name() == "base" => Some(element),
43            Node::Element(element) => element.children().find_map(|node| Self::find_base(node)),
44            _ => None,
45        }
46    }
47
48    pub(crate) fn from_markup5ever(node: &markup5ever_rcdom::Node) -> Self {
49        if matches!(node.data, NodeData::Document) {
50            Self::new(
51                node.children
52                    .borrow()
53                    .iter()
54                    .flat_map(|node| Node::from_markup5ever(node))
55                    .map(Arc::new)
56                    .collect(),
57            )
58        } else {
59            unreachable!()
60        }
61    }
62}