use axum::{
http::{HeaderValue, header},
response::{IntoResponse, Response},
};
pub const DATASTAR_VERSION: &str = "1.0.1";
pub const PICO_VERSION: &str = "2.1.1";
pub const PICO_PRESET: &str = "pumpkin";
const DATASTAR_JS: &[u8] = include_bytes!("../../assets/datastar.js");
const PICO_CSS: &[u8] = include_bytes!("../../assets/pico.pumpkin.min.css");
const APP_CSS: &[u8] = include_bytes!("../../assets/app.css");
const ICON_PNG: &[u8] = include_bytes!("../../assets/icon.png");
const IMMUTABLE: &str = "public, max-age=31536000, immutable";
pub struct Assets;
impl Assets {
pub async fn datastar_js() -> Response {
Self::serve(DATASTAR_JS, "text/javascript; charset=utf-8")
}
pub async fn pico_css() -> Response {
Self::serve(PICO_CSS, "text/css; charset=utf-8")
}
pub async fn app_css() -> Response {
Self::serve(APP_CSS, "text/css; charset=utf-8")
}
pub async fn icon_png() -> Response {
Self::serve(ICON_PNG, "image/png")
}
fn serve(body: &'static [u8], content_type: &'static str) -> Response {
(
[
(header::CONTENT_TYPE, HeaderValue::from_static(content_type)),
(header::CACHE_CONTROL, HeaderValue::from_static(IMMUTABLE)),
],
body,
)
.into_response()
}
}
#[cfg(test)]
mod tests {
use super::*;
use axum::http::StatusCode;
#[test]
fn assets_are_non_empty() {
assert!(!DATASTAR_JS.is_empty(), "datastar.js must be embedded");
assert!(!PICO_CSS.is_empty(), "pico css must be embedded");
assert!(!APP_CSS.is_empty(), "app.css must be embedded");
assert!(!ICON_PNG.is_empty(), "icon.png must be embedded");
}
#[test]
fn datastar_asset_matches_pinned_version() {
let head = std::str::from_utf8(&DATASTAR_JS[..64]).unwrap_or("");
assert!(
head.contains(DATASTAR_VERSION),
"datastar.js banner must contain {DATASTAR_VERSION}, got: {head:?}"
);
}
#[test]
fn pico_asset_matches_pinned_version() {
let head = std::str::from_utf8(&PICO_CSS[..160]).unwrap_or("");
assert!(
head.contains(PICO_VERSION),
"pico css banner must contain {PICO_VERSION}"
);
}
#[tokio::test]
async fn serve_sets_content_type_and_cache_headers() {
let resp = Assets::app_css().await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
"text/css; charset=utf-8"
);
assert_eq!(
resp.headers().get(header::CACHE_CONTROL).unwrap(),
IMMUTABLE
);
}
}