use std::path::Path; use actix_web::{get, http::StatusCode, web, HttpResponse, ResponseError}; use exun::{Expect, ResultErrorExt}; use grass::OutputStyle; use path_clean::clean; use raise::yeet; use serde::Serialize; use thiserror::Error; fn output_style() -> OutputStyle { if cfg!(debug_assertions) { OutputStyle::Expanded } else { OutputStyle::Compressed } } fn options() -> grass::Options<'static> { grass::Options::default() .load_path("static/style") .style(output_style()) } #[derive(Debug, Clone, Error, Serialize)] pub enum LoadStyleError { #[error("The requested stylesheet was not found")] FileNotFound(Box), } impl ResponseError for LoadStyleError { fn status_code(&self) -> StatusCode { match self { Self::FileNotFound(..) => StatusCode::NOT_FOUND, } } } pub fn load(stylesheet: &str) -> Result> { let options = options(); let path = clean(format!("static/style/{}.scss", stylesheet)); if !path.exists() { yeet!(LoadStyleError::FileNotFound(path.into()).into()); } let css = grass::from_path(format!("static/style/{}.scss", stylesheet), &options).unexpect()?; Ok(css) } #[get("/{stylesheet}.css")] pub async fn get_css(stylesheet: web::Path>) -> Result { let css = load(&stylesheet).map_err(|e| e.unwrap())?; let response = HttpResponse::Ok().content_type("text/css").body(css); Ok(response) }