mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +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.style import Style
|
||||||
from odf.table import Table, TableCell, TableColumn, TableRow
|
from odf.table import Table, TableCell, TableColumn, TableRow
|
||||||
from odf.text import P
|
from odf.text import P
|
||||||
|
from odf.teletype import extractText
|
||||||
|
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bonsai.bim.module.drawing.svgwriter import SvgWriter
|
from bonsai.bim.module.drawing.svgwriter import SvgWriter
|
||||||
@@ -63,6 +64,9 @@ class Scheduler:
|
|||||||
debug=False,
|
debug=False,
|
||||||
id="root",
|
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.padding = 1
|
||||||
self.margin = 1
|
self.margin = 1
|
||||||
|
|
||||||
@@ -548,7 +552,14 @@ class Scheduler:
|
|||||||
:param wrap_text: if True, text will be wrapped to fit in cell
|
:param wrap_text: if True, text will be wrapped to fit in cell
|
||||||
:param cell_width: width of cell, used for wrapping text
|
: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)
|
box_alignment_params = SvgWriter.get_box_alignment_parameters(box_alignment)
|
||||||
text_params = {"font-size": font_size}
|
text_params = {"font-size": font_size}
|
||||||
if bold:
|
if bold:
|
||||||
|
|||||||
Reference in New Issue
Block a user