text/x-rust
•
2.15 KB
•
79 lines
use askama::Template;
use axum::{
body::Body,
http::Response,
response::{Html, IntoResponse},
};
#[cfg(not(debug_assertions))]
const APP_THEME: &str = include_str!("../../dist/index.html");
pub fn extract_html_parts(html: &str) -> (&str, &str) {
let first_split = html
.split_once("</head>")
.expect("extract_html_parts first_split");
let head = first_split
.0
.split_once("<head>")
.expect("extract_html_parts head")
.1;
let rest = first_split
.1
.split_once("<body>")
.expect("extract_html_parts rest")
.1;
let body = rest
.split_once("</body>")
.expect("extract_html_parts body")
.0;
(head, body)
}
pub trait ThemedRender {
fn render_with_theme(&self) -> String;
fn response(&self) -> Response<Body>;
}
impl<T: Template> ThemedRender for T {
fn render_with_theme(&self) -> String {
#[cfg(not(debug_assertions))]
let theme = APP_THEME;
#[cfg(debug_assertions)]
let theme = std::fs::read_to_string("dist/index.html").expect("Couldn't read dist/index.html");
let contents = self.render().expect("Couldn't render template");
let (head, body) = extract_html_parts(&contents);
let theme = theme.replace("<!--HEAD-->", head);
theme.replace("<!--BODY-->", body)
}
fn response(&self) -> Response<Body> {
Html(self.render_with_theme()).into_response()
}
}
#[cfg(test)]
mod tests {
use super::extract_html_parts;
#[test]
fn extract_html_parts_returns_head_and_body() {
let html = "<html><head><title>Test</title></head><body><h1>Hi</h1></body></html>";
let (head, body) = extract_html_parts(html);
assert_eq!(head, "<title>Test</title>");
assert_eq!(body, "<h1>Hi</h1>");
}
#[test]
fn extract_html_parts_handles_whitespace() {
let html =
"<html><head>\n<meta charset=\"utf-8\">\n</head><body>\n<p>Test</p>\n</body></html>";
let (head, body) = extract_html_parts(html);
assert_eq!(head, "\n<meta charset=\"utf-8\">\n");
assert_eq!(body, "\n<p>Test</p>\n");
}
}