"""In-memory flattening of positional ```` elements. DrawingML's text-run model has no way to express "jump to a new x/y inside the same paragraph". Every ```` carrying ``x``, ``y`` or non-zero ``dy`` is therefore a layout instruction this converter cannot honour inline — without flattening, a 4-line dy-stacked block collapses onto a single baseline and an x-anchored tspan jumps to the wrong column. The on-disk ``finalize_svg`` pipeline solves this by promoting each positional tspan to an independent ```` element. This module performs the same transformation in memory so ``svg_to_pptx`` can consume ``svg_output/`` directly without that disk step. Public API: flatten_positional_tspans(tree) -> bool Walk the SVG element tree, replace every positional ```` with an independent ````, and return whether anything changed. Heavy lifting is delegated to ``svg_finalize.flatten_tspan`` so the two pipelines stay behaviourally aligned. """ from __future__ import annotations import sys from pathlib import Path from xml.etree import ElementTree as ET def _flatten_module(): """Load the shared on-disk flattener after exposing the scripts root.""" scripts_dir = Path(__file__).resolve().parent.parent if str(scripts_dir) not in sys.path: sys.path.insert(0, str(scripts_dir)) from svg_finalize import flatten_tspan # type: ignore return flatten_tspan def flatten_positional_tspans( tree: ET.ElementTree, merge_paragraphs: bool = False, preserve_line_breaks: bool = False, ) -> bool: """Flatten positional ```` elements into independent ````. Delegates to ``svg_finalize.flatten_tspan.flatten_text_with_tspans`` so the in-memory transform exactly matches the on-disk one. When ``merge_paragraphs`` is True, mergeable paragraph blocks are preserved as a single . ``preserve_line_breaks`` marks visual rows for hard DrawingML line breaks instead of reflow. Returns True if any tspan was rewritten. """ return _flatten_module().flatten_text_with_tspans( tree, merge_paragraphs=merge_paragraphs, preserve_line_breaks=preserve_line_breaks, ) def nested_positional_tspan_errors(root: ET.Element) -> list[str]: """Return shared diagnostics for unsupported nested baseline jumps.""" return _flatten_module().nested_positional_tspan_errors(root)