use crate::attributes::Attributes;
use crate::content::HeadContent;
use crate::html_container::HtmlContainer;
use crate::Html;
#[derive(Debug)]
pub struct HtmlPage {
head: Vec<String>,
body: Vec<String>,
}
impl Html for HtmlPage {
fn to_html_string(&self) -> String {
format!(
"<!DOCTYPE html><html><head>{}</head><body>{}</body></html>",
self.head.join(""),
self.body.join("")
)
}
}
impl HtmlContainer for HtmlPage {
#[inline]
fn add_html<H: Html>(&mut self, html: H) {
self.body.push(html.to_html_string());
}
}
impl Default for HtmlPage {
fn default() -> Self {
HtmlPage::new()
}
}
impl HtmlPage {
pub fn new() -> Self {
HtmlPage {
head: Vec::new(),
body: Vec::new(),
}
}
#[inline]
fn add_html_head<H: Html>(&mut self, html: H) {
self.head.push(html.to_html_string());
}
#[inline]
fn with_html_head<H: Html>(mut self, html: H) -> Self {
self.add_html_head(html);
self
}
pub fn add_head_link(&mut self, href: impl ToString, rel: impl ToString) {
self.add_html_head(HeadContent::Link {
href: href.to_string(),
rel: rel.to_string(),
attr: Attributes::default(),
})
}
pub fn with_head_link(self, href: impl ToString, rel: impl ToString) -> Self {
self.with_html_head(HeadContent::Link {
href: href.to_string(),
rel: rel.to_string(),
attr: Attributes::default(),
})
}
pub fn add_head_link_attr<A, S>(&mut self, href: impl ToString, rel: impl ToString, attr: A)
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.add_html_head(HeadContent::Link {
href: href.to_string(),
rel: rel.to_string(),
attr: attr.into(),
})
}
pub fn with_head_link_attr<A, S>(self, href: impl ToString, rel: impl ToString, attr: A) -> Self
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.with_html_head(HeadContent::Link {
href: href.to_string(),
rel: rel.to_string(),
attr: attr.into(),
})
}
pub fn add_meta<A, S>(&mut self, attributes: A)
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.add_html_head(HeadContent::Meta {
attr: attributes.into(),
})
}
pub fn with_meta<A, S>(self, attributes: A) -> Self
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.with_html_head(HeadContent::Meta {
attr: attributes.into(),
})
}
pub fn add_script_link(&mut self, src: impl ToString) {
self.add_html_head(HeadContent::ScriptLink {
src: src.to_string(),
attr: Attributes::default(),
})
}
pub fn with_script_link(self, src: impl ToString) -> Self {
self.with_html_head(HeadContent::ScriptLink {
src: src.to_string(),
attr: Attributes::default(),
})
}
pub fn add_script_link_attr<A, S>(&mut self, src: impl ToString, attributes: A)
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.add_html_head(HeadContent::ScriptLink {
src: src.to_string(),
attr: attributes.into(),
})
}
pub fn with_script_link_attr<A, S>(self, src: impl ToString, attributes: A) -> Self
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.with_html_head(HeadContent::ScriptLink {
src: src.to_string(),
attr: attributes.into(),
})
}
pub fn add_script_literal(&mut self, code: impl ToString) {
self.add_html_head(HeadContent::ScriptLiteral {
code: code.to_string(),
})
}
pub fn with_script_literal(self, code: impl ToString) -> Self {
self.with_html_head(HeadContent::ScriptLiteral {
code: code.to_string(),
})
}
pub fn add_style(&mut self, css: impl ToString) {
self.add_html_head(HeadContent::Style {
css: css.to_string(),
attr: Attributes::default(),
})
}
pub fn with_style(self, css: impl ToString) -> Self {
self.with_html_head(HeadContent::Style {
css: css.to_string(),
attr: Attributes::default(),
})
}
pub fn add_style_attr<A, S>(&mut self, css: impl ToString, attributes: A)
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.add_html_head(HeadContent::Style {
css: css.to_string(),
attr: attributes.into(),
})
}
pub fn with_style_attr<A, S>(self, css: impl ToString, attributes: A) -> Self
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.with_html_head(HeadContent::Style {
css: css.to_string(),
attr: attributes.into(),
})
}
#[inline]
pub fn add_stylesheet(&mut self, source: impl ToString) {
self.add_head_link(source, "stylesheet")
}
#[inline]
pub fn with_stylesheet(self, source: impl ToString) -> Self {
self.with_head_link(source, "stylesheet")
}
pub fn add_title(&mut self, title_text: impl ToString) {
self.add_html_head(HeadContent::Title {
content: title_text.to_string(),
})
}
pub fn with_title(self, title_text: impl ToString) -> Self {
self.with_html_head(HeadContent::Title {
content: title_text.to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default() {
let sut = HtmlPage::default();
let html_string = sut.to_html_string();
assert_eq!(
html_string,
"<!DOCTYPE html><html><head></head><body></body></html>"
)
}
}