1
Fork 0
mkdocs-site/hooks/static.py

81 lines
2.4 KiB
Python

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, get_plugin_logger
import hashlib
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))
env.add_extension(make_sri_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)
if file is None:
raise ValueError(f"Unable to find static file for {filename!r}")
return f"/{file.url}"
return StaticExtension
def make_sri_extension(files: Files):
class SRIExtension(StandaloneTag):
tags = {"sri_integrity"}
def render(self, filename):
file = files.get_file_from_path(filename)
if file is None:
raise ValueError(f"Unable to find static file for {filename!r}")
with open(file.abs_src_path, "rb") as f:
digest = hashlib.file_digest(f, "sha256").hexdigest()
return f"sha256-{digest}"
return SRIExtension