chore: enforce shared WebUI layouts
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Keep raw module page frames from growing while shared layouts are adopted."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
META_ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||
REPOS_ROOT = META_ROOT.parent
|
||||
BASELINE_PATH = pathlib.Path(__file__).with_name("shared-webui-layout-baseline.txt")
|
||||
RAW_PAGE_FRAME = 'className="content-pad workspace-data-page'
|
||||
LOCAL_PAGE_LAYOUT = re.compile(r"\b(?:function|class|const)\s+PageLayout\b")
|
||||
CENTRAL_LAYOUT = pathlib.Path("govoplan-core/webui/src/components/PageLayout.tsx")
|
||||
REQUIRED_CONSUMERS = (
|
||||
pathlib.Path("govoplan-core/webui/src/components/admin/AdminPageLayout.tsx"),
|
||||
pathlib.Path("govoplan-core/webui/src/features/dashboard/DashboardPage.tsx"),
|
||||
pathlib.Path("govoplan-dashboard/webui/src/features/dashboard/DashboardPage.tsx"),
|
||||
pathlib.Path("govoplan-ops/webui/src/features/ops/OpsPage.tsx"),
|
||||
)
|
||||
|
||||
|
||||
def baseline_paths() -> set[pathlib.Path]:
|
||||
return {
|
||||
pathlib.Path(line.strip())
|
||||
for line in BASELINE_PATH.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip() and not line.lstrip().startswith("#")
|
||||
}
|
||||
|
||||
|
||||
def source_paths() -> list[pathlib.Path]:
|
||||
paths: list[pathlib.Path] = []
|
||||
for repository in sorted(REPOS_ROOT.glob("govoplan*")):
|
||||
source_root = repository / "webui" / "src"
|
||||
if source_root.is_dir():
|
||||
paths.extend(sorted(source_root.rglob("*.tsx")))
|
||||
return paths
|
||||
|
||||
|
||||
def relative(path: pathlib.Path) -> pathlib.Path:
|
||||
return path.relative_to(REPOS_ROOT)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
sources = source_paths()
|
||||
source_text = {relative(path): path.read_text(encoding="utf-8") for path in sources}
|
||||
raw_frames = {path for path, text in source_text.items() if RAW_PAGE_FRAME in text}
|
||||
baseline = baseline_paths()
|
||||
available_baseline = {
|
||||
path for path in baseline if (REPOS_ROOT / path.parts[0]).is_dir()
|
||||
}
|
||||
errors: list[str] = []
|
||||
|
||||
unexpected = sorted(raw_frames - available_baseline)
|
||||
if unexpected:
|
||||
errors.append("New raw page frames must use @govoplan/core-webui PageLayout:")
|
||||
errors.extend(f"- {path}" for path in unexpected)
|
||||
|
||||
resolved = sorted(available_baseline - raw_frames)
|
||||
if resolved:
|
||||
errors.append("Remove migrated page frames from the shared-layout baseline:")
|
||||
errors.extend(f"- {path}" for path in resolved)
|
||||
|
||||
for path, text in source_text.items():
|
||||
if path != CENTRAL_LAYOUT and LOCAL_PAGE_LAYOUT.search(text):
|
||||
errors.append(f"Module-local PageLayout definition is not allowed: {path}")
|
||||
|
||||
for path in REQUIRED_CONSUMERS:
|
||||
absolute_path = REPOS_ROOT / path
|
||||
if not absolute_path.exists():
|
||||
continue
|
||||
text = absolute_path.read_text(encoding="utf-8")
|
||||
if "<PageLayout" not in text:
|
||||
errors.append(f"Required shared-layout consumer no longer uses PageLayout: {path}")
|
||||
if RAW_PAGE_FRAME in text:
|
||||
errors.append(f"Required shared-layout consumer restored the raw page frame: {path}")
|
||||
|
||||
core_index = REPOS_ROOT / "govoplan-core/webui/src/index.ts"
|
||||
if core_index.exists() and "PageLayout, PageHeader" not in core_index.read_text(encoding="utf-8"):
|
||||
errors.append("Core must export PageLayout and PageHeader from @govoplan/core-webui.")
|
||||
|
||||
if errors:
|
||||
print("\n".join(errors), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print(
|
||||
"Shared WebUI layout contract passed: "
|
||||
f"{len(REQUIRED_CONSUMERS)} central consumers, "
|
||||
f"{len(raw_frames)} registered legacy page-frame files."
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user