From 853b288663c53917be3cc408f5523b2109d0ce01 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Tue, 26 May 2026 04:25:32 +0300 Subject: [PATCH] Add automatic CSS and JS cache busting in CI. Hash site stylesheets and gallery.js before each Jekyll build, append the version as a query string in the layout, and ignore the generated assets data file. --- .github/workflows/jekyll.yml | 3 +++ .gitignore | 1 + README.md | 10 ++++++++++ _layouts/default.html | 7 ++++--- script/asset_version.py | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 script/asset_version.py diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml index 7902876..0104ba7 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll.yml @@ -30,6 +30,9 @@ jobs: - name: Check WebP derivatives run: python script/generate_webp.py --check + - name: Generate asset version + run: python script/asset_version.py + - name: Setup Pages uses: actions/configure-pages@v5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7f5ac8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +_data/assets.yml diff --git a/README.md b/README.md index fcb767f..017a867 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,13 @@ python script/generate_webp.py ``` CI runs `python script/generate_webp.py --check` to ensure WebP copies are present and up to date. Commit the generated `.webp` files with your image changes. + +### CSS/JS cache busting + +CI runs `python script/asset_version.py` before each Jekyll build. It hashes `css/style.css`, `css/github_markdown.css`, and `js/gallery.js`, then writes `_data/assets.yml`. Layout templates append `?v=` that hash to stylesheet and script URLs so browsers fetch new copies when those files change. + +For a local Jekyll preview, run the same script first: + +```bash +python script/asset_version.py +``` diff --git a/_layouts/default.html b/_layouts/default.html index a41d1b7..711f509 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -44,8 +44,9 @@ - - + {% assign assets_version = site.data.assets.assets_version | default: 'dev' %} + + @@ -140,7 +141,7 @@

Videos

{% if page.images %} - + {% endif %} diff --git a/script/asset_version.py b/script/asset_version.py new file mode 100644 index 0000000..98b6e23 --- /dev/null +++ b/script/asset_version.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Write _data/assets.yml with a content hash for CSS/JS cache busting.""" + +from __future__ import annotations + +import hashlib +import sys +from pathlib import Path + +ASSET_FILES = ( + Path("css/style.css"), + Path("css/github_markdown.css"), + Path("js/gallery.js"), +) +OUTPUT = Path("_data/assets.yml") + + +def main() -> int: + hasher = hashlib.sha256() + + for path in ASSET_FILES: + if not path.is_file(): + print(f"Missing asset file: {path}", file=sys.stderr) + return 1 + hasher.update(path.read_bytes()) + hasher.update(b"\0") + + version = hasher.hexdigest()[:8] + OUTPUT.parent.mkdir(exist_ok=True) + OUTPUT.write_text(f'assets_version: "{version}"\n', encoding="utf-8") + print(f"Wrote {OUTPUT} (assets_version: {version})") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())