typst_batch/html/node.rs
1//! HTML node wrapper.
2
3use super::{HtmlElement, HtmlFrame};
4
5/// An HTML node (element, text, or frame).
6///
7/// Use `kind()` to determine the node type and access its data.
8#[derive(Debug, Clone, Copy)]
9pub struct HtmlNode<'a>(pub(crate) &'a typst_html::HtmlNode);
10
11/// The kind of an HTML node.
12#[derive(Debug, Clone, Copy)]
13pub enum NodeKind<'a> {
14 /// An HTML element with tag, attributes, and children.
15 Element(HtmlElement<'a>),
16 /// Plain text content.
17 Text(&'a str),
18 /// A frame that should be rendered as SVG.
19 Frame(HtmlFrame<'a>),
20 /// An introspection tag (usually ignored during conversion).
21 Tag,
22}
23
24impl<'a> HtmlNode<'a> {
25 /// Get the kind of this node.
26 ///
27 /// # Example
28 ///
29 /// ```ignore
30 /// match node.kind() {
31 /// NodeKind::Element(elem) => {
32 /// println!("Element: {}", elem.tag());
33 /// }
34 /// NodeKind::Text(text) => {
35 /// println!("Text: {}", text);
36 /// }
37 /// NodeKind::Frame(frame) => {
38 /// #[cfg(feature = "svg")]
39 /// let svg = frame.to_svg(&doc);
40 /// }
41 /// NodeKind::Tag => {
42 /// // Introspection tag, usually ignored
43 /// }
44 /// }
45 /// ```
46 #[inline]
47 pub fn kind(&self) -> NodeKind<'a> {
48 match self.0 {
49 typst_html::HtmlNode::Tag(_) => NodeKind::Tag,
50 typst_html::HtmlNode::Text(text, _span) => NodeKind::Text(text.as_str()),
51 typst_html::HtmlNode::Element(elem) => NodeKind::Element(HtmlElement(elem)),
52 typst_html::HtmlNode::Frame(frame) => NodeKind::Frame(HtmlFrame(frame)),
53 }
54 }
55
56 /// Try to get this node as an element.
57 #[inline]
58 pub fn as_element(&self) -> Option<HtmlElement<'a>> {
59 match self.0 {
60 typst_html::HtmlNode::Element(elem) => Some(HtmlElement(elem)),
61 _ => None,
62 }
63 }
64
65 /// Try to get this node as text.
66 #[inline]
67 pub fn as_text(&self) -> Option<&'a str> {
68 match self.0 {
69 typst_html::HtmlNode::Text(text, _) => Some(text.as_str()),
70 _ => None,
71 }
72 }
73
74 /// Try to get this node as a frame.
75 #[inline]
76 pub fn as_frame(&self) -> Option<HtmlFrame<'a>> {
77 match self.0 {
78 typst_html::HtmlNode::Frame(frame) => Some(HtmlFrame(frame)),
79 _ => None,
80 }
81 }
82
83 /// Check if this is an element node.
84 #[inline]
85 pub fn is_element(&self) -> bool {
86 matches!(self.0, typst_html::HtmlNode::Element(_))
87 }
88
89 /// Check if this is a text node.
90 #[inline]
91 pub fn is_text(&self) -> bool {
92 matches!(self.0, typst_html::HtmlNode::Text(_, _))
93 }
94
95 /// Check if this is a frame node.
96 #[inline]
97 pub fn is_frame(&self) -> bool {
98 matches!(self.0, typst_html::HtmlNode::Frame(_))
99 }
100
101 /// Check if this is a tag node (introspection).
102 #[inline]
103 pub fn is_tag(&self) -> bool {
104 matches!(self.0, typst_html::HtmlNode::Tag(_))
105 }
106}