zen_rs/layouts/
html.rs

1//! This module defines the `HtmlBuilder` structure and related functions
2//! for generating HTML components with embedded CSS styles.
3//!
4//! The `HtmlBuilder` allows users to build a webpage by specifying various
5//! components such as containers, text, and icons, and applying custom CSS
6//! styles. It provides methods for importing fonts, disabling default browser
7//! CSS, and rendering the components into HTML strings.
8//!
9//! The components are modular, and the builder pattern is used to allow for
10//! easy chaining of method calls to configure and generate the final output.
11
12use crate::components::Components;
13
14mod container;
15mod icon;
16mod text;
17
18pub use container::*;
19pub use icon::*;
20pub use text::*;
21
22/// Creates a new `HtmlBuilder` with default values.
23pub fn html_builder() -> HtmlBuilder {
24    HtmlBuilder::default()
25}
26
27/// A builder for generating HTML with embedded CSS.
28///
29/// This structure allows users to add components (like containers, text, icons)
30/// and configure CSS properties such as font imports and default styling.
31#[derive(Debug, Default, Clone, PartialEq)]
32pub struct HtmlBuilder {
33    /// Array of font URL imports for the page's CSS.
34    ///
35    /// Example:
36    /// - @import url('<https://fonts.googleapis.com/css2?family=Doto:wght@100..900&display=swap>');
37    css_font_import_urls: String,
38    /// The main component to be rendered.
39    component: Components,
40}
41
42// CSS-related methods
43impl HtmlBuilder {
44    /// Gets the font import URLs for the CSS.
45    pub fn get_css_font_import_urls(&self) -> &str {
46        &self.css_font_import_urls
47    }
48
49    /// Sets the font import URLs for the CSS.
50    pub fn css_font_import_urls(mut self, css_font_import_urls: String) -> Self {
51        self.css_font_import_urls = css_font_import_urls;
52        self
53    }
54
55    /// Returns a default CSS reset to disable browser default styling.
56    pub fn css_disable_default_browser_css(&self) -> &str {
57        "* { margin: 0; padding: 0; box-sizing: border-box; overflow: clip; } html, body { height: 100%; line-height: 1.5; } body { background: none; color: inherit; text-align: inherit; } h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; margin: 0; } p { margin: 0; } ul, ol { list-style: none; } a { text-decoration: none; color: inherit; } "
58    }
59
60    /// Builds the full CSS style, including any custom font imports.
61    pub fn build_style(&self) -> String {
62        let css_font_import_urls = self.get_css_font_import_urls();
63        let disable_default = self.css_disable_default_browser_css();
64        format!(r#"<style>{disable_default}{css_font_import_urls}</style>"#)
65    }
66}
67
68// Component-related methods
69impl HtmlBuilder {
70    /// Sets the component to be rendered.
71    pub fn component(mut self, component: impl Into<Components>) -> Self {
72        self.component = component.into();
73        self
74    }
75
76    /// Gets the current component to be rendered.
77    pub fn get_component(&self) -> &Components {
78        &self.component
79    }
80}
81
82// Methods for building HTML output
83impl HtmlBuilder {
84    /// Converts a given component to HTML.
85    ///
86    /// This function matches the component type and calls the respective
87    /// rendering function for `Container`, `Text`, or `Icon` components.
88    pub fn render_component(component: &Components) -> String {
89        match component {
90            Components::Container(component) => container_html(component),
91            Components::Text(component) => text_html(component),
92            Components::Icon(component) => icon_html(component),
93        }
94    }
95
96    /// Renders the current component to HTML.
97    pub fn render(&self) -> String {
98        let component = self.get_component();
99        Self::render_component(component)
100    }
101
102    /// Renders the current component along with the CSS styles as a complete HTML.
103    pub fn build(&self) -> String {
104        let render = self.render();
105        let style = self.build_style();
106        format!(
107            r#"{render}
108            {style}"#
109        )
110    }
111
112    /// Generates a complete HTML document, including the head and body sections.
113    pub fn build_as_html(&self) -> String {
114        let render = self.render();
115        let style = self.build_style();
116        format!(r#"<html><head>{style}</head><body>{render}</body></html>"#)
117    }
118}