Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X4CAujMuib2tDqt9JRg6X
75 lines
3.1 KiB
Python
75 lines
3.1 KiB
Python
"""Versión de los .css y .js propios en cada liga (21-oct-2026).
|
|
|
|
Sin esto, después de un deploy el navegador sigue usando el tablero.css o el kanban.js anteriores
|
|
un buen rato: el nombre del archivo no cambia y el servidor no le pide revisarlo. Pasó el 21-oct: la
|
|
página de inicio nueva salió con la ruta a producción sin estilos hasta recargar a la fuerza.
|
|
|
|
Aquí, al construir, cada liga a un .css o .js que vive en docs/ recibe ?v=<huella del archivo>. Si el
|
|
archivo cambió, la dirección cambia y el navegador lo baja otra vez; si no cambió, sigue en caché.
|
|
Se aplica al HTML de las páginas de MkDocs (on_post_page) y a las páginas sueltas de docs/
|
|
(formularios, cuenta, admin, salir…, en on_post_build). Los archivos de docs/ no se tocan.
|
|
Los de Material ya traen su huella en el nombre (main.<huella>.min.css) y no se tocan.
|
|
"""
|
|
import hashlib
|
|
import logging
|
|
import os
|
|
import posixpath
|
|
import re
|
|
|
|
log = logging.getLogger("mkdocs.hooks.versiones")
|
|
_HUELLAS = {}
|
|
# href="…x.css" o src="…x.js" sin parámetros (si ya traen ?algo, se respetan)
|
|
_LIGA = re.compile(r'(\b(?:href|src)=")([^"#?]+\.(?:css|js))(")')
|
|
|
|
|
|
def on_pre_build(config, **kwargs):
|
|
_HUELLAS.clear()
|
|
docs = config["docs_dir"]
|
|
for raiz, _, archivos in os.walk(docs):
|
|
for f in archivos:
|
|
if f.endswith((".css", ".js")):
|
|
ruta = os.path.join(raiz, f)
|
|
with open(ruta, "rb") as fh:
|
|
_HUELLAS[os.path.relpath(ruta, docs).replace(os.sep, "/")] = hashlib.sha256(fh.read()).hexdigest()[:10]
|
|
|
|
|
|
def _base(url_pagina):
|
|
u = "/" + (url_pagina or "")
|
|
return u if u.endswith("/") else posixpath.dirname(u) + "/"
|
|
|
|
|
|
def _marcar(html, base):
|
|
def cambia(m):
|
|
url = m.group(2)
|
|
if url.startswith(("http:", "https:", "//", "data:")):
|
|
return m.group(0)
|
|
rel = (url if url.startswith("/") else posixpath.normpath(posixpath.join(base, url))).lstrip("/")
|
|
huella = _HUELLAS.get(rel)
|
|
return m.group(1) + url + "?v=" + huella + m.group(3) if huella else m.group(0)
|
|
return _LIGA.sub(cambia, html)
|
|
|
|
|
|
def on_post_page(output, page, config, **kwargs):
|
|
return _marcar(output, _base(page.url))
|
|
|
|
|
|
def on_post_build(config, **kwargs):
|
|
# páginas sueltas: el HTML de docs/ que MkDocs copia tal cual (formularios, cuenta, redirecciones…)
|
|
docs, site, n = config["docs_dir"], config["site_dir"], 0
|
|
for raiz, _, archivos in os.walk(docs):
|
|
for f in archivos:
|
|
if not f.endswith(".html"):
|
|
continue
|
|
rel = os.path.relpath(os.path.join(raiz, f), docs).replace(os.sep, "/")
|
|
destino = os.path.join(site, rel)
|
|
if not os.path.isfile(destino):
|
|
continue
|
|
with open(destino, encoding="utf-8") as fh:
|
|
html = fh.read()
|
|
nuevo = _marcar(html, _base(rel))
|
|
if nuevo != html:
|
|
with open(destino, "w", encoding="utf-8") as fh:
|
|
fh.write(nuevo)
|
|
n += 1
|
|
log.info("versiones: %d archivos .css/.js con huella; %d páginas sueltas marcadas", len(_HUELLAS), n)
|