Version HTML5 asset URLs
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from html import escape
|
from html import escape
|
||||||
|
from pathlib import Path
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
_HTML5_ASSETS_DIR = Path(__file__).resolve().parent / "static" / "html5"
|
||||||
|
|
||||||
|
|
||||||
def _page(title: str, body: str) -> str:
|
def _page(title: str, body: str) -> str:
|
||||||
return f"""<!doctype html>
|
return f"""<!doctype html>
|
||||||
@@ -11,14 +14,23 @@ def _page(title: str, body: str) -> str:
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>{escape(title)}</title>
|
<title>{escape(title)}</title>
|
||||||
<link rel="stylesheet" href="/html5/assets/html5.css" />
|
<link rel="stylesheet" href="{_asset_url("html5.css")}" />
|
||||||
<script defer src="/html5/assets/htmx.min.js"></script>
|
<script defer src="{_asset_url("htmx.min.js")}"></script>
|
||||||
<script defer src="/html5/assets/htmx-ext-sse.js"></script>
|
<script defer src="{_asset_url("htmx-ext-sse.js")}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>{body}</body>
|
<body>{body}</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
|
def _asset_url(filename: str) -> str:
|
||||||
|
asset_path = _HTML5_ASSETS_DIR / filename
|
||||||
|
try:
|
||||||
|
version = str(int(asset_path.stat().st_mtime))
|
||||||
|
except OSError:
|
||||||
|
version = "dev"
|
||||||
|
return f"/html5/assets/{quote(filename)}?v={version}"
|
||||||
|
|
||||||
|
|
||||||
def _project_link(project: object, active_project_id: str) -> str:
|
def _project_link(project: object, active_project_id: str) -> str:
|
||||||
project_id = str(getattr(project, "project_id", ""))
|
project_id = str(getattr(project, "project_id", ""))
|
||||||
name = str(getattr(project, "name", project_id))
|
name = str(getattr(project, "name", project_id))
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ _HTML5_ASSETS_DIR = Path(__file__).resolve().parent / "static" / "html5"
|
|||||||
class Html5StaticFiles(StaticFiles):
|
class Html5StaticFiles(StaticFiles):
|
||||||
def file_response(self, *args, **kwargs):
|
def file_response(self, *args, **kwargs):
|
||||||
response = super().file_response(*args, **kwargs)
|
response = super().file_response(*args, **kwargs)
|
||||||
response.headers.setdefault("Cache-Control", "public, max-age=3600")
|
response.headers.setdefault("Cache-Control", "public, max-age=86400")
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ def assert_html5_contract(text: str, *markers: str, full_page: bool = False) ->
|
|||||||
if full_page:
|
if full_page:
|
||||||
assert "<!doctype html>" in text
|
assert "<!doctype html>" in text
|
||||||
assert "<style>" not in text
|
assert "<style>" not in text
|
||||||
assert "/html5/assets/html5.css" in text
|
assert re.search(r'/html5/assets/html5\.css\?v=[^"]+', text)
|
||||||
assert "/html5/assets/htmx.min.js" in text
|
assert re.search(r'/html5/assets/htmx\.min\.js\?v=[^"]+', text)
|
||||||
assert "/html5/assets/htmx-ext-sse.js" in text
|
assert re.search(r'/html5/assets/htmx-ext-sse\.js\?v=[^"]+', text)
|
||||||
else:
|
else:
|
||||||
assert "<html" not in text
|
assert "<html" not in text
|
||||||
for marker in markers:
|
for marker in markers:
|
||||||
@@ -152,9 +152,9 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
assert 'hx-swap="outerHTML"' in editor.text
|
assert 'hx-swap="outerHTML"' in editor.text
|
||||||
assert "hx-ext=\"sse\"" in editor.text
|
assert "hx-ext=\"sse\"" in editor.text
|
||||||
assert f"sse-connect=\"/html5/projects/{project_id}/events\"" in editor.text
|
assert f"sse-connect=\"/html5/projects/{project_id}/events\"" in editor.text
|
||||||
assert '/html5/assets/html5.css' in editor.text
|
assert re.search(r'/html5/assets/html5\.css\?v=[^"]+', editor.text)
|
||||||
assert '/html5/assets/htmx.min.js' in editor.text
|
assert re.search(r'/html5/assets/htmx\.min\.js\?v=[^"]+', editor.text)
|
||||||
assert '/html5/assets/htmx-ext-sse.js' in editor.text
|
assert re.search(r'/html5/assets/htmx-ext-sse\.js\?v=[^"]+', editor.text)
|
||||||
assert "unpkg.com" not in editor.text
|
assert "unpkg.com" not in editor.text
|
||||||
assert "client-js: htmx+sse only" in editor.text
|
assert "client-js: htmx+sse only" in editor.text
|
||||||
css = client.get("/html5/assets/html5.css")
|
css = client.get("/html5/assets/html5.css")
|
||||||
@@ -257,17 +257,17 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
htmx_asset = client.get("/html5/assets/htmx.min.js")
|
htmx_asset = client.get("/html5/assets/htmx.min.js")
|
||||||
assert htmx_asset.status_code == 200
|
assert htmx_asset.status_code == 200
|
||||||
assert "javascript" in htmx_asset.headers["content-type"]
|
assert "javascript" in htmx_asset.headers["content-type"]
|
||||||
assert htmx_asset.headers["cache-control"] == "public, max-age=3600"
|
assert htmx_asset.headers["cache-control"] == "public, max-age=86400"
|
||||||
assert "htmx" in htmx_asset.text
|
assert "htmx" in htmx_asset.text
|
||||||
sse_asset = client.get("/html5/assets/htmx-ext-sse.js")
|
sse_asset = client.get("/html5/assets/htmx-ext-sse.js")
|
||||||
assert sse_asset.status_code == 200
|
assert sse_asset.status_code == 200
|
||||||
assert "javascript" in sse_asset.headers["content-type"]
|
assert "javascript" in sse_asset.headers["content-type"]
|
||||||
assert sse_asset.headers["cache-control"] == "public, max-age=3600"
|
assert sse_asset.headers["cache-control"] == "public, max-age=86400"
|
||||||
assert "sse" in sse_asset.text
|
assert "sse" in sse_asset.text
|
||||||
css_asset = client.get("/html5/assets/html5.css")
|
css_asset = client.get("/html5/assets/html5.css")
|
||||||
assert css_asset.status_code == 200
|
assert css_asset.status_code == 200
|
||||||
assert "text/css" in css_asset.headers["content-type"]
|
assert "text/css" in css_asset.headers["content-type"]
|
||||||
assert css_asset.headers["cache-control"] == "public, max-age=3600"
|
assert css_asset.headers["cache-control"] == "public, max-age=86400"
|
||||||
assert ".workspace" in css_asset.text
|
assert ".workspace" in css_asset.text
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user