63 lines
2.2 KiB
Python
Executable File
63 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Validate the diagram-only fixture contract."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import xml.etree.ElementTree as ET
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent
|
|
SVG_NS = {"svg": "http://www.w3.org/2000/svg"}
|
|
FORBIDDEN_EFFECTS = (
|
|
"<linearGradient",
|
|
"<radialGradient",
|
|
"<filter",
|
|
"<pattern",
|
|
"feGaussianBlur",
|
|
"drop-shadow",
|
|
)
|
|
FORBIDDEN_VISIBLE_PHRASES = (
|
|
"핵심 메시지",
|
|
"TECHVIZ · VISUAL GRAMMAR FIXTURE",
|
|
"Pattern 0",
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
directories = sorted(p for p in ROOT.iterdir() if p.is_dir() and len(p.name) > 3 and p.name[:2].isdigit() and p.name[2] == "-")
|
|
if not directories:
|
|
raise SystemExit("no numbered fixture directories found")
|
|
|
|
for directory in directories:
|
|
svgs = list(directory.glob("*.svg"))
|
|
if len(svgs) != 1:
|
|
raise SystemExit(f"{directory.name}: expected one SVG, found {len(svgs)}")
|
|
svg_path = svgs[0]
|
|
source = svg_path.read_text(encoding="utf-8")
|
|
root = ET.fromstring(source)
|
|
if root.find("svg:title", SVG_NS) is None or root.find("svg:desc", SVG_NS) is None:
|
|
raise SystemExit(f"{svg_path}: missing SVG title/desc")
|
|
for token in FORBIDDEN_EFFECTS:
|
|
if token in source:
|
|
raise SystemExit(f"{svg_path}: forbidden visual effect {token}")
|
|
for phrase in FORBIDDEN_VISIBLE_PHRASES:
|
|
if phrase in source:
|
|
raise SystemExit(f"{svg_path}: forbidden poster chrome {phrase}")
|
|
|
|
composition_path = directory / "composition.json"
|
|
composition = json.loads(composition_path.read_text(encoding="utf-8"))
|
|
if composition.get("diagram_only") is not True:
|
|
raise SystemExit(f"{composition_path}: diagram_only must be true")
|
|
required = {"global title", "footer", "takeaway band", "gradient", "drop shadow", "glow"}
|
|
actual = set(composition.get("forbidden_visible_elements", []))
|
|
missing = required - actual
|
|
if missing:
|
|
raise SystemExit(f"{composition_path}: missing forbidden items {sorted(missing)}")
|
|
|
|
print(f"PASS {len(directories)} diagram-only fixtures")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|