Skip to content

Commit

Permalink
refactor: improved html shell readability (#109)
Browse files Browse the repository at this point in the history
* Basic HtmlShell struct

* Make different types for various kinds of HTML shells

* Add an HtmlShell for displaying page error data
  • Loading branch information
Asha20 committed Jan 13, 2022
1 parent ceca773 commit 69e9f72
Show file tree
Hide file tree
Showing 8 changed files with 483 additions and 236 deletions.
6 changes: 3 additions & 3 deletions examples/basic/.perseus/builder/src/bin/export_error_page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use fmterr::fmt_err;
use perseus::{
internal::{
get_path_prefix_server,
serve::{build_error_page, get_render_cfg, prep_html_shell},
serve::{build_error_page, get_render_cfg, HtmlShell},
},
PluginAction, SsrNode,
};
Expand Down Expand Up @@ -38,7 +38,7 @@ async fn real_main() -> i32 {
return 1;
}
};
let html = prep_html_shell(html, &render_cfg, &get_path_prefix_server());
let html_shell = HtmlShell::new(html, &render_cfg, &get_path_prefix_server());
// Get the error code to build from the arguments to this executable
let args = env::args().collect::<Vec<String>>();
let err_code_to_build_for = match args.get(1) {
Expand Down Expand Up @@ -69,7 +69,7 @@ async fn real_main() -> i32 {
"",
None,
&error_pages,
&html,
&html_shell,
&root_id,
);

Expand Down
4 changes: 2 additions & 2 deletions packages/perseus-actix-web/src/configurer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use perseus::{
internal::{
get_path_prefix_server,
i18n::TranslationsManager,
serve::{get_render_cfg, prep_html_shell, ServerOptions, ServerProps},
serve::{get_render_cfg, HtmlShell, ServerOptions, ServerProps},
},
stores::MutableStore,
};
Expand Down Expand Up @@ -50,7 +50,7 @@ pub async fn configurer<M: MutableStore + 'static, T: TranslationsManager + 'sta
// Get the index file and inject the render configuration into ahead of time
// Anything done here will affect any status code and all loads
let index_file = fs::read_to_string(&opts.index).expect("Couldn't get HTML index file!");
let index_with_render_cfg = prep_html_shell(index_file, &render_cfg, &get_path_prefix_server());
let index_with_render_cfg = HtmlShell::new(index_file, &render_cfg, &get_path_prefix_server());

move |cfg: &mut web::ServiceConfig| {
cfg
Expand Down
49 changes: 32 additions & 17 deletions packages/perseus-actix-web/src/initial_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use perseus::{
i18n::{TranslationsManager, Translator},
router::{match_route_atomic, RouteInfoAtomic, RouteVerdictAtomic},
serve::{
build_error_page, get_path_slice, interpolate_locale_redirection_fallback,
interpolate_page_data, render::get_page_for_template, ServerOptions,
build_error_page, get_path_slice, render::get_page_for_template, HtmlShell,
ServerOptions,
},
},
stores::{ImmutableStore, MutableStore},
Expand All @@ -26,10 +26,18 @@ fn return_error_page(
err: &str,
translator: Option<Rc<Translator>>,
error_pages: &ErrorPages<SsrNode>,
html: &str,
html_shell: &HtmlShell,
root_id: &str,
) -> HttpResponse {
let html = build_error_page(url, status, err, translator, error_pages, html, root_id);
let html = build_error_page(
url,
status,
err,
translator,
error_pages,
html_shell,
root_id,
);
HttpResponse::build(StatusCode::from_u16(*status).unwrap())
.content_type("text/html")
.body(html)
Expand All @@ -40,7 +48,7 @@ fn return_error_page(
pub async fn initial_load<M: MutableStore, T: TranslationsManager>(
req: HttpRequest,
opts: web::Data<Rc<ServerOptions>>,
html_shell: web::Data<String>,
html_shell: web::Data<HtmlShell<'_>>,
render_cfg: web::Data<HashMap<String, String>>,
immutable_store: web::Data<ImmutableStore>,
mutable_store: web::Data<M>,
Expand Down Expand Up @@ -102,7 +110,11 @@ pub async fn initial_load<M: MutableStore, T: TranslationsManager>(
}
};

let final_html = interpolate_page_data(&html_shell, &page_data, &opts.root_id);
let final_html = html_shell
.get_ref()
.clone()
.page_data(&page_data, &opts.root_id)
.to_string();

let mut http_res = HttpResponse::Ok();
http_res.content_type("text/html");
Expand All @@ -118,17 +130,20 @@ pub async fn initial_load<M: MutableStore, T: TranslationsManager>(
// We use a `302 Found` status code to indicate a redirect
// We 'should' generate a `Location` field for the redirect, but it's not RFC-mandated, so we can use the app shell
HttpResponse::Found().content_type("text/html").body(
interpolate_locale_redirection_fallback(
html_shell.get_ref(),
// We'll redirect the user to the default locale
&format!(
"{}/{}/{}",
get_path_prefix_server(),
opts.locales.default,
path
),
&opts.root_id,
),
html_shell
.get_ref()
.clone()
.locale_redirection_fallback(
// We'll redirect the user to the default locale
&format!(
"{}/{}/{}",
get_path_prefix_server(),
opts.locales.default,
path
),
&opts.root_id,
)
.to_string(),
)
}
RouteVerdictAtomic::NotFound => html_err(404, "page not found"),
Expand Down
51 changes: 34 additions & 17 deletions packages/perseus-warp/src/initial_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use perseus::{
i18n::{TranslationsManager, Translator},
router::{match_route_atomic, RouteInfoAtomic, RouteVerdictAtomic},
serve::{
build_error_page, get_path_slice, interpolate_locale_redirection_fallback,
interpolate_page_data, render::get_page_for_template, ServerOptions,
build_error_page, get_path_slice, render::get_page_for_template, HtmlShell,
ServerOptions,
},
},
stores::{ImmutableStore, MutableStore},
Expand All @@ -24,10 +24,18 @@ fn return_error_page(
err: &str,
translator: Option<Rc<Translator>>,
error_pages: &ErrorPages<SsrNode>,
html: &str,
html_shell: &HtmlShell,
root_id: &str,
) -> Response<String> {
let html = build_error_page(url, status, err, translator, error_pages, html, root_id);
let html = build_error_page(
url,
status,
err,
translator,
error_pages,
html_shell,
root_id,
);
Response::builder().status(*status).body(html).unwrap()
}

Expand All @@ -38,7 +46,7 @@ pub async fn initial_load_handler<M: MutableStore, T: TranslationsManager>(
path: FullPath,
req: perseus::http::Request<()>,
opts: Arc<ServerOptions>,
html_shell: Arc<String>,
html_shell: Arc<HtmlShell<'_>>,
render_cfg: Arc<HashMap<String, String>>,
immutable_store: Arc<ImmutableStore>,
mutable_store: Arc<M>,
Expand Down Expand Up @@ -91,7 +99,11 @@ pub async fn initial_load_handler<M: MutableStore, T: TranslationsManager>(
}
};

let final_html = interpolate_page_data(&html_shell, &page_data, &opts.root_id);
let final_html = html_shell
.as_ref()
.clone()
.page_data(&page_data, &opts.root_id)
.to_string();

let mut http_res = Response::builder().status(200);
// http_res.content_type("text/html");
Expand All @@ -108,17 +120,22 @@ pub async fn initial_load_handler<M: MutableStore, T: TranslationsManager>(
// We 'should' generate a `Location` field for the redirect, but it's not RFC-mandated, so we can use the app shell
Response::builder()
.status(200)
.body(interpolate_locale_redirection_fallback(
html_shell.as_ref(),
// We'll redirect the user to the default locale
&format!(
"{}/{}/{}",
get_path_prefix_server(),
opts.locales.default,
path
),
&opts.root_id,
))
.body(
html_shell
.as_ref()
.clone()
.locale_redirection_fallback(
// We'll redirect the user to the default locale
&format!(
"{}/{}/{}",
get_path_prefix_server(),
opts.locales.default,
path
),
&opts.root_id,
)
.to_string(),
)
.unwrap()
}
RouteVerdictAtomic::NotFound => html_err(404, "page not found"),
Expand Down
4 changes: 2 additions & 2 deletions packages/perseus-warp/src/perseus_routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
};
use perseus::internal::serve::{get_render_cfg, ServerProps};
use perseus::{
internal::{get_path_prefix_server, i18n::TranslationsManager, serve::prep_html_shell},
internal::{get_path_prefix_server, i18n::TranslationsManager, serve::HtmlShell},
stores::MutableStore,
};
use std::{fs, sync::Arc};
Expand All @@ -28,7 +28,7 @@ pub async fn perseus_routes<M: MutableStore + 'static, T: TranslationsManager +
.await
.expect("Couldn't get render configuration!");
let index_file = fs::read_to_string(&opts.index).expect("Couldn't get HTML index file!");
let index_with_render_cfg = prep_html_shell(index_file, &render_cfg, &get_path_prefix_server());
let index_with_render_cfg = HtmlShell::new(index_file, &render_cfg, &get_path_prefix_server());

// Handle static files
let js_bundle = warp::path!(".perseus" / "bundle.js")
Expand Down
31 changes: 18 additions & 13 deletions packages/perseus/src/export.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::errors::*;
use crate::html_shell::{
interpolate_locale_redirection_fallback, interpolate_page_data, prep_html_shell,
};
use crate::html_shell::HtmlShell;
use crate::locales::Locales;
use crate::page_data::PageData;
use crate::server::get_render_cfg;
Expand Down Expand Up @@ -61,7 +59,7 @@ pub async fn export_app(
path: html_shell_path.to_string(),
source: err,
})?;
let html_shell = prep_html_shell(raw_html_shell, &render_cfg, &path_prefix);
let html_shell = HtmlShell::new(raw_html_shell, &render_cfg, &path_prefix);

// We can do literally everything concurrently here
let mut export_futs = Vec::new();
Expand Down Expand Up @@ -119,7 +117,7 @@ async fn export_path(
(path, template_path): (String, String),
templates: &TemplateMap<SsrNode>,
locales: &Locales,
html_shell: &str,
html_shell: &HtmlShell<'_>,
root_id: &str,
immutable_store: &ImmutableStore,
path_prefix: String,
Expand Down Expand Up @@ -154,12 +152,13 @@ async fn export_path(
immutable_store
.write(
&format!("exported/{}.html", &initial_load_path),
&interpolate_locale_redirection_fallback(
html_shell,
// If we don't include the path prefix, fallback redirection will fail for relative paths
&format!("{}/{}/{}", path_prefix, locales.default, &path),
root_id,
),
&html_shell
.clone()
.locale_redirection_fallback(
&format!("{}/{}/{}", path_prefix, locales.default, &path),
root_id,
)
.to_string(),
)
.await?;
}
Expand All @@ -176,7 +175,10 @@ async fn export_path(
.await?;
// Create a full HTML file from those that can be served for initial loads
// The build process writes these with a dummy default locale even though we're not using i18n
let full_html = interpolate_page_data(html_shell, &page_data, root_id);
let full_html = html_shell
.clone()
.page_data(&page_data, root_id)
.to_string();
immutable_store
.write(
&format!("exported/{}/{}.html", locale, initial_load_path),
Expand All @@ -202,7 +204,10 @@ async fn export_path(
.await?;
// Create a full HTML file from those that can be served for initial loads
// The build process writes these with a dummy default locale even though we're not using i18n
let full_html = interpolate_page_data(html_shell, &page_data, root_id);
let full_html = html_shell
.clone()
.page_data(&page_data, root_id)
.to_string();
// We don't add an extension because this will be queried directly by the browser
immutable_store
.write(&format!("exported/{}.html", initial_load_path), &full_html)
Expand Down
Loading

0 comments on commit 69e9f72

Please sign in to comment.