feat: make hydration more robust

This commit is contained in:
Jonathan Kelley committed 2022-01-07 00:33:09 -05:00
1 parent 4aadec1e30
commit bbb6ee10de
9 files changed
+354 -77

No files matched your search

+37 -15
View File
@@ -70,6 +70,13 @@ pub fn render_vdom(dom: &VirtualDom) -> String {
format!("{:}", TextRenderer::from_vdom(dom, SsrConfig::default()))
}
pub fn pre_render_vdom(dom: &VirtualDom) -> String {
format!(
"{:}",
TextRenderer::from_vdom(dom, SsrConfig::default().pre_render(true))
)
}
pub fn render_vdom_cfg(dom: &VirtualDom, cfg: impl FnOnce(SsrConfig) -> SsrConfig) -> String {
format!(
"{:}",
@@ -114,7 +121,8 @@ pub struct TextRenderer<'a, 'b> {
impl Display for TextRenderer<'_, '_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.html_render(self.root, f, 0)
let mut last_node_was_text = false;
self.html_render(self.root, f, 0, &mut last_node_was_text)
}
}
@@ -127,14 +135,27 @@ impl<'a> TextRenderer<'a, '_> {
}
}
fn html_render(&self, node: &VNode, f: &mut std::fmt::Formatter, il: u16) -> std::fmt::Result {
fn html_render(
&self,
node: &VNode,
f: &mut std::fmt::Formatter,
il: u16,
last_node_was_text: &mut bool,
) -> std::fmt::Result {
match &node {
VNode::Text(text) => {
if *last_node_was_text && self.cfg.pre_render {
write!(f, "<!--spacer-->")?;
}
if self.cfg.indent {
for _ in 0..il {
write!(f, " ")?;
}
}
*last_node_was_text = true;
write!(f, "{}", text.text)?
}
VNode::Placeholder(_anchor) => {
@@ -184,17 +205,17 @@ impl<'a> TextRenderer<'a, '_> {
}
}
// we write the element's id as a data attribute
//
// when the page is loaded, the `querySelectorAll` will be used to collect all the nodes, and then add
// them interpreter's stack
if let (true, Some(id)) = (self.cfg.pre_render, node.try_mounted_id()) {
write!(f, " dioxus-id=\"{}\"", id)?;
// // we write the element's id as a data attribute
// //
// // when the page is loaded, the `querySelectorAll` will be used to collect all the nodes, and then add
// // them interpreter's stack
// if let (true, Some(id)) = (self.cfg.pre_render, node.try_mounted_id()) {
// write!(f, " dioxus-id=\"{}\"", id)?;
for _listener in el.listeners {
// todo: write the listeners
}
}
// for _listener in el.listeners {
// // todo: write the listeners
// }
// }
match self.cfg.newline {
true => writeln!(f, ">")?,
@@ -204,8 +225,9 @@ impl<'a> TextRenderer<'a, '_> {
if let Some(inner_html) = inner_html {
write!(f, "{}", inner_html)?;
} else {
let mut last_node_was_text = false;
for child in el.children {
self.html_render(child, f, il + 1)?;
self.html_render(child, f, il + 1, &mut last_node_was_text)?;
}
}
@@ -225,7 +247,7 @@ impl<'a> TextRenderer<'a, '_> {
}
VNode::Fragment(frag) => {
for child in frag.children {
self.html_render(child, f, il + 1)?;
self.html_render(child, f, il + 1, last_node_was_text)?;
}
}
VNode::Component(vcomp) => {
@@ -233,7 +255,7 @@ impl<'a> TextRenderer<'a, '_> {
if let (Some(vdom), false) = (self.vdom, self.cfg.skip_components) {
let new_node = vdom.get_scope(idx).unwrap().root_node();
self.html_render(new_node, f, il + 1)?;
self.html_render(new_node, f, il + 1, last_node_was_text)?;
} else {
}
}