diff --git a/photomap/backend/photomap_server.py b/photomap/backend/photomap_server.py index 2b32df9f..81067e1d 100644 --- a/photomap/backend/photomap_server.py +++ b/photomap/backend/photomap_server.py @@ -14,6 +14,7 @@ from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates +from starlette.middleware.base import BaseHTTPMiddleware from photomap.backend.args import get_args, get_version from photomap.backend.config import get_config_manager @@ -46,6 +47,23 @@ app.include_router(curation_router, prefix="/api/curation", tags=["curation"]) + +class IECompatibilityMiddleware(BaseHTTPMiddleware): + """Add X-UA-Compatible header to every response. + + This prevents Microsoft Edge and Internet Explorer from switching into + IE Compatibility Mode, which breaks Swiper v11 (SCRIPT1028) and causes + various HTML parsing errors (HTML1416, HTML1500). + """ + + async def dispatch(self, request: Request, call_next): + response = await call_next(request) + response.headers["X-UA-Compatible"] = "IE=edge" + return response + + +app.add_middleware(IECompatibilityMiddleware) + # Mount static files and templates static_path = get_package_resource_path("static") app.mount("/static", StaticFiles(directory=static_path), name="static") diff --git a/photomap/frontend/static/unsupported-browser.html b/photomap/frontend/static/unsupported-browser.html new file mode 100644 index 00000000..69efe78c --- /dev/null +++ b/photomap/frontend/static/unsupported-browser.html @@ -0,0 +1,54 @@ + + + + + + Browser not supported — PhotoMapAI + + + +
+

Browser not supported

+

+ You are using Microsoft Edge (Legacy), which does not + support the modern JavaScript required by PhotoMapAI. +

+

Please upgrade to the new Microsoft Edge (Chromium):

+
    +
  1. + Visit + + microsoft.com/edge + +
  2. +
  3. Click Download and run the installer
  4. +
  5. After installation, open PhotoMapAI in the new Edge
  6. +
+

Chrome and Firefox are also fully supported.

+
+ + diff --git a/photomap/frontend/templates/main.html b/photomap/frontend/templates/main.html index 31718850..a68abd95 100644 --- a/photomap/frontend/templates/main.html +++ b/photomap/frontend/templates/main.html @@ -3,10 +3,27 @@ PhotoMap - + + + + + diff --git a/photomap/frontend/templates/modules/control-panel.html b/photomap/frontend/templates/modules/control-panel.html index 421d016e..759e1fd7 100644 --- a/photomap/frontend/templates/modules/control-panel.html +++ b/photomap/frontend/templates/modules/control-panel.html @@ -1,4 +1,4 @@ - +
diff --git a/photomap/frontend/templates/modules/metadata-drawer.html b/photomap/frontend/templates/modules/metadata-drawer.html index b2060dcf..2cf668c7 100644 --- a/photomap/frontend/templates/modules/metadata-drawer.html +++ b/photomap/frontend/templates/modules/metadata-drawer.html @@ -4,7 +4,7 @@
- +
diff --git a/photomap/frontend/templates/modules/search-panel.html b/photomap/frontend/templates/modules/search-panel.html index 4ebd42a2..ebad8c83 100644 --- a/photomap/frontend/templates/modules/search-panel.html +++ b/photomap/frontend/templates/modules/search-panel.html @@ -1,4 +1,4 @@ - +
Search
diff --git a/photomap/frontend/templates/modules/spinner.html b/photomap/frontend/templates/modules/spinner.html index b454aba1..2f0806c6 100644 --- a/photomap/frontend/templates/modules/spinner.html +++ b/photomap/frontend/templates/modules/spinner.html @@ -19,7 +19,7 @@ to="360 25 25" dur="1s" repeatCount="indefinite" - /> + >
diff --git a/tests/backend/test_app.py b/tests/backend/test_app.py index b7dadc2b..11dcbfa0 100644 --- a/tests/backend/test_app.py +++ b/tests/backend/test_app.py @@ -15,3 +15,34 @@ def test_root_route(client): assert response.template.name == "main.html" assert "PhotoMap" in response.text + +def test_ie_compatibility_header_on_html(client): + """The root page must carry X-UA-Compatible: IE=edge to prevent Edge/IE + from switching into IE Compatibility Mode, which would break Swiper v11 + and cause SCRIPT1028 / HTML1416 / HTML1500 console errors.""" + response = client.get("/") + assert response.headers.get("x-ua-compatible") == "IE=edge" + + +def test_ie_compatibility_header_on_api(client): + """The X-UA-Compatible header should also be present on API responses.""" + response = client.get("/api/albums/") + assert response.headers.get("x-ua-compatible") == "IE=edge" + + +def test_legacy_edge_detection_script_present(client): + """The root page must include an inline script that detects legacy EdgeHTML + (Edge ≤18 / Edge 44) and redirects to the upgrade-instructions page before + any ES2020 library code runs.""" + response = client.get("/") + assert "window.StyleMedia" in response.text + assert "/static/unsupported-browser.html" in response.text + + +def test_unsupported_browser_page_served(client): + """The static unsupported-browser page must be served and contain the + upgrade link so that legacy Edge users see the instructions.""" + response = client.get("/static/unsupported-browser.html") + assert response.status_code == 200 + assert "microsoft.com/edge" in response.text +