Skip to content

Commit 348dad6

Browse files
authored
Merge pull request #704 from Harbour-Enterprises/fix/paragraph-fields-inside-lists
fix: paragaph fields inside lists for export
2 parents b5d859d + a492e4f commit 348dad6

1 file changed

Lines changed: 63 additions & 4 deletions

File tree

  • packages/super-editor/src/core/super-converter

packages/super-editor/src/core/super-converter/exporter.js

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,65 @@ function translateList(params) {
784784
// In docx we need a single paragraph, but can include line breaks in a run
785785
const collapsedParagraphNode = convertMultipleListItemsIntoSingleNode(listItem);
786786

787-
const outputNode = exportSchemaToJson({ ...params, node: collapsedParagraphNode });
787+
let outputNode = exportSchemaToJson({ ...params, node: collapsedParagraphNode });
788+
789+
/**
790+
* MS Word does not allow paragraphs inside lists (which are just paragraphs in OOXML)
791+
* So we need to turn paragraphs into runs and add line breaks
792+
*
793+
* Two cases:
794+
* 1. Final doc (keep paragraph field content inside list item)
795+
* 2. Not final doc (keep w:sdt node, process its content)
796+
*/
797+
let nodesToFlatten = [];
798+
if (Array.isArray(outputNode) && params.isFinalDoc) {
799+
const parsedElements = [];
800+
outputNode?.forEach((node, index) => {
801+
if (node?.elements) {
802+
const runs = node.elements?.filter((n) => n.name === 'w:r');
803+
parsedElements.push(...runs);
804+
805+
if (node.name === 'w:p' && index < outputNode.length - 1) {
806+
parsedElements.push({
807+
name: 'w:br',
808+
});
809+
}
810+
}
811+
});
812+
813+
outputNode = {
814+
name: 'w:p',
815+
elements: [{ name: 'w:pPr', elements: [] }, ...parsedElements],
816+
};
817+
}
818+
819+
/** Case 2: Process w:sdt content */
820+
const sdtNodes = outputNode.elements?.filter((n) => n.name === 'w:sdt');
821+
if (sdtNodes && sdtNodes.length > 0) {
822+
nodesToFlatten = sdtNodes;
823+
nodesToFlatten?.forEach((sdtNode) => {
824+
const sdtContent = sdtNode.elements.find((n) => n.name === 'w:sdtContent');
825+
if (sdtContent && sdtContent.elements) {
826+
const parsedElements = [];
827+
sdtContent.elements.forEach((element, index) => {
828+
const runs = element.elements?.filter((n) => n.name === 'w:r');
829+
parsedElements.push(...runs);
830+
831+
if (element.name === 'w:p' && index < sdtContent.elements.length - 1) {
832+
parsedElements.push({
833+
name: 'w:br',
834+
});
835+
}
836+
});
837+
sdtContent.elements = parsedElements;
838+
}
839+
});
840+
}
841+
788842
const pPr = outputNode.elements?.find((n) => n.name === 'w:pPr');
789-
if (pPr && pPr.elements && numPrTag) pPr.elements.unshift(numPrTag);
843+
if (pPr && pPr.elements && numPrTag) {
844+
pPr.elements.unshift(numPrTag);
845+
}
790846

791847
const indentTag = restoreIndent(listItem.attrs.indent);
792848
indentTag && pPr?.elements?.push(indentTag);
@@ -801,6 +857,7 @@ function translateList(params) {
801857
pPr?.elements?.splice(numPrIndex, 1);
802858
}
803859
}
860+
804861
return [outputNode];
805862
}
806863

@@ -2058,7 +2115,8 @@ function prepareHtmlAnnotation(params) {
20582115
editorSchema,
20592116
} = params;
20602117

2061-
const paragraphHtmlContainer = sanitizeHtml(attrs.rawHtml);
2118+
let html = attrs.rawHtml || attrs.displayLabel;
2119+
const paragraphHtmlContainer = sanitizeHtml(html);
20622120
const marksFromAttrs = translateFieldAttrsToMarks(attrs);
20632121
const allMarks = [...marks, ...marksFromAttrs];
20642122

@@ -2223,7 +2281,7 @@ function translateFieldAnnotation(params) {
22232281
};
22242282
const annotationAttrsJson = JSON.stringify(annotationAttrs);
22252283

2226-
return {
2284+
const result = {
22272285
name: 'w:sdt',
22282286
elements: [
22292287
{
@@ -2239,6 +2297,7 @@ function translateFieldAnnotation(params) {
22392297
},
22402298
],
22412299
};
2300+
return result;
22422301
}
22432302

22442303
export function translateHardBreak(params) {

0 commit comments

Comments
 (0)