diff --git a/coverage/emitted-schema-known-failures.json b/coverage/emitted-schema-known-failures.json index a6d270b2..02007b7d 100644 --- a/coverage/emitted-schema-known-failures.json +++ b/coverage/emitted-schema-known-failures.json @@ -1,10 +1,4 @@ [ - { - "id": "ilpa-orphaned-ppr-close", - "issue": "#450", - "match": "not well-formed: Opening and ending tag mismatch: \"w:body\" != \"w:pPr\"", - "reason": "ILPA-pair comparison drops the opening of a paragraph-mark sectPr paragraph, leaving orphaned close tags at body level" - }, { "id": "duplicate-rprchange-in-rpr", "issue": "#451", diff --git a/packages/docx-core/src/baselines/diffmatch/xmlParser.test.ts b/packages/docx-core/src/baselines/diffmatch/xmlParser.test.ts index eae55e6a..f5b74baa 100644 --- a/packages/docx-core/src/baselines/diffmatch/xmlParser.test.ts +++ b/packages/docx-core/src/baselines/diffmatch/xmlParser.test.ts @@ -122,8 +122,36 @@ describe('diffmatch xml parser (xmldom)', () => { await then('the body parts and sectPr are correctly separated', () => { expect(parts.beforeBody).toContain(''); expect(parts.afterBody).toContain(''); - expect(extracted.content).toContain(''); - expect(extracted.sectPr).toContain(''); + expect(extracted.content).toContain('A'); + expect(extracted.sectPr).toContain(' { + let parts: ReturnType; + let extracted: ReturnType; + + await given('a body ending with a paragraph whose pPr contains sectPr and run content', () => { + const xml = ` + + + A + + +`; + parts = getBodyContent(xml); + }); + + await when('sectPr is extracted for document reconstruction', () => { + extracted = extractSectPr(parts.bodyContent); + }); + + await then('the paragraph remains intact and no body-level sectPr is returned', () => { + expect(extracted.sectPr).toBeNull(); + expect(extracted.content).toContain(''); + expect(extracted.content).toContain(''); }); }); }); diff --git a/packages/docx-core/src/baselines/diffmatch/xmlParser.ts b/packages/docx-core/src/baselines/diffmatch/xmlParser.ts index 9e281056..103996a5 100644 --- a/packages/docx-core/src/baselines/diffmatch/xmlParser.ts +++ b/packages/docx-core/src/baselines/diffmatch/xmlParser.ts @@ -210,17 +210,21 @@ export function extractSectPr(bodyContent: string): { content: string; sectPr: string | null; } { - // Find the last w:sectPr in the body - const sectPrMatch = bodyContent.match(/]*>[\s\S]*?<\/w:sectPr>\s*$/); + const trimmed = bodyContent.trimEnd(); + if (!trimmed.endsWith('')) return { content: bodyContent, sectPr: null }; - if (!sectPrMatch) { - return { content: bodyContent, sectPr: null }; - } + const sectPrStart = trimmed.lastIndexOf(''); + if (lastParagraphOpen > lastParagraphClose) return { content: bodyContent, sectPr: null }; - const sectPrStart = bodyContent.lastIndexOf(sectPrMatch[0]); + const trailingWhitespace = bodyContent.slice(trimmed.length); return { - content: bodyContent.slice(0, sectPrStart), - sectPr: sectPrMatch[0], + content: bodyContent.slice(0, sectPrStart) + trailingWhitespace, + sectPr: trimmed.slice(sectPrStart), }; } diff --git a/packages/docx-core/src/testing/outputs/typescript_redline.docx b/packages/docx-core/src/testing/outputs/typescript_redline.docx index bd8ccb95..3a879d50 100644 Binary files a/packages/docx-core/src/testing/outputs/typescript_redline.docx and b/packages/docx-core/src/testing/outputs/typescript_redline.docx differ