Skip to content

Commit e4106f6

Browse files
committed
feat: removed final wrapper <div>
Perseus will now inject directly into the root component provided by the user, with no intermediary wrapper `<div>`s, making styling full-page layouts substantially easier!
1 parent 3198558 commit e4106f6

File tree

2 files changed

+10
-20
lines changed

2 files changed

+10
-20
lines changed

examples/demos/full_page_layout/static/style.css

+2-6
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@
55

66
/* This makes all the elements that wrap our code take up the whole page, so that we can put things at the bottom.
77
* Without this, the footer would be just beneath the content if the content doesn't fill the whole page (try disabling this).
8-
*
9-
* Quirk: we have to deal with the wrapper around `#root` created by `PerseusRoot`
108
*/
11-
html, body, body > div, #root {
9+
html, body, #root {
1210
height: 100%;
1311
}
14-
/* This makes the `<div>` that wraps our whole app use CSS Grid to display three sections: the header, content, and footer.
15-
* Quirk: soon, this will just be `#root`
16-
*/
12+
/* This makes the `<div>` that wraps our whole app use CSS Grid to display three sections: the header, content, and footer. */
1713
#root {
1814
display: grid;
1915
grid-template-columns: 1fr;

packages/perseus/src/init.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::pin::Pin;
2020
use std::sync::Arc;
2121
use std::{collections::HashMap, rc::Rc};
2222
use sycamore::prelude::Scope;
23+
use sycamore::utils::hydrate::with_no_hydration_context;
2324
use sycamore::{
2425
prelude::{component, view},
2526
view::View,
@@ -527,20 +528,11 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
527528
// The lifetime of the provided function doesn't need to be static, because we
528529
// render using it and then we're done with it
529530
pub fn index_view<'a>(mut self, f: impl Fn(Scope) -> View<SsrNode> + 'a) -> Self {
530-
// This, very problematically, could add hydration IDs to the `<head>` and
531-
// `<body>`, which we MUST NOT have (or the HTML shell's interpolation breaks in
532-
// unexpected ways)
533-
let html_str = sycamore::render_to_string(f);
534-
// So, we get rid of the hydration IDs completely
535-
// We have to get rid of leftover spaces as well to make sure we're completely
536-
// good for the naive string replacement
537-
#[cfg(not(target_arch = "wasm32"))]
538-
let html_str = regex::Regex::new(r#"data-hk=".*?""#)
539-
.unwrap()
540-
.replace_all(&html_str, "")
541-
.to_string()
542-
.replace(" >", ">");
531+
// We need to render the index view without any hydration IDs (which would break
532+
// the HTML shell's interpolation mechanisms)
533+
let html_str = sycamore::render_to_string(|cx| with_no_hydration_context(|| f(cx)));
543534
self.index_view = html_str;
535+
544536
self
545537
}
546538
// Setters
@@ -859,7 +851,9 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
859851
#[allow(non_snake_case)]
860852
pub fn PerseusRoot<G: Html>(cx: Scope) -> View<G> {
861853
view! { cx,
862-
div(dangerously_set_inner_html = "<div id=\"root\"></div>")
854+
// Since we render the index view with no hydration IDs, this conforms
855+
// to the expectations of the HTML shell
856+
div(id = "root")
863857
}
864858
}
865859

0 commit comments

Comments
 (0)