html_tag/
lib.rs

1//! # HTMLTag
2//! The enigmatic way to use HTML in Rust.
3//!
4//! HTMLTag is a crate that allows you to create HTML tags in a simple and
5//! intuitive way.
6//! It aims to replace the need for using HTML in the form of strings or the heavy use of
7//! macros in your code to make it more readable and maintainable.
8//!
9//! ## Idea
10//!
11//! Strings are not always the best way to represent HTML in your code.
12//! You could probably use macros to make it more readable, but that is not always the best
13//! solution.
14//!
15//! Moreover, you could probably use a templating engine or a library like `html_builder` to
16//! generate large HTML documents, however, we are talking niche use cases here.
17//!
18//! The idea is to make it easy to create HTML tags in as simple and as "Rusty" way as possible.
19//!
20//! ## Usage
21//!
22//! ```rust
23//! use html_tag::HtmlTag;
24//!
25//! let mut a = HtmlTag::new("a");
26//! a.set_body("Hello World");
27//! a.add_class("test");
28//! a.set_href("https://example.com");
29//!
30//! assert_eq!(a.to_html(), "<a class=\"test\" href=\"https://example.com\">Hello World</a>");
31//! ```
32//!
33//! As apparent from the example above, you can essentially let HtmlTag act as a builder or
34//! rather a wrapper around the abstract concept of a HTML tag.
35//!
36//! You can also nest tags, like so:
37//!
38//! ```rust
39//! use html_tag::HtmlTag;
40//!
41//! let mut div = HtmlTag::new("div");
42//! div.add_class("test");
43//! let mut p = HtmlTag::new("p");
44//! p.set_body("Hello World");
45//! div.add_child(p);
46//!
47//! assert_eq!(div.to_html(), "<div class=\"test\"><p>Hello World</p></div>");
48//! ```
49//!
50//! ## Main Features
51//!
52//! - Create HTML tags in a simple and intuitive way.
53//! - Chain methods to make it more readable.
54//! - Nest tags inside each other.
55//! - Use custom tags.
56//! - Use custom attributes.
57//! - Use `Display` trait to print the HTML tag.
58//! - No dependencies.
59//!
60//! ## Contributing
61//!
62//! Contributions are welcome. Please open an issue or a PR if you find any bugs or have any
63//! suggestions.
64//!
65//! ## License
66//!
67//! This project is licensed under the MIT License.
68
69/// HTMLTag Related Stuff
70pub mod html;
71/// TagType Related Stuff
72pub mod tags;
73
74/// StyleSheet Related Stuff
75pub mod styles;
76
77pub use crate::html::HtmlTag;
78pub use crate::styles::{Class, Style, StyleSheet};
79pub use crate::tags::TagType;
80
81// Tests cause they are important
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn empty_tag() {
88        let actual_html = "<p></p>";
89        let p = html::HtmlTag::new("p");
90        assert_eq!(p.to_html(), actual_html);
91    }
92
93    #[test]
94    fn single_tag_match() {
95        let actual_html = "<p class=\"test\">Hello World</p>";
96        let mut p = html::HtmlTag::new("p");
97        p.add_class("test");
98        p.set_body("Hello World");
99        assert_eq!(p.to_html(), actual_html);
100    }
101
102    #[test]
103    fn children_tag_match() {
104        let actual_html = "<div class=\"test\"><p>Hello World</p></div>";
105        let mut div = html::HtmlTag::new("div");
106        div.add_class("test");
107        let mut p = html::HtmlTag::new("p");
108        p.set_body("Hello World");
109        div.add_child(p);
110        assert_eq!(div.to_html(), actual_html);
111    }
112
113    #[test]
114    fn test_styles_id_classes() {
115        let actual_html =
116            "<div id=\"test\" class=\"test\" style=\"color: red;\"><p>Hello World</p></div>";
117        let mut div = html::HtmlTag::new("div");
118        div.add_class("test");
119        div.set_id("test");
120        div.set_style("color", "red");
121        let mut p = html::HtmlTag::new("p");
122        p.set_body("Hello World");
123        div.add_child(p);
124        assert_eq!(div.to_html(), actual_html);
125    }
126
127    #[test]
128    fn test_with_add_styles() {
129        let actual_html =
130            "<div id=\"test\" class=\"test\" style=\"color: red;\"><p>Hello World</p></div>";
131        let mut div = html::HtmlTag::new("div")
132            .with_id("test")
133            .with_class("test")
134            .with_style("color", "red");
135        let mut p = html::HtmlTag::new("p");
136        p.set_body("Hello World");
137        div.add_child(p);
138        assert_eq!(div.to_html(), actual_html);
139    }
140
141    #[test]
142    fn test_styles_embed() {
143        let actual_html = "<style>.wow{color:red;font-family:sans-serif;font-size:20px;}h1{color:blue;font-size:30px;}</style><div id=\"wow\"><h1 class=\"wow\">Hello World</h1></div>";
144        let mut style = styles::StyleSheet::new();
145        style.add_style(".wow", "color", "red");
146        style.add_style(".wow", "font-size", "20px");
147        style.add_style(".wow", "font-family", "sans-serif");
148
149        style.add_style("h1", "color", "blue");
150        style.add_style("h1", "font-size", "30px");
151
152        let div = html::HtmlTag::new("div")
153            .with_id("wow")
154            .embed_style_sheet(&style)
155            .with_child(
156                html::HtmlTag::new("h1")
157                    .with_class("wow")
158                    .with_body("Hello World"),
159            );
160
161        assert_eq!(div.to_html(), actual_html);
162    }
163
164    #[test]
165    fn test_href() {
166        let actual_html = "<a href=\"https://www.google.com\">Hello World</a>";
167        let mut a = html::HtmlTag::new("a");
168        a.set_href("https://www.google.com");
169        a.set_body("Hello World");
170        assert_eq!(a.construct(), actual_html);
171    }
172
173    #[test]
174    fn test_custom_tag() {
175        let actual_html = "<custom>Hello World</custom>";
176        let mut custom = html::HtmlTag::new("custom");
177        custom.set_body("Hello World");
178        assert_eq!(custom.to_html(), actual_html);
179    }
180
181    #[test]
182    fn test_chaining() {
183        let actual_html =
184            "<div id=\"test\" class=\"test\" style=\"color: red;\"><p>Hello World</p></div>";
185        let mut div = html::HtmlTag::new("div")
186            .with_id("test")
187            .with_class("test")
188            .with_style("color", "red");
189        let mut p = html::HtmlTag::new("p");
190        p.set_body("Hello World");
191        div.add_child(p);
192        assert_eq!(div.to_html(), actual_html);
193    }
194
195    #[test]
196    fn test_custom_attributes() {
197        let actual_html = "<div id=\"test\" class=\"test\" style=\"color: red;\" data-test=\"test\"><p>Hello World</p></div>";
198        let mut div = html::HtmlTag::new("div");
199        div.add_class("test");
200        div.set_id("test");
201        div.set_style("color", "red");
202        div.add_attribute("data-test", "test");
203        let mut p = html::HtmlTag::new("p");
204        p.set_body("Hello World");
205        div.add_child(p);
206        assert_eq!(div.to_html(), actual_html);
207    }
208
209    #[test]
210    fn print_test() {
211        let actual_html = "<p class=\"test\">Hello World</p>";
212        let mut p = html::HtmlTag::new("p");
213        p.add_class("test");
214        p.set_body("Hello World");
215        assert_eq!(format!("{}", p), actual_html);
216    }
217
218    #[test]
219    fn ordering_test() {
220        let mut tags = vec![
221            tags::TagType::P,
222            tags::TagType::Div,
223            tags::TagType::Span,
224            tags::TagType::A,
225            tags::TagType::H1,
226            tags::TagType::H2,
227            tags::TagType::H3,
228            tags::TagType::H4,
229            tags::TagType::H5,
230            tags::TagType::H6,
231            tags::TagType::Img,
232            tags::TagType::Custom("custom".to_string()),
233        ];
234        tags.sort();
235        tags.reverse();
236        assert_eq!(
237            tags,
238            vec![
239                tags::TagType::Div,
240                tags::TagType::H1,
241                tags::TagType::H2,
242                tags::TagType::H3,
243                tags::TagType::H4,
244                tags::TagType::H5,
245                tags::TagType::H6,
246                tags::TagType::Img,
247                tags::TagType::Custom("custom".to_string()),
248                tags::TagType::A,
249                tags::TagType::Span,
250                tags::TagType::P,
251            ]
252        );
253    }
254}