From ed8c42ce86df88b9c2b9da5dbcc1d178824896e1 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Mon, 11 Sep 2023 22:49:52 +0100 Subject: [PATCH] Add cachebust hash to static files --- hooks/static.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 59 insertions(+) create mode 100644 hooks/static.py diff --git a/hooks/static.py b/hooks/static.py new file mode 100644 index 0000000..7a3e47f --- /dev/null +++ b/hooks/static.py @@ -0,0 +1,58 @@ +from jinja2_simple_tags import StandaloneTag +import jinja2 +from copy import deepcopy +from mkdocs.structure.files import File, Files +from mkdocs.plugins import event_priority +import hashlib +from mkdocs.plugins import get_plugin_logger +from concurrent.futures import ThreadPoolExecutor +from pathlib import Path + +logger = get_plugin_logger("static") + + +def transform_file_url(url: str, hash: str): + url_path = Path(url) + return str(url_path.with_stem(url_path.stem + "." + hash[:10])) + +def hash_file(file: File) -> File: + logger.debug("Hashing %s", file.url) + + hashed_file = deepcopy(file) + + with open(file.abs_src_path, "rb") as f: + digest = hashlib.file_digest(f, "md5").hexdigest() + + hashed_file.abs_dest_path = transform_file_url(hashed_file.abs_dest_path, digest) + hashed_file.dest_uri = transform_file_url(hashed_file.dest_uri, digest) + hashed_file.url = transform_file_url(hashed_file.url, digest) + + return hashed_file + +@event_priority(-100) +def on_files(files: Files, config): + with ThreadPoolExecutor() as executor: + for hashed_file in executor.map(hash_file, files.media_files()): + files.append(hashed_file) + + # HACK: Add a fake file with a `src_uri` of the hashed path so other integrations can find the right file + hashed_src_file = deepcopy(hashed_file) + hashed_src_file.src_uri = hashed_src_file.dest_uri + files.append(hashed_src_file) + + return files + +def on_env(env: jinja2.Environment, config, files): + env.add_extension(make_static_extension(files)) + + return env + +def make_static_extension(files: Files): + class StaticExtension(StandaloneTag): + tags = {"static"} + + def render(self, filename): + file = files.get_file_from_path(filename) + return file.url + + return StaticExtension diff --git a/mkdocs.yml b/mkdocs.yml index 802edd1..becef87 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,6 +12,7 @@ hooks: - hooks/tags.py - hooks/images.py - hooks/page-render.py + - hooks/static.py markdown_extensions: - attr_list