#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
#[cfg(feature = "yew")]
pub mod yew;
#[cfg(feature = "yew")]
use ::yew::{html, Html};
use std::{borrow::Cow, fmt::Display};
pub trait Htmlify
{
fn tag(&self) -> Cow<'static, str> { Cow::Borrowed("") }
fn attributes(&self) -> Vec<Attribute> { vec!() }
fn inner_html(&self) -> Vec<Box<dyn Htmlify>> { vec!() }
fn inner_html_as_string(&self) -> String
{
self.inner_html().iter().map(|e| e.as_raw_html()).collect::<Vec<String>>().join("")
}
fn as_raw_html(&self) -> String
{
format!
(
"<{0} {2}> {1} </{0}>",
self.tag(),
self.inner_html_as_string(),
self.attributes()
.iter()
.map(Attribute::to_string)
.collect::<Vec<String>>()
.join(" ")
)
}
#[cfg(feature = "web-sys")]
fn as_element(&self) -> Option<web_sys::Element>
{
use std::borrow::Borrow;
let document = web_sys::window().and_then(|win| win.document())?;
let element = document.create_element(self.tag().borrow()).ok()?;
for attribute in self.attributes()
{
element.set_attribute(attribute.name.borrow(), attribute.value.borrow()).ok()?;
}
for inner in self.inner_html()
{
if let "__STRING_MARKER" = inner.tag().borrow()
{
element.append_with_str_1(&inner.as_raw_html()).ok()?;
}
else
{
element.append_with_node_1(inner.as_element()?.as_ref()).ok()?;
}
}
Some(element)
}
#[cfg(feature = "yew")]
fn as_yew_node(&self) -> Html
{
html!
{
<crate::yew::RawHtml
tag={self.tag().to_string() }
attributes={self.attributes()}
html={Cow::from(self.inner_html_as_string())}
/>
}
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Attribute
{
pub name: Cow<'static, str>,
pub value: Cow<'static, str>
}
impl Attribute
{
pub fn new(name: impl Into<Cow<'static, str>>, value: impl Into<Cow<'static, str>>) -> Self
{
Attribute { name: name.into(), value: value.into() }
}
}
impl Display for Attribute
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
{
let value = self.value.to_string();
if value.is_empty()
{
write!(f, "{}", self.name)
}
else
{
write!(f, "{}=\"{}\"", self.name, self.value)
}
}
}
impl Htmlify for &str
{
fn tag(&self) -> Cow<'static, str> { Cow::Borrowed("__STRING_MARKER") }
fn as_raw_html(&self) -> String { self.to_string() }
#[cfg(feature = "web-sys")]
fn as_element(&self) -> Option<web_sys::Element> { None }
}
#[cfg(feature = "web-sys")]
pub fn append_to_document_body(htmlifiable: impl Htmlify) -> Result<(), impl std::fmt::Debug>
{
web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| doc.body())
.and_then(|body| htmlifiable.as_element().map(|e| body.append_with_node_1(e.as_ref())))
.transpose()
.map(|_|())
}