mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 06:52:20 +02:00
Merge pull request #18 from o3LL/fix/duplicate-keyframes
fix(css): collapse duplicate @keyframes names to the definition that wins
This commit is contained in:
@@ -28,10 +28,6 @@
|
||||
0%, 100% { transform: scale(1); opacity: 1; }
|
||||
50% { transform: scale(1.5); opacity: 0.7; }
|
||||
}
|
||||
@keyframes research-pulse {
|
||||
0%, 100% { background: color-mix(in srgb, var(--red) 12%, transparent); }
|
||||
50% { background: color-mix(in srgb, var(--red) 22%, transparent); }
|
||||
}
|
||||
#cookbook-gguf-delete-overlay {
|
||||
background:rgba(0,0,0,0.5);
|
||||
backdrop-filter:blur(4px);
|
||||
|
||||
@@ -1480,7 +1480,6 @@ body.bg-pattern-ascii-fireflies {
|
||||
0% { opacity: 1; transform: translateY(0) translateX(0) scale(1); }
|
||||
100% { opacity: 0; transform: translateY(6px) translateX(-3px) scale(0.94); }
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
.row { display:flex; gap:6px; align-items:center; }
|
||||
.list-item:hover,
|
||||
.models-row:hover {
|
||||
@@ -6119,9 +6118,6 @@ body.bg-pattern-ascii-fireflies {
|
||||
#mobile-backdrop, #mobile-menu-btn { display:none !important; }
|
||||
#sidebar-backdrop { display:none !important; }
|
||||
/* ----- Loading spinner ----- */
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@@ -6240,14 +6236,6 @@ body.bg-pattern-ascii-fireflies {
|
||||
.session-skeleton-bubble.is-user { width: 72%; }
|
||||
.session-skeleton-line { height: 9px; margin-top: 7px; }
|
||||
}
|
||||
@keyframes loading-bounce {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
/* Modal styling */
|
||||
.modal {
|
||||
position:fixed;
|
||||
@@ -7555,11 +7543,6 @@ body.bg-pattern-ascii-fireflies {
|
||||
animation: pulse 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0.7; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
#recording-indicator {
|
||||
position: fixed;
|
||||
@@ -8720,7 +8703,6 @@ pre { background: var(--code-bg, var(--hl-bg, #282c34)) !important; }
|
||||
}
|
||||
.compare-probe-start-anyway svg { color: currentColor; }
|
||||
.compare-probe-start-anyway span { font-weight: 700; }
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes pane-shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
15% { transform: translateX(-3px) rotate(-0.5deg); }
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"""No two @keyframes may share a name across the app's stylesheets.
|
||||
|
||||
Duplicate names resolve last-wins across the whole cascade, so an earlier
|
||||
definition is dead code that still looks live at its call site. Two of them
|
||||
existed and differed from the definition that actually won, which also blocked
|
||||
moving either animation during the stylesheet decomposition: relocating one
|
||||
changes which is last and therefore changes rendered behaviour.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
STATIC = ROOT / "static"
|
||||
|
||||
|
||||
def _stylesheets() -> list[Path]:
|
||||
"""App-owned stylesheets, in no particular order. Vendored CSS is excluded."""
|
||||
sheets = [STATIC / "style.css"]
|
||||
sheets.extend(sorted((STATIC / "css").glob("*.css")))
|
||||
return [s for s in sheets if s.exists()]
|
||||
|
||||
|
||||
def _keyframe_names(text: str) -> list[str]:
|
||||
without_comments = re.sub(r"/\*.*?\*/", "", text, flags=re.S)
|
||||
return re.findall(
|
||||
r"@(?:-webkit-)?keyframes\s+([A-Za-z0-9_-]+)\s*\{", without_comments
|
||||
)
|
||||
|
||||
|
||||
def test_app_stylesheets_exist() -> None:
|
||||
"""Guard the guard: a rename must not turn this file into a no-op."""
|
||||
assert _stylesheets(), "no app stylesheets found to check"
|
||||
|
||||
|
||||
def test_no_keyframes_name_is_declared_twice() -> None:
|
||||
counts: collections.Counter[str] = collections.Counter()
|
||||
where: dict[str, list[str]] = collections.defaultdict(list)
|
||||
|
||||
for sheet in _stylesheets():
|
||||
for name in _keyframe_names(sheet.read_text(encoding="utf-8")):
|
||||
counts[name] += 1
|
||||
where[name].append(sheet.relative_to(ROOT).as_posix())
|
||||
|
||||
duplicates = {name: where[name] for name, n in counts.items() if n > 1}
|
||||
|
||||
assert duplicates == {}, (
|
||||
"duplicate @keyframes names resolve last-wins, so every definition but "
|
||||
f"the last is dead: {duplicates}"
|
||||
)
|
||||
Reference in New Issue
Block a user