From 7cac0b38355483ccd757f0fcc4b4236b033bcbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EC=B0=BD=EC=9A=B1?= Date: Thu, 11 Jun 2026 11:13:46 +0900 Subject: [PATCH] fix: resolve code-review findings from the clean-review restyle Correctness: - Make the local-artifact audit test skip on fresh clones (data/ is gitignored), so the suite passes outside this workstation - Drop the transform from the viewRise entrance animation: an animated transform made .view.active a containing block for 320ms and threw the fixed decision panel off-screen on every workbench entry - Collapse the queue toolbar at 1380px instead of 1180px; 1280x800 laptops no longer get a horizontal scrollbar (verified live) - Serve .woff2 as font/woff2 with an immutable cache header so the 2MB bundled font is fetched once, not per page load (with test) - Clip overflow on top-bar status chips (long apiError strings spilled over neighbors at 981-1180px) - Give queue-row selection a selector that outranks the even-row zebra stripe (selection background was parity-dependent) Cleanup: - Replace the stale old-palette focus ring and ::selection literals with color-mix over var(--teal) - Delete dead tokens: unused back-compat aliases (the comment claiming they were referenced was false), --rail-bot, --ochre-deep, and --font-stamp (identical to --font-ui since the Pretendard switch) - Tokenize scattered raw colors: rail ink scale, soft tint levels, inset-well and bevel shadows, naver/internal source-chip triplets - Remove the asset-preload div and three orphan SVGs nothing renders; tests now reject reintroducing them Verified: 359 tests pass; Playwright audit at 1440/1280/390 shows zero horizontal overflow on all views, Pretendard active, decision panel fixed at the viewport corner mid-animation. --- src/rights_filter/server/http_app.py | 12 +++ tests/operator_gui/test_static_workbench.py | 16 ++- tests/rights_filter/server/test_http_app.py | 30 ++++++ web/operator-gui/assets/case-character.svg | 16 --- web/operator-gui/assets/case-emblem.svg | 11 -- web/operator-gui/assets/match-web.svg | 14 --- web/operator-gui/index.html | 7 -- web/operator-gui/styles.css | 110 +++++++++----------- 8 files changed, 102 insertions(+), 114 deletions(-) delete mode 100644 web/operator-gui/assets/case-character.svg delete mode 100644 web/operator-gui/assets/case-emblem.svg delete mode 100644 web/operator-gui/assets/match-web.svg diff --git a/src/rights_filter/server/http_app.py b/src/rights_filter/server/http_app.py index d739f3d..c7616d3 100644 --- a/src/rights_filter/server/http_app.py +++ b/src/rights_filter/server/http_app.py @@ -12,6 +12,16 @@ from urllib.parse import unquote, urlparse from rights_filter.server.image_store import LocalSubmissionImageStore, SUPPORTED_IMAGE_SUFFIXES from rights_filter.server.sqlite_store import CopyrighterStore +# Windows Python builds may not know .woff2, which would serve the bundled +# 2MB font as application/octet-stream. +mimetypes.add_type("font/woff2", ".woff2") +mimetypes.add_type("font/woff", ".woff") + +# Bundled font binaries never change between releases; without any cache +# validator the browser re-downloads the full file on every page load. +_IMMUTABLE_SUFFIXES = {".woff2", ".woff"} +_IMMUTABLE_CACHE_CONTROL = "public, max-age=31536000, immutable" + def build_server( host: str, @@ -214,6 +224,8 @@ def build_server( self.send_response(HTTPStatus.OK) self.send_header("Content-Type", content_type) self.send_header("Content-Length", str(len(data))) + if path.suffix.lower() in _IMMUTABLE_SUFFIXES: + self.send_header("Cache-Control", _IMMUTABLE_CACHE_CONTROL) if untrusted: # Neutralize stored XSS from operator-uploaded / externally # collected media (an SVG can carry an inline - -