use rustlavel_core::Config;
use rustlavel_http::plugin::{Plugin, Setup};
use rustlavel_http::{Request, Response};
pub const CHART_JS: &str = include_str!("../assets/chart.umd.js");
pub const INIT_JS: &str = include_str!("../assets/rustlavel-chart.js");
pub const CHART_JS_PATH: &str = "/vendor/chart/chart.umd.js";
pub const INIT_JS_PATH: &str = "/vendor/chart/rustlavel-chart.js";
pub const CHART_JS_VERSION: &str = "4.5.1";
pub struct Charts {
prefix: String,
}
impl Default for Charts {
fn default() -> Charts {
Charts { prefix: "/vendor/chart".to_string() }
}
}
impl Charts {
pub fn at(prefix: impl Into<String>) -> Charts {
Charts { prefix: prefix.into().trim_end_matches('/').to_string() }
}
}
impl Plugin for Charts {
fn name(&self) -> &'static str {
"charts"
}
fn register(self: Box<Self>, setup: &mut Setup<'_>) {
let immutable = immutable_caching(setup.config);
setup.router.get(&format!("{}/chart.umd.js", self.prefix), move |_: Request| async move {
script(CHART_JS, immutable)
});
setup.router.get(&format!("{}/rustlavel-chart.js", self.prefix), move |_: Request| async move {
script(INIT_JS, immutable)
});
}
}
fn immutable_caching(config: &Config) -> bool {
config.is_production()
}
fn script(body: &'static str, immutable: bool) -> Response {
let response = Response::ok()
.with_body(body)
.with_header("content-type", "text/javascript; charset=utf-8");
if immutable {
return response.with_header("cache-control", "public, max-age=31536000, immutable");
}
response.with_header("cache-control", "no-cache")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_vendored_library_is_the_version_the_constant_claims() {
let banner: String = CHART_JS.lines().take(6).collect::<Vec<_>>().join("\n");
assert!(
banner.contains(&format!("Chart.js v{CHART_JS_VERSION}")),
"the vendored file is not v{CHART_JS_VERSION}: {banner}"
);
assert!(banner.contains("MIT"), "the copyright banner was stripped: {banner}");
}
#[test]
fn the_licence_travels_with_the_library() {
let licence = include_str!("../assets/LICENSE-chart.js.md");
assert!(licence.contains("MIT License"), "{licence}");
assert!(licence.contains("Chart.js Contributors"));
}
#[test]
fn nothing_is_fetched_from_a_cdn() {
for script in [INIT_JS, CHART_JS] {
for host in ["cdn.jsdelivr.net", "unpkg.com", "cdnjs.cloudflare.com"] {
assert!(!script.contains(host), "a vendored script still reaches {host}");
}
}
}
#[test]
fn the_default_mount_matches_the_published_paths() {
let charts = Charts::default();
assert_eq!(format!("{}/chart.umd.js", charts.prefix), CHART_JS_PATH);
assert_eq!(format!("{}/rustlavel-chart.js", charts.prefix), INIT_JS_PATH);
}
#[test]
fn a_custom_mount_drops_a_trailing_slash() {
assert_eq!(Charts::at("/static/charts/").prefix, "/static/charts");
}
}