OXYGENHUB
◆ wiki-says-so oxygenhub / crates / hub / src / web / statics.rs
3.5 KiB · Rust · last changed Mermaid diagrams in Markdown 1 month ago source blame history raw
1
//! Compiled-in static assets: the stylesheet, fonts and icons.
2
3
use axum::extract::Path;
4
use axum::http::{header, StatusCode};
5
use axum::response::{IntoResponse, Response};
6
7
const CSS: &str = include_str!("../../../../templates/style.css");
8
const FAVICON: &str = include_str!("../../../../assets/icons/oxygenhub.svg");
9
10
/// A short hash of the stylesheets and script the pages link, put in their
11
/// URLs (`?v=…`): they are served for a long time and cached by any proxy
12
/// in front of the hub (Cloudflare held a day-old stylesheet), so a new
13
/// version must have a new URL.
14
pub fn assets_version() -> &'static str {
15
    static V: std::sync::OnceLock<String> = std::sync::OnceLock::new();
16
    V.get_or_init(|| {
17
        let mut h = blake3::Hasher::new();
18
        h.update(CSS.as_bytes());
19
        for a in ASSETS.iter().filter(|a| a.path == "github.css" || a.path == "hub.js") {
20
            h.update(a.bytes);
21
        }
22
        h.finalize().to_hex()[..12].to_string()
23
    })
24
}
25
26
struct Asset {
27
    path: &'static str,
28
    mime: &'static str,
29
    bytes: &'static [u8],
30
}
31
32
const ASSETS: &[Asset] = &[
33
    Asset { path: "fonts/Barlow-300.woff2", mime: "font/woff2", bytes: include_bytes!("../../../../assets/fonts/Barlow-300.woff2") },
34
    Asset { path: "fonts/Barlow-400.woff2", mime: "font/woff2", bytes: include_bytes!("../../../../assets/fonts/Barlow-400.woff2") },
35
    Asset { path: "fonts/Barlow-500.woff2", mime: "font/woff2", bytes: include_bytes!("../../../../assets/fonts/Barlow-500.woff2") },
36
    Asset { path: "fonts/Barlow-600.woff2", mime: "font/woff2", bytes: include_bytes!("../../../../assets/fonts/Barlow-600.woff2") },
37
    Asset {
38
        path: "fonts/PressStart2P-400.woff2",
39
        mime: "font/woff2",
40
        bytes: include_bytes!("../../../../assets/fonts/PressStart2P-400.woff2"),
41
    },
42
    Asset { path: "github.css", mime: "text/css; charset=utf-8", bytes: include_bytes!("../../../../assets/github.css") },
43
    Asset { path: "hub.js", mime: "text/javascript; charset=utf-8", bytes: include_bytes!("../../../../assets/hub.js") },
44
    Asset {
45
        path: "vendor/editor.js",
46
        mime: "text/javascript; charset=utf-8",
47
        bytes: include_bytes!("../../../../assets/vendor/editor.js"),
48
    },
49
    Asset {
50
        path: "vendor/easymde.min.js",
51
        mime: "text/javascript; charset=utf-8",
52
        bytes: include_bytes!("../../../../assets/vendor/easymde.min.js"),
53
    },
54
    // Mermaid 12.1.0 (MIT, assets/vendor/mermaid.LICENSE), from npm's
55
    // mermaid package, dist/mermaid.min.js; loaded only by pages with a
56
    // diagram.
57
    Asset {
58
        path: "vendor/mermaid.min.js",
59
        mime: "text/javascript; charset=utf-8",
60
        bytes: include_bytes!("../../../../assets/vendor/mermaid.min.js"),
61
    },
62
    Asset {
63
        path: "vendor/easymde.min.css",
64
        mime: "text/css; charset=utf-8",
65
        bytes: include_bytes!("../../../../assets/vendor/easymde.min.css"),
66
    },
67
];
68
69
const CACHE: &str = "public, max-age=86400";
70
71
pub async fn style() -> Response {
72
    ([(header::CONTENT_TYPE, "text/css; charset=utf-8"), (header::CACHE_CONTROL, CACHE)], CSS).into_response()
73
}
74
75
pub async fn favicon() -> Response {
76
    ([(header::CONTENT_TYPE, "image/svg+xml"), (header::CACHE_CONTROL, CACHE)], FAVICON).into_response()
77
}
78
79
pub async fn asset(Path(path): Path<String>) -> Response {
80
    match ASSETS.iter().find(|a| a.path == path) {
81
        Some(a) => {
82
            ([(header::CONTENT_TYPE, a.mime), (header::CACHE_CONTROL, "public, max-age=31536000, immutable")], a.bytes).into_response()
83
        }
84
        None => StatusCode::NOT_FOUND.into_response(),
85
    }
86
}