Skip to content

Warn on tracked changes in DOCX import and clamp table spans in export #677

Open

Description

@HMarzban

Goal

A DOCX import must tell the reader when it accepted tracked changes. One stored table span must not be able to exhaust the rest-api process during an export.

#662 led to this work. The commit is 508c9d607 on local main. It is not pushed yet, so the hash does not resolve on GitHub.

Facts

Tested through the real importDocx, exportDocx and renderDocumentHtml, on hand-built DOCX files. Not tested on a file authored in Word.

  • mammoth 1.13.0 keeps tracked insertions as plain text and drops tracked deletions. It reports neither, so the warning list stayed the same as for a clean file.
  • encodeContent validates content expressions, not attribute values, so a stored colspan is unbounded. A DOCX gridSpan reached the import result unchanged.
  • The renderer writes one <col> per span. Before the fix, a colspan of 100,000 added 398 MB of RSS in one DOCX export, against the 512M rest-api limit. After the fix, it adds 2 MB.
  • rowspan of 100,000 cost nothing measurable in a DOCX export, so it stays unclamped outside ODT. A low cap would break real long tables.

What changed

All code paths are under apps/hocuspocus.server/src/modules/document-conversion/.

  1. domain/docxImport.ts scans word/*.xml with JSZip, the reader mammoth uses. On a hit, tracked-changes-accepted goes first in warnings, because the panel lists only the first few.
  2. domain/portableJson.ts clamps colspan to MAX_TABLE_SPAN (64) for every writer. importDocx clamps it too, so an import cannot carry the value into a document.
  3. domain/mapNodes.ts now walks a swapped node's children. Without this, an embed inside a clamped cell reaches the writer unconverted.
  4. jszip 3.10.2 is now a direct dependency of @docs.plus/hocuspocus. It is the version already in the tree.
  5. API.md, the OpenAPI enum and apps/hocuspocus.server/CLAUDE.md are updated.

Decision

Accepting tracked changes with a warning is a deliberate exception to the Google Docs, Word and Notion rule. Maintainer ruling, 2026-11-02, recorded in AGENTS.md. Google Docs keeps them as suggestions, and Notion drops them and says so. docs.plus has no suggestion mode, and this issue does not build one.

Verification

  • 76 tests pass across conversion, OpenAPI and MCP. 11 are new, in docxImport.test.ts and portableJson.test.ts.
  • Each of 5 deliberate breaks of the fix made a test fail.
  • Typecheck and format are clean. ESLint has no findings in the source files.
  • A cold install passed: 1,709 packages, no integrity errors.

Still open

  • Push and deploy with back.
  • Check the warning in the import panel in a browser. Not done yet.
  • Check a real file authored in Word.

Out of scope, and not fixed here:

  • Comments, headers, charts and diagrams still drop with no warning. API.md says so. The panel line "You'll see what changes" still promises too much.
  • A large colspan already stored, or set through Yjs, still reaches the table view in each browser. That effect is not verified.
  • The zip guard work stays in #577.

Activity

  1. added this to the v2.3.0 milestone on Nov 2, 2026
  2. added
    bugSomething isn't working
    SecuritySecurity, access control, and data exposure
    PerformanceQuery cost, load, and capacity
    on Nov 2, 2026
  3. modified the milestones: v2.3.0, v2.4.0 on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    PerformanceQuery cost, load, and capacitySecuritySecurity, access control, and data exposurebugSomething isn't working

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions