Skip to content

fix: enhance drawing and inline node handling in translation [SD-824]#1271

Closed
palmer-cl wants to merge 2 commits intomainfrom
cp/fix/field-ids
Closed

fix: enhance drawing and inline node handling in translation [SD-824]#1271
palmer-cl wants to merge 2 commits intomainfrom
cp/fix/field-ids

Conversation

@palmer-cl
Copy link
Collaborator

  • Updated drawing-translator to only wrap valid wp:inline and wp:anchor children in w:drawing.
  • Improved translateInlineNode to guard against invalid drawing structures and ensure proper handling of image nodes.
  • Improved image and signature placeholder exports, ensuring non-zero IDs are generated when missing.
  • Added tests

- Updated `drawing-translator` to only wrap valid `wp:inline` and `wp:anchor` children in `w:drawing`.
- Added tests to ensure correct behavior when child nodes are not drawing elements.
- Improved `translateInlineNode` to guard against invalid drawing structures and ensure proper handling of image nodes.
- Introduced tests for image and signature placeholder exports, ensuring non-zero IDs are generated when missing.
@palmer-cl palmer-cl changed the title fix: enhance drawing and inline node handling in translation fix: enhance drawing and inline node handling in translation [SD-824] Nov 16, 2025
@linear
Copy link

linear bot commented Nov 16, 2025

@palmer-cl palmer-cl marked this pull request as ready for review November 26, 2025 05:23
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

Copy link
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

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

@palmer-cl good stuff — these fixes are still needed on main and the approach makes sense.

no blockers. one small edge case on the ID generation, and worth checking if the anchor path needs the same guard as inline.

code is clean — a couple cleanup suggestions inline.

tests cover the main paths well. adding a case for attrs.id = 0 would lock down the exact bug this fixes.

left inline comments.

const drawingXmlns = 'http://schemas.openxmlformats.org/drawingml/2006/main';
const pictureXmlns = 'http://schemas.openxmlformats.org/drawingml/2006/picture';

// Ensure valid positive docPr/cNvPr IDs
Copy link
Contributor

Choose a reason for hiding this comment

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

this can still produce id: 0 in rare cases (~1 in 2 billion). easy fix:

Suggested change
// Ensure valid positive docPr/cNvPr IDs
const docPrId = attrs.id && Number(attrs.id) > 0 ? attrs.id : Math.max(1, parseInt(generateDocxRandomId(), 16));

Comment on lines +64 to +66
// Guard: only wrap when we have wp:inline/wp:anchor content.
const validDrawingChildren = new Set(['wp:inline', 'wp:anchor']);
if (!resultNode || !validDrawingChildren.has(resultNode.name)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

no need for a Set with just two values — a plain check is clearer and avoids creating an object every call.

Suggested change
// Guard: only wrap when we have wp:inline/wp:anchor content.
const validDrawingChildren = new Set(['wp:inline', 'wp:anchor']);
if (!resultNode || !validDrawingChildren.has(resultNode.name)) {
if (!resultNode || (resultNode.name !== 'wp:inline' && resultNode.name !== 'wp:anchor')) {
return resultNode;
}

Comment on lines +17 to +24
if (!nodeElements || nodeElements.name === 'w:r') {
return nodeElements;
}
const hasExtent =
Array.isArray(nodeElements.elements) && nodeElements.elements.some((el) => el?.name === 'wp:extent');
if (!hasExtent) {
return nodeElements;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

these two guards do the same thing — both return nodeElements. one check covers all cases:

Suggested change
if (!nodeElements || nodeElements.name === 'w:r') {
return nodeElements;
}
const hasExtent =
Array.isArray(nodeElements.elements) && nodeElements.elements.some((el) => el?.name === 'wp:extent');
if (!hasExtent) {
return nodeElements;
}
if (!nodeElements?.elements?.some((el) => el?.name === 'wp:extent')) {
return nodeElements;
}

*
* Guard: ensure we only emit a valid inline drawing structure.
* wp:inline must contain expected drawing children (like wp:extent).

Copy link
Contributor

Choose a reason for hiding this comment

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

missing * on the empty line breaks the JSDoc block.

Comment on lines +28 to +32
const graphic = inline.elements.find((el) => el.name === 'a:graphic');
const graphicData = graphic.elements.find((el) => el.name === 'a:graphicData');
const pic = graphicData.elements.find((el) => el.name === 'pic:pic');
const nvPicPr = pic.elements.find((el) => el.name === 'pic:nvPicPr');
const cNvPr = nvPicPr.elements.find((el) => el.name === 'pic:cNvPr');
Copy link
Contributor

Choose a reason for hiding this comment

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

this 5-line walk to pic:cNvPr is copy-pasted at lines 57-61. a small findCNvPr(inline) helper at the top would clean it up.

@caio-pizzol
Copy link
Contributor

one more thing outside this diff: translateInlineNode now handles bad image data, but translateAnchorNode in packages/super-editor/src/core/super-converter/v3/handlers/wp/anchor/helpers/translate-anchor-node.js doesn't have the same guard. it accesses nodeElements.elements directly — if an anchor-positioned field annotation has invalid data, that would throw. worth adding the same guard there?

@caio-pizzol
Copy link
Contributor

closing this one in favor of #2363

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants