1use crate::{
4 attributes,
5 node::{Comment, Element, ElementType, Node},
6 tag::Tag,
7 text::Text,
8 url::Url,
9};
10use attributes::{Attribute, Value};
11use std::collections::HashMap;
12
13impl<'a> Node<'a> {
14 pub fn comment(text: &str) -> Self {
16 let comment: Comment = text.to_string().into();
17 comment.into()
18 }
19
20 pub fn text(text: &str) -> Self {
22 let text: Text = Text::create(text);
23 text.into()
24 }
25}
26
27impl<'a> Element<'a, ()> {
28 pub fn external_style(url: Url) -> Self {
30 let mut el = Element::<()>::create(Tag::LINK);
31 let url: Value<'a> = url.into();
32 el.set_attribute(Attribute::REL, Value::STYLESHEET);
33 el.set_attribute(Attribute::HREF, url);
34 el
35 }
36}
37
38impl<'a> Element<'a, Vec<Node<'a>>> {
39 pub fn push<N>(&mut self, node: N) -> ()
43 where
44 N: Into<Node<'a>>,
45 {
46 let node = node.into();
47 self.children.push(node);
48 }
49
50 pub fn anchor(url: Value<'a>, label: Text) -> Self {
53 let mut element = Element::<Vec<Node>>::create(Tag::A);
55 element.set_attribute(Attribute::HREF, url);
56 element.push(label);
57 element.into()
58 }
59
60 pub fn body<N>(children: Vec<N>) -> Self
62 where
63 N: Into<Node<'a>>,
64 {
65 let mut el = Element::<Vec<Node>>::create(Tag::BODY);
66 for child in children {
67 el.push(child);
68 }
69 el
70 }
71
72 pub fn html(
76 lang: Value<'a>,
77 header: Element<'a, Vec<Node<'a>>>,
78 body: Element<'a, Vec<Node<'a>>>,
79 ) -> Self {
80 let mut el = Element::<Vec<Node>>::create(Tag::HTML);
81 el.set_attribute(Attribute::LANG, lang);
82 el.push(header);
83 el.push(body);
84 el
85 }
86
87 pub fn title(title: Text) -> Self {
89 let mut el = Element::<Vec<Node>>::create(Tag::TITLE);
90 el.push(title);
91 el
92 }
93
94 pub fn inline_script(text: Text) -> Self {
96 let mut el = Element::<Vec<Node>>::create(Tag::SCRIPT);
97 el.push(text);
98 el
99 }
100
101 pub fn external_script(url: Url) -> Self {
103 let mut el = Element::<Vec<Node>>::create(Tag::SCRIPT);
104 let url: Value<'a> = url.into();
105 el.set_attribute(Attribute::SRC, url);
106 el
107 }
108
109 pub fn inline_style(text: Text) -> Self {
111 let mut el = Element::<Vec<Node>>::create(Tag::STYLE);
112 el.push(text);
113 el
114 }
115
116 pub fn head() -> Self {
118 Element::<Vec<Node>>::create(Tag::HEAD)
119 }
120
121 pub fn main() -> Self {
123 Element::<Vec<Node>>::create(Tag::MAIN)
124 }
125}
126
127impl<'a, T> Element<'a, T>
128where
129 T: ElementType,
130{
131 pub fn create(name: Tag<'a>) -> Self {
134 let attributes = HashMap::default();
135 let children = T::default();
136 let element = Element {
137 name,
138 attributes,
139 children,
140 };
141 element
142 }
143
144 pub fn set_bool_attribute(&mut self, key: Attribute<'a>) {
148 self.attributes.insert(key, None);
149 }
150
151 pub fn has_bool_attribute(&self, key: &Attribute<'a>) -> bool {
154 let attr = self.attributes.get(key);
155 let result = attr.is_some();
156 result
157 }
158
159 pub fn has_attribute(&self, key: &Attribute<'a>) -> bool {
162 let attr = self.attributes.get(key);
163 let result = attr.map(|x| x.is_some()).unwrap_or(false);
164 result
165 }
166
167 pub fn set_attribute(&mut self, key: Attribute<'a>, value: Value<'a>) {
170 self.attributes.insert(key, Some(value));
171 }
172
173 pub fn get_attribute_value(&self, key: &Attribute<'a>) -> &Option<Value<'a>> {
176 match self.attributes.get(key) {
177 None => &None,
178 Some(value) => value,
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186 use crate::attributes::Attribute;
187
188 #[test]
189 fn has_attribute_bool() {
190 let mut el = Element::<()>::create(Tag::BODY);
191 el.attributes.insert(Attribute::ID, None);
192 let result = el.has_bool_attribute(&Attribute::ID);
193 assert!(result);
194 }
195
196 #[test]
197 fn has_attribute() {
198 let value = Value::STYLESHEET;
199 let mut el = Element::<()>::create(Tag::BODY);
200 el.attributes.insert(Attribute::ID, Some(value));
201 let result = el.has_attribute(&Attribute::ID);
202 assert!(result);
203 }
204
205 #[test]
206 fn get_attribute_value() {
207 let value = Value::STYLESHEET;
208 let mut el = Element::<()>::create(Tag::BODY);
209 el.attributes.insert(Attribute::ID, Some(value));
210 let result = el.get_attribute_value(&Attribute::ID);
211 let expected = &Some(Value::STYLESHEET);
212 assert_eq!(result, expected);
213 }
214}