Skip to main content

muffy_document/html/
document.rs

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