From 6e3e8f037d7a5a5fb6bc522eff0157935f3309dc Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Thu, 16 Feb 2023 15:03:29 +0200 Subject: [PATCH] Append a hash ?digest to CSS files for cache-busting --- python_docs_theme/__init__.py | 51 +++++++++++++++++++++++++++++++++++ python_docs_theme/theme.conf | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py index 407d62a..62b16f0 100644 --- a/python_docs_theme/__init__.py +++ b/python_docs_theme/__init__.py @@ -1,4 +1,53 @@ +import hashlib import os +from functools import lru_cache +from pathlib import Path +from typing import Any, Dict, List + +import sphinx.application +from sphinx.builders.html import StandaloneHTMLBuilder + +THEME_PATH = Path(__file__).parent.resolve() + + +@lru_cache(maxsize=None) +def _asset_hash(path: str) -> str: + """Append a `?digest=` to an url based on the file content.""" + full_path = THEME_PATH / path.replace("_static/", "static/") + digest = hashlib.sha1(full_path.read_bytes()).hexdigest() + + return f"{path}?digest={digest}" + + +def _add_asset_hashes(static: List[str], add_digest_to: List[str]) -> None: + for asset in add_digest_to: + index = static.index(asset) + static[index].filename = _asset_hash(asset) # type: ignore + + +def _html_page_context( + app: sphinx.application.Sphinx, + pagename: str, + templatename: str, + context: Dict[str, Any], + doctree: Any, +) -> None: + if app.config.html_theme != "python_docs_theme": + return + + assert isinstance(app.builder, StandaloneHTMLBuilder) + + if "css_files" in context: + if "_static/pydoctheme.css" not in context["css_files"]: + raise ValueError( + "This documentation is not using `pydoctheme.css` as the stylesheet. " + "If you have set `html_style` in your conf.py file, remove it." + ) + + _add_asset_hashes( + context["css_files"], + ["_static/pydoctheme.css"], + ) def setup(app): @@ -6,6 +55,8 @@ def setup(app): app.add_html_theme( 'python_docs_theme', current_dir) + app.connect("html-page-context", _html_page_context) + return { 'parallel_read_safe': True, 'parallel_write_safe': True, diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf index 11670d3..dfdfdff 100644 --- a/python_docs_theme/theme.conf +++ b/python_docs_theme/theme.conf @@ -1,6 +1,6 @@ [theme] inherit = default -stylesheet = pydoctheme.css?2022.1 +stylesheet = pydoctheme.css pygments_style = default [options]