chore: 收口复查遗留项并补 radiogroup 键盘导航
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# scripts/legacy
|
||||
|
||||
保留的旧版分析工具,来自早期手工 CSS 工作流,当前纯 Dark Reader 架构下不再参与日常流程。
|
||||
|
||||
- `aggregate.py` — 聚合多路由扫描结果
|
||||
- `fetch_bundle.py` — 抓取线上部署 CSS bundle
|
||||
- `probe_conflict.py` — 探测 CSS 覆盖冲突
|
||||
|
||||
如需恢复手工 CSS 扫描工作流,可参考这些脚本;否则可在一段时间后删除。
|
||||
@@ -0,0 +1,30 @@
|
||||
# 聚合扫描结果:按 (元素, 类名, 问题) 分组,统计影响页面数
|
||||
import json
|
||||
import pathlib
|
||||
from collections import defaultdict
|
||||
|
||||
data = json.loads(
|
||||
(pathlib.Path(__file__).parent / "scan-results.json").read_text(encoding="utf-8")
|
||||
)
|
||||
|
||||
groups = defaultdict(lambda: {"pages": [], "sample": None})
|
||||
for route, items in data.items():
|
||||
if route.startswith("__") or isinstance(items, dict):
|
||||
continue
|
||||
for it in items:
|
||||
key = (it["tag"], it["cls"], tuple(it["issues"]))
|
||||
groups[key]["pages"].append(route)
|
||||
if groups[key]["sample"] is None:
|
||||
groups[key]["sample"] = it
|
||||
|
||||
# 按影响页面数降序
|
||||
ranked = sorted(groups.items(), key=lambda kv: -len(kv[1]["pages"]))
|
||||
for (tag, cls, issues), g in ranked:
|
||||
s = g["sample"]
|
||||
pages = g["pages"]
|
||||
print(f"[{len(pages)}页] <{tag}> .{cls[:80]}")
|
||||
print(f" 问题: {', '.join(issues)}")
|
||||
print(f" 路径: {s['path'][:130]}")
|
||||
print(f" 文本: {s['text'][:40]} 尺寸: {s['size']}")
|
||||
print(f" 页面: {', '.join(pages[:12])}{' ...' if len(pages) > 12 else ''}")
|
||||
print()
|
||||
@@ -0,0 +1,54 @@
|
||||
# 抓取服务端实际部署的插件 bundle.css,与本地构建产物对比
|
||||
import pathlib
|
||||
import re
|
||||
import time
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
ROOT = pathlib.Path(__file__).parent
|
||||
PROFILE = ROOT / "pw-profile"
|
||||
OUT = ROOT / "deployed-bundle.css"
|
||||
|
||||
with sync_playwright() as p:
|
||||
ctx = p.chromium.launch_persistent_context(
|
||||
str(PROFILE), channel="msedge", headless=True
|
||||
)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
page.goto("https://blog.liuhangyv.top/console/overview", wait_until="domcontentloaded")
|
||||
time.sleep(4)
|
||||
text = page.evaluate(
|
||||
"""async () => {
|
||||
const sheet = [...document.styleSheets].find(s => s.href && s.href.includes('bundle.css'));
|
||||
if (!sheet) return null;
|
||||
return await (await fetch(sheet.href)).text();
|
||||
}"""
|
||||
)
|
||||
ctx.close()
|
||||
|
||||
if not text:
|
||||
print("未找到 bundle.css")
|
||||
raise SystemExit(1)
|
||||
|
||||
OUT.write_text(text, encoding="utf-8")
|
||||
local = (ROOT.parent / "ui" / "build" / "dist" / "style.css").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def dark_selectors(css: str) -> set:
|
||||
# 提取所有 [data-halo-theme=dark] 规则的选择器(粗略切分)
|
||||
return set(re.findall(r"(\[data-halo-theme=dark\][^{]+)\{", css))
|
||||
|
||||
|
||||
dep = dark_selectors(text)
|
||||
loc = dark_selectors(local)
|
||||
print(f"部署版 dark 规则选择器数: {len(dep)}")
|
||||
print(f"本地构建 dark 规则选择器数: {len(loc)}")
|
||||
print(f"本地有而部署没有(未部署的新覆盖): {len(loc - dep)}")
|
||||
for s in sorted(loc - dep)[:40]:
|
||||
print(" +", s[:110])
|
||||
print(f"部署有而本地没有(本地已删除的旧规则): {len(dep - loc)}")
|
||||
for s in sorted(dep - loc)[:40]:
|
||||
print(" -", s[:110])
|
||||
|
||||
for kw in ["description-item__label", "description-item__content", "empty-title",
|
||||
"menu-item-title", "alert-wrapper"]:
|
||||
print(f"关键字 {kw!r}: 部署版={'有' if kw in text else '无'} 本地={'有' if kw in local else '无'}")
|
||||
@@ -0,0 +1,49 @@
|
||||
# 冲突溯源:找出与插件暗色规则竞争的原生规则及其样式表加载顺序
|
||||
import pathlib
|
||||
import time
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
ROOT = pathlib.Path(__file__).parent
|
||||
PROFILE = ROOT / "pw-profile"
|
||||
|
||||
with sync_playwright() as p:
|
||||
ctx = p.chromium.launch_persistent_context(
|
||||
str(PROFILE), channel="msedge", headless=True
|
||||
)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
page.goto("https://blog.liuhangyv.top/console/overview", wait_until="domcontentloaded")
|
||||
try:
|
||||
page.wait_for_load_state("networkidle", timeout=10000)
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(3)
|
||||
result = page.evaluate(
|
||||
"""() => {
|
||||
const targets = ['description-item__label', 'menu-item-title', 'empty-title', 'alert-wrapper'];
|
||||
const out = [];
|
||||
const sheets = [...document.styleSheets];
|
||||
sheets.forEach((sheet, si) => {
|
||||
let rules;
|
||||
try { rules = sheet.cssRules; } catch (e) { return; }
|
||||
for (const r of rules) {
|
||||
const sel = r.selectorText || '';
|
||||
if (sel.includes('data-halo-theme')) continue;
|
||||
for (const t of targets) {
|
||||
if (sel.includes(t)) {
|
||||
out.push({ sheetIndex: si, href: (sheet.href || '(inline)').slice(-60), selector: sel.slice(0, 120), body: r.style.cssText.slice(0, 120) });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 插件 bundle.css 的位置
|
||||
const pluginIdx = sheets.findIndex(s => s.href && s.href.includes('bundle.css'));
|
||||
return { pluginIdx, totalSheets: sheets.length, matches: out };
|
||||
}"""
|
||||
)
|
||||
ctx.close()
|
||||
|
||||
print(f"插件 bundle.css 样式表序号: {result['pluginIdx']} / 共 {result['totalSheets']} 个")
|
||||
for m in result["matches"]:
|
||||
print(f"[sheet #{m['sheetIndex']:>2}] {m['selector']}")
|
||||
print(f" {m['body']} <- {m['href']}")
|
||||
Reference in New Issue
Block a user