94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
"""Общие вставки в <head> HTML-ответов (favicon и т.д.)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from flask import Response
|
|
|
|
_FAVICON_TAGS = (
|
|
'<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">\n'
|
|
' <link rel="icon" href="/static/favicon-32.png" type="image/png" sizes="32x32">\n'
|
|
' <link rel="apple-touch-icon" href="/static/apple-touch-icon.png">'
|
|
)
|
|
|
|
_HAS_FAVICON_RE = re.compile(
|
|
r'<link[^>]+rel=["\'](?:shortcut\s+)?icon["\']',
|
|
re.IGNORECASE,
|
|
)
|
|
|
|
|
|
def inject_favicon_html(html: str) -> str:
|
|
"""Добавить favicon в <head>, если его ещё нет."""
|
|
if _HAS_FAVICON_RE.search(html):
|
|
return html
|
|
if "<head>" in html.lower():
|
|
return re.sub(
|
|
r"<head>",
|
|
"<head>\n " + _FAVICON_TAGS,
|
|
html,
|
|
count=1,
|
|
flags=re.IGNORECASE,
|
|
)
|
|
return _FAVICON_TAGS + "\n" + html
|
|
|
|
|
|
def _patch_html_response(response: Response, patch_fn) -> Response:
|
|
content_type = (response.content_type or "").lower()
|
|
if "text/html" not in content_type:
|
|
return response
|
|
if getattr(response, "direct_passthrough", False):
|
|
return response
|
|
try:
|
|
html = response.get_data(as_text=True)
|
|
except (TypeError, UnicodeDecodeError, RuntimeError):
|
|
return response
|
|
if not html or "<html" not in html.lower():
|
|
return response
|
|
patched = patch_fn(html)
|
|
if patched == html:
|
|
return response
|
|
response.set_data(patched)
|
|
if response.content_length is not None:
|
|
response.headers.pop("Content-Length", None)
|
|
return response
|
|
|
|
|
|
def inject_kiosk_cursor_html(html: str, path: str) -> str:
|
|
"""Скрыть курсор на страницах киоска (см. static/css/kiosk-cursor.css)."""
|
|
from flask import current_app
|
|
|
|
from app.kiosk_page_hints import is_kiosk_cursor_hidden_path
|
|
|
|
if not is_kiosk_cursor_hidden_path(path):
|
|
return html
|
|
if not current_app.config.get("WESP_KIOSK_HIDE_CURSOR", True):
|
|
return html
|
|
if "kiosk-cursor.css" in html:
|
|
return html
|
|
tag = (
|
|
'<link rel="stylesheet" href="/static/css/kiosk-cursor.css">\n'
|
|
' <script>document.documentElement.classList.add("wesp-kiosk-hide-cursor");</script>'
|
|
)
|
|
if "<head>" in html.lower():
|
|
return re.sub(
|
|
r"<head>",
|
|
"<head>\n " + tag,
|
|
html,
|
|
count=1,
|
|
flags=re.IGNORECASE,
|
|
)
|
|
return tag + "\n" + html
|
|
|
|
|
|
def _patch_head(html: str, path: str) -> str:
|
|
html = inject_favicon_html(html)
|
|
return inject_kiosk_cursor_html(html, path)
|
|
|
|
|
|
def apply_html_head_injects(response: Response, path: str) -> Response:
|
|
from app.kiosk_page_hints import apply_kiosk_translate_hints
|
|
|
|
response = apply_kiosk_translate_hints(response, path)
|
|
return _patch_html_response(response, lambda html: _patch_head(html, path))
|