From 1cc0c3a7b45f6a5f1590ff25a32f719f1d870c8c Mon Sep 17 00:00:00 2001 From: Tadeu Tupinamba Date: Wed, 4 Feb 2026 16:59:10 -0300 Subject: [PATCH] fix(converter): handle absolute paths in header/footer relationship targets Documents created by tools like Google Docs may use absolute paths (e.g., `/word/header1.xml`) in relationship target attributes instead of relative paths (e.g., `header1.xml`). This caused the relationship file lookup to construct invalid paths like `word/_rels//word/header1.xml.rels` instead of `word/_rels/header1.xml.rels`, resulting in images in headers not rendering. The fix extracts just the filename from the resolved path, which handles both absolute and relative paths correctly per the ECMA-376 OPC spec. Fixes SD-1786 --- .../v2/importer/docxImporter.js | 5 ++- .../encode-image-node-helpers-header.test.js | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/super-editor/src/core/super-converter/v2/importer/docxImporter.js b/packages/super-editor/src/core/super-converter/v2/importer/docxImporter.js index ae34942c3c..02c5b63586 100644 --- a/packages/super-editor/src/core/super-converter/v2/importer/docxImporter.js +++ b/packages/super-editor/src/core/super-converter/v2/importer/docxImporter.js @@ -759,7 +759,10 @@ const getHeaderFooterSectionData = (sectionData, docx) => { const target = sectionData.attributes.Target; const filePath = resolveOpcTargetPath(target, 'word'); const referenceFile = filePath ? docx[filePath] : undefined; - const currentFileName = target; + // Extract just the filename for relationship file lookup. + // This handles both absolute paths (/word/header1.xml -> header1.xml) + // and relative paths (header1.xml -> header1.xml) per ECMA-376 OPC spec. + const currentFileName = filePath ? filePath.split('/').pop() : target.split('/').pop(); return { rId, referenceFile, diff --git a/packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/encode-image-node-helpers-header.test.js b/packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/encode-image-node-helpers-header.test.js index 68289fb976..6416c600cb 100644 --- a/packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/encode-image-node-helpers-header.test.js +++ b/packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/encode-image-node-helpers-header.test.js @@ -341,4 +341,46 @@ describe('handleImageNode - Header/Footer Images', () => { expect(result?.attrs?.id).toBe('3'); expect(result?.attrs?.alt).toContain('Picture 3'); // From wp:docPr name attribute }); + + it('should handle absolute paths in image relationship targets (SD-1786)', () => { + // This test covers the SD-1786 bug where documents (e.g., from Google Docs) + // use absolute paths like "/word/media/image1.png" instead of relative paths. + // The normalizeTargetPath function should handle this correctly. + + const node = makeImageNode(); + + const params = { + filename: 'header1.xml', + docx: { + 'word/_rels/header1.xml.rels': { + elements: [ + { + name: 'Relationships', + attributes: { + xmlns: 'http://schemas.openxmlformats.org/package/2006/relationships', + }, + elements: [ + { + name: 'Relationship', + attributes: { + Id: 'rId1', + Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + // Absolute path (starts with /) - this is valid per ECMA-376 but less common + Target: '/word/media/image1.png', + }, + }, + ], + }, + ], + }, + }, + }; + + const result = handleImageNode(node, params, true); + + expect(result).not.toBeNull(); + expect(result?.type).toBe('image'); + // Should normalize to the correct path without leading slash + expect(result?.attrs?.src).toBe('word/media/image1.png'); + }); });