1
0
Jonathan Kelley 2 жил өмнө
parent
commit
34d9aafe0e

+ 2 - 2
examples/rsx_compile_fail.rs

@@ -2,13 +2,13 @@
 //! It also proves that lifetimes work properly, especially when used with use_ref
 
 use dioxus::prelude::*;
-use dioxus_ssr::config::SsrConfig;
+use dioxus_ssr::config::Config;
 
 fn main() {
     let mut vdom = VirtualDom::new(example);
     _ = vdom.rebuild();
 
-    let out = dioxus_ssr::render_vdom_cfg(&vdom, SsrConfig::default().newline(true).indent(true));
+    let out = dioxus_ssr::render_vdom_cfg(&vdom, Config::default().newline(true).indent(true));
     println!("{}", out);
 }
 

+ 2 - 2
examples/ssr.rs

@@ -5,7 +5,7 @@
 use std::fmt::Write;
 
 use dioxus::prelude::*;
-use dioxus_ssr::config::SsrConfig;
+use dioxus_ssr::config::Config;
 
 fn main() {
     // We can render VirtualDoms
@@ -26,7 +26,7 @@ fn main() {
     // We can configure the SSR rendering to add ids for rehydration
     println!(
         "{}",
-        dioxus_ssr::render_vdom_cfg(&vdom, SsrConfig::default().pre_render(true))
+        dioxus_ssr::render_vdom_cfg(&vdom, Config::default().pre_render(true))
     );
 
     // We can even render as a writer

+ 2 - 1
packages/core/src/create.rs

@@ -307,7 +307,8 @@ impl<'b> VirtualDom {
 
         let unbounded_props = unsafe { std::mem::transmute(props) };
 
-        let scope = self.new_scope(unbounded_props).id;
+        let scope = self.new_scope(unbounded_props, component.name);
+        let scope = scope.id;
         component.scope.set(Some(scope));
 
         let return_nodes = unsafe { self.run_scope(scope).extend_lifetime_ref() };

+ 6 - 1
packages/core/src/scope_arena.rs

@@ -17,7 +17,11 @@ use std::{
 };
 
 impl VirtualDom {
-    pub(super) fn new_scope(&mut self, props: Box<dyn AnyProps<'static>>) -> &ScopeState {
+    pub(super) fn new_scope(
+        &mut self,
+        props: Box<dyn AnyProps<'static>>,
+        name: &'static str,
+    ) -> &ScopeState {
         let parent = self.acquire_current_scope_raw();
         let entry = self.scopes.vacant_entry();
         let height = unsafe { parent.map(|f| (*f).height + 1).unwrap_or(0) };
@@ -28,6 +32,7 @@ impl VirtualDom {
             id,
             height,
             props: Some(props),
+            name,
             placeholder: Default::default(),
             node_arena_1: BumpFrame::new(50),
             node_arena_2: BumpFrame::new(50),

+ 6 - 0
packages/core/src/scopes.rs

@@ -68,6 +68,7 @@ pub struct ScopeId(pub usize);
 /// This struct exists to provide a common interface for all scopes without relying on generics.
 pub struct ScopeState {
     pub(crate) render_cnt: Cell<usize>,
+    pub(crate) name: &'static str,
 
     pub(crate) node_arena_1: BumpFrame,
     pub(crate) node_arena_2: BumpFrame,
@@ -115,6 +116,11 @@ impl<'src> ScopeState {
         }
     }
 
+    /// Get the name of this component
+    pub fn name(&self) -> &str {
+        self.name
+    }
+
     /// Get the current render since the inception of this component
     ///
     /// This can be used as a helpful diagnostic when debugging hooks/renders, etc

+ 4 - 5
packages/core/src/virtual_dom.rs

@@ -239,11 +239,10 @@ impl VirtualDom {
             mutations: Mutations::default(),
         };
 
-        let root = dom.new_scope(Box::new(VProps::new(
-            root,
-            |_, _| unreachable!(),
-            root_props,
-        )));
+        let root = dom.new_scope(
+            Box::new(VProps::new(root, |_, _| unreachable!(), root_props)),
+            "app",
+        );
 
         // The root component is always a suspense boundary for any async children
         // This could be unexpected, so we might rethink this behavior later

+ 2 - 8
packages/core/tests/context_api.rs

@@ -29,17 +29,11 @@ fn state_shares() {
 
     dom.mark_dirty(ScopeId(0));
     _ = dom.render_immediate();
-    assert_eq!(
-        dom.base_scope().consume_context::<i32>().unwrap().as_ref(),
-        &1
-    );
+    assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 1);
 
     dom.mark_dirty(ScopeId(0));
     _ = dom.render_immediate();
-    assert_eq!(
-        dom.base_scope().consume_context::<i32>().unwrap().as_ref(),
-        &2
-    );
+    assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 2);
 
     dom.mark_dirty(ScopeId(2));
     assert_eq!(

+ 3 - 1
packages/core/tests/safety.rs

@@ -1,5 +1,7 @@
 //! Tests related to safety of the library.
 
+use std::rc::Rc;
+
 use dioxus::prelude::*;
 use dioxus_core::SuspenseContext;
 
@@ -18,5 +20,5 @@ fn root_node_isnt_null() {
 
     // There should be a default suspense context
     // todo: there should also be a default error boundary
-    assert!(scope.has_context::<SuspenseContext>().is_some());
+    assert!(scope.has_context::<Rc<SuspenseContext>>().is_some());
 }

+ 3 - 2
packages/core/tests/suspense.rs

@@ -2,6 +2,7 @@ use dioxus::core::ElementId;
 use dioxus::core::{Mutation::*, SuspenseContext};
 use dioxus::prelude::*;
 use std::future::IntoFuture;
+use std::rc::Rc;
 use std::time::Duration;
 
 #[tokio::test]
@@ -51,11 +52,11 @@ fn app(cx: Scope) -> Element {
 
 fn suspense_boundary(cx: Scope) -> Element {
     cx.use_hook(|| {
-        cx.provide_context(SuspenseContext::new(cx.scope_id()));
+        cx.provide_context(Rc::new(SuspenseContext::new(cx.scope_id())));
     });
 
     // Ensure the right types are found
-    cx.has_context::<SuspenseContext>().unwrap();
+    cx.has_context::<Rc<SuspenseContext>>().unwrap();
 
     cx.render(rsx!(async_child {}))
 }

+ 0 - 37
packages/ssr/src/config.rs

@@ -1,38 +1 @@
-#[derive(Clone, Debug, Default)]
-pub struct SsrConfig {
-    /// currently not supported - control if we indent the HTML output
-    indent: bool,
 
-    /// Control if elements are written onto a new line
-    newline: bool,
-
-    /// Choose to write ElementIDs into elements so the page can be re-hydrated later on
-    pre_render: bool,
-
-    // Currently not implemented
-    // Don't proceed onto new components. Instead, put the name of the component.
-    // TODO: components don't have names :(
-    skip_components: bool,
-}
-
-impl SsrConfig {
-    pub fn indent(mut self, a: bool) -> Self {
-        self.indent = a;
-        self
-    }
-
-    pub fn newline(mut self, a: bool) -> Self {
-        self.newline = a;
-        self
-    }
-
-    pub fn pre_render(mut self, a: bool) -> Self {
-        self.pre_render = a;
-        self
-    }
-
-    pub fn skip_components(mut self, a: bool) -> Self {
-        self.skip_components = a;
-        self
-    }
-}

+ 0 - 50
packages/ssr/src/helpers.rs

@@ -1,50 +0,0 @@
-use std::fmt::Write;
-
-use dioxus_core::{LazyNodes, ScopeId, VirtualDom};
-
-use crate::config::SsrConfig;
-
-pub fn pre_render(dom: &VirtualDom) -> String {
-    todo!()
-}
-
-pub fn pre_render_to(dom: &VirtualDom, write: impl Write) {
-    todo!()
-}
-
-pub fn render_vdom(dom: &VirtualDom) -> String {
-    todo!()
-    // format!("{:}", TextRenderer::from_vdom(dom, SsrConfig::default()))
-}
-
-pub fn pre_render_vdom(dom: &VirtualDom) -> String {
-    todo!()
-    // format!(
-    //     "{:}",
-    //     TextRenderer::from_vdom(dom, SsrConfig::default().pre_render(true))
-    // )
-}
-
-pub fn render_vdom_cfg(dom: &VirtualDom, cfg: SsrConfig) -> String {
-    todo!()
-    // format!(
-    //     "{:}",
-    //     TextRenderer::from_vdom(dom, cfg(SsrConfig::default()))
-    // )
-}
-
-pub fn render_vdom_scope(vdom: &VirtualDom, scope: ScopeId) -> Option<String> {
-    todo!()
-    // Some(format!(
-    //     "{:}",
-    //     TextRenderer {
-    //         cfg: SsrConfig::default(),
-    //         root: vdom.get_scope(scope).unwrap().root_node(),
-    //         vdom: Some(vdom),
-    //     }
-    // ))
-}
-
-pub fn render_lazy<'a, 'b>(f: LazyNodes<'a, 'b>) -> String {
-    todo!()
-}

+ 40 - 3
packages/ssr/src/lib.rs

@@ -2,8 +2,45 @@
 
 mod cache;
 pub mod config;
-pub mod helpers;
 pub mod renderer;
 pub mod template;
-pub use helpers::*;
-pub use template::SsrRender;
+use dioxus_core::{Element, LazyNodes, Scope, VirtualDom};
+use std::cell::Cell;
+
+use crate::renderer::Renderer;
+
+/// A convenience function to render an `rsx!` call to a string
+///
+/// For advanced rendering, create a new `SsrRender`.
+pub fn render_lazy<'a, 'b>(f: LazyNodes<'a, 'b>) -> String {
+    // We need to somehow get the lazy call into the virtualdom even with the lifetime
+    // Since the lazy lifetime is valid for this function, we can just transmute it to static temporarily
+    // This is okay since we're returning an owned value
+    struct RootProps<'a, 'b> {
+        caller: Cell<Option<LazyNodes<'a, 'b>>>,
+    }
+
+    fn lazy_app<'a>(cx: Scope<'a, RootProps<'static, 'static>>) -> Element<'a> {
+        let lazy = cx.props.caller.take().unwrap();
+        let lazy: LazyNodes = unsafe { std::mem::transmute(lazy) };
+        Ok(lazy.call(cx))
+    }
+
+    let props: RootProps = unsafe {
+        std::mem::transmute(RootProps {
+            caller: Cell::new(Some(f)),
+        })
+    };
+
+    let mut dom = VirtualDom::new_with_props(lazy_app, props);
+    _ = dom.rebuild();
+
+    Renderer::new().render(&dom)
+}
+
+/// A convenience function to render an existing VirtualDom to a string
+///
+/// We generally recommend creating a new `Renderer` to take advantage of template caching.
+pub fn render(dom: &VirtualDom) -> String {
+    Renderer::new().render(dom)
+}

+ 181 - 146
packages/ssr/src/renderer.rs

@@ -1,146 +1,181 @@
-// use dioxus_core::VirtualDom;
-
-// use crate::config::SsrConfig;
-
-// pub struct SsrRenderer {
-//     vdom: VirtualDom,
-//     cfg: SsrConfig,
-// }
-
-// impl Default for SsrRenderer {
-//     fn default() -> Self {
-//         Self::new(SsrConfig::default())
-//     }
-// }
-
-// impl SsrRenderer {
-//     pub fn new(cfg: SsrConfig) -> Self {
-//         Self {
-//             vdom: VirtualDom::new(app),
-//             cfg,
-//         }
-//     }
-
-//     pub fn render_lazy<'a>(&'a mut self, f: LazyNodes<'a, '_>) -> String {
-//         let scope = self.vdom.base_scope();
-//         let root = f.call(scope);
-//         format!(
-//             "{:}",
-//             TextRenderer {
-//                 cfg: self.cfg.clone(),
-//                 root: &root,
-//                 vdom: Some(&self.vdom),
-//             }
-//         )
-//     }
-
-//     fn html_render(
-//         &self,
-//         node: &VNode,
-//         f: &mut impl Write,
-//         il: u16,
-//         last_node_was_text: &mut bool,
-//     ) -> std::fmt::Result {
-//         // match &node {
-//         //     VNode::Text(text) => {
-//         //         if *last_node_was_text {
-//         //             write!(f, "<!--spacer-->")?;
-//         //         }
-
-//         //         if self.cfg.indent {
-//         //             for _ in 0..il {
-//         //                 write!(f, "    ")?;
-//         //             }
-//         //         }
-
-//         //         *last_node_was_text = true;
-
-//         //         write!(f, "{}", text.text)?
-//         //     }
-//         //     VNode::Element(el) => {
-//         //         *last_node_was_text = false;
-
-//         //         if self.cfg.indent {
-//         //             for _ in 0..il {
-//         //                 write!(f, "    ")?;
-//         //             }
-//         //         }
-
-//         //         write!(f, "<{}", el.tag)?;
-
-//         //         let inner_html = render_attributes(el.attributes.iter(), f)?;
-
-//         //         match self.cfg.newline {
-//         //             true => writeln!(f, ">")?,
-//         //             false => write!(f, ">")?,
-//         //         }
-
-//         //         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, &mut last_node_was_text)?;
-//         //             }
-//         //         }
-
-//         //         if self.cfg.newline {
-//         //             writeln!(f)?;
-//         //         }
-//         //         if self.cfg.indent {
-//         //             for _ in 0..il {
-//         //                 write!(f, "    ")?;
-//         //             }
-//         //         }
-
-//         //         write!(f, "</{}>", el.tag)?;
-//         //         if self.cfg.newline {
-//         //             writeln!(f)?;
-//         //         }
-//         //     }
-//         //     VNode::Fragment(frag) => match frag.children.len() {
-//         //         0 => {
-//         //             *last_node_was_text = false;
-//         //             if self.cfg.indent {
-//         //                 for _ in 0..il {
-//         //                     write!(f, "    ")?;
-//         //                 }
-//         //             }
-//         //             write!(f, "<!--placeholder-->")?;
-//         //         }
-//         //         _ => {
-//         //             for child in frag.children {
-//         //                 self.html_render(child, f, il + 1, last_node_was_text)?;
-//         //             }
-//         //         }
-//         //     },
-//         //     VNode::Component(vcomp) => {
-//         //         let idx = vcomp.scope.get().unwrap();
-
-//         //         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, last_node_was_text)?;
-//         //         } else {
-//         //         }
-//         //     }
-//         //     VNode::Template(t) => {
-//         //         if let Some(vdom) = self.vdom {
-//         //             todo!()
-//         //         } else {
-//         //             panic!("Cannot render template without vdom");
-//         //         }
-//         //     }
-//         //     VNode::Placeholder(_) => {
-//         //         todo!()
-//         //     }
-//         // }
-//         Ok(())
-//     }
-// }
-
-// impl<'a: 'c, 'c> Display for SsrRenderer<'a, '_, 'c> {
-//     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-//         let mut last_node_was_text = false;
-//         self.html_render(self.root, f, 0, &mut last_node_was_text)
-//     }
-// }
+use super::cache::Segment;
+use crate::cache::StringCache;
+use dioxus_core::{prelude::*, AttributeValue, DynamicNode, RenderReturn};
+use std::collections::HashMap;
+use std::fmt::Write;
+use std::rc::Rc;
+
+/// A virtualdom renderer that caches the templates it has seen for faster rendering
+#[derive(Default)]
+pub struct Renderer {
+    /// should we do our best to prettify the output?
+    pub pretty: bool,
+
+    /// Control if elements are written onto a new line
+    pub newline: bool,
+
+    /// Should we sanitize text nodes? (escape HTML)
+    pub sanitize: bool,
+
+    /// Choose to write ElementIDs into elements so the page can be re-hydrated later on
+    pub pre_render: bool,
+
+    // Currently not implemented
+    // Don't proceed onto new components. Instead, put the name of the component.
+    pub skip_components: bool,
+
+    /// A cache of templates that have been rendered
+    template_cache: HashMap<&'static str, Rc<StringCache>>,
+}
+
+impl Renderer {
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    pub fn render(&mut self, dom: &VirtualDom) -> String {
+        let mut buf = String::new();
+        self.render_to(&mut buf, dom).unwrap();
+        buf
+    }
+
+    pub fn render_to(&mut self, buf: &mut impl Write, dom: &VirtualDom) -> std::fmt::Result {
+        self.render_scope(buf, dom, ScopeId(0))
+    }
+
+    pub fn render_scope(
+        &mut self,
+        buf: &mut impl Write,
+        dom: &VirtualDom,
+        scope: ScopeId,
+    ) -> std::fmt::Result {
+        // We should never ever run into async or errored nodes in SSR
+        // Error boundaries and suspense boundaries will convert these to sync
+        if let RenderReturn::Sync(Ok(node)) = dom.get_scope(scope).unwrap().root_node() {
+            self.render_template(buf, dom, node)?
+        };
+
+        Ok(())
+    }
+
+    fn render_template(
+        &mut self,
+        buf: &mut impl Write,
+        dom: &VirtualDom,
+        template: &VNode,
+    ) -> std::fmt::Result {
+        let entry = self
+            .template_cache
+            .entry(template.template.name)
+            .or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
+            .clone();
+
+        for segment in entry.segments.iter() {
+            match segment {
+                Segment::Attr(idx) => {
+                    let attr = &template.dynamic_attrs[*idx];
+                    match attr.value {
+                        AttributeValue::Text(value) => write!(buf, " {}=\"{}\"", attr.name, value)?,
+                        AttributeValue::Bool(value) => write!(buf, " {}={}", attr.name, value)?,
+                        _ => {}
+                    };
+                }
+                Segment::Node(idx) => match &template.dynamic_nodes[*idx] {
+                    DynamicNode::Component(node) => {
+                        if self.skip_components {
+                            write!(buf, "<{}><{}/>", node.name, node.name)?;
+                        } else {
+                            let id = node.scope.get().unwrap();
+                            let scope = dom.get_scope(id).unwrap();
+                            let node = scope.root_node();
+                            match node {
+                                RenderReturn::Sync(Ok(node)) => {
+                                    self.render_template(buf, dom, node)?
+                                }
+                                _ => todo!(
+                                    "generally, scopes should be sync, only if being traversed"
+                                ),
+                            }
+                        }
+                    }
+                    DynamicNode::Text(text) => {
+                        // in SSR, we are concerned that we can't hunt down the right text node since they might get merged
+                        if self.pre_render {
+                            write!(buf, "<!--#-->")?;
+                        }
+
+                        // todo: escape the text
+                        write!(buf, "{}", text.value)?;
+
+                        if self.pre_render {
+                            write!(buf, "<!--#-->")?;
+                        }
+                    }
+                    DynamicNode::Fragment(nodes) => {
+                        for child in *nodes {
+                            self.render_template(buf, dom, child)?;
+                        }
+                    }
+
+                    DynamicNode::Placeholder(_el) => {
+                        if self.pre_render {
+                            write!(buf, "<pre><pre/>")?;
+                        }
+                    }
+                },
+
+                Segment::PreRendered(contents) => write!(buf, "{}", contents)?,
+            }
+        }
+
+        Ok(())
+    }
+}
+
+#[test]
+fn to_string_works() {
+    use dioxus::prelude::*;
+
+    fn app(cx: Scope) -> Element {
+        let dynamic = 123;
+        let dyn2 = "</diiiiiiiiv>"; // todo: escape this
+
+        render! {
+            div { class: "asdasdasd", class: "asdasdasd", id: "id-{dynamic}",
+                "Hello world 1 -->" "{dynamic}" "<-- Hello world 2"
+                div { "nest 1" }
+                div {}
+                div { "nest 2" }
+                "{dyn2}"
+                (0..5).map(|i| rsx! { div { "finalize {i}" } })
+            }
+        }
+    }
+
+    let mut dom = VirtualDom::new(app);
+    _ = dom.rebuild();
+
+    let mut renderer = Renderer::new();
+
+    let out = renderer.render(&dom);
+
+    use Segment::*;
+    assert_eq!(
+        renderer.template_cache.iter().next().unwrap().1.segments,
+        vec![
+            PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
+            Attr(0,),
+            PreRendered(">Hello world 1 -->".into(),),
+            Node(0,),
+            PreRendered("<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),),
+            Node(1,),
+            Node(2,),
+            PreRendered("</div>".into(),),
+        ]
+    );
+
+    assert_eq!(
+        out,
+        "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --><!--#-->123<!--/#--><-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div><!--#--></diiiiiiiiv><!--/#--><div><!--#-->finalize 0<!--/#--></div><div><!--#-->finalize 1<!--/#--></div><div><!--#-->finalize 2<!--/#--></div><div><!--#-->finalize 3<!--/#--></div><div><!--#-->finalize 4<!--/#--></div></div>"
+    );
+}

+ 0 - 139
packages/ssr/src/template.rs

@@ -1,140 +1 @@
-use super::cache::Segment;
-use dioxus_core::{prelude::*, AttributeValue, DynamicNode, RenderReturn, VText};
-use std::collections::HashMap;
-use std::fmt::Write;
-use std::rc::Rc;
 
-use crate::cache::StringCache;
-
-/// A virtualdom renderer that caches the templates it has seen for faster rendering
-#[derive(Default)]
-pub struct SsrRender {
-    template_cache: HashMap<&'static str, Rc<StringCache>>,
-}
-
-impl SsrRender {
-    pub fn render_vdom(&mut self, dom: &VirtualDom) -> String {
-        let scope = dom.base_scope();
-        let root = scope.root_node();
-
-        let mut out = String::new();
-
-        match root {
-            RenderReturn::Sync(Ok(node)) => self.render_template(&mut out, dom, node).unwrap(),
-            _ => {}
-        };
-
-        out
-    }
-
-    fn render_template(
-        &mut self,
-        buf: &mut String,
-        dom: &VirtualDom,
-        template: &VNode,
-    ) -> std::fmt::Result {
-        let entry = self
-            .template_cache
-            .entry(template.template.name)
-            .or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
-            .clone();
-
-        for segment in entry.segments.iter() {
-            match segment {
-                Segment::Attr(idx) => {
-                    let attr = &template.dynamic_attrs[*idx];
-                    match attr.value {
-                        AttributeValue::Text(value) => write!(buf, " {}=\"{}\"", attr.name, value)?,
-                        AttributeValue::Bool(value) => write!(buf, " {}={}", attr.name, value)?,
-                        _ => {}
-                    };
-                }
-                Segment::Node(idx) => match &template.dynamic_nodes[*idx] {
-                    DynamicNode::Component(node) => {
-                        let id = node.scope.get().unwrap();
-                        let scope = dom.get_scope(id).unwrap();
-                        let node = scope.root_node();
-                        match node {
-                            RenderReturn::Sync(Ok(node)) => self.render_template(buf, dom, node)?,
-                            _ => todo!(),
-                        }
-                    }
-                    DynamicNode::Text(text) => {
-                        // in SSR, we are concerned that we can't hunt down the right text node since they might get merged
-                        // if !*inner {
-                        // write!(buf, "<!--#-->")?;
-                        // }
-
-                        // todo: escape the text
-                        write!(buf, "{}", text.value)?;
-
-                        // if !*inner {
-                        // write!(buf, "<!--/#-->")?;
-                        // }
-                    }
-                    DynamicNode::Fragment(nodes) => {
-                        for child in *nodes {
-                            self.render_template(buf, dom, child)?;
-                        }
-                    }
-
-                    DynamicNode::Placeholder(_el) => {
-                        // todo write a placeholder if in pre-render mode
-                        // write!(buf, "<!--placeholder-->")?;
-                    }
-                },
-
-                Segment::PreRendered(contents) => buf.push_str(contents),
-            }
-        }
-
-        Ok(())
-    }
-}
-
-#[test]
-fn to_string_works() {
-    use dioxus::prelude::*;
-
-    fn app(cx: Scope) -> Element {
-        let dynamic = 123;
-        let dyn2 = "</diiiiiiiiv>"; // todo: escape this
-
-        render! {
-            div { class: "asdasdasd", class: "asdasdasd", id: "id-{dynamic}",
-                "Hello world 1 -->" "{dynamic}" "<-- Hello world 2"
-                div { "nest 1" }
-                div {}
-                div { "nest 2" }
-                "{dyn2}"
-                (0..5).map(|i| rsx! { div { "finalize {i}" } })
-            }
-        }
-    }
-
-    let mut dom = VirtualDom::new(app);
-    dom.rebuild();
-
-    use Segment::*;
-
-    // assert_eq!(
-    //     StringCache::from_template(&dom.base_scope().root_node())
-    //         .unwrap()
-    //         .segments,
-    //     vec![
-    //         PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
-    //         Attr(0,),
-    //         PreRendered(">Hello world 1 -->".into(),),
-    //         Node(0,),
-    //         PreRendered("<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),),
-    //         Node(1,),
-    //         Node(2,),
-    //         PreRendered("</div>".into(),),
-    //     ]
-    // );
-
-    // assert_eq!(
-    //     SsrRender::default().render_vdom(&dom),
-    //     "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --><!--#-->123<!--/#--><-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div><!--#--></diiiiiiiiv><!--/#--><div><!--#-->finalize 0<!--/#--></div><div><!--#-->finalize 1<!--/#--></div><div><!--#-->finalize 2<!--/#--></div><div><!--#-->finalize 3<!--/#--></div><div><!--#-->finalize 4<!--/#--></div></div>"
-    // );
-}

+ 0 - 144
packages/ssr/tests.old/renders.rs

@@ -1,144 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_ssr::{render_lazy, render_vdom, render_vdom_cfg, SsrConfig, SsrRenderer, TextRenderer};
-
-static SIMPLE_APP: Component = |cx| {
-    cx.render(rsx!(div {
-        "hello world!"
-    }))
-};
-
-static SLIGHTLY_MORE_COMPLEX: Component = |cx| {
-    cx.render(rsx! {
-        div { title: "About W3Schools",
-            (0..20).map(|f| rsx!{
-                div {
-                    title: "About W3Schools",
-                    style: "color:blue;text-align:center",
-                    class: "About W3Schools",
-                    p {
-                        title: "About W3Schools",
-                        "Hello world!: {f}"
-                    }
-                }
-            })
-        }
-    })
-};
-
-static NESTED_APP: Component = |cx| {
-    cx.render(rsx!(
-        div {
-            SIMPLE_APP {}
-        }
-    ))
-};
-static FRAGMENT_APP: Component = |cx| {
-    cx.render(rsx!(
-        div { "f1" }
-        div { "f2" }
-        div { "f3" }
-        div { "f4" }
-    ))
-};
-
-#[test]
-fn to_string_works() {
-    let mut dom = VirtualDom::new(SIMPLE_APP);
-    dom.rebuild();
-    dbg!(render_vdom(&dom));
-}
-
-#[test]
-fn hydration() {
-    let mut dom = VirtualDom::new(NESTED_APP);
-    dom.rebuild();
-    dbg!(render_vdom_cfg(&dom, |c| c.pre_render(true)));
-}
-
-#[test]
-fn nested() {
-    let mut dom = VirtualDom::new(NESTED_APP);
-    dom.rebuild();
-    dbg!(render_vdom(&dom));
-}
-
-#[test]
-fn fragment_app() {
-    let mut dom = VirtualDom::new(FRAGMENT_APP);
-    dom.rebuild();
-    dbg!(render_vdom(&dom));
-}
-
-#[test]
-fn write_to_file() {
-    use std::fs::File;
-    use std::io::Write;
-
-    let mut file = File::create("index.html").unwrap();
-
-    let mut dom = VirtualDom::new(SLIGHTLY_MORE_COMPLEX);
-    dom.rebuild();
-
-    file.write_fmt(format_args!(
-        "{}",
-        TextRenderer::from_vdom(&dom, SsrConfig::default())
-    ))
-    .unwrap();
-}
-
-#[test]
-fn styles() {
-    static STLYE_APP: Component = |cx| {
-        cx.render(rsx! {
-            div { color: "blue", font_size: "46px"  }
-        })
-    };
-
-    let mut dom = VirtualDom::new(STLYE_APP);
-    dom.rebuild();
-    dbg!(render_vdom(&dom));
-}
-
-#[test]
-fn lazy() {
-    let p1 = SsrRenderer::new(|c| c).render_lazy(rsx! {
-        div { "ello"  }
-    });
-
-    let p2 = render_lazy(rsx! {
-        div {
-            "ello"
-        }
-    });
-    assert_eq!(p1, p2);
-}
-
-#[test]
-fn big_lazy() {
-    let s = render_lazy(rsx! {
-        div {
-            div {
-                div {
-                    h1 { "ello world" }
-                    h1 { "ello world" }
-                    h1 { "ello world" }
-                    h1 { "ello world" }
-                    h1 { "ello world" }
-                }
-            }
-        }
-    });
-
-    dbg!(s);
-}
-
-#[test]
-fn inner_html() {
-    let s = render_lazy(rsx! {
-        div {
-            dangerous_inner_html: "<div> ack </div>"
-        }
-    });
-
-    dbg!(s);
-}

+ 30 - 38
packages/ssr/tests/simple.rs

@@ -7,66 +7,43 @@ fn simple() {
     }
 
     let mut dom = VirtualDom::new(app);
-    dom.rebuild();
+    _ = dom.rebuild();
+
+    assert_eq!(dioxus_ssr::render(&dom), "<div>hello!</div>");
 
     assert_eq!(
-        dioxus_ssr::SsrRender::default().render_vdom(&dom),
+        dioxus_ssr::render_lazy(rsx!( div {"hello!"} )),
         "<div>hello!</div>"
     );
 }
 
 #[test]
 fn lists() {
-    fn app(cx: Scope) -> Element {
-        render! {
+    assert_eq!(
+        dioxus_ssr::render_lazy(rsx! {
             ul {
                 (0..5).map(|i| rsx! {
                     li { "item {i}" }
                 })
             }
-        }
-    }
-
-    let mut dom = VirtualDom::new(app);
-    dom.rebuild();
-
-    assert_eq!(
-        dioxus_ssr::SsrRender::default().render_vdom(&dom),
+        }),
         "<ul><li>item 0</li><li>item 1</li><li>item 2</li><li>item 3</li><li>item 4</li></ul>"
     );
 }
 
 #[test]
 fn dynamic() {
-    fn app(cx: Scope) -> Element {
-        let dynamic = 123;
-
-        render! {
-            div { "Hello world 1 -->" "{dynamic}" "<-- Hello world 2" }
-        }
-    }
-
-    let mut dom = VirtualDom::new(app);
-    dom.rebuild();
-
+    let dynamic = 123;
     assert_eq!(
-        dioxus_ssr::SsrRender::default().render_vdom(&dom),
+        dioxus_ssr::render_lazy(rsx! {
+            div { "Hello world 1 -->" "{dynamic}" "<-- Hello world 2" }
+        }),
         "<div>Hello world 1 -->123<-- Hello world 2</div>"
     );
 }
 
 #[test]
 fn components() {
-    fn app(cx: Scope) -> Element {
-        render! {
-            div {
-                (0..5).map(|name| rsx! {
-                    my_component { name: name }
-                })
-            }
-        }
-    }
-
     #[inline_props]
     fn my_component(cx: Scope, name: i32) -> Element {
         render! {
@@ -74,11 +51,26 @@ fn components() {
         }
     }
 
-    let mut dom = VirtualDom::new(app);
-    dom.rebuild();
-
     assert_eq!(
-        dioxus_ssr::SsrRender::default().render_vdom(&dom),
+        dioxus_ssr::render_lazy(rsx! {
+            div {
+                (0..5).map(|name| rsx! {
+                    my_component { name: name }
+                })
+            }
+        }),
         "<div><div>component 0</div><div>component 1</div><div>component 2</div><div>component 3</div><div>component 4</div></div>"
     );
 }
+
+#[test]
+fn fragments() {
+    assert_eq!(
+        dioxus_ssr::render_lazy(rsx! {
+            div {
+                (0..5).map(|_| rsx! (()))
+            }
+        }),
+        "<div></div>"
+    );
+}