Environment
- superdoc 1.43.2 (npm), browser editor,
documentMode: 'editing'
- Export via
superdoc.export({ exportType: ['docx'], triggerDownload: false })
- Source checked at commit 2b50f53 (2026-06-25)
Summary
When SuperDoc re-serializes a DrawingML text box on DOCX export, it writes an mc:AlternateContent element containing only the mc:Choice branch (Requires="wps") and no mc:Fallback. Per ECMA-376 Part 3 (Markup Compatibility and Extensibility), consumers that do not support the wps namespace rely on the Fallback branch. The resulting documents break downstream OOXML consumers.
We hit this while evaluating SuperDoc: a document that contained text box shapes (with proper Choice + Fallback pairs authored by Word) came back after an editing session with 4 Choice-only mc:AlternateContent blocks in word/document.xml.
Root cause (in source)
packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/wp/helpers/translate-drawingml-textbox.js (line 51) builds the wrapper with the Choice branch only:
const alternateContent = {
name: 'mc:AlternateContent',
elements: [
{
name: 'mc:Choice',
attributes: { Requires: 'wps' },
elements: [drawing],
},
// no mc:Fallback
],
};
The generic translator already does this correctly. packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/mc/altermateContent/alternate-content-translator.js (lines 76-88, decode()) emits both branches:
const fallback = {
name: 'mc:Fallback',
elements: [
{
name: 'w:drawing',
elements: carbonCopy(drawing.elements || []),
},
],
};
return {
name: 'mc:AlternateContent',
elements: [choice, fallback],
};
Impact
docx-preview (widely used OSS renderer) crashes on such documents: its checkAlternateContent returns the Fallback's first child when the Choice requires an unsupported namespace (wps is not in its supported list), so a missing Fallback yields Cannot read properties of undefined (reading 'localName') and the whole preview fails.
- Any consumer without wps support (older Word versions, converters) will silently render nothing where the shape was, since the compat branch is gone.
Suggested fix
Mirror the decode() pattern of alternate-content-translator.js in translate-drawingml-textbox.js: append an mc:Fallback carrying a copy of the drawing (or, better, preserve the original Fallback branch captured at import time when one existed).
We are happy to submit a PR along those lines if the approach sounds right to you.
Possibly related observation (not yet isolated)
In the same editing session, the exported package came back minimal: 9 parts instead of the original ~30, with the embedded fonts under word/fonts/ and the theme dropped (5.9 MB down to 25 KB). Our controlled round-trips (open, edit body text, export) preserve the full package, so we could not isolate the trigger yet. We can file a separate issue with a reproduction once we pin it down, but mentioning it here in case the text box re-serialization path also switches the exporter to a rebuild-from-scratch package mode.
Environment
documentMode: 'editing'superdoc.export({ exportType: ['docx'], triggerDownload: false })Summary
When SuperDoc re-serializes a DrawingML text box on DOCX export, it writes an
mc:AlternateContentelement containing only themc:Choicebranch (Requires="wps") and nomc:Fallback. Per ECMA-376 Part 3 (Markup Compatibility and Extensibility), consumers that do not support the wps namespace rely on the Fallback branch. The resulting documents break downstream OOXML consumers.We hit this while evaluating SuperDoc: a document that contained text box shapes (with proper Choice + Fallback pairs authored by Word) came back after an editing session with 4 Choice-only
mc:AlternateContentblocks inword/document.xml.Root cause (in source)
packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/wp/helpers/translate-drawingml-textbox.js(line 51) builds the wrapper with the Choice branch only:The generic translator already does this correctly.
packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/mc/altermateContent/alternate-content-translator.js(lines 76-88,decode()) emits both branches:Impact
docx-preview(widely used OSS renderer) crashes on such documents: itscheckAlternateContentreturns the Fallback's first child when the Choice requires an unsupported namespace (wps is not in its supported list), so a missing Fallback yieldsCannot read properties of undefined (reading 'localName')and the whole preview fails.Suggested fix
Mirror the
decode()pattern ofalternate-content-translator.jsintranslate-drawingml-textbox.js: append anmc:Fallbackcarrying a copy of the drawing (or, better, preserve the original Fallback branch captured at import time when one existed).We are happy to submit a PR along those lines if the approach sounds right to you.
Possibly related observation (not yet isolated)
In the same editing session, the exported package came back minimal: 9 parts instead of the original ~30, with the embedded fonts under
word/fonts/and the theme dropped (5.9 MB down to 25 KB). Our controlled round-trips (open, edit body text, export) preserve the full package, so we could not isolate the trigger yet. We can file a separate issue with a reproduction once we pin it down, but mentioning it here in case the text box re-serialization path also switches the exporter to a rebuild-from-scratch package mode.