Skip to content

fix(pptx): convert soft line breaks instead of emitting a vertical tab - #2513

Open
Lukas (L4XB) wants to merge 1 commit into
microsoft:mainfrom
L4XB:fix/pptx-soft-line-breaks
Open

Lukas (L4XB) wants to merge 1 commit into
microsoft:mainfrom
L4XB:fix/pptx-soft-line-breaks

Conversation

@L4XB

Copy link
Copy Markdown

Summary

Shift+Enter inside a PowerPoint paragraph is an <a:br/> — one paragraph, two
lines — and python-pptx reports it as \v. PptxConverter passes shape.text,
cell.text, the notes text and the chart title straight through, so that
vertical tab lands in the Markdown:

>>> MarkItDown().convert("address.pptx").markdown
'<!-- Slide number: 1 -->\nADDRESS LINE ONE\x0bADDRESS LINE TWO'

A vertical tab is a C0 control, not Markdown. A renderer drops it, so the two
lines run together (ADDRESS LINE ONEADDRESS LINE TWO), and nothing downstream
treats it as whitespace either — a splitter sees one long line and a tokenizer
sees one strange token. Address blocks, signature blocks and "name / title"
boxes are where this shows up, which is most of the text in a deck's smaller
shapes.

After:

<!-- Slide number: 1 -->
# TITLE ONE TITLE TWO
ADDRESS LINE ONE
ADDRESS LINE TWO
| HEADER A HEADER B | H2 |
| --- | --- |
| CELL LINE ONE CELL LINE TWO | C2 |

### Notes:
NOTE LINE ONE
NOTE LINE TWO

What changed

One helper, applied where the text enters: \v becomes \n. A shape's own
paragraphs already arrive joined with \n, so a soft break now reads the same
way, and the table path needs nothing special — the newline goes into the HTML
the table is built from, where it is ordinary whitespace and collapses to a
space, so the row stays one row.

A slide title is the one place a newline cannot go: an ATX heading ends at the
line break, which would leave the rest of the title as body text. Titles
therefore collapse their line breaks to spaces. That also repairs the
already-broken case of a multi-paragraph title, which produces
# First\nSecond today.

Tests

test_pptx_soft_line_breaks_are_not_vertical_tabs in
packages/markitdown/tests/test_module_misc.py builds a deck with a soft break
in a title, a text box, a header cell, a body cell and the speaker notes, then
asserts no \v survives and each one reads correctly.

$ pytest packages/markitdown/tests/ -q
893 passed, 14 skipped

$ pytest -k pptx                      # against the current converter
FAILED test_pptx_soft_line_breaks_are_not_vertical_tabs
1 failed, 4 passed

The 893 include the reference test.pptx vector, so the title change is covered
against a real deck as well as the synthetic one.

black==23.7.0 (the pinned pre-commit version) leaves both files unchanged.

Shift+Enter inside a PowerPoint paragraph is an `<a:br/>`, and python-pptx
reports it as `\v`. The converter passes `shape.text`, `cell.text`, the notes
text and the chart title straight through, so that vertical tab reaches the
Markdown. It is a C0 control, not Markdown: renderers drop it, so the two lines
run together, and nothing downstream treats it as whitespace either.

Normalize it where the text enters. A shape's own paragraphs already arrive
joined with newlines, so a soft break reads the same way. A table cell keeps its
row: the newline goes into the HTML the table is built from, where it is
ordinary whitespace and collapses to a space.

A slide title is a special case: an ATX heading cannot span lines, so a newline
there would close the heading and leave the rest as body text. Titles now
collapse their line breaks to spaces, which also fixes the multi-paragraph
titles that already produced a stray body line.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant