Skip to content

Make TextRun#text= work on runs with several w:t - #200

Merged
satoryu merged 1 commit into
masterfrom
fix-197-text-run-multiple-t
Oct 17, 2026
Merged

satoryu merged 1 commit into
masterfrom
fix-197-text-run-multiple-t

Conversation

@satoryu

@satoryu satoryu commented Oct 17, 2026

Copy link
Copy Markdown
Member

Bug (#197)

TextRun#text= only wrote when the run had exactly one w:t, or none. Otherwise it silently did nothing. Runs with several w:t are common:

  • LibreOffice and macOS textutil write text<w:br/>text in one run.
  • A hyperlink made of several runs is wrapped as a single TextRun.

As a result, Paragraph#text= on such a single-run paragraph and Bookmark#insert_text_before/after next to such a run silently did nothing.

Fix

TextRun#text= replaces the text from the first through the last w:t:

  • The content goes into the first w:t. The other w:t, and any w:br / w:tab / w:cr between them, are removed. #text never includes breaks or tabs, so a plain string can't say where they belong.
  • Breaks outside that range are kept, for example a trailing page break (<w:br w:type="page"/>), as are w:rPr, drawings and fields.
  • A run with a single w:t behaves exactly as before.
  • The doc comment points to Paragraph#substitute for edits that need line breaks to stay in place.

Bookmark#insert_text_before/after no longer go through text=. With the change above, text= would delete the adjacent run's line breaks just to add a few characters. Instead they write into the w:t right next to the bookmark: the end of the preceding run, or the start of the following one. When that run ends or starts with a break or tab, a new w:t is added on the bookmark's side of it. This also fixes an existing bug: on a run like <w:t>a</w:t><w:br/> before the bookmark, the text used to land before the break, on the wrong side.

remove_separators_between moved from Paragraph into Container (private), so Paragraph#substitute and TextRun#text= share it. No public API is added; the new constants and helpers are private.

Tests

  • text_run_spec:
    • several w:t with breaks and tabs between them → replaced, separators removed, formatting kept
    • a leading break and a trailing page break → kept
    • hyperlink made of two runs → replaced
  • paragraph_spec: #text= on a single run holding several w:t.
  • bookmark_spec, with the adjacent run holding several w:t:
    • insert_text_after → Xa<br>b
    • insert_text_before → a<tab>bX
    • the run ends with a break → a<br>X
    • the run starts with a break → X<br>a, with w:rPr still first

The full suite passes (293 examples), including the existing bookmark integration specs on real files.

Closes #197

🤖 Generated with Claude Code

TextRun#text= only wrote when the run had exactly one w:t (or none), so
on runs written by LibreOffice/textutil ("text<w:br/>text") and on
hyperlinks made of several runs it silently did nothing. That broke
Paragraph#text= on such single-run paragraphs and bookmark insertion.

text= now replaces the text from the first through the last w:t: the
content goes into the first w:t, and the other w:t and the line breaks
and tabs between them are removed. Breaks outside that range, such as a
trailing page break, and the run properties are kept. A run with a
single w:t behaves as before.

Bookmark#insert_text_before/after no longer go through text=, which
would now drop the adjacent run's breaks. They write into the w:t right
next to the bookmark instead (the end of the preceding run or the start
of the following one), adding a new w:t when the run ends or starts
with a break or tab. This also fixes text being inserted on the wrong
side of such a break.

Move remove_separators_between into Container so Paragraph and TextRun
share it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@satoryu
satoryu merged commit c45ba97 into master Oct 17, 2026
6 checks passed
@satoryu
satoryu deleted the fix-197-text-run-multiple-t branch October 17, 2026 17:03
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.

TextRun#text= does nothing on a run with more than one w:t

1 participant