From 0bbb460d18b6289991d589a77beee60354e13aa4 Mon Sep 17 00:00:00 2001 From: Harbor404 <2657212322@qq.com> Date: Fri, 2 Oct 2026 01:50:32 +0800 Subject: [PATCH] fix(pptx): preserve soft line breaks with link formats --- haystack/components/converters/pptx.py | 8 +++++++- ...-pptx-soft-line-breaks-97f4237b1266d42f.yaml | 6 ++++++ .../converters/test_pptx_to_document.py | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-pptx-soft-line-breaks-97f4237b1266d42f.yaml diff --git a/haystack/components/converters/pptx.py b/haystack/components/converters/pptx.py index f4d9fed086a..2ec673c332c 100644 --- a/haystack/components/converters/pptx.py +++ b/haystack/components/converters/pptx.py @@ -101,7 +101,13 @@ def _process_paragraph(self, paragraph: "_Paragraph") -> str: if self.link_format == "none": return paragraph.text parts = [] - for run in paragraph.runs: + runs = {run._r: run for run in paragraph.runs} + for content in paragraph._element.content_children: + run = runs.get(content) + if run is None: + if content.text == "\v": + parts.append("\v") + continue if run.hyperlink and run.hyperlink.address: if self.link_format == "markdown": parts.append(f"[{run.text}]({run.hyperlink.address})") diff --git a/releasenotes/notes/fix-pptx-soft-line-breaks-97f4237b1266d42f.yaml b/releasenotes/notes/fix-pptx-soft-line-breaks-97f4237b1266d42f.yaml new file mode 100644 index 00000000000..7f435f7d93b --- /dev/null +++ b/releasenotes/notes/fix-pptx-soft-line-breaks-97f4237b1266d42f.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixed ``PPTXToDocument`` dropping soft line breaks from paragraphs when ``link_format`` is + ``"markdown"`` or ``"plain"``. Soft line breaks are now preserved as vertical tabs + (``"\v"``), matching the behavior of the default ``"none"`` format. diff --git a/test/components/converters/test_pptx_to_document.py b/test/components/converters/test_pptx_to_document.py index 647a2a35719..679bf0a4782 100644 --- a/test/components/converters/test_pptx_to_document.py +++ b/test/components/converters/test_pptx_to_document.py @@ -2,11 +2,14 @@ # # SPDX-License-Identifier: Apache-2.0 +import io import logging import os from pathlib import Path import pytest +from pptx import Presentation +from pptx.util import Inches from haystack.components.converters.pptx import PPTXToDocument from haystack.dataclasses import ByteStream @@ -123,3 +126,17 @@ def test_no_link_extraction(self, test_files_path): assert "https://example.com" not in content assert "Example" in content + + @pytest.mark.parametrize("link_format", ["markdown", "plain"]) + def test_soft_line_break_preserved(self, link_format): + presentation = Presentation() + slide = presentation.slides.add_slide(presentation.slide_layouts[6]) + text_frame = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(7), Inches(2)).text_frame + text_frame.text = "Account: Alice\vBalance: 100" + buffer = io.BytesIO() + presentation.save(buffer) + + converter = PPTXToDocument(link_format=link_format) + output = converter.run(sources=[ByteStream(data=buffer.getvalue())]) + + assert output["documents"][0].content == "Account: Alice\vBalance: 100"