import { strToU8, zipSync } from "fflate"; type XmlParts = Record; interface NodeBufferLike extends Uint8Array { toString(encoding?: string): string; } const nodeBuffer = ( globalThis as unknown as { Buffer: { from(value: string | Uint8Array): NodeBufferLike; }; } ).Buffer; export interface OoxmlFixture { buffer: NodeBufferLike; mimeType: string; name: string; } const XML_DECLARATION = ''; function packageFixture( name: string, mimeType: string, parts: XmlParts, ): OoxmlFixture { const archive = Object.fromEntries( Object.entries(parts) .sort(([left], [right]) => left.localeCompare(right)) .map(([path, xml]) => [path, strToU8(xml)]), ); return { buffer: nodeBuffer.from(zipSync(archive, { level: 6 })), mimeType, name, }; } function contentTypes(overrides: string): string { return `${XML_DECLARATION} ${overrides} `; } function rootRelationships(target: string): string { return `${XML_DECLARATION} `; } export function createMinimalDocx(): OoxmlFixture { return packageFixture( "three-page-document.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", { "[Content_Types].xml": contentTypes(` `), "_rels/.rels": rootRelationships("word/document.xml"), "word/_rels/document.xml.rels": `${XML_DECLARATION} `, "word/styles.xml": `${XML_DECLARATION} `, "word/document.xml": `${XML_DECLARATION} Office Tools Document Fixture This text is rendered from a project-authored DOCX package. Feature Status Local viewing Ready Second Page Search Marker Navigation reaches this independently laid-out page. Third page trailing marker This trailing page makes the middle page a stable scroll target. `, }, ); } export function createMinimalXlsx(): OoxmlFixture { return packageFixture( "two-sheet-workbook.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", { "[Content_Types].xml": contentTypes(` `), "_rels/.rels": rootRelationships("xl/workbook.xml"), "xl/workbook.xml": `${XML_DECLARATION} `, "xl/_rels/workbook.xml.rels": `${XML_DECLARATION} `, "xl/sharedStrings.xml": `${XML_DECLARATION} Office Tools Workbook Fixture Amount Total Details Sheet Search Marker Item Quantity `, "xl/styles.xml": `${XML_DECLARATION} `, "xl/worksheets/sheet1.xml": `${XML_DECLARATION} 0 1 1923 2SUM(A3:B3)42 `, "xl/worksheets/sheet2.xml": `${XML_DECLARATION} 3 45 Local parser2 `, }, ); } const PRESENTATION_NS = 'xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"'; function slideXml(title: string, body: string): string { return `${XML_DECLARATION} ${title} ${body} `; } function slideRelationships(): string { return `${XML_DECLARATION} `; } export function createMinimalPptx(): OoxmlFixture { return packageFixture( "two-slide-presentation.pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation", { "[Content_Types].xml": contentTypes(` `), "_rels/.rels": rootRelationships("ppt/presentation.xml"), "ppt/presentation.xml": `${XML_DECLARATION} `, "ppt/_rels/presentation.xml.rels": `${XML_DECLARATION} `, "ppt/slides/slide1.xml": slideXml( "Office Tools Presentation Fixture", "This first slide is rendered entirely in the browser.", ), "ppt/slides/slide2.xml": slideXml( "Second Slide Search Marker", "Navigation reaches the second project-authored slide.", ), "ppt/slides/_rels/slide1.xml.rels": slideRelationships(), "ppt/slides/_rels/slide2.xml.rels": slideRelationships(), "ppt/slideLayouts/slideLayout1.xml": `${XML_DECLARATION} `, "ppt/slideLayouts/_rels/slideLayout1.xml.rels": `${XML_DECLARATION} `, "ppt/slideMasters/slideMaster1.xml": `${XML_DECLARATION} `, "ppt/slideMasters/_rels/slideMaster1.xml.rels": `${XML_DECLARATION} `, "ppt/theme/theme1.xml": `${XML_DECLARATION} `, }, ); } export function createMalformedDocx(): OoxmlFixture { return { buffer: nodeBuffer.from("This is deliberately not an OOXML ZIP package."), mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", name: "malformed-document.docx", }; }