mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Bonsai: keep newlines and multiple spaces in SVG schedules (#5123)
The schedule SVG builder extracted cell text with `str(p)` on each odfpy paragraph. `str()` concatenates only raw character data and silently drops ODF whitespace/line-break child elements (`<text:s>` which encodes runs of two or more spaces, `<text:tab>`, `<text:line-break>`), so multi-space runs and in-paragraph newlines disappeared from the rendered schedule. Use `odf.teletype.extractText`, which expands those elements into real characters, and split the result on newlines so each in-paragraph line break becomes its own SVG line. Also set `xml:space="preserve"` on the SVG root, otherwise renderers collapse the now-preserved runs of spaces back to one. Verified live in headless Blender with the real Scheduler().schedule(): a cell "CODE<3 spaces>INFO" now renders "CODE INFO" (was "CODEINFO"), and "FIRST<line-break>SECOND" renders as two lines (was "FIRSTSECOND"). Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ from odf.opendocument import load as load_ods
|
||||
from odf.style import Style
|
||||
from odf.table import Table, TableCell, TableColumn, TableRow
|
||||
from odf.text import P
|
||||
from odf.teletype import extractText
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.drawing.svgwriter import SvgWriter
|
||||
@@ -63,6 +64,9 @@ class Scheduler:
|
||||
debug=False,
|
||||
id="root",
|
||||
)
|
||||
# Preserve runs of whitespace inside cells; without this SVG renderers
|
||||
# collapse multiple spaces (e.g. from ODF `<text:s>`) down to one.
|
||||
self.svg.attribs["xml:space"] = "preserve"
|
||||
self.padding = 1
|
||||
self.margin = 1
|
||||
|
||||
@@ -548,7 +552,14 @@ class Scheduler:
|
||||
:param wrap_text: if True, text will be wrapped to fit in cell
|
||||
:param cell_width: width of cell, used for wrapping text
|
||||
"""
|
||||
text_lines = [str(p) for p in p_tags]
|
||||
# `str(p)` only concatenates raw character data and silently drops
|
||||
# ODF whitespace/line-break elements (`<text:s>`, `<text:tab>`,
|
||||
# `<text:line-break>`), so runs of spaces and in-paragraph newlines were
|
||||
# lost. `extractText` expands those into real characters; splitting on
|
||||
# the resulting newlines turns each line break into its own SVG line.
|
||||
text_lines = []
|
||||
for p in p_tags:
|
||||
text_lines.extend(extractText(p).split("\n"))
|
||||
box_alignment_params = SvgWriter.get_box_alignment_parameters(box_alignment)
|
||||
text_params = {"font-size": font_size}
|
||||
if bold:
|
||||
|
||||
Reference in New Issue
Block a user