1use crate::style::Style;
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum Tag {
10 Html,
11 Head,
12 Meta,
13 Title,
14 Body,
15 Div,
16 Span,
17 Table,
18 Tbody,
19 Tr,
20 Td,
21 Th,
22 P,
23 H1,
24 H2,
25 H3,
26 H4,
27 H5,
28 H6,
29 A,
30 Img,
31 Hr,
32 Br,
33 Pre,
34 Code,
35 Strong,
36 Em,
37 Custom(String),
39}
40
41impl Tag {
42 pub fn as_str(&self) -> &str {
44 match self {
45 Tag::Html => "html",
46 Tag::Head => "head",
47 Tag::Meta => "meta",
48 Tag::Title => "title",
49 Tag::Body => "body",
50 Tag::Div => "div",
51 Tag::Span => "span",
52 Tag::Table => "table",
53 Tag::Tbody => "tbody",
54 Tag::Tr => "tr",
55 Tag::Td => "td",
56 Tag::Th => "th",
57 Tag::P => "p",
58 Tag::H1 => "h1",
59 Tag::H2 => "h2",
60 Tag::H3 => "h3",
61 Tag::H4 => "h4",
62 Tag::H5 => "h5",
63 Tag::H6 => "h6",
64 Tag::A => "a",
65 Tag::Img => "img",
66 Tag::Hr => "hr",
67 Tag::Br => "br",
68 Tag::Pre => "pre",
69 Tag::Code => "code",
70 Tag::Strong => "strong",
71 Tag::Em => "em",
72 Tag::Custom(name) => name.as_str(),
73 }
74 }
75
76 pub fn is_void(&self) -> bool {
78 matches!(self, Tag::Meta | Tag::Img | Tag::Hr | Tag::Br)
79 }
80}
81
82#[derive(Debug, Clone, PartialEq)]
84pub struct Attr {
85 pub name: String,
86 pub value: String,
87}
88
89impl Attr {
90 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
91 Attr {
92 name: name.into(),
93 value: value.into(),
94 }
95 }
96}
97
98#[derive(Debug, Clone, PartialEq)]
100pub struct Element {
101 pub tag: Tag,
102 pub attrs: Vec<Attr>,
103 pub style: Style,
104 pub children: Vec<Node>,
105}
106
107impl Element {
108 pub fn new(tag: Tag) -> Self {
110 Element {
111 tag,
112 attrs: Vec::new(),
113 style: Style::default(),
114 children: Vec::new(),
115 }
116 }
117
118 pub fn attr(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
120 self.attrs.push(Attr::new(name, value));
121 self
122 }
123
124 pub fn style(mut self, style: Style) -> Self {
126 self.style = style;
127 self
128 }
129
130 pub fn child(mut self, child: Node) -> Self {
132 self.children.push(child);
133 self
134 }
135
136 pub fn children(mut self, children: impl IntoIterator<Item = Node>) -> Self {
138 self.children.extend(children);
139 self
140 }
141}
142
143#[derive(Debug, Clone, PartialEq)]
145#[allow(clippy::large_enum_variant)]
146pub enum Node {
147 Element(Element),
149 Text(String),
151 Fragment(Vec<Node>),
153 None,
155}
156
157impl Node {
158 pub fn text(content: impl Into<String>) -> Self {
160 Node::Text(content.into())
161 }
162
163 pub fn element(tag: Tag) -> Element {
165 Element::new(tag)
166 }
167
168 pub fn fragment(nodes: Vec<Node>) -> Self {
170 Node::Fragment(nodes)
171 }
172}