1use std::marker::PhantomData;
2
3#[cfg(feature = "json")]
4pub mod json;
5#[cfg(feature = "parse")]
6pub mod parser;
7#[cfg(feature = "print")]
8pub mod print;
9#[cfg(feature = "render")]
10pub mod render;
11
12pub mod hash;
13
14pub trait StaticTag {
15 fn static_tag() -> &'static str;
16}
17
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct Component<Tag, Attributes, Children> {
20 pub tag: Tag,
21 pub attributes: Attributes,
22 pub children: Children,
23}
24
25impl<T: Default, A: Default, C: Default> Default for Component<T, A, C> {
26 fn default() -> Self {
27 Self {
28 tag: T::default(),
29 attributes: A::default(),
30 children: C::default(),
31 }
32 }
33}
34
35impl<T, A, C> Component<PhantomData<T>, A, C> {
36 #[inline]
37 pub fn new(attributes: A, children: C) -> Self {
38 Self {
39 tag: PhantomData::<T>,
40 attributes,
41 children,
42 }
43 }
44}
45
46#[cfg(any(feature = "parse", feature = "print", feature = "render"))]
48pub(crate) fn is_void_element(tag: &str) -> bool {
49 matches!(
50 tag,
51 "area"
52 | "base"
53 | "br"
54 | "col"
55 | "embed"
56 | "hr"
57 | "img"
58 | "input"
59 | "link"
60 | "meta"
61 | "param"
62 | "source"
63 | "track"
64 | "wbr"
65 )
66}
67
68pub type AttributeMap = hash::Map<String, Option<String>>;
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71#[cfg_attr(feature = "json", derive(serde::Deserialize, serde::Serialize))]
72#[cfg_attr(feature = "json", serde(untagged))]
73pub enum OneOrMany<T> {
74 One(T),
75 Many(Vec<T>),
76}
77
78impl<T> Default for OneOrMany<T> {
79 fn default() -> Self {
80 OneOrMany::Many(Vec::default())
81 }
82}
83
84impl<T> OneOrMany<T> {
85 pub fn iter(&self) -> OneOrManyIter<'_, T> {
86 match self {
87 Self::One(item) => OneOrManyIter::One(std::iter::once(item)),
88 Self::Many(list) => OneOrManyIter::Many(list.iter()),
89 }
90 }
91}
92
93pub enum OneOrManyIter<'a, T> {
94 One(std::iter::Once<&'a T>),
95 Many(std::slice::Iter<'a, T>),
96}
97
98impl<'a, T> Iterator for OneOrManyIter<'a, T> {
99 type Item = &'a T;
100
101 fn next(&mut self) -> Option<Self::Item> {
102 match self {
103 Self::One(inner) => inner.next(),
104 Self::Many(inner) => inner.next(),
105 }
106 }
107}