| 1 | """Plan selector builders and text extraction shared by check-plan and apply. |
| 2 | |
| 3 | A replacement / table / chart edit can target a slot by ``slot_id`` (or |
| 4 | ``table_id`` / ``chart_id``), ``shape_id``, or ``shape_name``; these helpers turn |
| 5 | a plan entry into an ordered list of lookup keys and pull the new text out. |
| 6 | """ |
| 7 | |
| 8 | from __future__ import annotations |
| 9 | |
| 10 | from typing import Any |
| 11 | |
| 12 | |
| 13 | def _plain_len(value: str) -> int: |
| 14 | return len("".join(value.split())) |
| 15 | |
| 16 | |
| 17 | def _replacement_selectors(replacement: dict[str, Any]) -> list[str]: |
| 18 | selectors = [] |
| 19 | if replacement.get("slot_id"): |
| 20 | selectors.append(f"slot_id:{replacement['slot_id']}") |
| 21 | if replacement.get("shape_id"): |
| 22 | selectors.append(f"shape_id:{replacement['shape_id']}") |
| 23 | if replacement.get("shape_name"): |
| 24 | selectors.append(f"shape_name:{replacement['shape_name']}") |
| 25 | return selectors |
| 26 | |
| 27 | |
| 28 | def _table_selectors(table_edit: dict[str, Any]) -> list[str]: |
| 29 | selectors = [] |
| 30 | if table_edit.get("table_id"): |
| 31 | selectors.append(f"table_id:{table_edit['table_id']}") |
| 32 | if table_edit.get("shape_id"): |
| 33 | selectors.append(f"shape_id:{table_edit['shape_id']}") |
| 34 | if table_edit.get("shape_name"): |
| 35 | selectors.append(f"shape_name:{table_edit['shape_name']}") |
| 36 | return selectors |
| 37 | |
| 38 | |
| 39 | def _chart_selectors(chart_edit: dict[str, Any]) -> list[str]: |
| 40 | selectors = [] |
| 41 | if chart_edit.get("chart_id"): |
| 42 | selectors.append(f"chart_id:{chart_edit['chart_id']}") |
| 43 | if chart_edit.get("shape_id"): |
| 44 | selectors.append(f"shape_id:{chart_edit['shape_id']}") |
| 45 | if chart_edit.get("shape_name"): |
| 46 | selectors.append(f"shape_name:{chart_edit['shape_name']}") |
| 47 | return selectors |
| 48 | |
| 49 | |
| 50 | def _replacement_text(replacement: dict[str, Any]) -> str: |
| 51 | if "paragraphs" in replacement: |
| 52 | paragraphs = replacement["paragraphs"] |
| 53 | if not isinstance(paragraphs, list): |
| 54 | raise RuntimeError("Replacement field 'paragraphs' must be a list") |
| 55 | return "\n".join(str(item) for item in paragraphs) |
| 56 | return str(replacement.get("text", "")) |
| 57 | |
| 58 | |
| 59 | def _table_cell_text(cell_edit: dict[str, Any]) -> str: |
| 60 | if "paragraphs" in cell_edit: |
| 61 | paragraphs = cell_edit["paragraphs"] |
| 62 | if not isinstance(paragraphs, list): |
| 63 | raise RuntimeError("Table cell field 'paragraphs' must be a list") |
| 64 | return "\n".join(str(item) for item in paragraphs) |
| 65 | return str(cell_edit.get("text", "")) |
| 66 |