A text box in a Word document is read once, not once for each way Word draws it by Maya-Kid · Pull Request #1020 · deeplethe/utopia · GitHub
Skip to content

A text box in a Word document is read once, not once for each way Word draws it - #1020

Merged
WaylandYang merged 2 commits into
deeplethe:devfrom
Maya-Kid:fix/docx-text-box-read-once
Oct 1, 2026
Merged

WaylandYang merged 2 commits into
deeplethe:devfrom
Maya-Kid:fix/docx-text-box-read-once

Conversation

@Maya-Kid

Copy link
Copy Markdown
Contributor

Since Word 2010, a text box is written twice inside mc:AlternateContent:

  • an mc:Choice with the DrawingML shape (wps:txbx);
  • an mc:Fallback with a VML shape (v:textbox) for older versions of Word.

Both carry the box's paragraphs. docx_xml_to_text reads every w:t it meets, so the text of every text box comes out twice.

Problem

On dev, a paragraph with a text box reading "Quarterly revenue rose 12%" comes out as:

Before the box. Quarterly revenue rose 12%
Quarterly revenue rose 12%
After the box.

The same text box in a table cell gives | Revenue | Up 12% Up 12% |.

  • The box's sentence is extracted twice, so its statements and their evidence are counted twice.
  • In a cell, the doubled text becomes the value the table row carries.

Reports, forms and cover pages use text boxes for titles, call-outs and side notes.

Change

docx_xml_to_text follows the markup-compatibility rule. In each mc:AlternateContent it reads the first mc:Choice and skips the later Choices and the mc:Fallback. It counts the depth of a skipped subtree to know where it ends.

A document without mc:AlternateContent reads exactly as before.

Verification

Run on macOS (arm64): Rust 1.98.1; the workspace suite against PostgreSQL 16 with pgvector 0.8.2, with Poppler 26.06.

  • crates/utopia-ingest/tests/docx_text_boxes.rs builds the text box the way Word writes it: the wps shape in the Choice, the VML shape in the Fallback. It also builds a variant with a second Choice.
    • a_text_box_is_read_once: the sentence appears once, and the text before and after the box is intact.
    • a_text_box_in_a_table_cell_is_read_once: | Revenue | Up 12% |.
    • On dev with only this file added, both fail with the text above.
  • cargo test --locked -p utopia-ingest: 96 unit tests and every integration test pass.
  • fmt, clippy and the workspace suite:
    • cargo fmt --all --check and cargo clippy --locked --workspace --all-targets -- -D warnings are clean.
    • UTOPIA_TEST_REQUIRE_DB=1 UTOPIA_TEST_REQUIRE_PDFTOTEXT=1 cargo test --locked --workspace passes: 1,331 passed, 0 failed, 6 ignored.
    • That workspace run had this change merged with the three other utopia-ingest fixes opened alongside it: spreadsheet dates, slide line breaks and Word headings.

Notes

  • A text box's text is still read where Word anchors it, inside the paragraph it belongs to.
  • The Word-headings change edits the same function. The two merge without a conflict, checked locally.

@Maya-Kid
Maya-Kid force-pushed the fix/docx-text-box-read-once branch from 0e2cec1 to 53069f0 Compare September 30, 2026 14:34
…d draws it

Signed-off-by: dada-yan <BinjunYann@gmail.com>
@Maya-Kid
Maya-Kid force-pushed the fix/docx-text-box-read-once branch from 53069f0 to 98d0126 Compare September 30, 2026 20:36

@WaylandYang WaylandYang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Thanks @Maya-Kid. Reviewed at 98d0126: the markup-compatibility rule is followed exactly (first Choice read, later Choices and the Fallback skipped by depth), a document without mc:AlternateContent reads as before, and the table-cell case is covered. It touches the same function as #1018; I will land them one after the other with a branch update in between.

@WaylandYang
WaylandYang merged commit 2e7ba78 into deeplethe:dev Oct 1, 2026
6 checks passed
@Maya-Kid
Maya-Kid deleted the fix/docx-text-box-read-once branch October 1, 2026 06:04
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.

2 participants