1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4
5mod http;
7
8mod node;
10
11#[cfg(feature = "pretty")]
13pub mod pretty;
14
15#[cfg(feature = "typed")]
17pub mod typed;
18
19use std::fmt::{self, Display, Formatter};
20
21pub use self::node::*;
22#[cfg(feature = "typed")]
23use self::typed::TypedElement;
24
25#[derive(Debug, Clone, PartialEq, Eq)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum Node {
29 Comment(Comment),
35
36 Doctype(Doctype),
42
43 Fragment(Fragment),
51
52 Element(Element),
60
61 Text(Text),
69
70 UnsafeText(UnsafeText),
77}
78
79impl Node {
80 pub const EMPTY: Self = Self::Fragment(Fragment::EMPTY);
82
83 #[cfg(feature = "typed")]
85 pub fn from_typed<E: TypedElement>(element: E, children: Option<Vec<Self>>) -> Self {
86 element.into_node(children)
87 }
88
89 #[cfg(feature = "pretty")]
91 #[must_use]
92 pub fn pretty(self) -> pretty::Pretty {
93 self.into()
94 }
95
96 #[must_use]
99 pub fn as_children(&self) -> Option<&[Self]> {
100 match self {
101 Self::Fragment(fragment) => Some(&fragment.children),
102 Self::Element(element) => element.children.as_deref(),
103 _ => None,
104 }
105 }
106
107 pub fn children_iter(&self) -> impl Iterator<Item = &Self> {
109 self.as_children().unwrap_or_default().iter()
110 }
111
112 #[must_use]
115 pub fn children(self) -> Option<Vec<Self>> {
116 match self {
117 Self::Fragment(fragment) => Some(fragment.children),
118 Self::Element(element) => element.children,
119 _ => None,
120 }
121 }
122
123 pub fn into_children(self) -> impl Iterator<Item = Self> {
125 self.children().unwrap_or_default().into_iter()
126 }
127
128 #[must_use]
130 pub const fn as_comment(&self) -> Option<&Comment> {
131 if let Self::Comment(comment) = self {
132 Some(comment)
133 } else {
134 None
135 }
136 }
137
138 #[must_use]
140 pub const fn as_doctype(&self) -> Option<&Doctype> {
141 if let Self::Doctype(doctype) = self {
142 Some(doctype)
143 } else {
144 None
145 }
146 }
147
148 #[must_use]
150 pub const fn as_fragment(&self) -> Option<&Fragment> {
151 if let Self::Fragment(fragment) = self {
152 Some(fragment)
153 } else {
154 None
155 }
156 }
157
158 #[must_use]
160 pub const fn as_element(&self) -> Option<&Element> {
161 if let Self::Element(element) = self {
162 Some(element)
163 } else {
164 None
165 }
166 }
167
168 #[must_use]
170 pub const fn as_text(&self) -> Option<&Text> {
171 if let Self::Text(text) = self {
172 Some(text)
173 } else {
174 None
175 }
176 }
177
178 #[must_use]
180 pub const fn as_unsafe_text(&self) -> Option<&UnsafeText> {
181 if let Self::UnsafeText(text) = self {
182 Some(text)
183 } else {
184 None
185 }
186 }
187}
188
189impl Default for Node {
190 fn default() -> Self {
191 Self::EMPTY
192 }
193}
194
195impl Display for Node {
196 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
197 match &self {
198 Self::Comment(comment) => comment.fmt(f),
199 Self::Doctype(doctype) => doctype.fmt(f),
200 Self::Fragment(fragment) => fragment.fmt(f),
201 Self::Element(element) => element.fmt(f),
202 Self::Text(text) => text.fmt(f),
203 Self::UnsafeText(unsafe_text) => unsafe_text.fmt(f),
204 }
205 }
206}
207
208impl<I, N> From<I> for Node
209where
210 I: IntoIterator<Item = N>,
211 N: Into<Self>,
212{
213 fn from(iter: I) -> Self {
214 Self::Fragment(iter.into())
215 }
216}
217
218impl From<Comment> for Node {
219 fn from(comment: Comment) -> Self {
220 Self::Comment(comment)
221 }
222}
223
224impl From<Doctype> for Node {
225 fn from(doctype: Doctype) -> Self {
226 Self::Doctype(doctype)
227 }
228}
229
230impl From<Fragment> for Node {
231 fn from(fragment: Fragment) -> Self {
232 Self::Fragment(fragment)
233 }
234}
235
236impl From<Element> for Node {
237 fn from(element: Element) -> Self {
238 Self::Element(element)
239 }
240}
241
242impl From<Text> for Node {
243 fn from(text: Text) -> Self {
244 Self::Text(text)
245 }
246}
247
248impl From<UnsafeText> for Node {
249 fn from(text: UnsafeText) -> Self {
250 Self::UnsafeText(text)
251 }
252}