use self::attribute::Attribute;
use crate::{
hydration::Cursor,
no_attrs,
prelude::{AddAnyAttr, Mountable},
renderer::{
dom::{Element, Node},
CastFrom, Rndr,
},
view::{Position, PositionState, Render, RenderHtml},
};
use std::borrow::Cow;
pub mod attribute;
pub mod class;
pub mod directive;
pub mod element;
pub mod event;
pub mod islands;
pub mod node_ref;
pub mod property;
pub mod style;
pub struct Doctype {
value: &'static str,
}
pub fn doctype(value: &'static str) -> Doctype {
Doctype { value }
}
impl Render for Doctype {
type State = ();
fn build(self) -> Self::State {}
fn rebuild(self, _state: &mut Self::State) {}
}
no_attrs!(Doctype);
impl RenderHtml for Doctype {
type AsyncOutput = Self;
const MIN_LENGTH: usize = "<!DOCTYPE html>".len();
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
fn to_html_with_buf(
self,
buf: &mut String,
_position: &mut Position,
_escape: bool,
_mark_branches: bool,
) {
buf.push_str("<!DOCTYPE ");
buf.push_str(self.value);
buf.push('>');
}
fn hydrate<const FROM_SERVER: bool>(
self,
_cursor: &Cursor,
_position: &PositionState,
) -> Self::State {
}
}
pub struct InertElement {
html: Cow<'static, str>,
}
impl InertElement {
pub fn new(html: impl Into<Cow<'static, str>>) -> Self {
Self { html: html.into() }
}
}
pub struct InertElementState(Cow<'static, str>, Element);
impl Mountable for InertElementState {
fn unmount(&mut self) {
self.1.unmount();
}
fn mount(&mut self, parent: &Element, marker: Option<&Node>) {
self.1.mount(parent, marker)
}
fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
self.1.insert_before_this(child)
}
}
impl Render for InertElement {
type State = InertElementState;
fn build(self) -> Self::State {
let el = Rndr::create_element_from_html(&self.html);
InertElementState(self.html, el)
}
fn rebuild(self, state: &mut Self::State) {
let InertElementState(prev, el) = state;
if &self.html != prev {
let mut new_el = Rndr::create_element_from_html(&self.html);
el.insert_before_this(&mut new_el);
el.unmount();
*el = new_el;
*prev = self.html;
}
}
}
impl AddAnyAttr for InertElement {
type Output<SomeNewAttr: Attribute> = Self;
fn add_any_attr<NewAttr: Attribute>(
self,
_attr: NewAttr,
) -> Self::Output<NewAttr>
where
Self::Output<NewAttr>: RenderHtml,
{
panic!(
"InertElement does not support adding attributes. It should only \
be used as a child, and not returned at the top level."
)
}
}
impl RenderHtml for InertElement {
type AsyncOutput = Self;
const MIN_LENGTH: usize = 0;
fn html_len(&self) -> usize {
self.html.len()
}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self {
self
}
fn to_html_with_buf(
self,
buf: &mut String,
position: &mut Position,
_escape: bool,
_mark_branches: bool,
) {
buf.push_str(&self.html);
*position = Position::NextChild;
}
fn hydrate<const FROM_SERVER: bool>(
self,
cursor: &Cursor,
position: &PositionState,
) -> Self::State {
let curr_position = position.get();
if curr_position == Position::FirstChild {
cursor.child();
} else if curr_position != Position::Current {
cursor.sibling();
}
let el = crate::renderer::types::Element::cast_from(cursor.current())
.unwrap();
position.set(Position::NextChild);
InertElementState(self.html, el)
}
}