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    errors: Vec<String>,
16}
17
18impl Document {
19    /// Creates a document.
20    pub const fn new(children: Vec<Arc<Node>>) -> Self {
21        Self {
22            children,
23            errors: vec![],
24        }
25    }
26
27    /// Returns children.
28    pub fn children(&self) -> impl Iterator<Item = &Node> {
29        self.children.iter().map(Deref::deref)
30    }
31
32    /// Returns parse errors.
33    pub fn errors(&self) -> impl Iterator<Item = &str> {
34        self.errors.iter().map(String::as_str)
35    }
36
37    /// Sets parse errors.
38    pub fn set_errors(mut self, errors: Vec<String>) -> Self {
39        self.errors = errors;
40        self
41    }
42
43    /// Returns a base element.
44    pub fn base(&self) -> Option<&str> {
45        self.children()
46            .find_map(|node| Self::find_base(node))
47            .and_then(|element| {
48                element
49                    .attributes()
50                    .find(|(key, _)| *key == "href")
51                    .map(|(_, value)| value)
52            })
53    }
54
55    fn find_base(node: &Node) -> Option<&Element> {
56        match node {
57            Node::Element(element) if element.name() == "base" => Some(element),
58            Node::Element(element) => element.children().find_map(|node| Self::find_base(node)),
59            _ => None,
60        }
61    }
62
63    pub(crate) fn from_markup5ever(node: &markup5ever_rcdom::Node) -> Self {
64        debug_assert!(matches!(node.data, NodeData::Document));
65
66        Self::new(
67            node.children
68                .borrow()
69                .iter()
70                .flat_map(|node| Node::from_markup5ever(node))
71                .map(Arc::new)
72                .collect(),
73        )
74    }
75}