refactor: govern CSS tokens and cascade

This commit is contained in:
leefer
2026-07-29 21:56:39 +08:00
parent 8d617cfa17
commit ed2b47fe90
11 changed files with 551 additions and 425 deletions
+82
View File
@@ -0,0 +1,82 @@
from __future__ import annotations
import re
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
STATIC = ROOT / "static"
TOKENS = STATIC / "shared" / "tokens.css"
LEGACY_STYLESHEETS = (
"styles.css",
"renovation.css",
"redesign-v2.css",
"design-system.css",
"theme.css",
)
class CssGovernanceTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.html = (STATIC / "index.html").read_text(encoding="utf-8")
cls.tokens = TOKENS.read_text(encoding="utf-8")
def test_token_layer_loads_before_application_styles(self) -> None:
expected_order = (
"/shared/tokens.css",
"/styles.css",
"/renovation.css",
"/redesign-v2.css",
"/design-system.css",
"/theme.css",
"/wentian-v2.css",
)
positions = [self.html.index(path) for path in expected_order]
self.assertEqual(positions, sorted(positions))
def test_token_file_has_three_layer_contract(self) -> None:
for heading in (
"/* Primitive tokens */",
"/* Semantic tokens */",
"/* Component tokens */",
"/* Compatibility aliases.",
):
self.assertIn(heading, self.tokens)
for variable in (
"--color-action:",
"--surface-canvas:",
"--text-primary:",
"--card-bg:",
"--control-height:",
"--sidebar-width:",
):
self.assertIn(variable, self.tokens)
def test_light_and_dark_semantics_share_one_owner(self) -> None:
self.assertIn(':root[data-theme="dark"] {', self.tokens)
global_root = re.compile(r'(?m)^:root(?:\[data-theme="dark"\])?\s*\{')
for filename in LEGACY_STYLESHEETS:
stylesheet = (STATIC / filename).read_text(encoding="utf-8")
self.assertIsNone(global_root.search(stylesheet), filename)
def test_wentian_tokens_remain_isolated(self) -> None:
self.assertNotRegex(self.tokens, r"--wt-[a-z0-9-]+\s*:")
wentian = (STATIC / "wentian-v2.css").read_text(encoding="utf-8")
self.assertRegex(wentian, r"--wt-[a-z0-9-]+\s*:")
def test_compatibility_aliases_cover_historical_layers(self) -> None:
for variable in (
"--blue:",
"--up:",
"--xb-blue-500:",
"--r2-blue:",
"--chart-background:",
"--dragon-profile-list-width:",
):
self.assertIn(variable, self.tokens)
if __name__ == "__main__":
unittest.main()
+2 -1
View File
@@ -27,6 +27,7 @@ class FrontendContractTests(unittest.TestCase):
cls.ui_core = (STATIC_DIR / "ui-core.js").read_text(encoding="utf-8")
cls.design_system = (STATIC_DIR / "design-system.css").read_text(encoding="utf-8")
cls.theme = (STATIC_DIR / "theme.css").read_text(encoding="utf-8")
cls.tokens = (STATIC_DIR / "shared" / "tokens.css").read_text(encoding="utf-8")
collector = IdCollector()
collector.feed(cls.html)
cls.ids = collector.ids
@@ -268,7 +269,7 @@ class FrontendContractTests(unittest.TestCase):
self.assertIn("#sentimentCycleView .sentiment-history-frame {", self.theme)
self.assertIn("margin-bottom: var(--card-gap);", self.theme)
self.assertIn("padding-bottom: var(--card-gap);", self.theme)
self.assertIn("--sentiment-history-max-height:510px;", self.design_system)
self.assertIn("--sentiment-history-max-height: 510px;", self.tokens)
self.assertIn("max-height:var(--sentiment-history-max-height);", self.design_system)
self.assertIn("overflow:auto;", self.design_system)