Refine dateline format; fix stale page caching breaking theme hot swap
Dateline is now '1 Jan 2026', with ' – edited 3 Jan 2026' appended only when the last edit came at least 24h after publishing. The Last-Modified header added heuristic browser caching of pages (no Cache-Control was sent), so the site editor's re-fetch after a theme change served the cached page with the old stylesheet link. Pages now send 'Cache-Control: no-cache' — always revalidate, still cheap via the ETag.
This commit is contained in:
+13
-3
@@ -668,13 +668,20 @@ async def show_page(request: Request, path: str) -> HTMLResponse | Response:
|
||||
node = chain[-1] if chain else None
|
||||
if node is not None and node.published and node.content is not None:
|
||||
# ETag on content + render version; clients revalidate cheaply,
|
||||
# which keeps prefetched pages warm and current.
|
||||
# which keeps prefetched pages warm and current. no-cache forces
|
||||
# that revalidation: with Last-Modified but no Cache-Control,
|
||||
# browsers would otherwise cache heuristically and serve stale
|
||||
# pages (e.g. after a theme change) without asking us at all.
|
||||
etag = f'"{path}@{node.modified.timestamp()}v{data.version}"'
|
||||
if request.headers.get("if-none-match") == etag:
|
||||
return Response(status_code=304)
|
||||
return HTMLResponse(
|
||||
views.render_page(data.menu, path, data.brand, data.custom_css, data.theme, data.favicon),
|
||||
headers={"etag": etag, "last-modified": _http_date(node.modified)},
|
||||
headers={
|
||||
"etag": etag,
|
||||
"last-modified": _http_date(node.modified),
|
||||
"cache-control": "no-cache",
|
||||
},
|
||||
)
|
||||
if node is not None and node.published and node.content is None:
|
||||
# Category label without a landing page: placeholder with the pen
|
||||
@@ -682,7 +689,10 @@ async def show_page(request: Request, path: str) -> HTMLResponse | Response:
|
||||
return HTMLResponse(
|
||||
views.render_category(data.menu, path, data.brand, data.custom_css, data.theme, data.favicon),
|
||||
404,
|
||||
headers={"last-modified": _http_date(node.modified)},
|
||||
headers={
|
||||
"last-modified": _http_date(node.modified),
|
||||
"cache-control": "no-cache",
|
||||
},
|
||||
)
|
||||
if node is None and not path:
|
||||
# No front page (no top-level node with slug ""): "/" opens the
|
||||
|
||||
@@ -20,7 +20,7 @@ classes, e.g. `{.right}`.
|
||||
"""
|
||||
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from markdown_it import MarkdownIt
|
||||
from markdown_it.common.utils import escapeHtml
|
||||
@@ -156,13 +156,12 @@ def render(
|
||||
|
||||
|
||||
def _dateline(created: datetime, modified: datetime | None) -> str:
|
||||
"""Published/updated line for the ``{dates}`` tag. The updated date is
|
||||
shown only when it falls on a later day than the publication."""
|
||||
pub = f'<time datetime="{created.isoformat()}">{created.day} {created:%B %Y}</time>'
|
||||
out = f"Published {pub}"
|
||||
if modified is not None and modified.date() > created.date():
|
||||
upd = f'<time datetime="{modified.isoformat()}">{modified.day} {modified:%B %Y}</time>'
|
||||
out += f", updated {upd}"
|
||||
"""Dateline for the ``{dates}`` tag: "1 Jan 2026", plus
|
||||
" – edited 3 Jan 2026" when the last edit came >= 24h after
|
||||
publishing (quick fixes right after posting stay unmentioned)."""
|
||||
out = f'<time datetime="{created.isoformat()}">{created.day} {created:%b %Y}</time>'
|
||||
if modified is not None and modified - created >= timedelta(hours=24):
|
||||
out += f' – edited <time datetime="{modified.isoformat()}">{modified.day} {modified:%b %Y}</time>'
|
||||
return f'<p class="dateline">{out}</p>'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user