use crate::html::DEFAULT_HTML_OFFSET;
use crate::{HtmlBodyElement, HtmlElement, HtmlHeadElement, ToText, DEFAULT_HTML_DOCTYPE, DEFAULT_HTML_INDENT, DEFAULT_HTML_LANGUAGE, DEFAULT_HTML_NAMESPACE};
use std::fmt::{Display, Write};
use std::{fmt, fs, io};
#[derive(Debug, Clone)]
pub struct HtmlDocument {
doctype: Option<String>,
root: HtmlElement,
}
impl Default for HtmlDocument {
fn default() -> Self {
Self {
doctype: None,
root: HtmlElement::new("html").no_indent(),
}
}
}
impl HtmlDocument {
pub fn new() -> Self {
Self::default()
}
pub fn default_doctype(mut self) -> Self {
self.doctype = DEFAULT_HTML_DOCTYPE.to_string().into();
self
}
pub fn doctype(mut self, doctype: &str) -> Self {
self.doctype = doctype.to_string().into();
self
}
pub fn default_namespace(mut self) -> Self {
self.root.set_attribute("xmlns", DEFAULT_HTML_NAMESPACE);
self
}
pub fn namespace(mut self, namespace: &str) -> Self {
self.root.set_attribute("xmlns", namespace);
self
}
pub fn default_language(mut self) -> Self {
self.root.set_attribute("lang", DEFAULT_HTML_LANGUAGE);
self
}
pub fn language(mut self, language: &str) -> Self {
self.root.set_attribute("lang", language);
self
}
pub fn head(mut self, head: HtmlHeadElement) -> Self {
self.root.add_child(head);
self
}
pub fn body(mut self, body: HtmlBodyElement) -> Self {
self.root.add_child(body);
self
}
pub fn save(&self, file_name: &str, offset: usize, indent: usize) -> io::Result<()> {
fs::write(file_name, self.to_text(offset, indent))
}
}
impl ToText for HtmlDocument {
fn to_text(&self, offset: usize, indent: usize) -> String {
let mut buffer = String::new();
if let Some(doctype) = &self.doctype {
let _ = writeln!(&mut buffer, "{}", doctype);
}
self.root.write(offset, indent, &mut buffer);
let _ = writeln!(&mut buffer);
buffer
}
}
impl Display for HtmlDocument {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_text(DEFAULT_HTML_OFFSET, DEFAULT_HTML_INDENT))
}
}