diff --git a/Cargo.lock b/Cargo.lock
@@ -1855,10 +1855,12 @@ dependencies = [
"md5",
"moka",
"nom",
+ "once_cell",
"parking_lot 0.12.1",
"path-clean",
"rsass",
"serde",
+ "sha2",
"sled",
"syntect",
"time",
@@ -2062,6 +2064,17 @@ dependencies = [
"digest",
]
+[[package]]
+name = "sha2"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "sharded-slab"
version = "0.1.4"
diff --git a/Cargo.toml b/Cargo.toml
@@ -25,9 +25,11 @@ humantime = "2.1"
nom = "7.1"
md5 = "0.7"
moka = { version = "0.11.1", features = ["future"] }
+once_cell = "1.18"
path-clean = "1.0.1"
parking_lot = "0.12"
serde = { version = "1.0", features = ["derive"] }
+sha2 = "0.10"
syntect = "5"
sled = { version = "0.34", features = ["compression"] }
time = { version = "0.3", features = ["serde"] }
diff --git a/src/main.rs b/src/main.rs
@@ -20,6 +20,9 @@ use axum::{
};
use bat::assets::HighlightingAssets;
use clap::Parser;
+use once_cell::sync::{Lazy, OnceCell};
+use sha2::digest::FixedOutput;
+use sha2::Digest;
use sled::Db;
use syntect::html::ClassStyle;
use tokio::{
@@ -40,6 +43,12 @@ mod syntax_highlight;
const CRATE_VERSION: &str = clap::crate_version!();
+static GLOBAL_CSS: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/statics/css/style.css",));
+static GLOBAL_CSS_HASH: Lazy<Box<str>> = Lazy::new(|| build_asset_hash(GLOBAL_CSS));
+
+static HIGHLIGHT_CSS_HASH: OnceCell<Box<str>> = OnceCell::new();
+static DARK_HIGHLIGHT_CSS_HASH: OnceCell<Box<str>> = OnceCell::new();
+
#[derive(Parser, Debug)]
#[clap(author, version, about)]
pub struct Args {
@@ -114,6 +123,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.into_boxed_str()
.into_boxed_bytes(),
);
+ HIGHLIGHT_CSS_HASH.set(build_asset_hash(css)).unwrap();
let dark_theme = bat_assets.get_theme("TwoDark");
let dark_css =
@@ -123,6 +133,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.into_boxed_str()
.into_boxed_bytes(),
);
+ DARK_HIGHLIGHT_CSS_HASH
+ .set(build_asset_hash(dark_css))
+ .unwrap();
let static_favicon = |content: &'static [u8]| {
move || async move {
@@ -149,14 +162,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let app = Router::new()
.route("/", get(methods::index::handle))
.route(
- "/style.css",
- get(static_css(include_bytes!(concat!(
- env!("OUT_DIR"),
- "/statics/css/style.css"
- )))),
+ &format!("/style-{}.css", *GLOBAL_CSS_HASH),
+ get(static_css(GLOBAL_CSS)),
+ )
+ .route(
+ &format!("/highlight-{}.css", HIGHLIGHT_CSS_HASH.get().unwrap()),
+ get(static_css(css)),
+ )
+ .route(
+ &format!(
+ "/highlight-dark-{}.css",
+ DARK_HIGHLIGHT_CSS_HASH.get().unwrap()
+ ),
+ get(static_css(dark_css)),
)
- .route("/highlight.css", get(static_css(css)))
- .route("/highlight-dark.css", get(static_css(dark_css)))
.route(
"/favicon.ico",
get(static_favicon(include_bytes!("../statics/favicon.ico"))),
@@ -223,6 +242,15 @@ async fn run_indexer(
.await
}
+#[must_use]
+pub fn build_asset_hash(v: &[u8]) -> Box<str> {
+ let mut hasher = sha2::Sha256::default();
+ hasher.update(v);
+ let mut out = hex::encode(hasher.finalize_fixed());
+ out.truncate(10);
+ Box::from(out)
+}
+
#[instrument(skip(t))]
pub fn into_response<T: Template>(t: &T) -> Response {
match t.render() {
diff --git a/templates/base.html b/templates/base.html
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>{% block title %}rgit{% endblock %}</title>
- <link rel="stylesheet" type="text/css" href="/style.css" />
+ <link rel="stylesheet" type="text/css" href="/style-{{ crate::GLOBAL_CSS_HASH.as_ref() }}.css" />
{%- block head -%}{%- endblock %}
</head>
diff --git a/templates/repo/about.html b/templates/repo/about.html
@@ -3,8 +3,8 @@
{% block head -%}
{%- if let Some(readme) = readme -%}
{%- if readme.0 == crate::git::ReadmeFormat::Markdown %}
- <link rel="stylesheet" type="text/css" href="/highlight.css" />
- <link rel="stylesheet" type="text/css" href="/highlight-dark.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-{{ crate::HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-dark-{{ crate::DARK_HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
{%- endif -%}
{%- endif -%}
{% endblock %}
diff --git a/templates/repo/commit.html b/templates/repo/commit.html
@@ -1,8 +1,8 @@
{% extends "repo/base.html" %}
{% block head %}
- <link rel="stylesheet" type="text/css" href="/highlight.css" />
- <link rel="stylesheet" type="text/css" href="/highlight-dark.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-{{ crate::HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-dark-{{ crate::DARK_HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
{%- endblock %}
{% block commit_nav_class %}active{% endblock %}
diff --git a/templates/repo/diff.html b/templates/repo/diff.html
@@ -1,8 +1,8 @@
{% extends "repo/base.html" %}
{%- block head %}
- <link rel="stylesheet" type="text/css" href="/highlight.css" />
- <link rel="stylesheet" type="text/css" href="/highlight-dark.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-{{ crate::HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-dark-{{ crate::DARK_HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
{%- endblock -%}
{% block diff_nav_class %}active{% endblock %}
diff --git a/templates/repo/file.html b/templates/repo/file.html
@@ -1,8 +1,8 @@
{% extends "repo/base.html" %}
{% block head %}
- <link rel="stylesheet" type="text/css" href="/highlight.css" />
- <link rel="stylesheet" type="text/css" href="/highlight-dark.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-{{ crate::HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
+ <link rel="stylesheet" type="text/css" href="/highlight-dark-{{ crate::DARK_HIGHLIGHT_CSS_HASH.get().unwrap() }}.css" />
{%- endblock %}
{% block tree_nav_class %}active{% endblock %}