View-title text formatting#

Each view title has a French name line (index 0) and an English subtitle line (index 1). Per the in-house template, all title lines use a 5 mm char height and the subtitle must be Italic and come from a controlled vocabulary (FRONT VIEW, SECTION VIEW …). This demo checks both lines for three drift dimensions — char_height, vocabulary, and font_style — using each language’s view_type_patterns.

Input drawing#

Sheet 1 of support_assembly_wrong_view_names.json — three subtitles were each corrupted along a different dimension: FRONT VIEW scaled ×1.5 (5→7.5 mm), SECTION VIEWSECN VIEW (unknown vocabulary), and LEVELED SECTION VIEW flipped italic → regular.

How the check works#

Check title lines 0 and 1 of every titled view against char height, the language’s standard view-name patterns, and (for the subtitle) font style.

src/drawing_tools/demo_scenarios/view_names_formatting/minimal_script.py#
"""Demo: View-title text formatting.

Checks each view's name (line 0) and English subtitle (line 1) against the
in-house template (5 mm char height, standard view-name vocabulary, italic
subtitle), then writes:
  - ``view_names_report.md``  — Markdown formatting report (subtitle rows)
  - ``view_names_check.html`` — annotated drawing (green=OK, red=FAIL)

Both are written into the current working directory.
"""

from pathlib import Path

from ..shared import write_report
from ..viz_helpers import load_sheet, render_html
from . import build_visualization
from .build_visualization import DRAWING_JSON, OUT_HTML

#: relative → written to the current working directory.
REPORT_MD = Path("view_names_report.md")


def _property_columns(check: "build_visualization.LineCheck") -> tuple[str, str, str]:
    """Return (property, expected, found) strings for the first problem, or dashes."""
    if "char_height" in check.problems:
        rendered_size = check.rendered_size
        return "char_height", "5 mm", f"{rendered_size:g} mm" if rendered_size is not None else "?"
    if "vocabulary" in check.problems:
        return "text vocabulary", "standard english view name", check.text
    if "font_style" in check.problems:
        return "font_style", "Italic", check.font_style or "?"
    return "—", "—", "—"


def subtitle_rows(checks: list["build_visualization.LineCheck"]) -> list["build_visualization.LineCheck"]:
    """One row per view's subtitle (line 1), collapsing duplicate texts.

    Collapsing keys on ``(view_name, text)`` and keeps the first match — it assumes
    same-text duplicate subtitles share the same formatting (true here: both
    ``LEVELED SECTION VIEW`` copies were flipped identically). If divergent
    duplicates ever appear, key also on ``(check.ok, tuple(check.problems))`` so a
    differing copy is not hidden.
    """
    rows, seen = [], set()
    for check in checks:
        if check.line_idx != 1:
            continue
        key = (check.view_name, check.text)
        if key in seen:
            continue
        seen.add(key)
        rows.append(check)
    return rows


def build_report_md(rows: list["build_visualization.LineCheck"]) -> str:
    """Render the Markdown subtitle table + summary for the formatting report."""
    header = (
        "| | View | Line | Text | Property | Expected | Found | Status |\n"
        "|---|------|------|------|----------|----------|-------|--------|"
    )
    body_lines = []
    for check in rows:
        property_name, expected, found = _property_columns(check)
        badge = "🟢" if check.ok else "🔴"
        status = "OK" if check.ok else "FAIL"
        body_lines.append(
            f"| {badge} | {check.view_name} | 1 | {check.text} | {property_name} | {expected} | {found} | {status} |"
        )
    total = len(rows)
    ok = sum(check.ok for check in rows)
    rate = 100 * ok / total if total else 0.0
    summary = (
        f"**Summary (subtitles).** {total} subtitles checked · {ok} OK · " f"{total - ok} FAIL · pass rate {rate:.0f}%."
    )
    return "\n\n".join([header + "\n" + "\n".join(body_lines), summary])


def main() -> None:
    """Run the view-name formatting check, write the report and visualization."""
    sheet = load_sheet(DRAWING_JSON, sheet_index=1)

    checks = build_visualization.analyze(sheet)
    for check in checks:
        status = "OK" if check.ok else "FAIL"
        detail = "" if check.ok else " : " + ", ".join(check.problems)
        print(f"[{status}] {check.view_name!r} line[{check.line_idx}] {check.text!r}{detail}")

    rows = subtitle_rows(checks)
    write_report(REPORT_MD, "View-Title Formatting Check Report", [build_report_md(rows)])

    render_html(sheet, build_visualization.build_extras(sheet), OUT_HTML)


if __name__ == "__main__":
    main()

Result#

View

Subtitle

Property

Expected

Found

Status

VUE DE FACE

FRONT VIEW

char_height

5 mm

7.5 mm

🔴 FAIL

COUPE A2-A2

SECN VIEW

text vocabulary

standard name

SECN VIEW

🔴 FAIL

COUPE B2-B2

SECTION VIEW

🟢 OK

VUE ISOMETRIQUE

ISOMETRIC VIEW

🟢 OK

COUPE C2-C2 REDRESSEE

LEVELED SECTION VIEW

font_style

Italic

Regular

🔴 FAIL

5 subtitles · 2 OK · 3 FAIL · pass rate 40%. The visualization boxes each mutated subtitle red with a label (Wrong text size / Unknown view name / Wrong text style) and every other title line green.